io-like 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/NEWS +11 -0
  2. data/README +15 -1
  3. data/lib/io/like.rb +155 -105
  4. metadata +2 -2
data/NEWS CHANGED
@@ -6,6 +6,17 @@ detailed information is available in the rest of the documentation.
6
6
  <b>NOTE:</b> Date stamps in the following entries are in YYYY/MM/DD format.
7
7
 
8
8
 
9
+ == v0.3.0 (2009/04/29)
10
+
11
+ * Fixed the rewind method to work with write-only streams
12
+ * Fixed the read, gets, and readline methods to return partial data if they have
13
+ such data but receive low level errors before reaching a stopping point
14
+ * Renamed all private methods so that it is highly unlikely that they will be
15
+ accidentally overridden.
16
+ * Eliminated warnings caused by referencing uninitialized instance variables
17
+ * Improved the documentation for the read, gets, and readline methods
18
+
19
+
9
20
  == v0.2.0 (2009/03/11)
10
21
 
11
22
  * Added mspec tests borrowed from the rubyspec project
data/README CHANGED
@@ -78,7 +78,7 @@ A simple ROT13 codec:
78
78
  encode_rot13(@delegate_io.sysread(length))
79
79
  end
80
80
 
81
- def unbuffered_seek(offset, whence = IO::SEEKSET)
81
+ def unbuffered_seek(offset, whence = IO::SEEK_SET)
82
82
  @delegate_io.sysseek(offset, whence)
83
83
  end
84
84
 
@@ -109,6 +109,20 @@ A simple ROT13 codec:
109
109
  end
110
110
  end
111
111
 
112
+ File.open('normal_file.txt') do |f|
113
+ ROT13Filter.open(f) do |rot13|
114
+ rot13.pos = 5
115
+ puts(rot13.read) # -> vf n grfg
116
+ end
117
+ end
118
+
119
+ File.open('rot13_file.txt') do |f|
120
+ ROT13Filter.open(f) do |rot13|
121
+ rot13.pos = 5
122
+ puts(rot13.read) # -> is a test
123
+ end
124
+ end
125
+
112
126
  File.open('normal_file.txt') do |f|
113
127
  ROT13Filter.open(f) do |rot13|
114
128
  ROT13Filter.open(rot13) do |rot26| # ;-)
@@ -29,9 +29,10 @@ class IO # :nodoc:
29
29
  # ...
30
30
  # end
31
31
  #
32
- # This method must return the number of bytes written to the stream and
33
- # should raise SystemCallError on errors. Errno::EAGAIN should be raised if
34
- # no data can be written immediately and the write operation should not block.
32
+ # This method must either return the number of bytes written to the stream,
33
+ # which may be less than the length of _string_ in bytes, OR must raise an
34
+ # instance of SystemCallError. Errno::EAGAIN should be raised if no data can
35
+ # be written immediately and the write operation should not block.
35
36
  # Errno::EINTR should be raised if the write operation is interrupted before
36
37
  # any data is written.
37
38
  #
@@ -100,9 +101,9 @@ class IO # :nodoc:
100
101
  # returns +true+ and then sets a flag so that #closed? will return +true+.
101
102
  def close
102
103
  raise IOError, 'closed stream' if closed?
103
- @__io_like__closed_read = true
104
+ __io_like__close_read
104
105
  flush if writable?
105
- @__io_like__closed_write = true
106
+ __io_like__close_write
106
107
  nil
107
108
  end
108
109
 
@@ -117,11 +118,11 @@ class IO # :nodoc:
117
118
  # if #writable? returns +true+.
118
119
  def close_read
119
120
  raise IOError, 'closed stream' if closed?
120
- if @__io_like__closed_read || ! duplexed? && writable? then
121
+ if __io_like__closed_read? || ! duplexed? && writable? then
121
122
  raise IOError, 'closing non-duplex IO for reading'
122
123
  end
123
124
  if duplexed? then
124
- @__io_like__closed_read = true
125
+ __io_like__close_read
125
126
  else
126
127
  close
127
128
  end
@@ -139,12 +140,12 @@ class IO # :nodoc:
139
140
  # if #readable? returns +true+.
140
141
  def close_write
141
142
  raise IOError, 'closed stream' if closed?
