io-like 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CONTRIBUTORS +2 -0
- data/HACKING +2 -2
- data/LEGAL +49 -1
- data/LICENSE.rubyspec +22 -0
- data/MANIFEST +1 -1
- data/NEWS +7 -0
- data/README +4 -3
- data/lib/io/like.rb +354 -278
- metadata +5 -4
- data/test/lib/likestringio.rb +0 -167
data/CONTRIBUTORS
CHANGED
data/HACKING
CHANGED
@@ -17,8 +17,8 @@ some cases, but such cases will be rare.
|
|
17
17
|
=== Build
|
18
18
|
|
19
19
|
* rubygems 0.9.0 or greater
|
20
|
-
* rake 0.8.
|
21
|
-
*
|
20
|
+
* rake 0.8.3 or greater
|
21
|
+
* mspec 1.5.9 (optional - used for testing)
|
22
22
|
* allison 2.0.3 (optional - used for documentation only, if available)
|
23
23
|
* rsync (optional - used for publishing documentation)
|
24
24
|
|
data/LEGAL
CHANGED
@@ -5,4 +5,52 @@
|
|
5
5
|
The following file(s) are provided under a license or licenses separate from
|
6
6
|
this project.
|
7
7
|
|
8
|
-
|
8
|
+
See LICENSE.rubyspec for terms of use for the following:
|
9
|
+
spec/binmode_spec.rb
|
10
|
+
spec/close_read_spec.rb
|
11
|
+
spec/close_spec.rb
|
12
|
+
spec/close_write_spec.rb
|
13
|
+
spec/closed_spec.rb
|
14
|
+
spec/each_byte_spec.rb
|
15
|
+
spec/each_line_spec.rb
|
16
|
+
spec/each_spec.rb
|
17
|
+
spec/eof_spec.rb
|
18
|
+
spec/fixtures/classes.rb
|
19
|
+
spec/fixtures/gets.txt
|
20
|
+
spec/fixtures/numbered_lines.txt
|
21
|
+
spec/fixtures/one_byte.txt
|
22
|
+
spec/fixtures/paragraphs.txt
|
23
|
+
spec/fixtures/readlines.txt
|
24
|
+
spec/flush_spec.rb
|
25
|
+
spec/getc_spec.rb
|
26
|
+
spec/gets_spec.rb
|
27
|
+
spec/isatty_spec.rb
|
28
|
+
spec/lineno_spec.rb
|
29
|
+
spec/output_spec.rb
|
30
|
+
spec/pos_spec.rb
|
31
|
+
spec/print_spec.rb
|
32
|
+
spec/printf_spec.rb
|
33
|
+
spec/putc_spec.rb
|
34
|
+
spec/puts_spec.rb
|
35
|
+
spec/read_spec.rb
|
36
|
+
spec/readchar_spec.rb
|
37
|
+
spec/readline_spec.rb
|
38
|
+
spec/readlines_spec.rb
|
39
|
+
spec/readpartial_spec.rb
|
40
|
+
spec/rewind_spec.rb
|
41
|
+
spec/seek_spec.rb
|
42
|
+
spec/shared/each.rb
|
43
|
+
spec/shared/eof.rb
|
44
|
+
spec/shared/pos.rb
|
45
|
+
spec/shared/tty.rb
|
46
|
+
spec/shared/write.rb
|
47
|
+
spec/sync_spec.rb
|
48
|
+
spec/sysread_spec.rb
|
49
|
+
spec/sysseek_spec.rb
|
50
|
+
spec/syswrite_spec.rb
|
51
|
+
spec/tell_spec.rb
|
52
|
+
spec/to_io_spec.rb
|
53
|
+
spec/tty_spec.rb
|
54
|
+
spec/ungetc_spec.rb
|
55
|
+
spec/write_spec.rb
|
56
|
+
spec_helper.rb
|
data/LICENSE.rubyspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Engine Yard, Inc. All rights reserved.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/MANIFEST
CHANGED
data/NEWS
CHANGED
@@ -6,6 +6,13 @@ 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.2.0 (2009/03/11)
|
10
|
+
|
11
|
+
* Added mspec tests borrowed from the rubyspec project
|
12
|
+
* Fixed many, many defects related to IO compatibility (Mostly obscure corner
|
13
|
+
cases)
|
14
|
+
|
15
|
+
|
9
16
|
== v0.1.0 (2008/07/03)
|
10
17
|
|
11
18
|
* Initial release
|
data/README
CHANGED
@@ -12,11 +12,14 @@ methods.
|
|
12
12
|
|
13
13
|
== License
|
14
14
|
|
15
|
-
Copyright © 2008 Jeremy Bopp <jeremy at bopp dot net>
|
15
|
+
Copyright © 2008,2009 Jeremy Bopp <jeremy at bopp dot net>
|
16
16
|
|
17
17
|
Licensed under the same terms as Ruby -- See the included LICENSE file for
|
18
18
|
details
|
19
19
|
|
20
|
+
Some parts licensed under the same terms as the rubyspec project -- See the
|
21
|
+
included LEGAL and LICENSE.rubyspec files for details
|
22
|
+
|
20
23
|
|
21
24
|
== Installation/Removal
|
22
25
|
|
@@ -125,8 +128,6 @@ A simple ROT13 codec:
|
|
125
128
|
collected. Define a class open method in the manner of File.open which
|
126
129
|
guarantees that an appropriate close method will be called after executing a
|
127
130
|
block. Other than that, be diligent about calling the close methods.
|
128
|
-
3. Testcases needed. Maybe use some of rubyspec along with some test classes
|
129
|
-
act like the important parts of IO, File, and/or StringIO.
|
130
131
|
|
131
132
|
|
132
133
|
== Contributing
|
data/lib/io/like.rb
CHANGED
@@ -100,77 +100,65 @@ class IO # :nodoc:
|
|
100
100
|
# returns +true+ and then sets a flag so that #closed? will return +true+.
|
101
101
|
def close
|
102
102
|
raise IOError, 'closed stream' if closed?
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
else
|
107
|
-
flush if writable?
|
108
|
-
@__io_like__closed = true
|
109
|
-
end
|
103
|
+
@__io_like__closed_read = true
|
104
|
+
flush if writable?
|
105
|
+
@__io_like__closed_write = true
|
110
106
|
nil
|
111
107
|
end
|
112
108
|
|
113
109
|
# call-seq:
|
114
110
|
# ios.close_read -> nil
|
115
111
|
#
|
116
|
-
#
|
112
|
+
# Closes the read end of a duplexed object or the whole object if the object
|
113
|
+
# is read-only.
|
117
114
|
#
|
118
|
-
# Raises IOError if #
|
119
|
-
#
|
115
|
+
# Raises IOError if #closed? returns +true+. Raises IOError for duplexed
|
116
|
+
# objects if called more than once. Raises IOError for non-duplexed objects
|
117
|
+
# if #writable? returns +true+.
|
120
118
|
def close_read
|
121
|
-
raise IOError, 'closed stream' if
|
122
|
-
|
123
|
-
|
119
|
+
raise IOError, 'closed stream' if closed?
|
120
|
+
if @__io_like__closed_read || ! duplexed? && writable? then
|
121
|
+
raise IOError, 'closing non-duplex IO for reading'
|
122
|
+
end
|
123
|
+
if duplexed? then
|
124
|
+
@__io_like__closed_read = true
|
125
|
+
else
|
126
|
+
close
|
127
|
+
end
|
124
128
|
nil
|
125
129
|
end
|
126
130
|
|
127
131
|
# call-seq:
|
128
132
|
# ios.close_write -> nil
|
129
133
|
#
|
130
|
-
#
|
131
|
-
#
|
134
|
+
# Closes the write end of a duplexed object or the whole object if the
|
135
|
+
# object is write-only.
|
132
136
|
#
|
133
|
-
# Raises IOError if #
|
134
|
-
#
|
137
|
+
# Raises IOError if #closed? returns +true+. Raises IOError for duplexed
|
138
|
+
# objects if called more than once. Raises IOError for non-duplexed objects
|
139
|
+
# if #readable? returns +true+.
|
135
140
|
def close_write
|
136
|
-
raise IOError, 'closed stream' if
|
137
|
-
|
138
|
-
|
139
|
-
|
141
|
+
raise IOError, 'closed stream' if closed?
|
142
|
+
if @__io_like__closed_write || ! duplexed? && readable? then
|
143
|
+
raise IOError, 'closing non-duplex IO for reading'
|
144
|
+
end
|
145
|
+
if duplexed? then
|
146
|
+
flush
|
147
|
+
@__io_like__closed_write = true
|
148
|
+
else
|
149
|
+
close
|
150
|
+
end
|
140
151
|
nil
|
141
152
|
end
|
142
153
|
|
143
154
|
# call-seq:
|
144
155
|
# ios.closed? -> true or false
|
145
156
|
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
# and #closed_write? return true.
|
157
|
+
# Returns +true+ if this object is closed or otherwise unusable for read and
|
158
|
+
# write operations.
|
149
159
|
def closed?
|
150
|
-
|
151
|
-
@
|
152
|
-
end
|
153
|
-
|
154
|
-
# call-seq:
|
155
|
-
# ios.closed_read? -> true or false
|
156
|
-
#
|
157
|
-
# Returns the result of calling #closed? for non-duplexed objects. For
|
158
|
-
# duplexed objects, returns +true+ if close_read was called, +false+
|
159
|
-
# otherwise.
|
160
|
-
def closed_read?
|
161
|
-
return closed? unless duplexed?
|
162
|
-
@__io_like__closed_read || false
|
163
|
-
end
|
164
|
-
|
165
|
-
# call-seq:
|
166
|
-
# ios.closed_write? -> true or false
|
167
|
-
#
|
168
|
-
# Returns the result of calling #closed? for non-duplexed objects. For
|
169
|
-
# duplexed objects, returns +true+ if close_write was called, +false+
|
170
|
-
# otherwise.
|
171
|
-
def closed_write?
|
172
|
-
return closed? unless duplexed?
|
173
|
-
@__io_like__closed_read || false
|
160
|
+
(@__io_like__closed_read || ! readable?) &&
|
161
|
+
(@__io_like__closed_write || ! writable?)
|
174
162
|
end
|
175
163
|
|
176
164
|
# call-seq:
|
@@ -183,12 +171,12 @@ class IO # :nodoc:
|
|
183
171
|
end
|
184
172
|
|
185
173
|
# call-seq:
|
186
|
-
# ios.each_byte {|byte| block} -> ios
|
174
|
+
# ios.each_byte { |byte| block } -> ios
|
187
175
|
#
|
188
176
|
# Reads each byte (0..255) from the stream using #getc and calls the given
|
189
177
|
# block once for each byte, passing the byte as an argument.
|
190
178
|
#
|
191
|
-
# NOTE
|
179
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
192
180
|
# #unbuffered_read. Therefore, this method always blocks. Aside from that
|
193
181
|
# exception and the conversion of EOFError results into +nil+ results, this
|
194
182
|
# method will also raise the same errors and block at the same times as
|
@@ -201,17 +189,17 @@ class IO # :nodoc:
|
|
201
189
|
end
|
202
190
|
|
203
191
|
# call-seq:
|
204
|
-
# ios.each_line(sep_string = $/) {|line| block } -> ios
|
205
|
-
# ios.each(sep_string = $/) {|line| block } -> ios
|
192
|
+
# ios.each_line(sep_string = $/) { |line| block } -> ios
|
193
|
+
# ios.each(sep_string = $/) { |line| block } -> ios
|
206
194
|
#
|
207
195
|
# Reads each line from the stream using #gets and calls the given block once
|
208
196
|
# for each line, passing the line as an argument.
|
209
197
|
#
|
210
|
-
# NOTE
|
211
|
-
# and Errno::EINTR raised by #unbuffered_read. Therefore,
|
212
|
-
# always blocks. Aside from that exception and the conversion
|
213
|
-
# results into +nil+ results, this method will also raise the
|
214
|
-
# and block at the same times as #unbuffered_read.
|
198
|
+
# <b>NOTE:</b> When _sep_string_ is not +nil+, this method ignores
|
199
|
+
# Errno::EAGAIN and Errno::EINTR raised by #unbuffered_read. Therefore,
|
200
|
+
# this method always blocks. Aside from that exception and the conversion
|
201
|
+
# of EOFError results into +nil+ results, this method will also raise the
|
202
|
+
# same errors and block at the same times as #unbuffered_read.
|
215
203
|
def each_line(sep_string = $/)
|
216
204
|
while (line = gets(sep_string)) do
|
217
205
|
yield(line)
|
@@ -230,7 +218,7 @@ class IO # :nodoc:
|
|
230
218
|
# put the character back if one was fetched. It may be a good idea to
|
231
219
|
# replace this implementation in derivative classes.
|
232
220
|
#
|
233
|
-
# NOTE
|
221
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
234
222
|
# #unbuffered_read. Therefore, this method always blocks. Aside from that
|
235
223
|
# exception and the conversion of EOFError results into +nil+ results, this
|
236
224
|
# method will also raise the same errors and block at the same times as
|
@@ -247,7 +235,7 @@ class IO # :nodoc:
|
|
247
235
|
# call-seq:
|
248
236
|
# ios.fcntl
|
249
237
|
#
|
250
|
-
# Raises NotImplementedError
|
238
|
+
# Raises NotImplementedError.
|
251
239
|
def fcntl(*args)
|
252
240
|
raise NotImplementedError, 'not implemented'
|
253
241
|
end
|
@@ -267,10 +255,10 @@ class IO # :nodoc:
|
|
267
255
|
# buffer needs to be refilled. Unless set explicitly via #fill_size=, this
|
268
256
|
# defaults to 4096.
|
269
257
|
#
|
270
|
-
# Raises IOError if #
|
258
|
+
# Raises IOError if #closed? returns +true+. Raises IOError if the
|
271
259
|
# stream is not opened for reading.
|
272
260
|
def fill_size
|
273
|
-
raise IOError, 'closed stream' if
|
261
|
+
raise IOError, 'closed stream' if closed?
|
274
262
|
raise IOError, 'not opened for reading' unless readable?
|
275
263
|
|
276
264
|
@__io_like__fill_size ||= 4096
|
@@ -283,10 +271,10 @@ class IO # :nodoc:
|
|
283
271
|
# buffer needs to be refilled. The new value must be a number greater than
|
284
272
|
# or equal to 0. Setting this to 0 effectively disables buffering.
|
285
273
|
#
|
286
|
-
# Raises IOError if #
|
274
|
+
# Raises IOError if #closed? returns +true+. Raises IOError if the
|
287
275
|
# stream is not opened for reading.
|
288
276
|
def fill_size=(fill_size)
|
289
|
-
raise IOError, 'closed stream' if
|
277
|
+
raise IOError, 'closed stream' if closed?
|
290
278
|
raise IOError, 'not opened for reading' unless readable?
|
291
279
|
|
292
280
|
unless fill_size >= 0 then
|
@@ -304,17 +292,15 @@ class IO # :nodoc:
|
|
304
292
|
# during writing, this method will block until either all the data is
|
305
293
|
# flushed or until an error is raised.
|
306
294
|
#
|
307
|
-
# Raises IOError if #
|
295
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
308
296
|
# #writable? returns +true+.
|
309
297
|
#
|
310
|
-
# NOTE
|
298
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
311
299
|
# #unbuffered_write. Therefore, this method always blocks if unable to
|
312
300
|
# flush the internal write buffer. Aside from that exception, this
|
313
301
|
# method will also raise the same errors and block at the same times as
|
314
302
|
# #unbuffered_write.
|
315
303
|
def flush
|
316
|
-
raise IOError, 'closed stream' if closed_write?
|
317
|
-
|
318
304
|
begin
|
319
305
|
buffered_flush
|
320
306
|
rescue Errno::EAGAIN, Errno::EINTR
|
@@ -330,10 +316,10 @@ class IO # :nodoc:
|
|
330
316
|
# automatically to the data stream. Unless set explicitly via #flush_size=,
|
331
317
|
# this defaults to 4096.
|
332
318
|
#
|
333
|
-
# Raises IOError if #
|
319
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
334
320
|
# #writable? returns +true+.
|
335
321
|
def flush_size
|
336
|
-
raise IOError, 'closed stream' if
|
322
|
+
raise IOError, 'closed stream' if closed?
|
337
323
|
raise IOError, 'not opened for writing' unless writable?
|
338
324
|
|
339
325
|
@__io_like__flush_size ||= 4096
|
@@ -346,10 +332,10 @@ class IO # :nodoc:
|
|
346
332
|
# automatically to the data stream. The new value must be a number greater
|
347
333
|
# than or equal to 0. Setting this to 0 effectively disables buffering.
|
348
334
|
#
|
349
|
-
# Raises IOError if #
|
335
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
350
336
|
# #writable? returns +true+.
|
351
337
|
def flush_size=(flush_size)
|
352
|
-
raise IOError, 'closed stream' if
|
338
|
+
raise IOError, 'closed stream' if closed?
|
353
339
|
raise IOError, 'not opened for writing' unless writable?
|
354
340
|
|
355
341
|
unless flush_size >= 0 then
|
@@ -364,11 +350,11 @@ class IO # :nodoc:
|
|
364
350
|
# Calls #readchar and either returns the result or +nil+ if #readchar raises
|
365
351
|
# EOFError.
|
366
352
|
#
|
367
|
-
# Raises IOError if #
|
353
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
368
354
|
# #readable? returns +true+. Raises all errors raised by #unbuffered_read
|
369
355
|
# except for EOFError.
|
370
356
|
#
|
371
|
-
# NOTE
|
357
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
372
358
|
# #unbuffered_read. Therefore, this method always blocks. Aside from that
|
373
359
|
# exception and the conversion of EOFError results into +nil+ results, this
|
374
360
|
# method will also raise the same errors and block at the same times as
|
@@ -387,15 +373,15 @@ class IO # :nodoc:
|
|
387
373
|
# data, the returned data is assigned to <tt>$_</tt> and <tt>$.</tt> is set
|
388
374
|
# to the value of #lineno.
|
389
375
|
#
|
390
|
-
# Raises IOError if #
|
376
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
391
377
|
# #readable? returns +true+. Raises all errors raised by #unbuffered_read
|
392
378
|
# except for EOFError.
|
393
379
|
#
|
394
|
-
# NOTE
|
395
|
-
# and Errno::EINTR raised by #unbuffered_read. Therefore,
|
396
|
-
# always blocks. Aside from that exception and the conversion
|
397
|
-
# results into +nil+ results, this method will also raise the
|
398
|
-
# and block at the same times as #unbuffered_read.
|
380
|
+
# <b>NOTE:</b> When _sep_string_ is not +nil+, this method ignores
|
381
|
+
# 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.
|
399
385
|
def gets(sep_string = $/)
|
400
386
|
# Set the last read line in the global.
|
401
387
|
$_ = readline(sep_string)
|
@@ -411,7 +397,10 @@ class IO # :nodoc:
|
|
411
397
|
# ios.isatty -> false
|
412
398
|
#
|
413
399
|
# Returns +false+. Just for compatibility with IO.
|
400
|
+
#
|
401
|
+
# Raises IOError if #closed? returns +true+.
|
414
402
|
def isatty
|
403
|
+
raise IOError, 'closed stream' if closed?
|
415
404
|
false
|
416
405
|
end
|
417
406
|
alias :tty? :isatty
|
@@ -424,10 +413,10 @@ class IO # :nodoc:
|
|
424
413
|
# the other line-based reading methods with a non-default value for
|
425
414
|
# _sep_string_ or after changing <tt>$/</tt> will affect this.
|
426
415
|
#
|
427
|
-
# Raises IOError if #
|
416
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
428
417
|
# #readable? returns +true+.
|
429
418
|
def lineno
|
430
|
-
raise IOError, 'closed stream' if
|
419
|
+
raise IOError, 'closed stream' if closed?
|
431
420
|
raise IOError, 'not opened for reading' unless readable?
|
432
421
|
@__io_like__lineno ||= 0
|
433
422
|
end
|
@@ -436,14 +425,20 @@ class IO # :nodoc:
|
|
436
425
|
# ios.lineno = lineno -> lineno
|
437
426
|
#
|
438
427
|
# Sets the current line number to the given value. <tt>$.</tt> is updated
|
439
|
-
# by the _next_ call to #gets.
|
428
|
+
# by the _next_ call to #gets. If the object given is not an integer, it is
|
429
|
+
# converted to one using its to_int method.
|
440
430
|
#
|
441
|
-
# Raises IOError if #
|
431
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
442
432
|
# #readable? returns +true+.
|
443
433
|
def lineno=(integer)
|
444
|
-
raise IOError, 'closed stream' if
|
434
|
+
raise IOError, 'closed stream' if closed?
|
445
435
|
raise IOError, 'not opened for reading' unless readable?
|
446
|
-
|
436
|
+
if integer.nil? then
|
437
|
+
raise TypeError, 'no implicit conversion from nil to integer'
|
438
|
+
elsif ! integer.respond_to?(:to_int) then
|
439
|
+
raise TypeError, "can't convert #{integer.class} into Integer"
|
440
|
+
end
|
441
|
+
@__io_like__lineno = integer.to_int
|
447
442
|
end
|
448
443
|
|
449
444
|
# call-seq:
|
@@ -464,14 +459,36 @@ class IO # :nodoc:
|
|
464
459
|
# Raises IOError if #closed? returns +true+. Raises Errno::ESPIPE unless
|
465
460
|
# #seekable? returns +true+.
|
466
461
|
#
|
467
|
-
# NOTE
|
468
|
-
# (when the internal write buffer is not empty), it will
|
469
|
-
# errors and block at the same times as those functions.
|
462
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_seek and
|
463
|
+
# #unbuffered_write (when the internal write buffer is not empty), it will
|
464
|
+
# also raise the same errors and block at the same times as those functions.
|
470
465
|
def pos=(position)
|
471
466
|
seek(position, IO::SEEK_SET)
|
472
467
|
position
|
473
468
|
end
|
474
469
|
|
470
|
+
# call-seq:
|
471
|
+
# ios.pos -> integer
|
472
|
+
#
|
473
|
+
# Returns the current offest of ios.
|
474
|
+
#
|
475
|
+
# Raises IOError if #closed? returns +true+. Raises Errno::ESPIPE unless
|
476
|
+
# #seekable? returns +true+.
|
477
|
+
#
|
478
|
+
# As a side effect, the internal write buffer is flushed unless this is
|
479
|
+
# a writable, non-duplexed object. This is for compatibility with the
|
480
|
+
# behavior of IO#pos.
|
481
|
+
#
|
482
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_seek and
|
483
|
+
# #unbuffered_write (when the internal write buffer is not empty), it will
|
484
|
+
# also raise the same errors and block at the same times as those functions.
|
485
|
+
def pos
|
486
|
+
# Flush the internal write buffer for writable, non-duplexed objects.
|
487
|
+
buffered_flush if writable? && ! duplexed?
|
488
|
+
buffered_seek(0, IO::SEEK_CUR)
|
489
|
+
end
|
490
|
+
alias :tell :pos
|
491
|
+
|
475
492
|
# call-seq:
|
476
493
|
# ios.print([obj, ...]) -> nil
|
477
494
|
#
|
@@ -482,10 +499,10 @@ class IO # :nodoc:
|
|
482
499
|
# record separator (<tt>$\\</tt>) is written after all other data if it is
|
483
500
|
# not nil.
|
484
501
|
#
|
485
|
-
# Raises IOError if #
|
502
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
486
503
|
# #writable? returns +true+.
|
487
504
|
#
|
488
|
-
# NOTE
|
505
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
489
506
|
# #unbuffered_write. Therefore, this method always blocks if unable to
|
490
507
|
# immediately write +[obj, ...]+ completely. Aside from that exception,
|
491
508
|
# this method will also raise the same errors and block at the same times as
|
@@ -522,10 +539,10 @@ class IO # :nodoc:
|
|
522
539
|
# Writes the String returned by calling Kernel.sprintf using the given
|
523
540
|
# arguments.
|
524
541
|
#
|
525
|
-
# Raises IOError if #
|
542
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
526
543
|
# #writable? returns +true+.
|
527
544
|
#
|
528
|
-
# NOTE
|
545
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
529
546
|
# #unbuffered_write. Therefore, this method always blocks if unable to
|
530
547
|
# immediately write its arguments completely. Aside from that exception,
|
531
548
|
# this method will also raise the same errors and block at the same times as
|
@@ -538,23 +555,23 @@ class IO # :nodoc:
|
|
538
555
|
# call-seq:
|
539
556
|
# ios.putc(obj) -> obj
|
540
557
|
#
|
541
|
-
# If _obj_ is
|
542
|
-
# write the
|
558
|
+
# If _obj_ is a String, write the first byte; otherwise, convert _obj_ to a
|
559
|
+
# integer using its _to_int_ method and write the low order byte.
|
543
560
|
#
|
544
|
-
# Raises IOError if #
|
561
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
545
562
|
# #writable? returns +true+.
|
546
563
|
#
|
547
|
-
# NOTE
|
564
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
548
565
|
# #unbuffered_write. Therefore, this method always blocks if unable to
|
549
566
|
# immediately write _obj_ completely. Aside from that exception, this
|
550
567
|
# method will also raise the same errors and block at the same times as
|
551
568
|
# #unbuffered_write.
|
552
569
|
def putc(obj)
|
553
570
|
char = case obj
|
554
|
-
when
|
555
|
-
obj.chr
|
571
|
+
when String
|
572
|
+
obj[0].chr
|
556
573
|
else
|
557
|
-
obj.
|
574
|
+
[obj.to_int].pack('V')[0].chr
|
558
575
|
end
|
559
576
|
write(char)
|
560
577
|
obj
|
@@ -569,18 +586,18 @@ class IO # :nodoc:
|
|
569
586
|
# is written after each object which does not end with the record separator
|
570
587
|
# already. If no objects are given, a single record separator is written.
|
571
588
|
#
|
572
|
-
# Raises IOError if #
|
589
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
573
590
|
# #writable? returns +true+.
|
574
591
|
#
|
575
|
-
# NOTE
|
592
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
576
593
|
# #unbuffered_write. Therefore, this method always blocks if unable to
|
577
594
|
# immediately write +[obj, ...]+ completely. Aside from that exception,
|
578
595
|
# this method will also raise the same errors and block at the same times as
|
579
596
|
# #unbuffered_write.
|
580
597
|
#
|
581
|
-
# NOTE
|
582
|
-
# currently hardcoded to be a single newline (<tt>"\n"</tt>) even though
|
583
|
-
# documentation implies that the output record separator (<tt>$\\</tt>)
|
598
|
+
# <b>NOTE:</b> In order to be compatible with IO#puts, the record separator
|
599
|
+
# is currently hardcoded to be a single newline (<tt>"\n"</tt>) even though
|
600
|
+
# the documentation implies that the output record separator (<tt>$\\</tt>)
|
584
601
|
# should be used.
|
585
602
|
def puts(*args)
|
586
603
|
# Set the output record separator such that this method is compatible with
|
@@ -596,13 +613,13 @@ class IO # :nodoc:
|
|
596
613
|
# Write each argument followed by the record separator. Recursively
|
597
614
|
# process arguments which are Array instances.
|
598
615
|
args.each do |arg|
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
616
|
+
line = arg.nil? ?
|
617
|
+
'nil' :
|
618
|
+
arg.kind_of?(Array) ?
|
619
|
+
array_join(arg, ors) :
|
620
|
+
arg.to_s
|
621
|
+
line += ors if line.index(ors, -ors.length).nil?
|
622
|
+
write(line)
|
606
623
|
end
|
607
624
|
|
608
625
|
nil
|
@@ -619,22 +636,22 @@ class IO # :nodoc:
|
|
619
636
|
# If _length_ is unspecified or +nil+, all remaining data is returned. If
|
620
637
|
# no data would be returned at all, an empty String is returned.
|
621
638
|
#
|
622
|
-
# If _buffer_ is specified, it
|
623
|
-
# with the returned data if
|
639
|
+
# If _buffer_ is specified, it will be converted to a String using its
|
640
|
+
# +to_str+ method if necessary and will be filled with the returned data if
|
641
|
+
# any.
|
624
642
|
#
|
625
|
-
# Raises IOError if #
|
643
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
626
644
|
# #readable? returns +true+.
|
627
645
|
#
|
628
|
-
# NOTE
|
629
|
-
# the same errors and block at the same times as that function.
|
646
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_read, it will also
|
647
|
+
# raise the same errors and block at the same times as that function.
|
630
648
|
def read(length = nil, buffer = nil)
|
631
649
|
# Check the validity of the method arguments.
|
632
650
|
unless length.nil? || length >= 0 then
|
633
651
|
raise ArgumentError, "negative length #{length} given"
|
634
652
|
end
|
635
|
-
buffer = ''
|
636
|
-
|
637
|
-
buffer.slice!(0..-1)
|
653
|
+
buffer = buffer.nil? ? '' : buffer.to_str
|
654
|
+
buffer.slice!(0..-1) unless buffer.empty?
|
638
655
|
|
639
656
|
if length.nil? then
|
640
657
|
# Read and return everything.
|
@@ -667,8 +684,8 @@ class IO # :nodoc:
|
|
667
684
|
# This default implementation of #read_ready? is a hack which should be able
|
668
685
|
# to work for both real IO objects and IO-like objects; however, it is
|
669
686
|
# inefficient since it merely sleeps for 1 second and then returns +true+ as
|
670
|
-
# long as #
|
671
|
-
#
|
687
|
+
# long as #closed? returns +false+. IO.select should be used for real IO
|
688
|
+
# objects to wait for a readable condition on platforms with support for
|
672
689
|
# IO.select. Other solutions should be found as necessary to improve this
|
673
690
|
# implementation on a case by case basis.
|
674
691
|
#
|
@@ -684,12 +701,12 @@ class IO # :nodoc:
|
|
684
701
|
#
|
685
702
|
# Returns +true+ if the stream is both open and readable, +false+ otherwise.
|
686
703
|
#
|
687
|
-
# This implementation
|
688
|
-
#
|
689
|
-
#
|
690
|
-
#
|
704
|
+
# This implementation checks to see if #unbuffered_read is defined in order
|
705
|
+
# to make its determination. Override this if the implementing class always
|
706
|
+
# provides the #unbuffered_read method but may not always be open in a
|
707
|
+
# readable mode.
|
691
708
|
def readable?
|
692
|
-
!
|
709
|
+
! @__io_like__closed_read && respond_to?(:unbuffered_read, true)
|
693
710
|
end
|
694
711
|
|
695
712
|
# call-seq:
|
@@ -698,17 +715,17 @@ class IO # :nodoc:
|
|
698
715
|
# Reads and returns _length_ bytes from the data stream.
|
699
716
|
#
|
700
717
|
# Raises EOFError if reading begins at the end of the stream. Raises
|
701
|
-
# IOError if #
|
702
|
-
#
|
703
|
-
#
|
718
|
+
# IOError if #closed? returns +true+. Raises IOError unless #readable?
|
719
|
+
# returns +true+. Raises TruncatedDataError if insufficient data is
|
720
|
+
# immediately available to satisfy the request.
|
704
721
|
#
|
705
722
|
# In the case of TruncatedDataError being raised, the retrieved data can be
|
706
723
|
# fetched from the _data_ attribute of the exception.
|
707
724
|
#
|
708
725
|
# This method is basically copied from IO#readbytes.
|
709
726
|
#
|
710
|
-
# NOTE
|
711
|
-
# the same errors and block at the same times as that function.
|
727
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_read, it will also
|
728
|
+
# raise the same errors and block at the same times as that function.
|
712
729
|
def readbytes(length)
|
713
730
|
buffer = read(length)
|
714
731
|
if buffer.nil? then
|
@@ -726,15 +743,14 @@ class IO # :nodoc:
|
|
726
743
|
# Returns the next 8-bit byte (0..255) from the stream.
|
727
744
|
#
|
728
745
|
# Raises EOFError when there is no more data in the stream. Raises IOError
|
729
|
-
# if #
|
746
|
+
# if #closed? returns +true+. Raises IOError unless #readable? returns
|
730
747
|
# +true+.
|
731
748
|
#
|
732
|
-
# NOTE
|
749
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
733
750
|
# #unbuffered_read. Therefore, this method always blocks. Aside from that
|
734
751
|
# exception, this method will also raise the same errors and block at the
|
735
752
|
# same times as #unbuffered_read.
|
736
753
|
def readchar
|
737
|
-
raise IOError, 'closed stream' if closed_read?
|
738
754
|
buffered_read(1)[0]
|
739
755
|
rescue Errno::EAGAIN, Errno::EINTR
|
740
756
|
retry if read_ready?
|
@@ -747,22 +763,28 @@ class IO # :nodoc:
|
|
747
763
|
# _sep_string_. Increments #lineno.
|
748
764
|
#
|
749
765
|
# If _sep_string_ is +nil+, a line is defined as the remaining contents of
|
750
|
-
# the stream. If _sep_string_ is
|
751
|
-
#
|
752
|
-
#
|
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).
|
753
771
|
#
|
754
772
|
# In any case, the end of the stream terminates the current line.
|
755
773
|
#
|
756
774
|
# Raises EOFError when there is no more data in the stream. Raises IOError
|
757
|
-
# if #
|
775
|
+
# if #closed? returns +true+. Raises IOError unless #readable? returns
|
758
776
|
# +true+.
|
759
777
|
#
|
760
|
-
# NOTE
|
761
|
-
# and Errno::EINTR raised by #unbuffered_read. Therefore,
|
762
|
-
# always blocks. Aside from that exception, this method will
|
763
|
-
# same errors and block at the same times as
|
778
|
+
# <b>NOTE:</b> When _sep_string_ is not +nil+, this method ignores
|
779
|
+
# 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
|
782
|
+
# #unbuffered_read.
|
764
783
|
def readline(sep_string = $/)
|
765
|
-
|
784
|
+
# Ensure that sep_string is either nil or a String.
|
785
|
+
unless sep_string.nil? || sep_string.kind_of?(String) then
|
786
|
+
sep_string = sep_string.to_str
|
787
|
+
end
|
766
788
|
|
767
789
|
buffer = ''
|
768
790
|
begin
|
@@ -777,14 +799,14 @@ class IO # :nodoc:
|
|
777
799
|
# Record if the user requested paragraphs rather than lines.
|
778
800
|
paragraph_requested = sep_string.empty?
|
779
801
|
# An empty line separator string indicates that the user wants to
|
780
|
-
# return paragraphs. A pair of newlines in the stream is used to
|
781
|
-
# this.
|
802
|
+
# return paragraphs. A pair of newlines in the stream is used to
|
803
|
+
# mark this.
|
782
804
|
sep_string = "\n\n" if paragraph_requested
|
783
805
|
|
784
806
|
# Add each character from the input to the buffer until either the
|
785
807
|
# buffer has the right ending or the end of the input is reached.
|
786
808
|
while buffer.index(sep_string, -sep_string.length).nil? &&
|
787
|
-
(char =
|
809
|
+
(char = buffered_read(1)) do
|
788
810
|
buffer << char
|
789
811
|
end
|
790
812
|
|
@@ -792,7 +814,9 @@ class IO # :nodoc:
|
|
792
814
|
# If the user requested paragraphs instead of lines, we need to
|
793
815
|
# consume and discard all newlines remaining at the front of the
|
794
816
|
# input.
|
795
|
-
while
|
817
|
+
while char == "\n" && (char = buffered_read(1)) do
|
818
|
+
nil
|
819
|
+
end
|
796
820
|
# Put back the last character.
|
797
821
|
ungetc(char[0])
|
798
822
|
end
|
@@ -814,20 +838,23 @@ class IO # :nodoc:
|
|
814
838
|
# Returns an Array containing the lines in the stream using #each_line.
|
815
839
|
#
|
816
840
|
# If _sep_string_ is +nil+, a line is defined as the remaining contents of
|
817
|
-
# the stream. If _sep_string_ is
|
818
|
-
#
|
819
|
-
#
|
841
|
+
# the stream. If _sep_string_ is not a String, it is converted to one using
|
842
|
+
# its +to_str+ method. If _sep_string_ is empty, a paragraph is returned,
|
843
|
+
# where a paragraph is defined as data followed by 2 or more successive
|
844
|
+
# newline characters (only 2 newlines are returned at the end of the
|
845
|
+
# returned data).
|
820
846
|
#
|
821
847
|
# In any case, the end of the stream terminates the current line.
|
822
848
|
#
|
823
849
|
# Raises EOFError when there is no more data in the stream. Raises IOError
|
824
|
-
# if #
|
850
|
+
# if #closed? returns +true+. Raises IOError unless #readable? returns
|
825
851
|
# +true+.
|
826
852
|
#
|
827
|
-
# NOTE
|
828
|
-
# and Errno::EINTR raised by #unbuffered_read. Therefore,
|
829
|
-
# always blocks. Aside from that exception, this method will
|
830
|
-
# same errors and block at the same times as
|
853
|
+
# <b>NOTE:</b> When _sep_string_ is not +nil+, this method ignores
|
854
|
+
# Errno::EAGAIN and Errno::EINTR raised by #unbuffered_read. Therefore,
|
855
|
+
# this method always blocks. Aside from that exception, this method will
|
856
|
+
# also raise the same errors and block at the same times as
|
857
|
+
# #unbuffered_read.
|
831
858
|
def readlines(sep_string = $/)
|
832
859
|
lines = []
|
833
860
|
each_line(sep_string) { |line| lines << line }
|
@@ -844,10 +871,10 @@ class IO # :nodoc:
|
|
844
871
|
# whether or not the data stream would block.
|
845
872
|
#
|
846
873
|
# Raises EOFError when there is no more data in the stream. Raises IOError
|
847
|
-
# if #
|
874
|
+
# if #closed? returns +true+. Raises IOError unless #readable? returns
|
848
875
|
# +true+.
|
849
876
|
#
|
850
|
-
# NOTE
|
877
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
851
878
|
# #unbuffered_read. Therefore, this method always blocks if unable to
|
852
879
|
# immediately return _length_ bytes. Aside from that exception, this method
|
853
880
|
# will also raise the same errors and block at the same times as
|
@@ -861,9 +888,6 @@ class IO # :nodoc:
|
|
861
888
|
# Flush the buffer.
|
862
889
|
buffer.slice!(0..-1)
|
863
890
|
|
864
|
-
raise IOError, 'closed stream' if closed_read?
|
865
|
-
raise IOError, 'not opened for reading' unless readable?
|
866
|
-
|
867
891
|
# Read and return up to length bytes.
|
868
892
|
if internal_read_buffer.empty? then
|
869
893
|
begin
|
@@ -872,6 +896,9 @@ class IO # :nodoc:
|
|
872
896
|
retry if read_ready?
|
873
897
|
end
|
874
898
|
else
|
899
|
+
raise IOError, 'closed stream' if closed?
|
900
|
+
raise IOError, 'not opened for reading' unless readable?
|
901
|
+
|
875
902
|
buffer << internal_read_buffer.slice!(0, length)
|
876
903
|
end
|
877
904
|
buffer
|
@@ -889,9 +916,9 @@ class IO # :nodoc:
|
|
889
916
|
# Raises IOError if #closed? returns +true+. Raises Errno::ESPIPE unless
|
890
917
|
# #seekable? returns +true+.
|
891
918
|
#
|
892
|
-
# NOTE
|
893
|
-
# (when the internal write buffer is not empty), it will
|
894
|
-
# errors and block at the same times as those functions.
|
919
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_seek and
|
920
|
+
# #unbuffered_write (when the internal write buffer is not empty), it will
|
921
|
+
# also raise the same errors and block at the same times as those functions.
|
895
922
|
def rewind
|
896
923
|
seek(0, IO::SEEK_SET)
|
897
924
|
self.lineno = 0
|
@@ -906,17 +933,17 @@ class IO # :nodoc:
|
|
906
933
|
# counts from the end of the data (_offset_ should be negative here). If
|
907
934
|
# _whence_ is IO::SEEK_CUR, _offset_ is relative to the current position.
|
908
935
|
#
|
909
|
-
# As a side effect, the internal read and write buffers are flushed
|
936
|
+
# As a side effect, the internal read and write buffers are flushed except
|
937
|
+
# when seeking relative to the current position (whence is IO::SEEK_CUR) to
|
938
|
+
# a location within the internal read buffer.
|
910
939
|
#
|
911
940
|
# Raises IOError if #closed? returns +true+. Raises Errno::ESPIPE unless
|
912
941
|
# #seekable? returns +true+.
|
913
942
|
#
|
914
|
-
# NOTE
|
915
|
-
# (when the internal write buffer is not empty), it will
|
916
|
-
# errors and block at the same times as those functions.
|
943
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_seek and
|
944
|
+
# #unbuffered_write (when the internal write buffer is not empty), it will
|
945
|
+
# also raise the same errors and block at the same times as those functions.
|
917
946
|
def seek(offset, whence = IO::SEEK_SET)
|
918
|
-
raise IOError, 'closed stream' if closed?
|
919
|
-
|
920
947
|
buffered_seek(offset, whence)
|
921
948
|
0
|
922
949
|
end
|
@@ -924,14 +951,14 @@ class IO # :nodoc:
|
|
924
951
|
# call-seq:
|
925
952
|
# ios.seekable? -> true or false
|
926
953
|
#
|
927
|
-
# Returns +true+ if the stream is
|
954
|
+
# Returns +true+ if the stream is seekable, +false+ otherwise.
|
928
955
|
#
|
929
|
-
# This implementation
|
930
|
-
# is defined in order to make its
|
931
|
-
#
|
932
|
-
# always be seekable.
|
956
|
+
# This implementation always returns +false+ for duplexed objects and
|
957
|
+
# checks to see if #unbuffered_seek is defined in order to make its
|
958
|
+
# determination otherwise. Override this if the implementing class always
|
959
|
+
# provides the #unbuffered_seek method but may not always be seekable.
|
933
960
|
def seekable?
|
934
|
-
!
|
961
|
+
! duplexed? && respond_to?(:unbuffered_seek, true)
|
935
962
|
end
|
936
963
|
|
937
964
|
# call-seq:
|
@@ -940,9 +967,9 @@ class IO # :nodoc:
|
|
940
967
|
# Returns true if the internal write buffer is currently being bypassed,
|
941
968
|
# false otherwise.
|
942
969
|
#
|
943
|
-
# Raises IOError if #
|
970
|
+
# Raises IOError if #closed? returns +true+.
|
944
971
|
def sync
|
945
|
-
raise IOError, 'closed stream' if
|
972
|
+
raise IOError, 'closed stream' if closed?
|
946
973
|
@__io_like__sync ||= false
|
947
974
|
end
|
948
975
|
|
@@ -954,10 +981,10 @@ class IO # :nodoc:
|
|
954
981
|
# operation. When set to +false+, the internal write buffer will be
|
955
982
|
# enabled.
|
956
983
|
#
|
957
|
-
# Raises IOError if #
|
984
|
+
# Raises IOError if #closed? returns +true+.
|
958
985
|
def sync=(sync)
|
959
|
-
raise IOError, 'closed stream' if
|
960
|
-
@__io_like__sync = sync
|
986
|
+
raise IOError, 'closed stream' if closed?
|
987
|
+
@__io_like__sync = sync ? true : false
|
961
988
|
end
|
962
989
|
|
963
990
|
# call-seq:
|
@@ -971,38 +998,42 @@ class IO # :nodoc:
|
|
971
998
|
#
|
972
999
|
# Raises EOFError if reading begins at the end of the stream. Raises
|
973
1000
|
# IOError if the internal read buffer is not empty. Raises IOError if
|
974
|
-
# #
|
1001
|
+
# #closed? returns +true+.
|
975
1002
|
#
|
976
|
-
# NOTE
|
977
|
-
# the same errors and block at the same times as that function.
|
1003
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_read, it will also
|
1004
|
+
# raise the same errors and block at the same times as that function.
|
978
1005
|
def sysread(length, buffer = nil)
|
979
|
-
buffer = ''
|
980
|
-
buffer.slice!(0..-1)
|
1006
|
+
buffer = buffer.nil? ? '' : buffer.to_str
|
1007
|
+
buffer.slice!(0..-1) unless buffer.empty?
|
981
1008
|
return buffer if length == 0
|
982
1009
|
|
983
|
-
raise IOError, 'closed stream' if
|
1010
|
+
raise IOError, 'closed stream' if closed?
|
984
1011
|
raise IOError, 'not opened for reading' unless readable?
|
985
1012
|
unless internal_read_buffer.empty? then
|
986
1013
|
raise IOError, 'sysread on buffered IO'
|
987
1014
|
end
|
988
1015
|
|
1016
|
+
# Flush the internal write buffer for writable, non-duplexed objects.
|
1017
|
+
buffered_flush if writable? && ! duplexed?
|
1018
|
+
|
989
1019
|
buffer << unbuffered_read(length)
|
990
1020
|
end
|
991
1021
|
|
992
1022
|
# call-seq:
|
993
|
-
# ios.sysseek(offset, whence) -> integer
|
1023
|
+
# ios.sysseek(offset[, whence]) -> integer
|
994
1024
|
#
|
995
|
-
# Sets the data
|
996
|
-
#
|
1025
|
+
# Sets the current data position to _offset_ based on the setting of
|
1026
|
+
# _whence_. If _whence_ is unspecified or IO::SEEK_SET, _offset_ counts
|
1027
|
+
# from the beginning of the data. If _whence_ is IO::SEEK_END, _offset_
|
1028
|
+
# counts from the end of the data (_offset_ should be negative here). If
|
1029
|
+
# _whence_ is IO::SEEK_CUR, _offset_ is relative to the current position.
|
997
1030
|
#
|
998
1031
|
# Raises IOError if the internal read buffer is not empty. Raises IOError
|
999
|
-
# if #closed? returns +true+.
|
1032
|
+
# if #closed? returns +true+. Raises Errno::ESPIPE unless #seekable?
|
1033
|
+
# returns +true+.
|
1000
1034
|
#
|
1001
|
-
#
|
1002
|
-
#
|
1003
|
-
#
|
1004
|
-
# NOTE: Because this method relies on #unbuffered_seek, it will also raise
|
1005
|
-
# the same errors and block at the same times as that function.
|
1035
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_seek, it will also
|
1036
|
+
# raise the same errors and block at the same times as that function.
|
1006
1037
|
def sysseek(offset, whence = IO::SEEK_SET)
|
1007
1038
|
raise IOError, 'closed stream' if closed?
|
1008
1039
|
raise Errno::ESPIPE, 'Illegal seek' unless seekable?
|
@@ -1010,6 +1041,7 @@ class IO # :nodoc:
|
|
1010
1041
|
unless internal_write_buffer.empty? then
|
1011
1042
|
warn('warning: sysseek on buffered IO')
|
1012
1043
|
end
|
1044
|
+
|
1013
1045
|
unbuffered_seek(offset, whence)
|
1014
1046
|
end
|
1015
1047
|
|
@@ -1022,46 +1054,27 @@ class IO # :nodoc:
|
|
1022
1054
|
# As a side effect for non-duplex objects, the internal read buffer is
|
1023
1055
|
# flushed.
|
1024
1056
|
#
|
1025
|
-
# Raises IOError if #
|
1057
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
1026
1058
|
# #writable? returns +true+.
|
1027
1059
|
#
|
1028
|
-
# NOTE
|
1029
|
-
# the same errors and block at the same times as that function.
|
1060
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_write, it will also
|
1061
|
+
# raise the same errors and block at the same times as that function.
|
1030
1062
|
def syswrite(string)
|
1031
|
-
raise IOError, 'closed stream' if
|
1063
|
+
raise IOError, 'closed stream' if closed?
|
1032
1064
|
raise IOError, 'not opened for writing' unless writable?
|
1033
|
-
unless duplexed? || internal_read_buffer.empty? then
|
1034
|
-
internal_read_buffer.slice(0..-1)
|
1035
|
-
end
|
1036
1065
|
unless internal_write_buffer.empty? then
|
1037
1066
|
warn('warning: syswrite on buffered IO')
|
1038
1067
|
end
|
1039
1068
|
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
# Returns the current offest of ios.
|
1047
|
-
#
|
1048
|
-
# Raises IOError if #closed? returns +true+. Raises Errno::ESPIPE unless
|
1049
|
-
# #seekable? returns +true+.
|
1050
|
-
#
|
1051
|
-
# As a side effect, the internal write buffer is flushed unless this is
|
1052
|
-
# a duplexed object. This is for compatibility with the behavior of
|
1053
|
-
# IO#tell.
|
1054
|
-
#
|
1055
|
-
# NOTE: Because this method relies on #unbuffered_seek and #unbuffered_write
|
1056
|
-
# (when the internal write buffer is not empty), it will also raise the same
|
1057
|
-
# errors and block at the same times as those functions.
|
1058
|
-
def tell
|
1059
|
-
raise IOError, 'closed stream' if closed?
|
1069
|
+
# Flush the internal read buffer and set the unbuffered position to the
|
1070
|
+
# 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)
|
1074
|
+
end
|
1060
1075
|
|
1061
|
-
|
1062
|
-
buffered_tell
|
1076
|
+
unbuffered_write(string)
|
1063
1077
|
end
|
1064
|
-
alias :pos :tell
|
1065
1078
|
|
1066
1079
|
# call-seq:
|
1067
1080
|
# ios.to_io -> ios
|
@@ -1076,7 +1089,7 @@ class IO # :nodoc:
|
|
1076
1089
|
#
|
1077
1090
|
# Calls #unread with <tt>integer.chr</tt> as an argument.
|
1078
1091
|
#
|
1079
|
-
# Raises IOError if #
|
1092
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
1080
1093
|
# #readable? returns +true+.
|
1081
1094
|
def ungetc(integer)
|
1082
1095
|
unread(integer.chr)
|
@@ -1089,12 +1102,12 @@ class IO # :nodoc:
|
|
1089
1102
|
# returns +nil+. If _string_ is not a String, it is converted to one using
|
1090
1103
|
# its +to_s+ method.
|
1091
1104
|
#
|
1092
|
-
# Raises IOError if #
|
1105
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
1093
1106
|
# #readable? returns +true+.
|
1094
1107
|
def unread(string)
|
1095
|
-
raise IOError, 'closed stream' if
|
1108
|
+
raise IOError, 'closed stream' if closed?
|
1096
1109
|
raise IOError, 'not opened for reading' unless readable?
|
1097
|
-
internal_read_buffer.insert(0,
|
1110
|
+
internal_read_buffer.insert(0, string.to_s)
|
1098
1111
|
nil
|
1099
1112
|
end
|
1100
1113
|
|
@@ -1107,7 +1120,7 @@ class IO # :nodoc:
|
|
1107
1120
|
# This default implementation of #write_ready? is a hack which should be
|
1108
1121
|
# able to work for both real IO objects and IO-like objects; however, it is
|
1109
1122
|
# inefficient since it merely sleeps for 1 second and then returns +true+ as
|
1110
|
-
# long as #
|
1123
|
+
# long as #closed? returns +false+. IO.select should be used for real
|
1111
1124
|
# IO objects to wait for a writeable condition on platforms with support for
|
1112
1125
|
# IO.select. Other solutions should be found as necessary to improve this
|
1113
1126
|
# implementation on a case by case basis.
|
@@ -1124,12 +1137,12 @@ class IO # :nodoc:
|
|
1124
1137
|
#
|
1125
1138
|
# Returns +true+ if the stream is both open and writable, +false+ otherwise.
|
1126
1139
|
#
|
1127
|
-
# This implementation
|
1128
|
-
#
|
1129
|
-
#
|
1130
|
-
#
|
1140
|
+
# This implementation checks to see if #unbuffered_write is defined in order
|
1141
|
+
# to make its determination. Override this if the implementing class always
|
1142
|
+
# provides the #unbuffered_write method but may not always be open in a
|
1143
|
+
# writable mode.
|
1131
1144
|
def writable?
|
1132
|
-
!
|
1145
|
+
! @__io_like__closed_write && respond_to?(:unbuffered_write, true)
|
1133
1146
|
end
|
1134
1147
|
|
1135
1148
|
# call-seq:
|
@@ -1140,18 +1153,18 @@ class IO # :nodoc:
|
|
1140
1153
|
# convert it into one. The entire contents of _string_ are written,
|
1141
1154
|
# blocking as necessary even if the data stream does not block.
|
1142
1155
|
#
|
1143
|
-
# Raises IOError if #
|
1156
|
+
# Raises IOError if #closed? returns +true+. Raises IOError unless
|
1144
1157
|
# #writable? returns +true+.
|
1145
1158
|
#
|
1146
|
-
# NOTE
|
1159
|
+
# <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
|
1147
1160
|
# #unbuffered_write. Therefore, this method always blocks if unable to
|
1148
1161
|
# immediately write _string_ completely. Aside from that exception, this
|
1149
1162
|
# method will also raise the same errors and block at the same times as
|
1150
1163
|
# #unbuffered_write.
|
1151
1164
|
def write(string)
|
1152
|
-
raise IOError, 'closed stream' if closed_write?
|
1153
|
-
|
1154
1165
|
string = string.to_s
|
1166
|
+
return 0 if string.empty?
|
1167
|
+
|
1155
1168
|
bytes_written = 0
|
1156
1169
|
while bytes_written < string.length do
|
1157
1170
|
begin
|
@@ -1172,10 +1185,11 @@ class IO # :nodoc:
|
|
1172
1185
|
#
|
1173
1186
|
# Raises IOError unless #writable? returns +true+.
|
1174
1187
|
#
|
1175
|
-
# NOTE
|
1176
|
-
# errors raised by #unbuffered_write and blocks when #unbuffered_write
|
1188
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_write, it raises
|
1189
|
+
# all errors raised by #unbuffered_write and blocks when #unbuffered_write
|
1177
1190
|
# blocks.
|
1178
|
-
def buffered_flush
|
1191
|
+
def buffered_flush
|
1192
|
+
raise IOError, 'closed stream' if closed?
|
1179
1193
|
raise IOError, 'not opened for writing' unless writable?
|
1180
1194
|
|
1181
1195
|
until internal_write_buffer.empty? do
|
@@ -1193,17 +1207,18 @@ class IO # :nodoc:
|
|
1193
1207
|
# Raises EOFError if the internal read buffer is empty and reading begins at
|
1194
1208
|
# the end of the stream. Raises IOError unless #readable? returns +true+.
|
1195
1209
|
#
|
1196
|
-
# NOTE
|
1197
|
-
# raised by #unbuffered_read and blocks when #unbuffered_read blocks
|
1210
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_read, it raises all
|
1211
|
+
# errors raised by #unbuffered_read and blocks when #unbuffered_read blocks
|
1198
1212
|
# whenever the internal read buffer is unable to fulfill the request.
|
1199
|
-
def buffered_read(length)
|
1213
|
+
def buffered_read(length)
|
1200
1214
|
# Check the validity of the method arguments.
|
1201
1215
|
raise ArgumentError, "non-positive length #{length} given" if length < 0
|
1202
1216
|
|
1217
|
+
raise IOError, 'closed stream' if closed?
|
1203
1218
|
raise IOError, 'not opened for reading' unless readable?
|
1204
1219
|
|
1205
|
-
# Flush the internal write buffer for non-duplexed objects.
|
1206
|
-
buffered_flush
|
1220
|
+
# Flush the internal write buffer for writable, non-duplexed objects.
|
1221
|
+
buffered_flush if writable? && ! duplexed?
|
1207
1222
|
|
1208
1223
|
# Ensure that the internal read buffer has at least enough data to satisfy
|
1209
1224
|
# the request.
|
@@ -1228,41 +1243,57 @@ class IO # :nodoc:
|
|
1228
1243
|
# call-seq:
|
1229
1244
|
# ios.buffered_seek(offset[, whence]) -> integer
|
1230
1245
|
#
|
1231
|
-
# Sets the
|
1232
|
-
# _whence_
|
1246
|
+
# Sets the current data position to _offset_ based on the setting of
|
1247
|
+
# _whence_. If _whence_ is unspecified or IO::SEEK_SET, _offset_ counts
|
1248
|
+
# from the beginning of the data. If _whence_ is IO::SEEK_END, _offset_
|
1249
|
+
# counts from the end of the data (_offset_ should be negative here). If
|
1250
|
+
# _whence_ is IO::SEEK_CUR, _offset_ is relative to the current position.
|
1233
1251
|
#
|
1234
|
-
# As a side effect, the internal read and write buffers are flushed
|
1252
|
+
# As a side effect, the internal read and write buffers are flushed except
|
1253
|
+
# when seeking relative to the current position (whence is IO::SEEK_CUR) to
|
1254
|
+
# a location within the internal read buffer.
|
1235
1255
|
#
|
1236
1256
|
# Raises Errno::ESPIPE unless #seekable? returns +true+.
|
1237
1257
|
#
|
1238
1258
|
# See #seek for the usage of _offset_ and _whence_.
|
1239
1259
|
#
|
1240
|
-
# NOTE
|
1241
|
-
# (when the internal write buffer is not empty), it will
|
1242
|
-
# errors and block at the same times as those functions.
|
1243
|
-
def buffered_seek(offset, whence = IO::SEEK_SET)
|
1244
|
-
raise
|
1245
|
-
|
1246
|
-
# Flush the internal buffers.
|
1247
|
-
internal_read_buffer.slice!(0..-1)
|
1248
|
-
buffered_flush unless internal_write_buffer.empty?
|
1249
|
-
# Move the data stream's position as requested.
|
1250
|
-
unbuffered_seek(offset, whence)
|
1251
|
-
end
|
1252
|
-
|
1253
|
-
# call-seq:
|
1254
|
-
# ios.buffered_tell
|
1255
|
-
#
|
1256
|
-
# Returns the current position in the stream.
|
1257
|
-
#
|
1258
|
-
# Raises Errno::ESPIPE unless #seekable? returns +true+.
|
1259
|
-
def buffered_tell # :nodoc:
|
1260
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_seek and
|
1261
|
+
# #unbuffered_write (when the internal write buffer is not empty), it will
|
1262
|
+
# raise the same errors and block at the same times as those functions.
|
1263
|
+
def buffered_seek(offset, whence = IO::SEEK_SET)
|
1264
|
+
raise IOError, 'closed stream' if closed?
|
1260
1265
|
raise Errno::ESPIPE, 'Illegal seek' unless seekable?
|
1261
1266
|
|
1262
|
-
|
1267
|
+
if whence == IO::SEEK_CUR && offset == 0 then
|
1268
|
+
# The seek is only determining the current position, so return the
|
1269
|
+
# buffered position based on the read buffer if it's not empty and the
|
1270
|
+
# 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
|
1274
|
+
elsif whence == IO::SEEK_CUR && offset > 0 &&
|
1275
|
+
internal_write_buffer.empty? &&
|
1276
|
+
offset <= internal_read_buffer.length then
|
1277
|
+
# The seek is within the read buffer, so just discard a sufficient
|
1278
|
+
# amount of the buffer and report the new buffered position.
|
1279
|
+
internal_read_buffer.slice!(0, offset)
|
1263
1280
|
unbuffered_seek(0, IO::SEEK_CUR) - internal_read_buffer.length
|
1264
1281
|
else
|
1265
|
-
|
1282
|
+
# The seek target is outside of the buffers, so flush the buffers and
|
1283
|
+
# jump to the new position.
|
1284
|
+
if whence == IO::SEEK_CUR then
|
1285
|
+
# 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
|
1289
|
+
end
|
1290
|
+
|
1291
|
+
# Flush the internal buffers.
|
1292
|
+
internal_read_buffer.slice!(0..-1)
|
1293
|
+
buffered_flush if writable?
|
1294
|
+
|
1295
|
+
# Move the data stream's position as requested.
|
1296
|
+
unbuffered_seek(offset, whence)
|
1266
1297
|
end
|
1267
1298
|
end
|
1268
1299
|
|
@@ -1276,16 +1307,17 @@ class IO # :nodoc:
|
|
1276
1307
|
# the internal write buffer cannot be immediately flushed due to the
|
1277
1308
|
# underlying stream not blocking when unable to accept more data.
|
1278
1309
|
#
|
1279
|
-
# NOTE
|
1280
|
-
# errors raised by #unbuffered_write and blocks when #unbuffered_write
|
1310
|
+
# <b>NOTE:</b> Because this method relies on #unbuffered_write, it raises
|
1311
|
+
# all errors raised by #unbuffered_write and blocks when #unbuffered_write
|
1281
1312
|
# blocks whenever the internal write buffer is unable to fulfill the
|
1282
1313
|
# request.
|
1283
|
-
def buffered_write(string)
|
1314
|
+
def buffered_write(string)
|
1315
|
+
raise IOError, 'closed stream' if closed?
|
1284
1316
|
raise IOError, 'not opened for writing' unless writable?
|
1285
1317
|
|
1286
1318
|
# Flush the internal read buffer and set the unbuffered position to the
|
1287
1319
|
# buffered position when dealing with non-duplexed objects.
|
1288
|
-
|
1320
|
+
unless duplexed? || internal_read_buffer.empty? then
|
1289
1321
|
unbuffered_seek(-internal_read_buffer.length, IO::SEEK_CUR)
|
1290
1322
|
internal_read_buffer.slice!(0..-1)
|
1291
1323
|
end
|
@@ -1315,14 +1347,58 @@ class IO # :nodoc:
|
|
1315
1347
|
end
|
1316
1348
|
|
1317
1349
|
# Returns a reference to the internal read buffer.
|
1318
|
-
def internal_read_buffer
|
1350
|
+
def internal_read_buffer
|
1319
1351
|
@__io_like__read_buffer ||= ''
|
1320
1352
|
end
|
1321
1353
|
|
1322
1354
|
# Returns a reference to the internal write buffer.
|
1323
|
-
def internal_write_buffer
|
1355
|
+
def internal_write_buffer
|
1324
1356
|
@__io_like__write_buffer ||= ''
|
1325
1357
|
end
|
1358
|
+
|
1359
|
+
# This method joins the elements of _array_ together with _separator_
|
1360
|
+
# between each element and returns the result. _seen_ is a list of object
|
1361
|
+
# IDs representing arrays which have already started processing.
|
1362
|
+
#
|
1363
|
+
# This method exists only because Array#join apparently behaves in an
|
1364
|
+
# implementation dependent manner when joining recursive arrays and so does
|
1365
|
+
# not always produce the expected results. Specifically, MRI 1.8.6 and
|
1366
|
+
# 1.8.7 behave as follows:
|
1367
|
+
#
|
1368
|
+
# x = []
|
1369
|
+
# x << 1 << x << 2
|
1370
|
+
# x.join(', ') => "1, 1, [...], 2, 2"
|
1371
|
+
#
|
1372
|
+
# The expected and necessary result for use with #puts is:
|
1373
|
+
#
|
1374
|
+
# "1, [...], 2"
|
1375
|
+
#
|
1376
|
+
# Things get progressively worse as the nesting and recursion become more
|
1377
|
+
# convoluted.
|
1378
|
+
def array_join(array, separator, seen = [])
|
1379
|
+
first = true
|
1380
|
+
seen.push(array.object_id)
|
1381
|
+
result = array.inject('') do |memo, item|
|
1382
|
+
if first then
|
1383
|
+
first = false
|
1384
|
+
else
|
1385
|
+
memo << separator
|
1386
|
+
end
|
1387
|
+
|
1388
|
+
memo << if item.kind_of?(Array) then
|
1389
|
+
if seen.include?(item.object_id) then
|
1390
|
+
'[...]'
|
1391
|
+
else
|
1392
|
+
array_join(item, separator, seen)
|
1393
|
+
end
|
1394
|
+
else
|
1395
|
+
item.to_s
|
1396
|
+
end
|
1397
|
+
end
|
1398
|
+
seen.pop
|
1399
|
+
|
1400
|
+
result
|
1401
|
+
end
|
1326
1402
|
end
|
1327
1403
|
end
|
1328
1404
|
|