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