142
- if @__io_like__closed_write || ! duplexed? && readable? then
143
+ if __io_like__closed_write? || ! duplexed? && readable? then
143
144
  raise IOError, 'closing non-duplex IO for reading'
144
145
  end
145
146
  if duplexed? then
146
147
  flush
147
- @__io_like__closed_write = true
148
+ __io_like__close_write
148
149
  else
149
150
  close
150
151
  end
@@ -157,8 +158,8 @@ class IO # :nodoc:
157
158
  # Returns +true+ if this object is closed or otherwise unusable for read and
158
159
  # write operations.
159
160
  def closed?
160
- (@__io_like__closed_read || ! readable?) &&
161
- (@__io_like__closed_write || ! writable?)
161
+ (__io_like__closed_read? || ! readable?) &&
162
+ (__io_like__closed_write? || ! writable?)
162
163
  end
163
164
 
164
165
  # call-seq:
@@ -302,7 +303,7 @@ class IO # :nodoc:
302
303
  # #unbuffered_write.
303
304
  def flush
304
305
  begin
305
- buffered_flush
306
+ __io_like__buffered_flush
306
307
  rescue Errno::EAGAIN, Errno::EINTR
307
308
  retry if write_ready?
308
309
  end
@@ -370,8 +371,11 @@ class IO # :nodoc:
370
371
  #
371
372
  # Calls #readline with _sep_string_ as an argument and either returns the
372
373
  # result or +nil+ if #readline raises EOFError. If #readline returns some
373
- # data, the returned data is assigned to <tt>$_</tt> and <tt>$.</tt> is set
374
- # to the value of #lineno.
374
+ # data, <tt>$.</tt> is set to the value of #lineno.
375
+ #
376
+ # <b>NOTE:</b> Due to limitations of MRI up to version 1.9.x when running
377
+ # managed (Ruby) code, this method fails to set <tt>$_</tt> to the returned
378
+ # data; however, other implementations may allow it.
375
379
  #
376
380
  # Raises IOError if #closed? returns +true+. Raises IOError unless
377
381
  # #readable? returns +true+. Raises all errors raised by #unbuffered_read
@@ -379,9 +383,9 @@ class IO # :nodoc:
379
383
  #
380
384
  # <b>NOTE:</b> When _sep_string_ is not +nil+, this method ignores
381
385
  # Errno::EAGAIN and Errno::EINTR raised by #unbuffered_read. Therefore,
382
- # this method always blocks. Aside from that exception and the conversion
383
- # of EOFError results into +nil+ results, this method will also raise the
384
- # same errors and block at the same times as #unbuffered_read.
386
+ # this method will always block in that case. Aside from that exception,
387
+ # this method will raise the same errors and block at the same times as
388
+ # #unbuffered_read.
385
389
  def gets(sep_string = $/)
386
390
  # Set the last read line in the global.
387
391
  $_ = readline(sep_string)
@@ -484,8 +488,8 @@ class IO # :nodoc:
484
488
  # also raise the same errors and block at the same times as those functions.
485
489
  def pos
486
490
  # Flush the internal write buffer for writable, non-duplexed objects.
487
- buffered_flush if writable? && ! duplexed?
488
- buffered_seek(0, IO::SEEK_CUR)
491
+ __io_like__buffered_flush if writable? && ! duplexed?
492
+ __io_like__buffered_seek(0, IO::SEEK_CUR)
489
493
  end
490
494
  alias :tell :pos
491
495
 
@@ -616,7 +620,7 @@ class IO # :nodoc:
616
620
  line = arg.nil? ?
617
621
  'nil' :
618
622
  arg.kind_of?(Array) ?
619
- array_join(arg, ors) :
623
+ __io_like__array_join(arg, ors) :
620
624
  arg.to_s
621
625
  line += ors if line.index(ors, -ors.length).nil?
622
626
  write(line)
@@ -633,8 +637,10 @@ class IO # :nodoc:
633
637
  # left to fulfill the request. If the read starts at the end of data, +nil+
634
638
  # is returned.
635
639
  #
636
- # If _length_ is unspecified or +nil+, all remaining data is returned. If
637
- # no data would be returned at all, an empty String is returned.
640
+ # If _length_ is unspecified or +nil+, an attempt to return all remaining
641
+ # data is made. Partial data will be returned if a low-level error is
642
+ # raised after some data is retrieved. If no data would be returned at all,
643
+ # an empty String is returned.
638
644
  #
