OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class _FileInputStream implements FileInputStream { | 5 class _FileInputStream implements FileInputStream { |
6 _FileInputStream(File file) { | 6 _FileInputStream(File file) { |
7 _file = new File(file.name); | 7 _file = new File(file.name); |
8 _file.openSync(); | 8 _file.openSync(); |
9 } | 9 } |
10 | 10 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 void close() { | 86 void close() { |
87 _file.closeSync(); | 87 _file.closeSync(); |
88 } | 88 } |
89 | 89 |
90 File _file; | 90 File _file; |
91 } | 91 } |
92 | 92 |
93 | 93 |
Søren Gjesse
2011/11/01 13:22:49
Instead of using a Map for the operations one coul
Mads Ager (google)
2011/11/01 14:04:31
Yes, that would be cleaner. I would like to do tha
| |
94 class _FileOperationIsolate extends Isolate { | |
95 static int EXISTS = 0; | |
96 static int OPEN = 1; | |
97 static int CLOSE = 2; | |
98 static int READ_BYTE = 3; | |
99 static int READ_LIST = 4; | |
100 static int WRITE_BYTE = 5; | |
101 static int WRITE_LIST = 6; | |
102 static int WRITE_STRING = 7; | |
103 static int POSITION = 8; | |
104 static int LENGTH = 9; | |
105 static int FLUSH = 10; | |
106 static int EXIT = 11; | |
107 | |
108 _FileOperationIsolate() : super.heavy(); | |
109 | |
110 void handleOperation(Map message, SendPort ignored) { | |
111 switch (message["type"]) { | |
112 case EXISTS: | |
113 message["reply"].send(_File._exists(message["name"]), | |
114 port.toSendPort()); | |
115 break; | |
116 case OPEN: | |
117 var name = message["name"]; | |
118 var writable = message["writable"]; | |
119 message["reply"].send(_File._open(name, writable), | |
120 port.toSendPort()); | |
121 break; | |
122 case CLOSE: | |
123 message["reply"].send(_File._close(message["id"]), | |
124 port.toSendPort()); | |
125 break; | |
126 case READ_BYTE: | |
127 message["reply"].send(_File._readByte(message["id"]), | |
128 port.toSendPort()); | |
129 break; | |
130 case READ_LIST: | |
131 var replyPort = message["reply"]; | |
132 var bytes = message["bytes"]; | |
133 var offset = message["offset"]; | |
134 var length = message["length"]; | |
135 var id = message["id"]; | |
136 if (bytes == 0) { | |
137 replyPort.send(0, port.toSendPort()); | |
138 return; | |
139 } | |
140 if (offset < 0) { | |
141 replyPort.send("index out of range in readList: $offset", | |
142 port.toSendPort()); | |
143 return; | |
144 } | |
145 if (bytes < 0) { | |
146 replyPort.send("index out of range in readList: $bytes", | |
147 port.toSendPort()); | |
148 return; | |
149 } | |
150 if ((offset + bytes) > length) { | |
151 replyPort.send("index out of range in readList: ${offset + bytes}", | |
152 port.toSendPort()); | |
153 return; | |
154 } | |
155 var buffer = new List(bytes); | |
Søren Gjesse
2011/11/01 13:22:49
Can't we just call writeByteSync in a try catch bl
Mads Ager (google)
2011/11/01 14:04:31
Unfortunately not. In order to call writeByteSync
| |
156 var result = { "read": _File._readList(id, buffer, 0, bytes), | |
157 "buffer": buffer }; | |
158 replyPort.send(result, port.toSendPort()); | |
159 break; | |
160 case WRITE_BYTE: | |
161 message["reply"].send(_File._writeByte(message["id"], message["value"]), | |
162 port.toSendPort()); | |
163 break; | |
164 case WRITE_LIST: | |
165 var replyPort = message["reply"]; | |
166 var buffer = message["buffer"]; | |
167 var bytes = message["bytes"]; | |
168 var offset = message["offset"]; | |
169 var id = message["id"]; | |
170 if (bytes == 0) { | |
171 replyPort.send(0, port.toSendPort()); | |
172 return; | |
173 } | |
174 if (offset < 0) { | |
175 replyPort.send("index out of range in writeList: $offset", | |
176 port.toSendPort()); | |
177 return; | |
178 } | |
179 if (bytes < 0) { | |
180 replyPort.send("index out of range in writeList: $bytes", | |
181 port.toSendPort()); | |
182 return; | |
183 } | |
184 if ((offset + bytes) > buffer.length) { | |
185 replyPort.send("index out of range in writeList: ${offset + bytes}", | |
186 port.toSendPort()); | |
187 return; | |
188 } | |
189 var result = _File._writeList(id, buffer, offset, bytes); | |
190 replyPort.send(result, port.toSendPort()); | |
191 break; | |
192 case WRITE_STRING: | |
193 var id = message["id"]; | |
194 var string = message["string"]; | |
195 message["reply"].send(_File._writeString(id, string), | |
196 port.toSendPort()); | |
197 break; | |
198 case POSITION: | |
199 message["reply"].send(_File._position(message["id"]), | |
200 port.toSendPort()); | |
201 break; | |
202 case LENGTH: | |
203 message["reply"].send(_File._length(message["id"]), | |
204 port.toSendPort()); | |
205 break; | |
206 case FLUSH: | |
207 message["reply"].send(_File._flush(message["id"]), | |
208 port.toSendPort()); | |
209 break; | |
210 case EXIT: | |
211 port.close(); | |
212 return; | |
213 } | |
214 port.receive(handleOperation); | |
215 } | |
216 | |
217 void main() { | |
218 port.receive(handleOperation); | |
219 } | |
220 } | |
221 | |
222 | |
223 class _FileOperationScheduler { | |
224 _FileOperationScheduler() : _queue = new Queue(); | |
225 | |
226 void schedule(SendPort port) { | |
227 assert(_isolate != null); | |
228 if (_queue.isEmpty()) { | |
229 port.send({ "type": _FileOperationIsolate.EXIT }); | |
230 _isolate = null; | |
231 } else { | |
232 port.send(_queue.removeFirst()); | |
233 } | |
234 } | |
235 | |
236 void scheduleWrap(void callback(result, ignored)) { | |
237 return (result, replyTo) { | |
238 callback(result, replyTo); | |
239 schedule(replyTo); | |
240 }; | |
241 } | |
242 | |
243 void enqueue(Map params, void callback(result, ignored)) { | |
244 ReceivePort replyPort = new ReceivePort.singleShot(); | |
245 replyPort.receive(scheduleWrap(callback)); | |
246 params["reply"] = replyPort.toSendPort(); | |
247 _queue.addLast(params); | |
248 if (_isolate == null) { | |
249 _isolate = new _FileOperationIsolate(); | |
250 _isolate.spawn().then((port) { | |
251 schedule(port); | |
252 }); | |
253 } | |
254 } | |
255 | |
256 bool noPendingWrite() { | |
257 int queuedWrites = 0; | |
258 _queue.forEach((map) { | |
259 if (_isWriteOperation(map["type"])) { | |
260 queuedWrites++; | |
261 } | |
262 }); | |
263 return queuedWrites == 0; | |
264 } | |
265 | |
266 bool _isWriteOperation(int type) { | |
267 return (type == _FileOperationIsolate.WRITE_BYTE) || | |
268 (type == _FileOperationIsolate.WRITE_LIST) || | |
269 (type == _FileOperationIsolate.WRITE_STRING); | |
270 } | |
271 | |
272 Queue<Map> _queue; | |
273 _FileOperationIsolate _isolate; | |
274 } | |
275 | |
276 | |
94 // Class for encapsulating the native implementation of files. | 277 // Class for encapsulating the native implementation of files. |
95 class _File implements File { | 278 class _File implements File { |
96 // Constructor for file. | 279 // Constructor for file. |
97 _File(String this._name); | 280 _File(String this._name) |
281 : _scheduler = new _FileOperationScheduler(), | |
282 _asyncUsed = false; | |
283 | |
284 static bool _exists(String name) native "File_Exists"; | |
285 static int _open(String name, bool writable) native "File_Open"; | |
286 static int _close(int id) native "File_Close"; | |
287 static int _readByte(int id) native "File_ReadByte"; | |
288 static int _readList(int id, List<int> buffer, int offset, int bytes) | |
289 native "File_ReadList"; | |
290 static int _writeByte(int id, int value) native "File_WriteByte"; | |
291 static int _writeList(int id, List<int> buffer, int offset, int bytes) | |
292 native "File_WriteList"; | |
293 static int _writeString(int id, String string) native "File_WriteString"; | |
294 static int _position(int id) native "File_Position"; | |
295 static int _length(int id) native "File_Length"; | |
296 static int _flush(int id) native "File_Flush"; | |
98 | 297 |
99 void exists() { | 298 void exists() { |
299 _asyncUsed = true; | |
300 var handler = | |
301 (_existsHandler != null) ? _existsHandler : (result) => null; | |
302 Map params = { | |
303 "type": _FileOperationIsolate.EXISTS, | |
304 "name": _name | |
305 }; | |
306 _scheduler.enqueue(params, (result, ignored) { _existsHandler(result); }); | |
307 } | |
308 | |
309 bool existsSync() { | |
310 if (_asyncUsed) { | |
311 throw new FileIOException( | |
312 "mixed use of synchronous and asynchronous API"); | |
Søren Gjesse
2011/11/01 13:22:49
Uppercase M in mixed.
Mads Ager (google)
2011/11/01 14:04:31
Thanks, done throughout the file.
| |
313 } | |
314 return _exists(_name); | |
315 } | |
316 | |
317 void create() { | |
318 _asyncUsed = true; | |
100 throw "Unimplemented"; | 319 throw "Unimplemented"; |
101 } | 320 } |
102 | 321 |
103 bool existsSync() { | 322 void createSync() { |
104 return _fileExists(_name); | 323 if (_asyncUsed) { |
105 } | 324 throw new FileIOException( |
106 | 325 "mixed use of synchronous and asynchronous API"); |
107 bool _fileExists(String name) native "File_Exists"; | 326 } |
108 | |
109 void create() { | |
110 throw "Unimplemented"; | 327 throw "Unimplemented"; |
111 } | 328 } |
112 | 329 |
113 void createSync() { | |
114 throw "Unimplemented"; | |
115 } | |
116 | |
117 void open([bool writable = false]) { | 330 void open([bool writable = false]) { |
118 throw "Unimplemented"; | 331 _asyncUsed = true; |
332 var handler = (_openHandler != null) ? _openHandler : () => null; | |
333 var handleOpenResult = (result, ignored) { | |
334 if (result != 0) { | |
335 _id = result; | |
336 handler(); | |
337 } else if (_errorHandler != null) { | |
338 _errorHandler("Cannot open file: $_name"); | |
339 } | |
340 }; | |
341 Map params = { | |
342 "type": _FileOperationIsolate.OPEN, | |
343 "name": _name, | |
344 "writable": writable | |
345 }; | |
346 _scheduler.enqueue(params, handleOpenResult); | |
119 } | 347 } |
120 | 348 |
121 void openSync([bool writable = false]) { | 349 void openSync([bool writable = false]) { |
122 if (!_openFile(_name, writable)) { | 350 if (_asyncUsed) { |
351 throw new FileIOException( | |
352 "mixed use of synchronous and asynchronous API"); | |
353 } | |
354 _id = _open(_name, writable); | |
355 if (_id == 0) { | |
123 throw new FileIOException("Cannot open file: $_name"); | 356 throw new FileIOException("Cannot open file: $_name"); |
124 } | 357 } |
125 } | 358 } |
126 | 359 |
127 bool _openFile(String name, bool writable) native "File_OpenFile"; | |
128 | |
129 void close() { | 360 void close() { |
130 throw "Unimplemented"; | 361 _asyncUsed = true; |
362 var handler = (_closeHandler != null) ? _closeHandler : () => null; | |
363 var handleOpenResult = (result, ignored) { | |
364 if (result != -1) { | |
365 _id = result; | |
366 handler(); | |
367 } else if (_errorHandler != null) { | |
368 _errorHandler("Cannot open file: $_name"); | |
369 } | |
370 }; | |
371 Map params = { | |
372 "type": _FileOperationIsolate.CLOSE, | |
373 "id": _id | |
374 }; | |
375 _scheduler.enqueue(params, handleOpenResult); | |
131 } | 376 } |
132 | 377 |
133 void closeSync() { | 378 void closeSync() { |
134 _close(); | 379 if (_asyncUsed) { |
135 } | 380 throw new FileIOException( |
136 | 381 "mixed use of synchronous and asynchronous API"); |
137 int _close() native "File_Close"; | 382 } |
383 _id = _close(_id); | |
384 if (_id == -1) { | |
385 throw new FileIOException("Cannot close file: $_name"); | |
386 } | |
387 } | |
138 | 388 |
139 void readByte() { | 389 void readByte() { |
140 throw "Unimplemented"; | 390 _asyncUsed = true; |
391 var handler = | |
392 (_readByteHandler != null) ? _readByteHandler : (byte) => null; | |
393 var handleReadByteResult = (result, ignored) { | |
394 if (result != -1) { | |
395 handler(result); | |
396 } else if (_errorHandler != null) { | |
397 _errorHandler("readByte failed"); | |
398 } | |
399 }; | |
400 Map params = { | |
401 "type": _FileOperationIsolate.READ_BYTE, | |
402 "id": _id | |
403 }; | |
404 _scheduler.enqueue(params, handleReadByteResult); | |
141 } | 405 } |
142 | 406 |
143 int readByteSync() { | 407 int readByteSync() { |
144 int result = _readByte(); | 408 if (_asyncUsed) { |
409 throw new FileIOException( | |
410 "mixed use of synchronous and asynchronous API"); | |
411 } | |
412 int result = _readByte(_id); | |
145 if (result == -1) { | 413 if (result == -1) { |
146 throw new FileIOException("Error: readByte failed"); | 414 throw new FileIOException("readByte failed"); |
147 } | 415 } |
148 return result; | 416 return result; |
149 } | 417 } |
150 | 418 |
151 int _readByte() native "File_ReadByte"; | |
152 | |
153 void readList(List<int> buffer, int offset, int bytes) { | 419 void readList(List<int> buffer, int offset, int bytes) { |
154 throw "Unimplemented"; | 420 _asyncUsed = true; |
421 var handler = | |
422 (_readListHandler != null) ? _readListHandler : (result) => null; | |
423 var errorHandler = | |
Søren Gjesse
2011/11/01 13:22:49
is "var errorHandler" actually used?
Mads Ager (google)
2011/11/01 14:04:31
Done.
| |
424 (_errorHandler != null) ? _errorHandler : (error) => null; | |
425 var handleReadListResult = (result, ignored) { | |
426 if (result is Map && result["read"] != -1) { | |
427 var read = result["read"]; | |
428 buffer.setRange(offset, read, result["buffer"]); | |
429 handler(read); | |
430 return; | |
431 } | |
432 if (_errorHandler != null) { | |
433 _errorHandler(result is String ? result : "readList failed"); | |
434 } | |
435 }; | |
436 Map params = { | |
437 "type": _FileOperationIsolate.READ_LIST, | |
438 "length": buffer.length, | |
439 "offset": offset, | |
440 "bytes": bytes, | |
441 "id": _id | |
442 }; | |
443 _scheduler.enqueue(params, handleReadListResult); | |
155 } | 444 } |
156 | 445 |
157 int readListSync(List<int> buffer, int offset, int bytes) { | 446 int readListSync(List<int> buffer, int offset, int bytes) { |
447 if (_asyncUsed) { | |
448 throw new FileIOException( | |
449 "mixed use of synchronous and asynchronous API"); | |
450 } | |
158 if (bytes == 0) { | 451 if (bytes == 0) { |
159 return 0; | 452 return 0; |
160 } | 453 } |
161 if (offset < 0) { | 454 if (offset < 0) { |
162 throw new IndexOutOfRangeException(offset); | 455 throw new IndexOutOfRangeException(offset); |
163 } | 456 } |
164 if (bytes < 0) { | 457 if (bytes < 0) { |
165 throw new IndexOutOfRangeException(bytes); | 458 throw new IndexOutOfRangeException(bytes); |
166 } | 459 } |
167 if ((offset + bytes) > buffer.length) { | 460 if ((offset + bytes) > buffer.length) { |
168 throw new IndexOutOfRangeException(offset + bytes); | 461 throw new IndexOutOfRangeException(offset + bytes); |
169 } | 462 } |
170 int result = _readList(buffer, offset, bytes); | 463 int result = _readList(_id, buffer, offset, bytes); |
171 if (result == -1) { | 464 if (result == -1) { |
172 throw new FileIOException("Error: readList failed"); | 465 throw new FileIOException("readList failed"); |
173 } | 466 } |
174 return result; | 467 return result; |
175 } | 468 } |
176 | 469 |
177 int _readList(List<int> buffer, int offset, int bytes) native "File_ReadList"; | 470 void _checkPendingWrites() { |
471 if (_scheduler.noPendingWrite() && _noPendingWriteHandler != null) { | |
472 _noPendingWriteHandler(); | |
473 } | |
474 } | |
178 | 475 |
179 void writeByte(int value) { | 476 void writeByte(int value) { |
180 throw "Unimplemented"; | 477 _asyncUsed = true; |
478 var handleReadByteResult = (result, ignored) { | |
479 if (result == -1 &&_errorHandler != null) { | |
480 _errorHandler("writeByte failed"); | |
481 return; | |
482 } | |
483 _checkPendingWrites(); | |
484 }; | |
485 Map params = { | |
486 "type": _FileOperationIsolate.WRITE_BYTE, | |
487 "value": value, | |
488 "id": _id | |
489 }; | |
490 _scheduler.enqueue(params, handleReadByteResult); | |
181 } | 491 } |
182 | 492 |
183 int writeByteSync(int value) { | 493 int writeByteSync(int value) { |
184 int result = _writeByte(value); | 494 if (_asyncUsed) { |
495 throw new FileIOException( | |
496 "mixed use of synchronous and asynchronous API"); | |
497 } | |
498 int result = _writeByte(_id, value); | |
185 if (result == -1) { | 499 if (result == -1) { |
186 throw new FileIOException("Error: writeByte failed"); | 500 throw new FileIOException("writeByte failed"); |
187 } | 501 } |
188 return result; | 502 return result; |
189 } | 503 } |
190 | 504 |
191 int _writeByte(int value) native "File_WriteByte"; | 505 void writeList(List<int> buffer, int offset, int bytes) { |
192 | 506 _asyncUsed = true; |
193 int writeList(List<int> buffer, int offset, int bytes) { | 507 var errorHandler = |
Søren Gjesse
2011/11/01 13:22:49
var errorHandler used?
Mads Ager (google)
2011/11/01 14:04:31
Done.
| |
194 throw "Unimplemented"; | 508 (_errorHandler != null) ? _errorHandler : (error) => null; |
509 var handleWriteListResult = (result, ignored) { | |
510 if (result is !String && result != -1) { | |
511 if (result < bytes) { | |
512 writeList(buffer, offset + result, bytes - result); | |
513 } else { | |
514 _checkPendingWrites(); | |
515 } | |
516 return; | |
517 } | |
518 if (_errorHandler != null) { | |
519 _errorHandler(result is String ? result : "writeList failed"); | |
520 } | |
521 }; | |
522 Map params = { | |
523 "type": _FileOperationIsolate.WRITE_LIST, | |
524 "buffer": buffer, | |
525 "offset": offset, | |
526 "bytes": bytes, | |
527 "id": _id | |
528 }; | |
529 _scheduler.enqueue(params, handleWriteListResult); | |
195 } | 530 } |
196 | 531 |
197 int writeListSync(List<int> buffer, int offset, int bytes) { | 532 int writeListSync(List<int> buffer, int offset, int bytes) { |
533 if (_asyncUsed) { | |
534 throw new FileIOException( | |
535 "mixed use of synchronous and asynchronous API"); | |
536 } | |
198 if (bytes == 0) { | 537 if (bytes == 0) { |
199 return 0; | 538 return 0; |
200 } | 539 } |
201 if (offset < 0) { | 540 if (offset < 0) { |
202 throw new IndexOutOfRangeException(offset); | 541 throw new IndexOutOfRangeException(offset); |
203 } | 542 } |
204 if (bytes < 0) { | 543 if (bytes < 0) { |
205 throw new IndexOutOfRangeException(bytes); | 544 throw new IndexOutOfRangeException(bytes); |
206 } | 545 } |
207 if ((offset + bytes) > buffer.length) { | 546 if ((offset + bytes) > buffer.length) { |
208 throw new IndexOutOfRangeException(offset + bytes); | 547 throw new IndexOutOfRangeException(offset + bytes); |
209 } | 548 } |
210 int result = _writeList(buffer, offset, bytes); | 549 int result = _writeList(_id, buffer, offset, bytes); |
211 if (result == -1) { | 550 if (result == -1) { |
212 throw new FileIOException("Error: writeList failed"); | 551 throw new FileIOException("writeList failed"); |
213 } | 552 } |
214 return result; | 553 return result; |
215 } | 554 } |
216 | 555 |
217 int _writeList(List<int> buffer, int offset, int bytes) | 556 void writeString(String string) { |
218 native "File_WriteList"; | 557 _asyncUsed = true; |
219 | 558 var handleWriteStringResult = (result, ignored) { |
220 int writeString(String string) { | 559 if (result == -1 &&_errorHandler != null) { |
221 throw "Unimplemented"; | 560 _errorHandler("writeString failed"); |
561 return; | |
562 } | |
563 if (result < string.length) { | |
564 writeString(string.substring(result)); | |
565 } else { | |
566 _checkPendingWrites(); | |
567 } | |
568 }; | |
569 Map params = { | |
570 "type": _FileOperationIsolate.WRITE_STRING, | |
571 "string": string, | |
572 "id": _id | |
573 }; | |
574 _scheduler.enqueue(params, handleWriteStringResult); | |
222 } | 575 } |
223 | 576 |
224 int writeStringSync(String string) { | 577 int writeStringSync(String string) { |
225 int result = _writeString(string); | 578 if (_asyncUsed) { |
579 throw new FileIOException( | |
580 "mixed use of synchronous and asynchronous API"); | |
581 } | |
582 int result = _writeString(_id, string); | |
226 if (result == -1) { | 583 if (result == -1) { |
227 throw new FileIOException("Error: writeString failed"); | 584 throw new FileIOException("Error: writeString failed"); |
228 } | 585 } |
229 return result; | 586 return result; |
230 } | 587 } |
231 | 588 |
232 int _writeString(String string) native "File_WriteString"; | 589 void position() { |
233 | 590 _asyncUsed = true; |
234 int position() { | 591 var handler = (_positionHandler != null) ? _positionHandler : (pos) => null; |
235 throw "Unimplemented"; | 592 var handlePositionResult = (result, ignored) { |
593 if (result == -1 && _errorHandler != null) { | |
594 _errorHandler("position failed"); | |
595 return; | |
596 } | |
597 handler(result); | |
598 }; | |
599 Map params = { | |
600 "type": _FileOperationIsolate.POSITION, | |
601 "id": _id | |
602 }; | |
603 _scheduler.enqueue(params, handlePositionResult); | |
236 } | 604 } |
237 | 605 |
238 int positionSync() { | 606 int positionSync() { |
239 int result = _position; | 607 if (_asyncUsed) { |
608 throw new FileIOException( | |
609 "mixed use of synchronous and asynchronous API"); | |
610 } | |
611 int result = _position(_id); | |
240 if (result == -1) { | 612 if (result == -1) { |
241 throw new FileIOException("Error: get position failed"); | 613 throw new FileIOException("position failed"); |
242 } | 614 } |
243 return result; | 615 return result; |
244 } | 616 } |
245 | 617 |
246 int get _position() native "File_Position"; | 618 void length() { |
247 | 619 _asyncUsed = true; |
248 int length() { | 620 var handler = (_lengthHandler != null) ? _lengthHandler : (pos) => null; |
249 throw "Unimplemented"; | 621 var handleLengthResult = (result, ignored) { |
622 if (result == -1 && _errorHandler != null) { | |
623 _errorHandler("length failed"); | |
624 return; | |
625 } | |
626 handler(result); | |
627 }; | |
628 Map params = { | |
629 "type": _FileOperationIsolate.LENGTH, | |
630 "id": _id | |
631 }; | |
632 _scheduler.enqueue(params, handleLengthResult); | |
250 } | 633 } |
251 | 634 |
252 int lengthSync() { | 635 int lengthSync() { |
253 int result = _length; | 636 if (_asyncUsed) { |
637 throw new FileIOException( | |
638 "mixed use of synchronous and asynchronous API"); | |
639 } | |
640 int result = _length(_id); | |
254 if (result == -1) { | 641 if (result == -1) { |
255 throw new FileIOException("Error: get length failed"); | 642 throw new FileIOException("length failed"); |
256 } | 643 } |
257 return result; | 644 return result; |
258 } | 645 } |
259 | 646 |
260 int get _length() native "File_Length"; | |
261 | |
262 void flush() { | 647 void flush() { |
263 throw "Unimplemented"; | 648 _asyncUsed = true; |
649 var handler = (_flushHandler != null) ? _flushHandler : (pos) => null; | |
650 var handleFlushResult = (result, ignored) { | |
651 if (result == -1 && _errorHandler != null) { | |
652 _errorHandler("flush failed"); | |
653 return; | |
654 } | |
655 handler(); | |
656 }; | |
657 Map params = { | |
658 "type": _FileOperationIsolate.FLUSH, | |
659 "id": _id | |
660 }; | |
661 _scheduler.enqueue(params, handleFlushResult); | |
264 } | 662 } |
265 | 663 |
266 void flushSync() { | 664 void flushSync() { |
267 int result = _flush(); | 665 if (_asyncUsed) { |
666 throw new FileIOException( | |
667 "mixed use of synchronous and asynchronous API"); | |
668 } | |
669 int result = _flush(_id); | |
268 if (result == -1) { | 670 if (result == -1) { |
269 throw new FileIOException("Error: flush failed"); | 671 throw new FileIOException("flush failed"); |
270 } | 672 } |
271 } | 673 } |
272 | 674 |
273 int _flush() native "File_Flush"; | |
274 | |
275 InputStream openInputStream() { | 675 InputStream openInputStream() { |
276 return new _FileInputStream(this); | 676 return new _FileInputStream(this); |
277 } | 677 } |
278 | 678 |
279 OutputStream openOutputStream() { | 679 OutputStream openOutputStream() { |
280 return new _FileOutputStream(this); | 680 return new _FileOutputStream(this); |
281 } | 681 } |
282 | 682 |
283 String get name() { | 683 String get name() { |
284 return _name; | 684 return _name; |
(...skipping 20 matching lines...) Expand all Loading... | |
305 } | 705 } |
306 | 706 |
307 void set readListHandler(void handler(int read)) { | 707 void set readListHandler(void handler(int read)) { |
308 _readListHandler = handler; | 708 _readListHandler = handler; |
309 } | 709 } |
310 | 710 |
311 void set noPendingWriteHandler(void handler()) { | 711 void set noPendingWriteHandler(void handler()) { |
312 _noPendingWriteHandler = handler; | 712 _noPendingWriteHandler = handler; |
313 } | 713 } |
314 | 714 |
715 void set positionHandler(void handler(int pos)) { | |
716 _positionHandler = handler; | |
717 } | |
718 | |
719 void set lengthHandler(void handler(int length)) { | |
720 _lengthHandler = handler; | |
721 } | |
722 | |
723 void set flushHandler(void handler()) { | |
724 _flushHandler = handler; | |
725 } | |
726 | |
315 void set errorHandler(void handler(String error)) { | 727 void set errorHandler(void handler(String error)) { |
316 _errorHandler = handler; | 728 _errorHandler = handler; |
317 } | 729 } |
318 | 730 |
319 String _name; | 731 String _name; |
320 int _id; | 732 int _id; |
733 bool _asyncUsed; | |
734 | |
735 _FileOperationScheduler _scheduler; | |
321 | 736 |
322 var _existsHandler; | 737 var _existsHandler; |
323 var _createHandler; | 738 var _createHandler; |
324 var _openHandler; | 739 var _openHandler; |
325 var _closeHandler; | 740 var _closeHandler; |
326 var _readByteHandler; | 741 var _readByteHandler; |
327 var _readListHandler; | 742 var _readListHandler; |
328 var _noPendingWriteHandler; | 743 var _noPendingWriteHandler; |
744 var _positionHandler; | |
745 var _lengthHandler; | |
746 var _flushHandler; | |
329 var _errorHandler; | 747 var _errorHandler; |
330 } | 748 } |
OLD | NEW |