OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 part of dart.io; | 5 part of dart.io; |
6 | 6 |
7 // Read the file in blocks of size 64k. | 7 // Read the file in blocks of size 64k. |
8 const int _BLOCK_SIZE = 64 * 1024; | 8 const int _BLOCK_SIZE = 64 * 1024; |
9 | 9 |
10 | 10 |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 _openFuture = new Future.immediate(_File._openStdioSync(fd)); | 161 _openFuture = new Future.immediate(_File._openStdioSync(fd)); |
162 } | 162 } |
163 | 163 |
164 Future<File> addStream(Stream<List<int>> stream) { | 164 Future<File> addStream(Stream<List<int>> stream) { |
165 Completer<File> completer = new Completer<File>(); | 165 Completer<File> completer = new Completer<File>(); |
166 _openFuture | 166 _openFuture |
167 .then((openedFile) { | 167 .then((openedFile) { |
168 _subscription = stream.listen( | 168 _subscription = stream.listen( |
169 (d) { | 169 (d) { |
170 _subscription.pause(); | 170 _subscription.pause(); |
171 openedFile.writeList(d, 0, d.length) | 171 openedFile.writeFrom(d, 0, d.length) |
172 .then((_) => _subscription.resume()) | 172 .then((_) => _subscription.resume()) |
173 .catchError((e) { | 173 .catchError((e) { |
174 openedFile.close(); | 174 openedFile.close(); |
175 completer.completeError(e); | 175 completer.completeError(e); |
176 }); | 176 }); |
177 }, | 177 }, |
178 onDone: () { | 178 onDone: () { |
179 completer.complete(_file); | 179 completer.complete(_file); |
180 }, | 180 }, |
181 onError: (e) { | 181 onError: (e) { |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 sink.add(bytes); | 556 sink.add(bytes); |
557 sink.close(); | 557 sink.close(); |
558 return sink.done.then((_) => this);; | 558 return sink.done.then((_) => this);; |
559 } catch (e) { | 559 } catch (e) { |
560 return new Future.immediateError(e); | 560 return new Future.immediateError(e); |
561 } | 561 } |
562 } | 562 } |
563 | 563 |
564 void writeAsBytesSync(List<int> bytes, {FileMode mode: FileMode.WRITE}) { | 564 void writeAsBytesSync(List<int> bytes, {FileMode mode: FileMode.WRITE}) { |
565 RandomAccessFile opened = openSync(mode: mode); | 565 RandomAccessFile opened = openSync(mode: mode); |
566 opened.writeListSync(bytes, 0, bytes.length); | 566 opened.writeFromSync(bytes, 0, bytes.length); |
567 opened.closeSync(); | 567 opened.closeSync(); |
568 } | 568 } |
569 | 569 |
570 Future<File> writeAsString(String contents, | 570 Future<File> writeAsString(String contents, |
571 {FileMode mode: FileMode.WRITE, | 571 {FileMode mode: FileMode.WRITE, |
572 Encoding encoding: Encoding.UTF_8}) { | 572 Encoding encoding: Encoding.UTF_8}) { |
573 try { | 573 try { |
574 return writeAsBytes(_encodeString(contents, encoding), mode: mode); | 574 return writeAsBytes(_encodeString(contents, encoding), mode: mode); |
575 } catch (e) { | 575 } catch (e) { |
576 var completer = new Completer(); | 576 var completer = new Completer(); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
704 "Invalid arguments to readSync for file '$_path'"); | 704 "Invalid arguments to readSync for file '$_path'"); |
705 } | 705 } |
706 var result = _read(_id, bytes); | 706 var result = _read(_id, bytes); |
707 if (result is OSError) { | 707 if (result is OSError) { |
708 throw new FileIOException("readSync failed for file '$_path'", | 708 throw new FileIOException("readSync failed for file '$_path'", |
709 result); | 709 result); |
710 } | 710 } |
711 return result; | 711 return result; |
712 } | 712 } |
713 | 713 |
714 Future<int> readList(List<int> buffer, int offset, int bytes) { | 714 Future<int> readInto(List<int> buffer, [int start, int end]) { |
715 _ensureFileService(); | 715 _ensureFileService(); |
| 716 if (buffer is !List || |
| 717 (start != null && start is !int) || |
| 718 (end != null && end is !int)) { |
| 719 return new Future.immediateError(new FileIOException( |
| 720 "Invalid arguments to readInto for file '$_path'")); |
| 721 }; |
716 Completer<int> completer = new Completer<int>(); | 722 Completer<int> completer = new Completer<int>(); |
717 if (buffer is !List || offset is !int || bytes is !int) { | |
718 // Complete asynchronously so the user has a chance to setup | |
719 // handlers without getting exceptions when registering the | |
720 // then handler. | |
721 Timer.run(() { | |
722 completer.completeError(new FileIOException( | |
723 "Invalid arguments to readList for file '$_path'")); | |
724 }); | |
725 return completer.future; | |
726 }; | |
727 if (closed) return _completeWithClosedException(completer); | 723 if (closed) return _completeWithClosedException(completer); |
728 List request = new List(3); | 724 List request = new List(3); |
| 725 if (start == null) start = 0; |
| 726 if (end == null) end = buffer.length; |
729 request[0] = _READ_LIST_REQUEST; | 727 request[0] = _READ_LIST_REQUEST; |
730 request[1] = _id; | 728 request[1] = _id; |
731 request[2] = bytes; | 729 request[2] = end - start; |
732 return _fileService.call(request).then((response) { | 730 return _fileService.call(request).then((response) { |
733 if (_isErrorResponse(response)) { | 731 if (_isErrorResponse(response)) { |
734 throw _exceptionFromResponse(response, | 732 throw _exceptionFromResponse(response, |
735 "readList failed for file '$_path'"); | 733 "readInto failed for file '$_path'"); |
736 } | 734 } |
737 var read = response[1]; | 735 var read = response[1]; |
738 var data = response[2]; | 736 var data = response[2]; |
739 buffer.setRange(offset, offset + read, data); | 737 buffer.setRange(start, start + read, data); |
740 return read; | 738 return read; |
741 }); | 739 }); |
742 } | 740 } |
743 | 741 |
744 static void _checkReadWriteListArguments(int length, int offset, int bytes) { | 742 static void _checkReadWriteListArguments(int length, int start, int end) { |
745 if (offset < 0) throw new RangeError.value(offset); | 743 if (start < 0) throw new RangeError.value(start); |
746 if (bytes < 0) throw new RangeError.value(bytes); | 744 if (end < start) throw new RangeError.value(end); |
747 if ((offset + bytes) > length) { | 745 if (end > length) { |
748 throw new RangeError.value(offset + bytes); | 746 throw new RangeError.value(end); |
749 } | 747 } |
750 } | 748 } |
751 | 749 |
752 external static _readList(int id, List<int> buffer, int offset, int bytes); | 750 external static _readInto(int id, List<int> buffer, int start, int end); |
753 | 751 |
754 int readListSync(List<int> buffer, int offset, int bytes) { | 752 int readIntoSync(List<int> buffer, [int start, int end]) { |
755 _checkNotClosed(); | 753 _checkNotClosed(); |
756 if (buffer is !List || offset is !int || bytes is !int) { | 754 if (buffer is !List || |
| 755 (start != null && start is !int) || |
| 756 (end != null && end is !int)) { |
757 throw new FileIOException( | 757 throw new FileIOException( |
758 "Invalid arguments to readList for file '$_path'"); | 758 "Invalid arguments to readInto for file '$_path'"); |
759 } | 759 } |
760 if (bytes == 0) return 0; | 760 if (start == null) start = 0; |
761 _checkReadWriteListArguments(buffer.length, offset, bytes); | 761 if (end == null) end = buffer.length; |
762 var result = _readList(_id, buffer, offset, bytes); | 762 if (end == start) return 0; |
| 763 _checkReadWriteListArguments(buffer.length, start, end); |
| 764 var result = _readInto(_id, buffer, start, end); |
763 if (result is OSError) { | 765 if (result is OSError) { |
764 throw new FileIOException("readList failed for file '$_path'", | 766 throw new FileIOException("readInto failed for file '$_path'", |
765 result); | 767 result); |
766 } | 768 } |
767 return result; | 769 return result; |
768 } | 770 } |
769 | 771 |
770 Future<RandomAccessFile> writeByte(int value) { | 772 Future<RandomAccessFile> writeByte(int value) { |
771 _ensureFileService(); | 773 _ensureFileService(); |
772 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 774 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
773 if (value is !int) { | 775 if (value is !int) { |
774 // Complete asynchronously so the user has a chance to setup | 776 // Complete asynchronously so the user has a chance to setup |
(...skipping 28 matching lines...) Expand all Loading... |
803 "Invalid argument to writeByte for file '$_path'"); | 805 "Invalid argument to writeByte for file '$_path'"); |
804 } | 806 } |
805 var result = _writeByte(_id, value); | 807 var result = _writeByte(_id, value); |
806 if (result is OSError) { | 808 if (result is OSError) { |
807 throw new FileIOException("writeByte failed for file '$_path'", | 809 throw new FileIOException("writeByte failed for file '$_path'", |
808 result); | 810 result); |
809 } | 811 } |
810 return result; | 812 return result; |
811 } | 813 } |
812 | 814 |
813 Future<RandomAccessFile> writeList(List<int> buffer, int offset, int bytes) { | 815 Future<RandomAccessFile> writeFrom(List<int> buffer, [int start, int end]) { |
814 _ensureFileService(); | 816 _ensureFileService(); |
| 817 if ((buffer is !List && buffer is !ByteData) || |
| 818 (start != null && start is !int) || |
| 819 (end != null && end is !int)) { |
| 820 return new Future.immediateError(new FileIOException( |
| 821 "Invalid arguments to writeFrom for file '$_path'")); |
| 822 } |
815 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); | 823 Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>(); |
816 if ((buffer is !List && buffer is !ByteData) || | 824 |
817 offset is !int || | |
818 bytes is !int) { | |
819 // Complete asynchronously so the user has a chance to setup | |
820 // handlers without getting exceptions when registering the | |
821 // then handler. | |
822 Timer.run(() { | |
823 completer.completeError(new FileIOException( | |
824 "Invalid arguments to writeList for file '$_path'")); | |
825 }); | |
826 return completer.future; | |
827 } | |
828 if (closed) return _completeWithClosedException(completer); | 825 if (closed) return _completeWithClosedException(completer); |
829 | 826 |
830 _BufferAndOffset result; | 827 _BufferAndStart result; |
831 try { | 828 try { |
832 result = _ensureFastAndSerializableBuffer(buffer, offset, bytes); | 829 result = _ensureFastAndSerializableBuffer(buffer, start, end); |
833 } catch (e) { | 830 } catch (e) { |
834 // Complete asynchronously so the user has a chance to setup | 831 return new Future.immediateError(e); |
835 // handlers without getting exceptions when registering the | |
836 // then handler. | |
837 Timer.run(() => completer.completeError(e)); | |
838 return completer.future; | |
839 } | 832 } |
840 | 833 |
841 List request = new List(5); | 834 List request = new List(5); |
842 request[0] = _WRITE_LIST_REQUEST; | 835 request[0] = _WRITE_LIST_REQUEST; |
843 request[1] = _id; | 836 request[1] = _id; |
844 request[2] = result.buffer; | 837 request[2] = result.buffer; |
845 request[3] = result.offset; | 838 request[3] = result.start; |
846 request[4] = bytes; | 839 request[4] = end - (start - result.start); |
847 return _fileService.call(request).then((response) { | 840 return _fileService.call(request).then((response) { |
848 if (_isErrorResponse(response)) { | 841 if (_isErrorResponse(response)) { |
849 throw _exceptionFromResponse(response, | 842 throw _exceptionFromResponse(response, |
850 "writeList failed for file '$_path'"); | 843 "writeFrom failed for file '$_path'"); |
851 } | 844 } |
852 return this; | 845 return this; |
853 }); | 846 }); |
854 } | 847 } |
855 | 848 |
856 external static _writeList(int id, List<int> buffer, int offset, int bytes); | 849 external static _writeFrom(int id, List<int> buffer, int start, int end); |
857 | 850 |
858 int writeListSync(List<int> buffer, int offset, int bytes) { | 851 void writeFromSync(List<int> buffer, [int start, int end]) { |
859 _checkNotClosed(); | 852 _checkNotClosed(); |
860 if (buffer is !List || offset is !int || bytes is !int) { | 853 if (buffer is !List || |
| 854 (start != null && start is !int) || |
| 855 (end != null && end is !int)) { |
861 throw new FileIOException( | 856 throw new FileIOException( |
862 "Invalid arguments to writeList for file '$_path'"); | 857 "Invalid arguments to writeFrom for file '$_path'"); |
863 } | 858 } |
864 if (bytes == 0) return 0; | 859 if (start == null) start = 0; |
865 _checkReadWriteListArguments(buffer.length, offset, bytes); | 860 if (end == null) end = buffer.length; |
866 _BufferAndOffset bufferAndOffset = | 861 if (end == start) return; |
867 _ensureFastAndSerializableBuffer(buffer, offset, bytes); | 862 _checkReadWriteListArguments(buffer.length, start, end); |
868 var result = | 863 _BufferAndStart bufferAndStart = |
869 _writeList(_id, bufferAndOffset.buffer, bufferAndOffset.offset, bytes); | 864 _ensureFastAndSerializableBuffer(buffer, start, end); |
| 865 var result = _writeFrom(_id, |
| 866 bufferAndStart.buffer, |
| 867 bufferAndStart.start, |
| 868 end - (start - bufferAndStart.start)); |
870 if (result is OSError) { | 869 if (result is OSError) { |
871 throw new FileIOException("writeList failed for file '$_path'", result); | 870 throw new FileIOException("writeFrom failed for file '$_path'", result); |
872 } | 871 } |
873 return result; | |
874 } | 872 } |
875 | 873 |
876 Future<RandomAccessFile> writeString(String string, | 874 Future<RandomAccessFile> writeString(String string, |
877 {Encoding encoding: Encoding.UTF_8}) { | 875 {Encoding encoding: Encoding.UTF_8}) { |
878 if (encoding is! Encoding) { | 876 if (encoding is! Encoding) { |
879 var completer = new Completer(); | 877 var completer = new Completer(); |
880 Timer.run(() { | 878 Timer.run(() { |
881 completer.completeError(new FileIOException( | 879 completer.completeError(new FileIOException( |
882 "Invalid encoding in writeString: $encoding")); | 880 "Invalid encoding in writeString: $encoding")); |
883 }); | 881 }); |
884 return completer.future; | 882 return completer.future; |
885 } | 883 } |
886 var data = _encodeString(string, encoding); | 884 var data = _encodeString(string, encoding); |
887 return writeList(data, 0, data.length); | 885 return writeFrom(data, 0, data.length); |
888 } | 886 } |
889 | 887 |
890 int writeStringSync(String string, {Encoding encoding: Encoding.UTF_8}) { | 888 void writeStringSync(String string, {Encoding encoding: Encoding.UTF_8}) { |
891 if (encoding is! Encoding) { | 889 if (encoding is! Encoding) { |
892 throw new FileIOException( | 890 throw new FileIOException( |
893 "Invalid encoding in writeStringSync: $encoding"); | 891 "Invalid encoding in writeStringSync: $encoding"); |
894 } | 892 } |
895 var data = _encodeString(string, encoding); | 893 var data = _encodeString(string, encoding); |
896 return writeListSync(data, 0, data.length); | 894 writeFromSync(data, 0, data.length); |
897 } | 895 } |
898 | 896 |
899 Future<int> position() { | 897 Future<int> position() { |
900 _ensureFileService(); | 898 _ensureFileService(); |
901 Completer<int> completer = new Completer<int>(); | 899 Completer<int> completer = new Completer<int>(); |
902 if (closed) return _completeWithClosedException(completer); | 900 if (closed) return _completeWithClosedException(completer); |
903 List request = new List(2); | 901 List request = new List(2); |
904 request[0] = _POSITION_REQUEST; | 902 request[0] = _POSITION_REQUEST; |
905 request[1] = _id; | 903 request[1] = _id; |
906 return _fileService.call(request).then((response) { | 904 return _fileService.call(request).then((response) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 new FileIOException("File closed '$_path'")); | 1050 new FileIOException("File closed '$_path'")); |
1053 }); | 1051 }); |
1054 return completer.future; | 1052 return completer.future; |
1055 } | 1053 } |
1056 | 1054 |
1057 final String _path; | 1055 final String _path; |
1058 int _id; | 1056 int _id; |
1059 | 1057 |
1060 SendPort _fileService; | 1058 SendPort _fileService; |
1061 } | 1059 } |
OLD | NEW |