639
645
  # If _buffer_ is specified, it will be converted to a String using its
640
646
  # +to_str+ method if necessary and will be filled with the returned data if
@@ -657,15 +663,18 @@ class IO # :nodoc:
657
663
  # Read and return everything.
658
664
  begin
659
665
  loop do
660
- buffer << buffered_read(4096)
666
+ buffer << __io_like__buffered_read(4096)
661
667
  end
662
668
  rescue EOFError
663
669
  # Ignore this.
670
+ rescue SystemCallError
671
+ # Reraise the error if there is nothing to return.
672
+ raise if buffer.empty?
664
673
  end
665
674
  else
666
675
  # Read and return up to length bytes.
667
676
  begin
668
- buffer << buffered_read(length)
677
+ buffer << __io_like__buffered_read(length)
669
678
  rescue EOFError
670
679
  # Return nil to the caller at end of file when requesting a specific
671
680
  # amount of data.
@@ -706,7 +715,7 @@ class IO # :nodoc:
706
715
  # provides the #unbuffered_read method but may not always be open in a
707
716
  # readable mode.
708
717
  def readable?
709
- ! @__io_like__closed_read && respond_to?(:unbuffered_read, true)
718
+ ! __io_like__closed_read? && respond_to?(:unbuffered_read, true)
710
719
  end
711
720
 
712
721
  # call-seq:
@@ -751,7 +760,7 @@ class IO # :nodoc:
751
760
  # exception, this method will also raise the same errors and block at the
752
761
  # same times as #unbuffered_read.
753
762
  def readchar
754
- buffered_read(1)[0]
763
+ __io_like__buffered_read(1)[0]
755
764
  rescue Errno::EAGAIN, Errno::EINTR
756
765
  retry if read_ready?
757
766
  end
@@ -760,14 +769,27 @@ class IO # :nodoc:
760
769
  # ios.readline(sep_string = $/) -> string
761
770
  #
762
771
  # Returns the next line from the stream, where lines are separated by
763
- # _sep_string_. Increments #lineno.
772
+ # _sep_string_. Increments #lineno by <tt>1</tt> for each call regardless
773
+ # of the value of _sep_string_.
774
+ #
775
+ # If _sep_string_ is not +nil+ and not a String, it is first converted to a
776
+ # String using its +to_str+ method and processing continues as follows.
764
777
  #
765
778
  # If _sep_string_ is +nil+, a line is defined as the remaining contents of
766
- # the stream. If _sep_string_ is not a String, it is converted to one using
767
- # its +to_str+ method. If _sep_string_ is empty, a paragraph is returned,
768
- # where a paragraph is defined as data followed by 2 or more successive
769
- # newline characters (only 2 newlines are returned at the end of the
770
- # returned data).
779
+ # the stream. Partial data will be returned if a low-level error of any
780
+ # kind is raised after some data is retrieved. This is equivalent to
781
+ # calling #read without any arguments except that this method will raise an
782
+ # EOFError if called at the end of the stream.
783
+ #
784
+ # If _sep_string_ is an empty String, a paragraph is returned, where a
785
+ # paragraph is defined as data followed by 2 or more successive newline
786
+ # characters. A maximum of 2 newlines are returned at the end of the
787
+ # returned data. Fewer may be returned if the stream ends before at least 2
788
+ # successive newlines are seen.
789
+ #
790
+ # Any other value for _sep_string_ is used as a delimiter to mark the end of
791
+ # a line. The returned data includes this delimiter unless the stream ends
792
+ # before the delimiter is seen.
771
793
  #
772
794
  # In any case, the end of the stream terminates the current line.
773
795
  #
@@ -777,8 +799,8 @@ class IO # :nodoc:
777
799
  #
778
800
  # <b>NOTE:</b> When _sep_string_ is not +nil+, this method ignores
779
801
  # Errno::EAGAIN and Errno::EINTR raised by #unbuffered_read. Therefore,
780
- # this method always blocks. Aside from that exception, this method will
781
- # also raise the same errors and block at the same times as
802
+ # this method will always block in that case. Aside from that exception,
803
+ # this method will raise the same errors and block at the same times as
782
804
  # #unbuffered_read.
