OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 extends _BaseDataInputStream implements InputStream { | 5 class _FileInputStream extends _BaseDataInputStream implements InputStream { |
6 _FileInputStream(String name) { | 6 _FileInputStream(String name) { |
7 _file = new File(name); | 7 _file = new File(name); |
8 _data = []; | 8 _data = []; |
9 _position = 0; | 9 _position = 0; |
10 _file.errorHandler = (String s) { | 10 _file.onError = (String s) { |
11 if (_clientErrorHandler != null) { | 11 if (_clientErrorHandler != null) { |
12 _clientErrorHandler(); | 12 _clientErrorHandler(); |
13 } | 13 } |
14 }; | 14 }; |
15 _file.open(); | 15 _file.open(FileMode.READ, (openedFile) { |
16 _file.openHandler = (openedFile) { | |
17 _readDataFromFile(openedFile); | 16 _readDataFromFile(openedFile); |
18 }; | 17 }); |
19 } | 18 } |
20 | 19 |
21 _FileInputStream.fromStdio(int fd) { | 20 _FileInputStream.fromStdio(int fd) { |
22 assert(fd == 0); | 21 assert(fd == 0); |
23 _file = _File._openStdioSync(fd); | 22 _file = _File._openStdioSync(fd); |
24 _data = []; | 23 _data = []; |
25 _position = 0; | 24 _position = 0; |
26 _readDataFromFile(_file); | 25 _readDataFromFile(_file); |
27 } | 26 } |
28 | 27 |
29 void _readDataFromFile(RandomAccessFile openedFile) { | 28 void _readDataFromFile(RandomAccessFile openedFile) { |
30 openedFile.errorHandler = (String s) { | 29 openedFile.onError = (String s) { |
31 if (_clientErrorHandler != null) { | 30 if (_clientErrorHandler != null) { |
32 _clientErrorHandler(); | 31 _clientErrorHandler(); |
33 } | 32 } |
34 }; | 33 }; |
35 openedFile.length(); | 34 openedFile.length((length) { |
36 openedFile.lengthHandler = (length) { | |
37 var contents = new ByteArray(length); | 35 var contents = new ByteArray(length); |
38 if (length != 0) { | 36 if (length != 0) { |
39 openedFile.readList(contents, 0, length); | 37 openedFile.readList(contents, 0, length, (read) { |
40 openedFile.readListHandler = (read) { | |
41 if (read != length) { | 38 if (read != length) { |
42 if (_clientErrorHandler != null) { | 39 if (_clientErrorHandler != null) { |
43 _clientErrorHandler(); | 40 _clientErrorHandler(); |
44 } | 41 } |
45 } else { | 42 } else { |
46 _data = contents; | 43 _data = contents; |
47 } | 44 } |
48 openedFile.close(); | 45 openedFile.close(() { |
49 openedFile.closeHandler = () { | |
50 _streamMarkedClosed = true; | 46 _streamMarkedClosed = true; |
51 _checkScheduleCallbacks(); | 47 _checkScheduleCallbacks(); |
52 }; | 48 }); |
53 }; | 49 }); |
54 } else { | 50 } else { |
55 openedFile.close(); | 51 openedFile.close(() { |
56 openedFile.closeHandler = () { | |
57 _streamMarkedClosed = true; | 52 _streamMarkedClosed = true; |
58 _checkScheduleCallbacks(); | 53 _checkScheduleCallbacks(); |
59 }; | 54 }); |
60 }; | 55 } |
61 }; | 56 }); |
62 } | 57 } |
63 | 58 |
64 int available() { | 59 int available() { |
65 return _closed ? 0 : _data.length - _position; | 60 return _closed ? 0 : _data.length - _position; |
66 } | 61 } |
67 | 62 |
68 void pipe(OutputStream output, [bool close = true]) { | 63 void pipe(OutputStream output, [bool close = true]) { |
69 _pipe(this, output, close: close); | 64 _pipe(this, output, close: close); |
70 } | 65 } |
71 | 66 |
(...skipping 21 matching lines...) Expand all Loading... |
93 List<int> _data; | 88 List<int> _data; |
94 int _position; | 89 int _position; |
95 bool _closed = false; | 90 bool _closed = false; |
96 } | 91 } |
97 | 92 |
98 | 93 |
99 class _FileOutputStream implements OutputStream { | 94 class _FileOutputStream implements OutputStream { |
100 _FileOutputStream(String name, FileMode mode) { | 95 _FileOutputStream(String name, FileMode mode) { |
101 _pendingOperations = new List<List<int>>(); | 96 _pendingOperations = new List<List<int>>(); |
102 var f = new File(name); | 97 var f = new File(name); |
103 f.open(mode); | 98 f.open(mode, (openedFile) { |
104 f.openHandler = (openedFile) { | |
105 _file = openedFile; | 99 _file = openedFile; |
106 _setupFileHandlers(); | 100 _setupFileHandlers(); |
107 _processPendingOperations(); | 101 _processPendingOperations(); |
108 }; | 102 }); |
109 f.errorHandler = (e) { | 103 f.onError = (e) { |
110 if (_errorHandler != null) _errorHandler(); | 104 if (_onError != null) _onError(); |
111 }; | 105 }; |
112 } | 106 } |
113 | 107 |
114 _FileOutputStream.fromStdio(int fd) { | 108 _FileOutputStream.fromStdio(int fd) { |
115 assert(1 <= fd && fd <= 2); | 109 assert(1 <= fd && fd <= 2); |
116 _file = _File._openStdioSync(fd); | 110 _file = _File._openStdioSync(fd); |
117 _setupFileHandlers(); | 111 _setupFileHandlers(); |
118 } | 112 } |
119 | 113 |
120 | 114 |
121 void _setupFileHandlers() { | 115 void _setupFileHandlers() { |
122 _file.errorHandler = (e) { | 116 _file.onError = (e) { |
123 if (_errorHandler != null) _errorHandler(); | 117 if (_onError != null) _onError(); |
124 }; | 118 }; |
125 _file.noPendingWriteHandler = () { | 119 _file.onNoPendingWrites = () { |
126 if (!_streamMarkedClosed && _noPendingWriteHandler != null) { | 120 if (!_streamMarkedClosed && _onNoPendingWrites != null) { |
127 _noPendingWriteHandler(); | 121 _onNoPendingWrites(); |
128 } | 122 } |
129 }; | 123 }; |
130 _file.closeHandler = () { | |
131 if (_closeHandler != null) _closeHandler(); | |
132 }; | |
133 } | 124 } |
134 | 125 |
135 bool write(List<int> buffer, [bool copyBuffer = false]) { | 126 bool write(List<int> buffer, [bool copyBuffer = false]) { |
136 var data = buffer; | 127 var data = buffer; |
137 if (copyBuffer) { | 128 if (copyBuffer) { |
138 var length = buffer.length; | 129 var length = buffer.length; |
139 data = new ByteArray(length); | 130 data = new ByteArray(length); |
140 data.setRange(0, length, buffer, 0); | 131 data.setRange(0, length, buffer, 0); |
141 } | 132 } |
142 if (_file == null) { | 133 if (_file == null) { |
(...skipping 13 matching lines...) Expand all Loading... |
156 } | 147 } |
157 var copy = new ByteArray(length); | 148 var copy = new ByteArray(length); |
158 copy.setRange(0, length, buffer, offset); | 149 copy.setRange(0, length, buffer, offset); |
159 return write(copy); | 150 return write(copy); |
160 } | 151 } |
161 | 152 |
162 void close() { | 153 void close() { |
163 if (_file == null) { | 154 if (_file == null) { |
164 _pendingOperations.add(null); | 155 _pendingOperations.add(null); |
165 } else if (!_streamMarkedClosed) { | 156 } else if (!_streamMarkedClosed) { |
166 _file.close(); | 157 _file.close(() { |
| 158 if (_onClosed != null) _onClosed(); |
| 159 }); |
167 _streamMarkedClosed = true; | 160 _streamMarkedClosed = true; |
168 } | 161 } |
169 } | 162 } |
170 | 163 |
171 void set noPendingWriteHandler(void callback()) { | 164 void set onNoPendingWrites(void callback()) { |
172 _noPendingWriteHandler = callback; | 165 _onNoPendingWrites = callback; |
173 } | 166 } |
174 | 167 |
175 void set closeHandler(void callback()) { | 168 void set onClosed(void callback()) { |
176 _closeHandler = callback; | 169 _onClosed = callback; |
177 } | 170 } |
178 | 171 |
179 void set errorHandler(void callback()) { | 172 void set onError(void callback()) { |
180 _errorHandler = callback; | 173 _onError = callback; |
181 } | 174 } |
182 | 175 |
183 void _processPendingOperations() { | 176 void _processPendingOperations() { |
184 _pendingOperations.forEach((buffer) { | 177 _pendingOperations.forEach((buffer) { |
185 (buffer != null) ? write(buffer) : close(); | 178 (buffer != null) ? write(buffer) : close(); |
186 }); | 179 }); |
187 _pendingOperations = null; | 180 _pendingOperations = null; |
188 } | 181 } |
189 | 182 |
190 void _write(List<int> buffer, int offset, int len) { | 183 void _write(List<int> buffer, int offset, int len) { |
191 _file.writeList(buffer, offset, len); | 184 _file.writeList(buffer, offset, len); |
192 } | 185 } |
193 | 186 |
194 RandomAccessFile _file; | 187 RandomAccessFile _file; |
195 | 188 |
196 // When this is set to true the stream is marked closed. When a | 189 // When this is set to true the stream is marked closed. When a |
197 // stream is marked closed no more data can be written. | 190 // stream is marked closed no more data can be written. |
198 bool _streamMarkedClosed = false; | 191 bool _streamMarkedClosed = false; |
199 | 192 |
200 // When this is set to true the close callback has been called and | 193 // When this is set to true the close callback has been called and |
201 // the stream is fully closed. | 194 // the stream is fully closed. |
202 bool _closeCallbackCalled = false; | 195 bool _closeCallbackCalled = false; |
203 | 196 |
204 // List of pending writes that were issued before the underlying | 197 // List of pending writes that were issued before the underlying |
205 // file was successfully opened. | 198 // file was successfully opened. |
206 List<List<int>> _pendingOperations; | 199 List<List<int>> _pendingOperations; |
207 | 200 |
208 Function _noPendingWriteHandler; | 201 Function _onNoPendingWrites; |
209 Function _closeHandler; | 202 Function _onClosed; |
210 Function _errorHandler; | 203 Function _onError; |
211 } | 204 } |
212 | 205 |
213 | 206 |
214 // Helper class containing static file helper methods. | 207 // Helper class containing static file helper methods. |
215 class _FileUtils { | 208 class _FileUtils { |
216 static final kExistsRequest = 0; | 209 static final kExistsRequest = 0; |
217 static final kCreateRequest = 1; | 210 static final kCreateRequest = 1; |
218 static final kDeleteRequest = 2; | 211 static final kDeleteRequest = 2; |
219 static final kOpenRequest = 3; | 212 static final kOpenRequest = 3; |
220 static final kFullPathRequest = 4; | 213 static final kFullPathRequest = 4; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 return writeString(id, string); | 311 return writeString(id, string); |
319 } | 312 } |
320 } | 313 } |
321 | 314 |
322 | 315 |
323 // Class for encapsulating the native implementation of files. | 316 // Class for encapsulating the native implementation of files. |
324 class _File implements File { | 317 class _File implements File { |
325 // Constructor for file. | 318 // Constructor for file. |
326 _File(String this._name) : _asyncUsed = false; | 319 _File(String this._name) : _asyncUsed = false; |
327 | 320 |
328 void exists() { | 321 void exists(void callback(bool exists)) { |
329 _ensureFileService(); | 322 _ensureFileService(); |
330 _asyncUsed = true; | 323 _asyncUsed = true; |
331 if (_name is !String) { | 324 if (_name is !String) { |
332 if (_errorHandler != null) { | 325 if (_onError != null) { |
333 _errorHandler('File name is not a string: $_name'); | 326 _onError('File name is not a string: $_name'); |
334 } | 327 } |
335 return; | 328 return; |
336 } | 329 } |
337 List request = new List(2); | 330 List request = new List(2); |
338 request[0] = _FileUtils.kExistsRequest; | 331 request[0] = _FileUtils.kExistsRequest; |
339 request[1] = _name; | 332 request[1] = _name; |
340 _fileService.call(request).receive((exists, replyTo) { | 333 _fileService.call(request).receive((exists, replyTo) { |
341 if (_existsHandler != null) _existsHandler(exists); | 334 callback(exists); |
342 }); | 335 }); |
343 } | 336 } |
344 | 337 |
345 bool existsSync() { | 338 bool existsSync() { |
346 if (_asyncUsed) { | 339 if (_asyncUsed) { |
347 throw new FileIOException( | 340 throw new FileIOException( |
348 "Mixed use of synchronous and asynchronous API"); | 341 "Mixed use of synchronous and asynchronous API"); |
349 } | 342 } |
350 if (_name is !String) { | 343 if (_name is !String) { |
351 throw new FileIOException('File name is not a string: $_name'); | 344 throw new FileIOException('File name is not a string: $_name'); |
352 } | 345 } |
353 return _FileUtils.exists(_name); | 346 return _FileUtils.exists(_name); |
354 } | 347 } |
355 | 348 |
356 void create() { | 349 void create(void callback()) { |
357 _ensureFileService(); | 350 _ensureFileService(); |
358 _asyncUsed = true; | 351 _asyncUsed = true; |
359 List request = new List(2); | 352 List request = new List(2); |
360 request[0] = _FileUtils.kCreateRequest; | 353 request[0] = _FileUtils.kCreateRequest; |
361 request[1] = _name; | 354 request[1] = _name; |
362 _fileService.call(request).receive((created, replyTo) { | 355 _fileService.call(request).receive((created, replyTo) { |
363 if (created) { | 356 if (created) { |
364 if (_createHandler != null) _createHandler(); | 357 callback(); |
365 } else if (_errorHandler != null) { | 358 } else if (_onError != null) { |
366 _errorHandler("Cannot create file: $_name"); | 359 _onError("Cannot create file: $_name"); |
367 } | 360 } |
368 }); | 361 }); |
369 } | 362 } |
370 | 363 |
371 void createSync() { | 364 void createSync() { |
372 if (_asyncUsed) { | 365 if (_asyncUsed) { |
373 throw new FileIOException( | 366 throw new FileIOException( |
374 "Mixed use of synchronous and asynchronous API"); | 367 "Mixed use of synchronous and asynchronous API"); |
375 } | 368 } |
376 bool created = _FileUtils.checkedCreate(_name); | 369 bool created = _FileUtils.checkedCreate(_name); |
377 if (!created) { | 370 if (!created) { |
378 throw new FileIOException("Cannot create file: $_name"); | 371 throw new FileIOException("Cannot create file: $_name"); |
379 } | 372 } |
380 } | 373 } |
381 | 374 |
382 void delete() { | 375 void delete(void callback()) { |
383 _ensureFileService(); | 376 _ensureFileService(); |
384 _asyncUsed = true; | 377 _asyncUsed = true; |
385 List request = new List(2); | 378 List request = new List(2); |
386 request[0] = _FileUtils.kDeleteRequest; | 379 request[0] = _FileUtils.kDeleteRequest; |
387 request[1] = _name; | 380 request[1] = _name; |
388 _fileService.call(request).receive((deleted, replyTo) { | 381 _fileService.call(request).receive((deleted, replyTo) { |
389 if (deleted) { | 382 if (deleted) { |
390 if (_deleteHandler != null) _deleteHandler(); | 383 callback(); |
391 } else if (_errorHandler != null) { | 384 } else if (_onError != null) { |
392 _errorHandler("Cannot delete file: $_name"); | 385 _onError("Cannot delete file: $_name"); |
393 } | 386 } |
394 }); | 387 }); |
395 } | 388 } |
396 | 389 |
397 void deleteSync() { | 390 void deleteSync() { |
398 if (_asyncUsed) { | 391 if (_asyncUsed) { |
399 throw new FileIOException( | 392 throw new FileIOException( |
400 "Mixed use of synchronous and asynchronous API"); | 393 "Mixed use of synchronous and asynchronous API"); |
401 } | 394 } |
402 bool deleted = _FileUtils.checkedDelete(_name); | 395 bool deleted = _FileUtils.checkedDelete(_name); |
403 if (!deleted) { | 396 if (!deleted) { |
404 throw new FileIOException("Cannot delete file: $_name"); | 397 throw new FileIOException("Cannot delete file: $_name"); |
405 } | 398 } |
406 } | 399 } |
407 | 400 |
408 void directory() { | 401 void directory(void callback(Directory dir)) { |
409 _ensureFileService(); | 402 _ensureFileService(); |
410 _asyncUsed = true; | 403 _asyncUsed = true; |
411 List request = new List(2); | 404 List request = new List(2); |
412 request[0] = _FileUtils.kDirectoryRequest; | 405 request[0] = _FileUtils.kDirectoryRequest; |
413 request[1] = _name; | 406 request[1] = _name; |
414 _fileService.call(request).receive((path, replyTo) { | 407 _fileService.call(request).receive((path, replyTo) { |
415 if (path != null) { | 408 if (path != null) { |
416 if (_directoryHandler != null) _directoryHandler(new Directory(path)); | 409 callback(new Directory(path)); |
417 } else if (_errorHandler != null) { | 410 } else if (_onError != null) { |
418 _errorHandler("Cannot get directory for: ${_name}"); | 411 _onError("Cannot get directory for: ${_name}"); |
419 } | 412 } |
420 }); | 413 }); |
421 } | 414 } |
422 | 415 |
423 Directory directorySync() { | 416 Directory directorySync() { |
424 if (_asyncUsed) { | 417 if (_asyncUsed) { |
425 throw new FileIOException( | 418 throw new FileIOException( |
426 "Mixed use of synchronous and asynchronous API"); | 419 "Mixed use of synchronous and asynchronous API"); |
427 } | 420 } |
428 if (!existsSync()) { | 421 if (!existsSync()) { |
429 throw new FileIOException("Cannot get directory for: $_name"); | 422 throw new FileIOException("Cannot get directory for: $_name"); |
430 } | 423 } |
431 return new Directory(_FileUtils.directory(_name)); | 424 return new Directory(_FileUtils.directory(_name)); |
432 } | 425 } |
433 | 426 |
434 void open([FileMode mode = FileMode.READ]) { | 427 void open(FileMode mode, void callback(RandomAccessFile file)) { |
435 _ensureFileService(); | 428 _ensureFileService(); |
436 _asyncUsed = true; | 429 _asyncUsed = true; |
437 if (mode != FileMode.READ && | 430 if (mode != FileMode.READ && |
438 mode != FileMode.WRITE && | 431 mode != FileMode.WRITE && |
439 mode != FileMode.APPEND) { | 432 mode != FileMode.APPEND) { |
440 if (_errorHandler != null) { | 433 if (_onError != null) { |
441 _errorHandler("Unknown file mode. Use FileMode.READ, FileMode.WRITE " + | 434 _onError("Unknown file mode. Use FileMode.READ, FileMode.WRITE " + |
442 "or FileMode.APPEND."); | 435 "or FileMode.APPEND."); |
443 return; | 436 return; |
444 } | 437 } |
445 } | 438 } |
446 List request = new List(3); | 439 List request = new List(3); |
447 request[0] = _FileUtils.kOpenRequest; | 440 request[0] = _FileUtils.kOpenRequest; |
448 request[1] = _name; | 441 request[1] = _name; |
449 request[2] = mode._mode; // Direct int value for serialization. | 442 request[2] = mode._mode; // Direct int value for serialization. |
450 _fileService.call(request).receive((id, replyTo) { | 443 _fileService.call(request).receive((id, replyTo) { |
451 var handler = _openHandler; | |
452 if (handler === null) { | |
453 // If no open handler is present, close the file immediately to | |
454 // avoid leaking an open file descriptor. | |
455 handler = (file) => file.close(); | |
456 } | |
457 if (id != 0) { | 444 if (id != 0) { |
458 var randomAccessFile = new _RandomAccessFile(id, _name); | 445 callback(new _RandomAccessFile(id, _name)); |
459 handler(randomAccessFile); | 446 } else if (_onError != null) { |
460 } else if (_errorHandler != null) { | 447 _onError("Cannot open file: $_name"); |
461 _errorHandler("Cannot open file: $_name"); | |
462 } | 448 } |
463 }); | 449 }); |
464 } | 450 } |
465 | 451 |
466 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { | 452 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { |
467 if (_asyncUsed) { | 453 if (_asyncUsed) { |
468 throw new FileIOException( | 454 throw new FileIOException( |
469 "Mixed use of synchronous and asynchronous API"); | 455 "Mixed use of synchronous and asynchronous API"); |
470 } | 456 } |
471 if (mode != FileMode.READ && | 457 if (mode != FileMode.READ && |
(...skipping 10 matching lines...) Expand all Loading... |
482 } | 468 } |
483 | 469 |
484 static RandomAccessFile _openStdioSync(int fd) { | 470 static RandomAccessFile _openStdioSync(int fd) { |
485 var id = _FileUtils.openStdio(fd); | 471 var id = _FileUtils.openStdio(fd); |
486 if (id == 0) { | 472 if (id == 0) { |
487 throw new FileIOException("Cannot open stdio file for: $fd"); | 473 throw new FileIOException("Cannot open stdio file for: $fd"); |
488 } | 474 } |
489 return new _RandomAccessFile(id, ""); | 475 return new _RandomAccessFile(id, ""); |
490 } | 476 } |
491 | 477 |
492 void fullPath() { | 478 void fullPath(void callback(String result)) { |
493 _ensureFileService(); | 479 _ensureFileService(); |
494 _asyncUsed = true; | 480 _asyncUsed = true; |
495 List request = new List(2); | 481 List request = new List(2); |
496 request[0] = _FileUtils.kFullPathRequest; | 482 request[0] = _FileUtils.kFullPathRequest; |
497 request[1] = _name; | 483 request[1] = _name; |
498 _fileService.call(request).receive((result, replyTo) { | 484 _fileService.call(request).receive((result, replyTo) { |
499 if (result != null) { | 485 if (result != null) { |
500 if (_fullPathHandler != null) _fullPathHandler(result); | 486 callback(result); |
501 } else if (_errorHandler != null) { | 487 } else if (_onError != null) { |
502 _errorHandler("fullPath failed"); | 488 _onError("fullPath failed"); |
503 } | 489 } |
504 }); | 490 }); |
505 } | 491 } |
506 | 492 |
507 String fullPathSync() { | 493 String fullPathSync() { |
508 if (_asyncUsed) { | 494 if (_asyncUsed) { |
509 throw new FileIOException( | 495 throw new FileIOException( |
510 "Mixed use of synchronous and asynchronous API"); | 496 "Mixed use of synchronous and asynchronous API"); |
511 } | 497 } |
512 String result = _FileUtils.checkedFullPath(_name); | 498 String result = _FileUtils.checkedFullPath(_name); |
513 if (result == null) { | 499 if (result == null) { |
514 throw new FileIOException("fullPath failed"); | 500 throw new FileIOException("fullPath failed"); |
515 } | 501 } |
516 return result; | 502 return result; |
517 } | 503 } |
518 | 504 |
519 InputStream openInputStream() { | 505 InputStream openInputStream() { |
520 return new _FileInputStream(_name); | 506 return new _FileInputStream(_name); |
521 } | 507 } |
522 | 508 |
523 OutputStream openOutputStream([FileMode mode = FileMode.WRITE]) { | 509 OutputStream openOutputStream([FileMode mode = FileMode.WRITE]) { |
524 if (mode != FileMode.WRITE && | 510 if (mode != FileMode.WRITE && |
525 mode != FileMode.APPEND) { | 511 mode != FileMode.APPEND) { |
526 throw new FileIOException( | 512 throw new FileIOException( |
527 "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); | 513 "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND"); |
528 } | 514 } |
529 return new _FileOutputStream(_name, mode); | 515 return new _FileOutputStream(_name, mode); |
530 } | 516 } |
531 | 517 |
532 void readAsBytes() { | 518 void readAsBytes(void callback(List<int> bytes)) { |
533 _asyncUsed = true; | 519 _asyncUsed = true; |
534 var chunks = new _BufferList(); | 520 var chunks = new _BufferList(); |
535 var stream = openInputStream(); | 521 var stream = openInputStream(); |
536 stream.closeHandler = () { | 522 stream.onClosed = () { |
537 if (_readAsBytesHandler != null) { | 523 callback(chunks.readBytes(chunks.length)); |
538 _readAsBytesHandler(chunks.readBytes(chunks.length)); | |
539 } | |
540 }; | 524 }; |
541 stream.dataHandler = () { | 525 stream.onData = () { |
542 var chunk = stream.read(); | 526 var chunk = stream.read(); |
543 chunks.add(chunk); | 527 chunks.add(chunk); |
544 }; | 528 }; |
545 stream.errorHandler = () { | 529 stream.onError = () { |
546 if (_errorHandler != null) { | 530 if (_onError != null) { |
547 _errorHandler("Failed to read file as bytes: $_name"); | 531 _onError("Failed to read file as bytes: $_name"); |
548 } | 532 } |
549 }; | 533 }; |
550 } | 534 } |
551 | 535 |
552 List<int> readAsBytesSync() { | 536 List<int> readAsBytesSync() { |
553 if (_asyncUsed) { | 537 if (_asyncUsed) { |
554 throw new FileIOException( | 538 throw new FileIOException( |
555 "Mixed use of synchronous and asynchronous API"); | 539 "Mixed use of synchronous and asynchronous API"); |
556 } | 540 } |
557 var opened = openSync(); | 541 var opened = openSync(); |
558 var length = opened.lengthSync(); | 542 var length = opened.lengthSync(); |
559 var result = new ByteArray(length); | 543 var result = new ByteArray(length); |
560 var read = opened.readListSync(result, 0, length); | 544 var read = opened.readListSync(result, 0, length); |
561 if (read != length) { | 545 if (read != length) { |
562 throw new FileIOException("Failed reading file as bytes: $_name"); | 546 throw new FileIOException("Failed reading file as bytes: $_name"); |
563 } | 547 } |
564 opened.close(); | 548 opened.closeSync(); |
565 return result; | 549 return result; |
566 } | 550 } |
567 | 551 |
568 _StringDecoder _getDecoder(encoding) { | 552 _StringDecoder _getDecoder(encoding) { |
569 if (encoding == "UTF-8") { | 553 if (encoding == "UTF-8") { |
570 return new _UTF8Decoder(); | 554 return new _UTF8Decoder(); |
571 } else if (encoding == "ISO-8859-1") { | 555 } else if (encoding == "ISO-8859-1") { |
572 return new _Latin1Decoder(); | 556 return new _Latin1Decoder(); |
573 } else if (encoding == "ASCII") { | 557 } else if (encoding == "ASCII") { |
574 return new _AsciiDecoder(); | 558 return new _AsciiDecoder(); |
575 } | 559 } |
576 throw new FileIOException("Unsupported encoding $_encoding"); | 560 throw new FileIOException("Unsupported encoding $_encoding"); |
577 } | 561 } |
578 | 562 |
579 void readAsText([String encoding = "UTF-8"]) { | 563 void readAsText(String encoding, void callback(String text)) { |
580 _asyncUsed = true; | 564 _asyncUsed = true; |
581 var decoder = _getDecoder(encoding); | 565 var decoder = _getDecoder(encoding); |
582 readAsBytes(); | 566 readAsBytes((bytes) { |
583 readAsBytesHandler = (bytes) { | 567 try { |
584 if (_readAsTextHandler != null) { | 568 decoder.write(bytes); |
585 try { | 569 } catch (var e) { |
586 decoder.write(bytes); | 570 if (_onError != null) { |
587 } catch (var e) { | 571 _onError(e.toString()); |
588 if (_errorHandler != null) { | 572 return; |
589 _errorHandler(e.toString()); | |
590 return; | |
591 } | |
592 } | 573 } |
593 _readAsTextHandler(decoder.decoded); | |
594 } | 574 } |
595 }; | 575 callback(decoder.decoded); |
| 576 }); |
596 } | 577 } |
597 | 578 |
598 String readAsTextSync([String encoding = "UTF-8"]) { | 579 String readAsTextSync([String encoding = 'UTF-8']) { |
599 if (_asyncUsed) { | 580 if (_asyncUsed) { |
600 throw new FileIOException( | 581 throw new FileIOException( |
601 "Mixed use of synchronous and asynchronous API"); | 582 "Mixed use of synchronous and asynchronous API"); |
602 } | 583 } |
603 var decoder = _getDecoder(encoding); | 584 var decoder = _getDecoder(encoding); |
604 List<int> bytes = readAsBytesSync(); | 585 List<int> bytes = readAsBytesSync(); |
605 decoder.write(bytes); | 586 decoder.write(bytes); |
606 return decoder.decoded; | 587 return decoder.decoded; |
607 } | 588 } |
608 | 589 |
609 List<String> _getDecodedLines(_StringDecoder decoder) { | 590 List<String> _getDecodedLines(_StringDecoder decoder) { |
610 List<String> result = []; | 591 List<String> result = []; |
611 var line = decoder.decodedLine; | 592 var line = decoder.decodedLine; |
612 while (line != null) { | 593 while (line != null) { |
613 result.add(line); | 594 result.add(line); |
614 line = decoder.decodedLine; | 595 line = decoder.decodedLine; |
615 } | 596 } |
616 // If there is more data with no terminating line break we treat | 597 // If there is more data with no terminating line break we treat |
617 // it as the last line. | 598 // it as the last line. |
618 var data = decoder.decoded; | 599 var data = decoder.decoded; |
619 if (data != null) { | 600 if (data != null) { |
620 result.add(data); | 601 result.add(data); |
621 } | 602 } |
622 return result; | 603 return result; |
623 } | 604 } |
624 | 605 |
625 void readAsLines([String encoding = "UTF-8"]) { | 606 void readAsLines(String encoding, void callback(List<String> lines)) { |
626 _asyncUsed = true; | 607 _asyncUsed = true; |
627 var decoder = _getDecoder(encoding); | 608 var decoder = _getDecoder(encoding); |
628 readAsBytes(); | 609 readAsBytes((bytes) { |
629 readAsBytesHandler = (bytes) { | 610 try { |
630 if (_readAsLinesHandler != null) { | 611 decoder.write(bytes); |
631 try { | 612 } catch (var e) { |
632 decoder.write(bytes); | 613 if (_onError != null) { |
633 } catch (var e) { | 614 _onError(e.toString()); |
634 if (_errorHandler != null) { | 615 return; |
635 _errorHandler(e.toString()); | |
636 return; | |
637 } | |
638 } | 616 } |
639 _readAsLinesHandler(_getDecodedLines(decoder)); | |
640 } | 617 } |
641 }; | 618 callback(_getDecodedLines(decoder)); |
| 619 }); |
642 } | 620 } |
643 | 621 |
644 List<String> readAsLinesSync([String encoding = "UTF-8"]) { | 622 List<String> readAsLinesSync([String encoding = "UTF-8"]) { |
645 if (_asyncUsed) { | 623 if (_asyncUsed) { |
646 throw new FileIOException( | 624 throw new FileIOException( |
647 "Mixed use of synchronous and asynchronous API"); | 625 "Mixed use of synchronous and asynchronous API"); |
648 } | 626 } |
649 var decoder = _getDecoder(encoding); | 627 var decoder = _getDecoder(encoding); |
650 List<int> bytes = readAsBytesSync(); | 628 List<int> bytes = readAsBytesSync(); |
651 decoder.write(bytes); | 629 decoder.write(bytes); |
652 return _getDecodedLines(decoder); | 630 return _getDecodedLines(decoder); |
653 } | 631 } |
654 | 632 |
655 String get name() => _name; | 633 String get name() => _name; |
656 | 634 |
657 void set existsHandler(void handler(bool exists)) { | 635 void set onError(void handler(String error)) { |
658 _existsHandler = handler; | 636 _onError = handler; |
659 } | |
660 | |
661 void set createHandler(void handler()) { | |
662 _createHandler = handler; | |
663 } | |
664 | |
665 void set deleteHandler(void handler()) { | |
666 _deleteHandler = handler; | |
667 } | |
668 | |
669 void set directoryHandler(void handler(Directory directory)) { | |
670 _directoryHandler = handler; | |
671 } | |
672 | |
673 void set openHandler(void handler(RandomAccessFile file)) { | |
674 _openHandler = handler; | |
675 } | |
676 | |
677 void set readAsBytesHandler(void handler(List<int> bytes)) { | |
678 _readAsBytesHandler = handler; | |
679 } | |
680 | |
681 void set readAsTextHandler(void handler(String text)) { | |
682 _readAsTextHandler = handler; | |
683 } | |
684 | |
685 void set readAsLinesHandler(void handler(List<String> lines)) { | |
686 _readAsLinesHandler = handler; | |
687 } | |
688 | |
689 void set fullPathHandler(void handler(String)) { | |
690 _fullPathHandler = handler; | |
691 } | |
692 | |
693 void set errorHandler(void handler(String error)) { | |
694 _errorHandler = handler; | |
695 } | 637 } |
696 | 638 |
697 void _ensureFileService() { | 639 void _ensureFileService() { |
698 if (_fileService == null) { | 640 if (_fileService == null) { |
699 _fileService = _FileUtils.newServicePort(); | 641 _fileService = _FileUtils.newServicePort(); |
700 } | 642 } |
701 } | 643 } |
702 | 644 |
703 String _name; | 645 String _name; |
704 bool _asyncUsed; | 646 bool _asyncUsed; |
705 | 647 |
706 SendPort _fileService; | 648 SendPort _fileService; |
707 | 649 |
708 Function _existsHandler; | 650 Function _onError; |
709 Function _createHandler; | |
710 Function _deleteHandler; | |
711 Function _directoryHandler; | |
712 Function _openHandler; | |
713 Function _readAsBytesHandler; | |
714 Function _readAsTextHandler; | |
715 Function _readAsLinesHandler; | |
716 Function _fullPathHandler; | |
717 Function _errorHandler; | |
718 } | 651 } |
719 | 652 |
720 | 653 |
721 class _RandomAccessFile implements RandomAccessFile { | 654 class _RandomAccessFile implements RandomAccessFile { |
722 _RandomAccessFile(int this._id, String this._name) : _asyncUsed = false; | 655 _RandomAccessFile(int this._id, String this._name) : _asyncUsed = false; |
723 | 656 |
724 void close() { | 657 void close(void callback()) { |
725 if (_id == 0) return; | 658 if (_id == 0) return; |
726 _ensureFileService(); | 659 _ensureFileService(); |
727 _asyncUsed = true; | 660 _asyncUsed = true; |
728 List request = new List(2); | 661 List request = new List(2); |
729 request[0] = _FileUtils.kCloseRequest; | 662 request[0] = _FileUtils.kCloseRequest; |
730 request[1] = _id; | 663 request[1] = _id; |
731 // Set the id_ to 0 (NULL) to ensure the no more async requests | 664 // Set the id_ to 0 (NULL) to ensure the no more async requests |
732 // can be issues for this file. | 665 // can be issues for this file. |
733 _id = 0; | 666 _id = 0; |
734 _fileService.call(request).receive((result, replyTo) { | 667 _fileService.call(request).receive((result, replyTo) { |
735 if (result != -1) { | 668 if (result != -1) { |
736 _id = result; | 669 _id = result; |
737 if (_closeHandler != null) _closeHandler(); | 670 callback(); |
738 } else if (_errorHandler != null) { | 671 } else if (_onError != null) { |
739 _errorHandler("Cannot close file: $_name"); | 672 _onError("Cannot close file: $_name"); |
740 } | 673 } |
741 }); | 674 }); |
742 } | 675 } |
743 | 676 |
744 void closeSync() { | 677 void closeSync() { |
745 if (_asyncUsed) { | 678 if (_asyncUsed) { |
746 throw new FileIOException( | 679 throw new FileIOException( |
747 "Mixed use of synchronous and asynchronous API"); | 680 "Mixed use of synchronous and asynchronous API"); |
748 } | 681 } |
749 var id = _FileUtils.close(_id); | 682 var id = _FileUtils.close(_id); |
750 if (id == -1) { | 683 if (id == -1) { |
751 throw new FileIOException("Cannot close file: $_name"); | 684 throw new FileIOException("Cannot close file: $_name"); |
752 } | 685 } |
753 _id = id; | 686 _id = id; |
754 } | 687 } |
755 | 688 |
756 void readByte() { | 689 void readByte(void callback(int byte)) { |
757 _ensureFileService(); | 690 _ensureFileService(); |
758 _asyncUsed = true; | 691 _asyncUsed = true; |
759 List request = new List(2); | 692 List request = new List(2); |
760 request[0] = _FileUtils.kReadByteRequest; | 693 request[0] = _FileUtils.kReadByteRequest; |
761 request[1] = _id; | 694 request[1] = _id; |
762 _fileService.call(request).receive((result, replyTo) { | 695 _fileService.call(request).receive((result, replyTo) { |
763 if (result != -1) { | 696 if (result != -1) { |
764 if (_readByteHandler != null) _readByteHandler(result); | 697 callback(result); |
765 } else if (_errorHandler != null) { | 698 } else if (_onError != null) { |
766 _errorHandler("readByte failed"); | 699 _onError("readByte failed"); |
767 } | 700 } |
768 }); | 701 }); |
769 } | 702 } |
770 | 703 |
771 int readByteSync() { | 704 int readByteSync() { |
772 if (_asyncUsed) { | 705 if (_asyncUsed) { |
773 throw new FileIOException( | 706 throw new FileIOException( |
774 "Mixed use of synchronous and asynchronous API"); | 707 "Mixed use of synchronous and asynchronous API"); |
775 } | 708 } |
776 int result = _FileUtils.readByte(_id); | 709 int result = _FileUtils.readByte(_id); |
777 if (result == -1) { | 710 if (result == -1) { |
778 throw new FileIOException("readByte failed"); | 711 throw new FileIOException("readByte failed"); |
779 } | 712 } |
780 return result; | 713 return result; |
781 } | 714 } |
782 | 715 |
783 void readList(List<int> buffer, int offset, int bytes) { | 716 void readList(List<int> buffer, int offset, int bytes, |
| 717 void callback(int read)) { |
784 _ensureFileService(); | 718 _ensureFileService(); |
785 _asyncUsed = true; | 719 _asyncUsed = true; |
786 if (buffer is !List || offset is !int || bytes is !int) { | 720 if (buffer is !List || offset is !int || bytes is !int) { |
787 if (_errorHandler != null) { | 721 if (_onError != null) { |
788 _errorHandler("Invalid arguments to readList"); | 722 _onError("Invalid arguments to readList"); |
789 } | 723 } |
790 return; | 724 return; |
791 }; | 725 }; |
792 List request = new List(3); | 726 List request = new List(3); |
793 request[0] = _FileUtils.kReadListRequest; | 727 request[0] = _FileUtils.kReadListRequest; |
794 request[1] = _id; | 728 request[1] = _id; |
795 request[2] = bytes; | 729 request[2] = bytes; |
796 _fileService.call(request).receive((result, replyTo) { | 730 _fileService.call(request).receive((result, replyTo) { |
797 if (result is List && result.length == 2 && result[0] != -1) { | 731 if (result is List && result.length == 2 && result[0] != -1) { |
798 var read = result[0]; | 732 var read = result[0]; |
799 var data = result[1]; | 733 var data = result[1]; |
800 buffer.setRange(offset, read, data); | 734 buffer.setRange(offset, read, data); |
801 if (_readListHandler != null) _readListHandler(read); | 735 callback(read); |
802 return; | 736 return; |
803 } else if (_errorHandler != null) { | 737 } else if (_onError != null) { |
804 _errorHandler(result is String ? result : "readList failed"); | 738 _onError(result is String ? result : "readList failed"); |
805 } | 739 } |
806 }); | 740 }); |
807 } | 741 } |
808 | 742 |
809 int readListSync(List<int> buffer, int offset, int bytes) { | 743 int readListSync(List<int> buffer, int offset, int bytes) { |
810 if (_asyncUsed) { | 744 if (_asyncUsed) { |
811 throw new FileIOException( | 745 throw new FileIOException( |
812 "Mixed use of synchronous and asynchronous API"); | 746 "Mixed use of synchronous and asynchronous API"); |
813 } | 747 } |
814 if (buffer is !List || offset is !int || bytes is !int) { | 748 if (buffer is !List || offset is !int || bytes is !int) { |
815 throw new FileIOException("Invalid arguments to readList"); | 749 throw new FileIOException("Invalid arguments to readList"); |
816 } | 750 } |
817 if (bytes == 0) return 0; | 751 if (bytes == 0) return 0; |
818 int index = | 752 int index = |
819 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); | 753 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); |
820 if (index != 0) { | 754 if (index != 0) { |
821 throw new IndexOutOfRangeException(index); | 755 throw new IndexOutOfRangeException(index); |
822 } | 756 } |
823 int result = _FileUtils.readList(_id, buffer, offset, bytes); | 757 int result = _FileUtils.readList(_id, buffer, offset, bytes); |
824 if (result == -1) { | 758 if (result == -1) { |
825 throw new FileIOException("readList failed"); | 759 throw new FileIOException("readList failed"); |
826 } | 760 } |
827 return result; | 761 return result; |
828 } | 762 } |
829 | 763 |
830 void writeByte(int value) { | 764 void writeByte(int value) { |
831 _ensureFileService(); | 765 _ensureFileService(); |
832 _asyncUsed = true; | 766 _asyncUsed = true; |
833 if (value is !int) { | 767 if (value is !int) { |
834 if (_errorHandler != null) { | 768 if (_onError != null) { |
835 _errorHandler("Invalid argument to writeByte"); | 769 _onError("Invalid argument to writeByte"); |
836 } | 770 } |
837 return; | 771 return; |
838 } | 772 } |
839 List request = new List(3); | 773 List request = new List(3); |
840 request[0] = _FileUtils.kWriteByteRequest; | 774 request[0] = _FileUtils.kWriteByteRequest; |
841 request[1] = _id; | 775 request[1] = _id; |
842 request[2] = value; | 776 request[2] = value; |
843 _writeEnqueued(); | 777 _writeEnqueued(); |
844 _fileService.call(request).receive((result, replyTo) { | 778 _fileService.call(request).receive((result, replyTo) { |
845 _writeCompleted(); | 779 _writeCompleted(); |
846 if (result == -1 && _errorHandler !== null) { | 780 if (result == -1 && _onError !== null) { |
847 _errorHandler("writeByte failed"); | 781 _onError("writeByte failed"); |
848 } | 782 } |
849 }); | 783 }); |
850 } | 784 } |
851 | 785 |
852 int writeByteSync(int value) { | 786 int writeByteSync(int value) { |
853 if (_asyncUsed) { | 787 if (_asyncUsed) { |
854 throw new FileIOException( | 788 throw new FileIOException( |
855 "Mixed use of synchronous and asynchronous API"); | 789 "Mixed use of synchronous and asynchronous API"); |
856 } | 790 } |
857 if (value is !int) { | 791 if (value is !int) { |
858 throw new FileIOException("Invalid argument to writeByte"); | 792 throw new FileIOException("Invalid argument to writeByte"); |
859 } | 793 } |
860 int result = _FileUtils.writeByte(_id, value); | 794 int result = _FileUtils.writeByte(_id, value); |
861 if (result == -1) { | 795 if (result == -1) { |
862 throw new FileIOException("writeByte failed"); | 796 throw new FileIOException("writeByte failed"); |
863 } | 797 } |
864 return result; | 798 return result; |
865 } | 799 } |
866 | 800 |
867 void writeList(List<int> buffer, int offset, int bytes) { | 801 void writeList(List<int> buffer, int offset, int bytes) { |
868 _ensureFileService(); | 802 _ensureFileService(); |
869 _asyncUsed = true; | 803 _asyncUsed = true; |
870 if (buffer is !List || offset is !int || bytes is !int) { | 804 if (buffer is !List || offset is !int || bytes is !int) { |
871 if (_errorHandler != null) { | 805 if (_onError != null) { |
872 _errorHandler("Invalid arguments to writeList"); | 806 _onError("Invalid arguments to writeList"); |
873 } | 807 } |
874 return; | 808 return; |
875 } | 809 } |
876 | 810 |
877 List result = | 811 List result = |
878 _FileUtils.ensureFastAndSerializableBuffer(buffer, offset, bytes); | 812 _FileUtils.ensureFastAndSerializableBuffer(buffer, offset, bytes); |
879 List outBuffer = result[0]; | 813 List outBuffer = result[0]; |
880 int outOffset = result[1]; | 814 int outOffset = result[1]; |
881 | 815 |
882 List request = new List(5); | 816 List request = new List(5); |
883 request[0] = _FileUtils.kWriteListRequest; | 817 request[0] = _FileUtils.kWriteListRequest; |
884 request[1] = _id; | 818 request[1] = _id; |
885 request[2] = outBuffer; | 819 request[2] = outBuffer; |
886 request[3] = outOffset; | 820 request[3] = outOffset; |
887 request[4] = bytes; | 821 request[4] = bytes; |
888 _writeEnqueued(); | 822 _writeEnqueued(); |
889 _fileService.call(request).receive((result, replyTo) { | 823 _fileService.call(request).receive((result, replyTo) { |
890 _writeCompleted(); | 824 _writeCompleted(); |
891 if (result == -1 && _errorHandler !== null) { | 825 if (result == -1 && _onError !== null) { |
892 _errorHandler("writeList failed"); | 826 _onError("writeList failed"); |
893 } | 827 } |
894 }); | 828 }); |
895 } | 829 } |
896 | 830 |
897 int writeListSync(List<int> buffer, int offset, int bytes) { | 831 int writeListSync(List<int> buffer, int offset, int bytes) { |
898 if (_asyncUsed) { | 832 if (_asyncUsed) { |
899 throw new FileIOException( | 833 throw new FileIOException( |
900 "Mixed use of synchronous and asynchronous API"); | 834 "Mixed use of synchronous and asynchronous API"); |
901 } | 835 } |
902 if (buffer is !List || offset is !int || bytes is !int) { | 836 if (buffer is !List || offset is !int || bytes is !int) { |
(...skipping 15 matching lines...) Expand all Loading... |
918 void writeString(String string) { | 852 void writeString(String string) { |
919 _ensureFileService(); | 853 _ensureFileService(); |
920 _asyncUsed = true; | 854 _asyncUsed = true; |
921 List request = new List(3); | 855 List request = new List(3); |
922 request[0] = _FileUtils.kWriteStringRequest; | 856 request[0] = _FileUtils.kWriteStringRequest; |
923 request[1] = _id; | 857 request[1] = _id; |
924 request[2] = string; | 858 request[2] = string; |
925 _writeEnqueued(); | 859 _writeEnqueued(); |
926 _fileService.call(request).receive((result, replyTo) { | 860 _fileService.call(request).receive((result, replyTo) { |
927 _writeCompleted(); | 861 _writeCompleted(); |
928 if (result == -1 && _errorHandler !== null) { | 862 if (result == -1 && _onError !== null) { |
929 _errorHandler("writeString failed"); | 863 _onError("writeString failed"); |
930 } | 864 } |
931 }); | 865 }); |
932 } | 866 } |
933 | 867 |
934 int writeStringSync(String string) { | 868 int writeStringSync(String string) { |
935 if (_asyncUsed) { | 869 if (_asyncUsed) { |
936 throw new FileIOException( | 870 throw new FileIOException( |
937 "Mixed use of synchronous and asynchronous API"); | 871 "Mixed use of synchronous and asynchronous API"); |
938 } | 872 } |
939 int result = _FileUtils.checkedWriteString(_id, string); | 873 int result = _FileUtils.checkedWriteString(_id, string); |
940 if (result == -1) { | 874 if (result == -1) { |
941 throw new FileIOException("writeString failed"); | 875 throw new FileIOException("writeString failed"); |
942 } | 876 } |
943 return result; | 877 return result; |
944 } | 878 } |
945 | 879 |
946 void position() { | 880 void position(void callback(int position)) { |
947 _ensureFileService(); | 881 _ensureFileService(); |
948 _asyncUsed = true; | 882 _asyncUsed = true; |
949 List request = new List(2); | 883 List request = new List(2); |
950 request[0] = _FileUtils.kPositionRequest; | 884 request[0] = _FileUtils.kPositionRequest; |
951 request[1] = _id; | 885 request[1] = _id; |
952 _fileService.call(request).receive((result, replyTo) { | 886 _fileService.call(request).receive((result, replyTo) { |
953 if (result != -1) { | 887 if (result != -1) { |
954 if (_positionHandler != null) _positionHandler(result); | 888 callback(result); |
955 } else if (_errorHandler != null) { | 889 } else if (_onError != null) { |
956 _errorHandler("position failed"); | 890 _onError("position failed"); |
957 } | 891 } |
958 }); | 892 }); |
959 } | 893 } |
960 | 894 |
961 int positionSync() { | 895 int positionSync() { |
962 if (_asyncUsed) { | 896 if (_asyncUsed) { |
963 throw new FileIOException( | 897 throw new FileIOException( |
964 "Mixed use of synchronous and asynchronous API"); | 898 "Mixed use of synchronous and asynchronous API"); |
965 } | 899 } |
966 int result = _FileUtils.position(_id); | 900 int result = _FileUtils.position(_id); |
967 if (result == -1) { | 901 if (result == -1) { |
968 throw new FileIOException("position failed"); | 902 throw new FileIOException("position failed"); |
969 } | 903 } |
970 return result; | 904 return result; |
971 } | 905 } |
972 | 906 |
973 void setPosition(int position) { | 907 void setPosition(int position, void callback()) { |
974 _ensureFileService(); | 908 _ensureFileService(); |
975 _asyncUsed = true; | 909 _asyncUsed = true; |
976 List request = new List(3); | 910 List request = new List(3); |
977 request[0] = _FileUtils.kSetPositionRequest; | 911 request[0] = _FileUtils.kSetPositionRequest; |
978 request[1] = _id; | 912 request[1] = _id; |
979 request[2] = position; | 913 request[2] = position; |
980 _fileService.call(request).receive((result, replyTo) { | 914 _fileService.call(request).receive((result, replyTo) { |
981 if (result) { | 915 if (result) { |
982 if (_setPositionHandler != null) _setPositionHandler(); | 916 callback(); |
983 } else if (_errorHandler != null) { | 917 } else if (_onError != null) { |
984 _errorHandler("setPosition failed"); | 918 _onError("setPosition failed"); |
985 } | 919 } |
986 }); | 920 }); |
987 } | 921 } |
988 | 922 |
989 void setPositionSync(int position) { | 923 void setPositionSync(int position) { |
990 _ensureFileService(); | 924 _ensureFileService(); |
991 if (_asyncUsed) { | 925 if (_asyncUsed) { |
992 throw new FileIOException( | 926 throw new FileIOException( |
993 "Mixed use of synchronous and asynchronous API"); | 927 "Mixed use of synchronous and asynchronous API"); |
994 } | 928 } |
995 bool result = _FileUtils.setPosition(_id, position); | 929 bool result = _FileUtils.setPosition(_id, position); |
996 if (result == false) { | 930 if (result == false) { |
997 throw new FileIOException("setPosition failed"); | 931 throw new FileIOException("setPosition failed"); |
998 } | 932 } |
999 } | 933 } |
1000 | 934 |
1001 void truncate(int length) { | 935 void truncate(int length, void callback()) { |
1002 _ensureFileService(); | 936 _ensureFileService(); |
1003 _asyncUsed = true; | 937 _asyncUsed = true; |
1004 List request = new List(3); | 938 List request = new List(3); |
1005 request[0] = _FileUtils.kTruncateRequest; | 939 request[0] = _FileUtils.kTruncateRequest; |
1006 request[1] = _id; | 940 request[1] = _id; |
1007 request[2] = length; | 941 request[2] = length; |
1008 _fileService.call(request).receive((result, replyTo) { | 942 _fileService.call(request).receive((result, replyTo) { |
1009 if (result) { | 943 if (result) { |
1010 if (_truncateHandler != null) _truncateHandler(); | 944 callback(); |
1011 } else if (_errorHandler != null) { | 945 } else if (_onError != null) { |
1012 _errorHandler("truncate failed"); | 946 _onError("truncate failed"); |
1013 } | 947 } |
1014 }); | 948 }); |
1015 } | 949 } |
1016 | 950 |
1017 void truncateSync(int length) { | 951 void truncateSync(int length) { |
1018 if (_asyncUsed) { | 952 if (_asyncUsed) { |
1019 throw new FileIOException( | 953 throw new FileIOException( |
1020 "Mixed use of synchronous and asynchronous API"); | 954 "Mixed use of synchronous and asynchronous API"); |
1021 } | 955 } |
1022 bool result = _FileUtils.truncate(_id, length); | 956 bool result = _FileUtils.truncate(_id, length); |
1023 if (result == false) { | 957 if (result == false) { |
1024 throw new FileIOException("truncate failed"); | 958 throw new FileIOException("truncate failed"); |
1025 } | 959 } |
1026 } | 960 } |
1027 | 961 |
1028 void length() { | 962 void length(void callback(int length)) { |
1029 _ensureFileService(); | 963 _ensureFileService(); |
1030 _asyncUsed = true; | 964 _asyncUsed = true; |
1031 List request = new List(2); | 965 List request = new List(2); |
1032 request[0] = _FileUtils.kLengthRequest; | 966 request[0] = _FileUtils.kLengthRequest; |
1033 request[1] = _id; | 967 request[1] = _id; |
1034 _fileService.call(request).receive((result, replyTo) { | 968 _fileService.call(request).receive((result, replyTo) { |
1035 if (result != -1) { | 969 if (result != -1) { |
1036 if (_lengthHandler != null) _lengthHandler(result); | 970 callback(result); |
1037 } else if (_errorHandler != null) { | 971 } else if (_onError != null) { |
1038 _errorHandler("length failed"); | 972 _onError("length failed"); |
1039 } | 973 } |
1040 }); | 974 }); |
1041 } | 975 } |
1042 | 976 |
1043 int lengthSync() { | 977 int lengthSync() { |
1044 if (_asyncUsed) { | 978 if (_asyncUsed) { |
1045 throw new FileIOException( | 979 throw new FileIOException( |
1046 "Mixed use of synchronous and asynchronous API"); | 980 "Mixed use of synchronous and asynchronous API"); |
1047 } | 981 } |
1048 int result = _FileUtils.length(_id); | 982 int result = _FileUtils.length(_id); |
1049 if (result == -1) { | 983 if (result == -1) { |
1050 throw new FileIOException("length failed"); | 984 throw new FileIOException("length failed"); |
1051 } | 985 } |
1052 return result; | 986 return result; |
1053 } | 987 } |
1054 | 988 |
1055 void flush() { | 989 void flush(void callback()) { |
1056 _ensureFileService(); | 990 _ensureFileService(); |
1057 _asyncUsed = true; | 991 _asyncUsed = true; |
1058 List request = new List(2); | 992 List request = new List(2); |
1059 request[0] = _FileUtils.kFlushRequest; | 993 request[0] = _FileUtils.kFlushRequest; |
1060 request[1] = _id; | 994 request[1] = _id; |
1061 _fileService.call(request).receive((result, replyTo) { | 995 _fileService.call(request).receive((result, replyTo) { |
1062 if (result != -1) { | 996 if (result != -1) { |
1063 if (_flushHandler != null) _flushHandler(); | 997 callback(); |
1064 } else if (_errorHandler != null) { | 998 } else if (_onError != null) { |
1065 _errorHandler("flush failed"); | 999 _onError("flush failed"); |
1066 } | 1000 } |
1067 }); | 1001 }); |
1068 } | 1002 } |
1069 | 1003 |
1070 void flushSync() { | 1004 void flushSync() { |
1071 if (_asyncUsed) { | 1005 if (_asyncUsed) { |
1072 throw new FileIOException( | 1006 throw new FileIOException( |
1073 "Mixed use of synchronous and asynchronous API"); | 1007 "Mixed use of synchronous and asynchronous API"); |
1074 } | 1008 } |
1075 int result = _FileUtils.flush(_id); | 1009 int result = _FileUtils.flush(_id); |
1076 if (result == -1) { | 1010 if (result == -1) { |
1077 throw new FileIOException("flush failed"); | 1011 throw new FileIOException("flush failed"); |
1078 } | 1012 } |
1079 } | 1013 } |
1080 | 1014 |
1081 String get name() => _name; | 1015 String get name() => _name; |
1082 | 1016 |
1083 void set errorHandler(void handler(String error)) { | 1017 void set onError(void handler(String error)) { |
1084 _errorHandler = handler; | 1018 _onError = handler; |
1085 } | 1019 } |
1086 | 1020 |
1087 void set closeHandler(void handler()) { | 1021 void set onNoPendingWrites(void handler()) { |
1088 _closeHandler = handler; | 1022 _onNoPendingWrites = handler; |
1089 } | |
1090 | |
1091 void set readByteHandler(void handler(int byte)) { | |
1092 _readByteHandler = handler; | |
1093 } | |
1094 | |
1095 void set readListHandler(void handler(int read)) { | |
1096 _readListHandler = handler; | |
1097 } | |
1098 | |
1099 void set noPendingWriteHandler(void handler()) { | |
1100 _noPendingWriteHandler = handler; | |
1101 if (_pendingWrites == 0) { | 1023 if (_pendingWrites == 0) { |
1102 _noPendingWriteTimer = new Timer((t) { | 1024 _noPendingWriteTimer = new Timer((t) { |
1103 if (_noPendingWriteHandler != null) _noPendingWriteHandler(); | 1025 if (_onNoPendingWrites != null) _onNoPendingWrites(); |
1104 }, 0); | 1026 }, 0); |
1105 } | 1027 } |
1106 } | 1028 } |
1107 | 1029 |
1108 void set positionHandler(void handler(int pos)) { | |
1109 _positionHandler = handler; | |
1110 } | |
1111 | |
1112 void set setPositionHandler(void handler()) { | |
1113 _setPositionHandler = handler; | |
1114 } | |
1115 | |
1116 void set truncateHandler(void handler()) { | |
1117 _truncateHandler = handler; | |
1118 } | |
1119 | |
1120 void set lengthHandler(void handler(int length)) { | |
1121 _lengthHandler = handler; | |
1122 } | |
1123 | |
1124 void set flushHandler(void handler()) { | |
1125 _flushHandler = handler; | |
1126 } | |
1127 | |
1128 void _ensureFileService() { | 1030 void _ensureFileService() { |
1129 if (_fileService == null) { | 1031 if (_fileService == null) { |
1130 _fileService = _FileUtils.newServicePort(); | 1032 _fileService = _FileUtils.newServicePort(); |
1131 } | 1033 } |
1132 } | 1034 } |
1133 | 1035 |
1134 void _writeEnqueued() { | 1036 void _writeEnqueued() { |
1135 _pendingWrites++; | 1037 _pendingWrites++; |
1136 if (_noPendingWriteTimer != null) { | 1038 if (_noPendingWriteTimer != null) { |
1137 _noPendingWriteTimer.cancel(); | 1039 _noPendingWriteTimer.cancel(); |
1138 _noPendingWriteTimer = null; | 1040 _noPendingWriteTimer = null; |
1139 } | 1041 } |
1140 } | 1042 } |
1141 | 1043 |
1142 void _writeCompleted() { | 1044 void _writeCompleted() { |
1143 _pendingWrites--; | 1045 _pendingWrites--; |
1144 if (_pendingWrites == 0 && _noPendingWriteHandler != null) { | 1046 if (_pendingWrites == 0 && _onNoPendingWrites != null) { |
1145 _noPendingWriteHandler(); | 1047 _onNoPendingWrites(); |
1146 } | 1048 } |
1147 } | 1049 } |
1148 | 1050 |
1149 | 1051 |
1150 String _name; | 1052 String _name; |
1151 int _id; | 1053 int _id; |
1152 bool _asyncUsed; | 1054 bool _asyncUsed; |
1153 int _pendingWrites = 0; | 1055 int _pendingWrites = 0; |
1154 | 1056 |
1155 SendPort _fileService; | 1057 SendPort _fileService; |
1156 | 1058 |
1157 Timer _noPendingWriteTimer; | 1059 Timer _noPendingWriteTimer; |
1158 | 1060 |
1159 Function _closeHandler; | 1061 Function _onNoPendingWrites; |
1160 Function _readByteHandler; | 1062 Function _onError; |
1161 Function _readListHandler; | |
1162 Function _noPendingWriteHandler; | |
1163 Function _positionHandler; | |
1164 Function _setPositionHandler; | |
1165 Function _truncateHandler; | |
1166 Function _lengthHandler; | |
1167 Function _flushHandler; | |
1168 Function _errorHandler; | |
1169 } | 1063 } |
OLD | NEW |