io-like 0.1.0 → 0.2.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.
- 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
|
|