783
805
  def readline(sep_string = $/)
784
806
  # Ensure that sep_string is either nil or a String.
@@ -792,7 +814,7 @@ class IO # :nodoc:
792
814
  # A nil line separator means that the user wants to capture all the
793
815
  # remaining input.
794
816
  loop do
795
- buffer << buffered_read(4096)
817
+ buffer << __io_like__buffered_read(4096)
796
818
  end
797
819
  else
798
820
  begin
@@ -806,7 +828,7 @@ class IO # :nodoc:
806
828
  # Add each character from the input to the buffer until either the
807
829
  # buffer has the right ending or the end of the input is reached.
808
830
  while buffer.index(sep_string, -sep_string.length).nil? &&
809
- (char = buffered_read(1)) do
831
+ (char = __io_like__buffered_read(1)) do
810
832
  buffer << char
811
833
  end
812
834
 
@@ -814,7 +836,7 @@ class IO # :nodoc:
814
836
  # If the user requested paragraphs instead of lines, we need to
815
837
  # consume and discard all newlines remaining at the front of the
816
838
  # input.
817
- while char == "\n" && (char = buffered_read(1)) do
839
+ while char == "\n" && (char = __io_like__buffered_read(1)) do
818
840
  nil
819
841
  end
820
842
  # Put back the last character.
@@ -824,7 +846,8 @@ class IO # :nodoc:
824
846
  retry if read_ready?
825
847
  end
826
848
  end
827
- rescue EOFError
849
+ rescue EOFError, SystemCallError
850
+ # Reraise the error if there is nothing to return.
828
851
  raise if buffer.empty?
829
852
  end
830
853
  # Increment the number of times this method has returned a "line".
@@ -889,9 +912,9 @@ class IO # :nodoc:
889
912
  buffer.slice!(0..-1)
890
913
 
891
914
  # Read and return up to length bytes.
892
- if internal_read_buffer.empty? then
915
+ if __io_like__internal_read_buffer.empty? then
893
916
  begin
894
- buffer << buffered_read(length)
917
+ buffer << __io_like__buffered_read(length)
895
918
  rescue Errno::EAGAIN, Errno::EINTR
896
919
  retry if read_ready?
897
920
  end
@@ -899,7 +922,7 @@ class IO # :nodoc:
899
922
  raise IOError, 'closed stream' if closed?
900
923
  raise IOError, 'not opened for reading' unless readable?
901
924
 
902
- buffer << internal_read_buffer.slice!(0, length)
925
+ buffer << __io_like__internal_read_buffer.slice!(0, length)
903
926
  end
904
927
  buffer
905
928
  end
@@ -909,7 +932,7 @@ class IO # :nodoc:
909
932
  #
910
933
  # Sets the position of the file pointer to the beginning of the stream and
911
934
  # returns 0 when complete. The lineno attribute is reset to 0 if
912
- # successful.
935
+ # successful and the stream is readable according to #readable?.
913
936
  #
914
937
  # As a side effect, the internal read and write buffers are flushed.
915
938
  #
@@ -921,7 +944,8 @@ class IO # :nodoc:
921
944
  # also raise the same errors and block at the same times as those functions.
922
945
  def rewind
923
946
  seek(0, IO::SEEK_SET)
924
- self.lineno = 0
947
+ self.lineno = 0 if readable?
948
+ 0
925
949
  end
926
950
 
927
951
  # call-seq:
@@ -944,7 +968,7 @@ class IO # :nodoc:
944
968
  # #unbuffered_write (when the internal write buffer is not empty), it will
945
969
  # also raise the same errors and block at the same times as those functions.
946
970
  def seek(offset, whence = IO::SEEK_SET)
947
- buffered_seek(offset, whence)
971
+ __io_like__buffered_seek(offset, whence)
948
972
  0
949
973
  end
950
974
 
@@ -1009,12 +1033,12 @@ class IO # :nodoc:
1009
1033
 
1010
1034
  raise IOError, 'closed stream' if closed?
1011
1035
  raise IOError, 'not opened for reading' unless readable?
1012
- unless internal_read_buffer.empty? then
1036
+ unless __io_like__internal_read_buffer.empty? then
1013
1037
  raise IOError, 'sysread on buffered IO'
1014
1038
  end
1015
1039
 
1016
1040
  # Flush the internal write buffer for writable, non-duplexed objects.
1017
- buffered_flush if writable? && ! duplexed?
1041
+ __io_like__buffered_flush if writable? && ! duplexed?
1018
1042
 
1019
1043
  buffer << unbuffered_read(length)
1020
1044
  end
@@ -1036,9 +1060,11 @@ class IO # :nodoc:
1036
1060
  # raise the same errors and block at the same times as that function.
1037
1061
  def sysseek(offset, whence = IO::SEEK_SET)
1038
1062
  raise IOError, 'closed stream' if closed?
1039
- raise Errno::ESPIPE, 'Illegal seek' unless seekable?
1040
- raise IOError, 'sysseek on buffered IO' unless internal_read_buffer.empty?
1041
- unless internal_write_buffer.empty? then
1063
+ raise Errno::ESPIPE unless seekable?
1064
+ unless __io_like__internal_read_buffer.empty? then
1065
+ raise IOError, 'sysseek on buffered IO'
1066
+ end
1067
+ unless __io_like__internal_write_buffer.empty? then
1042
1068
  warn('warning: sysseek on buffered IO')
1043
1069
  end
1044
1070
 
@@ -1062,15 +1088,15 @@ class IO # :nodoc:
1062
1088
  def syswrite(string)
1063
1089
  raise IOError, 'closed stream' if closed?
1064
1090
  raise IOError, 'not opened for writing' unless writable?
1065
- unless internal_write_buffer.empty? then
1091
+ unless __io_like__internal_write_buffer.empty? then
1066
1092
  warn('warning: syswrite on buffered IO')
1067
1093
  end
1068
1094
 
1069
1095
  # Flush the internal read buffer and set the unbuffered position to the
1070
1096
  # buffered position when dealing with non-duplexed objects.
1071
- unless duplexed? || internal_read_buffer.empty? then
1072
- unbuffered_seek(-internal_read_buffer.length, IO::SEEK_CUR)
1073
- internal_read_buffer.slice!(0..-1)
1097
+ unless duplexed? || __io_like__internal_read_buffer.empty? then
1098
+ unbuffered_seek(-__io_like__internal_read_buffer.length, IO::SEEK_CUR)
1099
+ __io_like__internal_read_buffer.slice!(0..-1)
1074
1100
  end
1075
1101
 
1076
1102
  unbuffered_write(string)
@@ -1107,7 +1133,7 @@ class IO # :nodoc:
1107
1133
  def unread(string)
1108
1134
  raise IOError, 'closed stream' if closed?
1109
1135
  raise IOError, 'not opened for reading' unless readable?
1110
- internal_read_buffer.insert(0, string.to_s)
1136
+ __io_like__internal_read_buffer.insert(0, string.to_s)
1111
1137
  nil
1112
1138
  end
1113
1139
 
@@ -1142,7 +1168,7 @@ class IO # :nodoc:
1142
1168
  # provides the #unbuffered_write method but may not always be open in a
1143
1169
  # writable mode.
1144
1170
  def writable?
1145
- ! @__io_like__closed_write && respond_to?(:unbuffered_write, true)
1171
+ ! __io_like__closed_write? && respond_to?(:unbuffered_write, true)
1146
1172
  end
1147
1173
 
1148
1174
  # call-seq:
@@ -1168,7 +1194,8 @@ class IO # :nodoc:
1168
1194
  bytes_written = 0
1169
1195
  while bytes_written < string.length do
1170
1196
  begin
1171
- bytes_written += buffered_write(string.to_s.slice(bytes_written..-1))
1197
+ bytes_written +=
1198
+ __io_like__buffered_write(string.to_s.slice(bytes_written..-1))
1172
1199
  rescue Errno::EAGAIN, Errno::EINTR
1173
1200
  retry if write_ready?
1174
1201
  end
@@ -1179,7 +1206,7 @@ class IO # :nodoc:
1179
1206
  private
1180
1207
 
1181
1208
  # call-seq:
1182
- # ios.buffered_flush -> 0
1209
+ # ios.__io_like__buffered_flush -> 0
1183
1210
  #
1184
1211
  # Attempts to completely flush the internal write buffer to the data stream.
1185
1212
  #
@@ -1188,18 +1215,20 @@ class IO # :nodoc:
1188
1215
  # <b>NOTE:</b> Because this method relies on #unbuffered_write, it raises
1189
1216
  # all errors raised by #unbuffered_write and blocks when #unbuffered_write
1190
1217
  # blocks.
1191
- def buffered_flush
1218
+ def __io_like__buffered_flush
1192
1219
  raise IOError, 'closed stream' if closed?
1193
1220
  raise IOError, 'not opened for writing' unless writable?
1194
1221
 
1195
- until internal_write_buffer.empty? do
1196
- internal_write_buffer.slice!(0, unbuffered_write(internal_write_buffer))
1222
+ until __io_like__internal_write_buffer.empty? do
1223
+ __io_like__internal_write_buffer.slice!(
1224
+ 0, unbuffered_write(__io_like__internal_write_buffer)
1225
+ )
1197
1226
  end
1198
1227
  0
1199
1228
  end
1200
1229
 
1201
1230
  # call-seq:
1202
- # ios.buffered_read(length) -> string
1231
+ # ios.__io_like__buffered_read(length) -> string
1203
1232
  #
1204
1233
  # Reads at most _length_ bytes first from an internal read buffer followed
1205
1234
  # by the underlying stream if necessary and returns the resulting buffer.
@@ -1210,7 +1239,7 @@ class IO # :nodoc:
1210
1239
  # <b>NOTE:</b> Because this method relies on #unbuffered_read, it raises all
1211
1240
  # errors raised by #unbuffered_read and blocks when #unbuffered_read blocks
1212
1241
  # whenever the internal read buffer is unable to fulfill the request.
1213
- def buffered_read(length)
1242
+ def __io_like__buffered_read(length)
1214
1243
  # Check the validity of the method arguments.
1215
1244
  raise ArgumentError, "non-positive length #{length} given" if length < 0
1216
1245
 
@@ -1218,30 +1247,30 @@ class IO # :nodoc:
1218
1247
  raise IOError, 'not opened for reading' unless readable?
1219
1248
 
1220
1249
  # Flush the internal write buffer for writable, non-duplexed objects.
1221
- buffered_flush if writable? && ! duplexed?
1250
+ __io_like__buffered_flush if writable? && ! duplexed?
1222
1251
 
1223
1252
  # Ensure that the internal read buffer has at least enough data to satisfy
1224
1253
  # the request.
1225
- if internal_read_buffer.length < length then
1226
- unbuffered_length = length - internal_read_buffer.length
1254
+ if __io_like__internal_read_buffer.length < length then
1255
+ unbuffered_length = length - __io_like__internal_read_buffer.length
1227
1256
  unbuffered_length = fill_size if unbuffered_length < fill_size
1228
1257
 
1229
1258
  begin
1230
- internal_read_buffer << unbuffered_read(unbuffered_length)
1259
+ __io_like__internal_read_buffer << unbuffered_read(unbuffered_length)
1231
1260
  rescue EOFError, SystemCallError
1232
1261
  # Reraise the error if there is no data to return.
1233
- raise if internal_read_buffer.empty?
1262
+ raise if __io_like__internal_read_buffer.empty?
1234
1263
  end
1235
1264
  end
1236
1265
 
1237
1266
  # Read from the internal read buffer.
1238
- buffer = internal_read_buffer.slice!(0, length)
1267
+ buffer = __io_like__internal_read_buffer.slice!(0, length)
1239
1268
 
1240
1269
  buffer
1241
1270
  end
1242
1271
 
1243
1272
  # call-seq:
1244
- # ios.buffered_seek(offset[, whence]) -> integer
1273
+ # ios.__io_like__buffered_seek(offset[, whence]) -> integer
1245
1274
  #
1246
1275
  # Sets the current data position to _offset_ based on the setting of
1247
1276
  # _whence_. If _whence_ is unspecified or IO::SEEK_SET, _offset_ counts
@@ -1260,37 +1289,40 @@ class IO # :nodoc:
1260
1289
  # <b>NOTE:</b> Because this method relies on #unbuffered_seek and
1261
1290
  # #unbuffered_write (when the internal write buffer is not empty), it will
1262
1291
  # raise the same errors and block at the same times as those functions.
1263
- def buffered_seek(offset, whence = IO::SEEK_SET)
1292
+ def __io_like__buffered_seek(offset, whence = IO::SEEK_SET)
1264
1293
  raise IOError, 'closed stream' if closed?
1265
- raise Errno::ESPIPE, 'Illegal seek' unless seekable?
1294
+ raise Errno::ESPIPE unless seekable?
1266
1295
 
1267
1296
  if whence == IO::SEEK_CUR && offset == 0 then
1268
1297
  # The seek is only determining the current position, so return the
1269
1298
  # buffered position based on the read buffer if it's not empty and the
1270
1299
  # write buffer otherwise.
1271
- internal_read_buffer.empty? ?
1272
- unbuffered_seek(0, IO::SEEK_CUR) + internal_write_buffer.length :
1273
- unbuffered_seek(0, IO::SEEK_CUR) - internal_read_buffer.length
1300
+ __io_like__internal_read_buffer.empty? ?
1301
+ unbuffered_seek(0, IO::SEEK_CUR) +
1302
+ __io_like__internal_write_buffer.length :
1303
+ unbuffered_seek(0, IO::SEEK_CUR) -
1304
+ __io_like__internal_read_buffer.length
1274
1305
  elsif whence == IO::SEEK_CUR && offset > 0 &&
1275
- internal_write_buffer.empty? &&
1276
- offset <= internal_read_buffer.length then
1306
+ __io_like__internal_write_buffer.empty? &&
1307
+ offset <= __io_like__internal_read_buffer.length then
1277
1308
  # The seek is within the read buffer, so just discard a sufficient
1278
1309
  # amount of the buffer and report the new buffered position.
1279
- internal_read_buffer.slice!(0, offset)
1280
- unbuffered_seek(0, IO::SEEK_CUR) - internal_read_buffer.length
1310
+ __io_like__internal_read_buffer.slice!(0, offset)
1311
+ unbuffered_seek(0, IO::SEEK_CUR) -
1312
+ __io_like__internal_read_buffer.length
1281
1313
  else
1282
1314
  # The seek target is outside of the buffers, so flush the buffers and
1283
1315
  # jump to the new position.
1284
1316
  if whence == IO::SEEK_CUR then
1285
1317
  # Adjust relative offsets based on the current buffered offset.
1286
- offset += internal_read_buffer.empty? ?
1287
- internal_write_buffer.length :
1288
- -internal_read_buffer.length
1318
+ offset += __io_like__internal_read_buffer.empty? ?
1319
+ __io_like__internal_write_buffer.length :
1320
+ -__io_like__internal_read_buffer.length
1289
1321
  end
1290
1322
 
1291
1323
  # Flush the internal buffers.
1292
- internal_read_buffer.slice!(0..-1)
1293
- buffered_flush if writable?
1324
+ __io_like__internal_read_buffer.slice!(0..-1)
1325
+ __io_like__buffered_flush if writable?
1294
1326
 
1295
1327
  # Move the data stream's position as requested.
1296
1328
  unbuffered_seek(offset, whence)
@@ -1298,7 +1330,7 @@ class IO # :nodoc:
1298
1330
  end
1299
1331
 
1300
1332
  # call-seq:
1301
- # ios.buffered_write(string) -> integer
1333
+ # ios.__io_like__buffered_write(string) -> integer
1302
1334
  #
1303
1335
  # Writes _string_ to the internal write buffer and returns the number of
1304
1336
  # bytes written. If the internal write buffer is overfilled by _string_, it
@@ -1311,51 +1343,72 @@ class IO # :nodoc:
1311
1343
  # all errors raised by #unbuffered_write and blocks when #unbuffered_write
1312
1344
  # blocks whenever the internal write buffer is unable to fulfill the
1313
1345
  # request.
1314
- def buffered_write(string)
1346
+ def __io_like__buffered_write(string)
1315
1347
  raise IOError, 'closed stream' if closed?
1316
1348
  raise IOError, 'not opened for writing' unless writable?
1317
1349
 
1318
1350
  # Flush the internal read buffer and set the unbuffered position to the
1319
1351
  # buffered position when dealing with non-duplexed objects.
1320
- unless duplexed? || internal_read_buffer.empty? then
1321
- unbuffered_seek(-internal_read_buffer.length, IO::SEEK_CUR)
1322
- internal_read_buffer.slice!(0..-1)
1352
+ unless duplexed? || __io_like__internal_read_buffer.empty? then
1353
+ unbuffered_seek(-__io_like__internal_read_buffer.length, IO::SEEK_CUR)
1354
+ __io_like__internal_read_buffer.slice!(0..-1)
1323
1355
  end
1324
1356
 
1325
1357
  bytes_written = 0
1326
1358
  if sync then
1327
1359
  # Flush the internal write buffer and then bypass it when in synchronous
1328
1360
  # mode.
1329
- buffered_flush
1361
+ __io_like__buffered_flush
1330
1362
  bytes_written = unbuffered_write(string)
1331
1363
  else
1332
- if internal_write_buffer.length + string.length >= flush_size then
1364
+ if __io_like__internal_write_buffer.length + string.length >= flush_size then
1333
1365
  # The tipping point for the write buffer would be surpassed by this
1334
1366
  # request, so flush everything.
1335
- buffered_flush
1367
+ __io_like__buffered_flush
1336
1368
  bytes_written = unbuffered_write(string)
1337
1369
  else
1338
1370
  # The buffer can absorb the entire request.
1339
- internal_write_buffer << string
1371
+ __io_like__internal_write_buffer << string
1340
1372
  bytes_written = string.length
1341
1373
  end
1342
1374
  end
1343
- rescue SystemCallError
1344
- raise if bytes_written == 0
1345
- else
1346
1375
  return bytes_written
1347
1376
  end
1348
1377
 
1349
1378
  # Returns a reference to the internal read buffer.
1350
- def internal_read_buffer
1379
+ def __io_like__internal_read_buffer
1351
1380
  @__io_like__read_buffer ||= ''
1352
1381
  end
1353
1382
 
1354
1383
  # Returns a reference to the internal write buffer.
1355
- def internal_write_buffer
1384
+ def __io_like__internal_write_buffer
1356
1385
  @__io_like__write_buffer ||= ''
1357
1386
  end
1358
1387
 
1388
+ # Returns +true+ if this object has been closed for reading; otherwise,
1389
+ # returns +false+.
1390
+ def __io_like__closed_read?
1391
+ @__io_like__closed_read ||= false
1392
+ end
1393
+
1394
+ # Arranges for #__io_like__closed_read? to return +true+.
1395
+ def __io_like__close_read
1396
+ @__io_like__closed_read = true
1397
+ nil
1398
+ end
1399
+
1400
+ # Returns +true+ if this object has been closed for writing; otherwise,
1401
+ # returns +false+.
1402
+ def __io_like__closed_write?
1403
+ @__io_like__closed_write ||= false
1404
+ end
1405
+
1406
+ # Arranges for #__io_like__closed_write? to return +true+.
1407
+ def __io_like__close_write
1408
+ @__io_like__closed_write = true
1409
+ nil
1410
+ end
1411
+
1359
1412
  # This method joins the elements of _array_ together with _separator_
1360
1413
  # between each element and returns the result. _seen_ is a list of object
1361
1414
  # IDs representing arrays which have already started processing.
@@ -1375,21 +1428,18 @@ class IO # :nodoc:
1375
1428
  #
1376
1429
  # Things get progressively worse as the nesting and recursion become more
1377
1430
  # convoluted.
1378
- def array_join(array, separator, seen = [])
1379
- first = true
1431
+ def __io_like__array_join(array, separator, seen = [])
1380
1432
  seen.push(array.object_id)
1433
+ need_separator = false
1381
1434
  result = array.inject('') do |memo, item|
1382
- if first then
1383
- first = false
1384
- else
1385
- memo << separator
1386
- end
1435
+ memo << separator if need_separator
1436
+ need_separator = true
1387
1437
 
1388
1438
  memo << if item.kind_of?(Array) then
1389
1439
  if seen.include?(item.object_id) then
1390
1440
  '[...]'
1391
1441
  else
1392
- array_join(item, separator, seen)
1442
+ __io_like__array_join(item, separator, seen)
1393
1443
  end
1394
1444
  else
1395
1445
  item.to_s
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-like
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Bopp
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-11 00:00:00 -05:00
12
+ date: 2009-04-29 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15