rubysl-stringio 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/rubysl/stringio.rb +2 -0
  9. data/lib/rubysl/stringio/stringio.rb +611 -0
  10. data/lib/rubysl/stringio/version.rb +5 -0
  11. data/lib/stringio.rb +1 -0
  12. data/rubysl-stringio.gemspec +24 -0
  13. data/spec/append_spec.rb +83 -0
  14. data/spec/binmode_spec.rb +8 -0
  15. data/spec/bytes_spec.rb +12 -0
  16. data/spec/chars_spec.rb +12 -0
  17. data/spec/close_read_spec.rb +30 -0
  18. data/spec/close_spec.rb +22 -0
  19. data/spec/close_write_spec.rb +30 -0
  20. data/spec/closed_read_spec.rb +11 -0
  21. data/spec/closed_spec.rb +15 -0
  22. data/spec/closed_write_spec.rb +11 -0
  23. data/spec/codepoints_spec.rb +11 -0
  24. data/spec/each_byte_spec.rb +10 -0
  25. data/spec/each_char_spec.rb +12 -0
  26. data/spec/each_codepoint_spec.rb +12 -0
  27. data/spec/each_line_spec.rb +14 -0
  28. data/spec/each_spec.rb +14 -0
  29. data/spec/eof_spec.rb +10 -0
  30. data/spec/external_encoding_spec.rb +12 -0
  31. data/spec/fcntl_spec.rb +7 -0
  32. data/spec/fileno_spec.rb +8 -0
  33. data/spec/fixtures/classes.rb +15 -0
  34. data/spec/flush_spec.rb +8 -0
  35. data/spec/fsync_spec.rb +8 -0
  36. data/spec/getbyte_spec.rb +25 -0
  37. data/spec/getc_spec.rb +31 -0
  38. data/spec/gets_spec.rb +245 -0
  39. data/spec/initialize_copy_spec.rb +95 -0
  40. data/spec/initialize_spec.rb +193 -0
  41. data/spec/internal_encoding_spec.rb +12 -0
  42. data/spec/isatty_spec.rb +6 -0
  43. data/spec/length_spec.rb +6 -0
  44. data/spec/lineno_spec.rb +29 -0
  45. data/spec/lines_spec.rb +16 -0
  46. data/spec/open_spec.rb +215 -0
  47. data/spec/path_spec.rb +15 -0
  48. data/spec/pid_spec.rb +7 -0
  49. data/spec/pos_spec.rb +27 -0
  50. data/spec/print_spec.rb +113 -0
  51. data/spec/printf_spec.rb +60 -0
  52. data/spec/putc_spec.rb +105 -0
  53. data/spec/puts_spec.rb +173 -0
  54. data/spec/read_nonblock_spec.rb +29 -0
  55. data/spec/read_spec.rb +62 -0
  56. data/spec/readbyte_spec.rb +21 -0
  57. data/spec/readchar_spec.rb +19 -0
  58. data/spec/readline_spec.rb +127 -0
  59. data/spec/readlines_spec.rb +124 -0
  60. data/spec/readpartial_spec.rb +29 -0
  61. data/spec/reopen_spec.rb +303 -0
  62. data/spec/rewind_spec.rb +23 -0
  63. data/spec/seek_spec.rb +75 -0
  64. data/spec/set_encoding_spec.rb +34 -0
  65. data/spec/shared/codepoints.rb +45 -0
  66. data/spec/shared/each.rb +162 -0
  67. data/spec/shared/each_byte.rb +60 -0
  68. data/spec/shared/each_char.rb +50 -0
  69. data/spec/shared/eof.rb +24 -0
  70. data/spec/shared/getc.rb +43 -0
  71. data/spec/shared/isatty.rb +5 -0
  72. data/spec/shared/length.rb +12 -0
  73. data/spec/shared/read.rb +186 -0
  74. data/spec/shared/readchar.rb +29 -0
  75. data/spec/shared/sysread.rb +27 -0
  76. data/spec/shared/tell.rb +12 -0
  77. data/spec/shared/write.rb +134 -0
  78. data/spec/size_spec.rb +6 -0
  79. data/spec/string_spec.rb +49 -0
  80. data/spec/stringio_spec.rb +8 -0
  81. data/spec/sync_spec.rb +18 -0
  82. data/spec/sysread_spec.rb +27 -0
  83. data/spec/syswrite_spec.rb +18 -0
  84. data/spec/tell_spec.rb +6 -0
  85. data/spec/truncate_spec.rb +69 -0
  86. data/spec/tty_spec.rb +6 -0
  87. data/spec/ungetbyte_spec.rb +88 -0
  88. data/spec/ungetc_spec.rb +98 -0
  89. data/spec/write_nonblock_spec.rb +20 -0
  90. data/spec/write_spec.rb +18 -0
  91. metadata +267 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f0e9dcf590f3bb0ca5bf669afb14bca85d488e1a
4
+ data.tar.gz: 7551574d3cb4596b9b8d8d2ae5f3ba0ff7f60d4e
5
+ SHA512:
6
+ metadata.gz: 06114a3723e28167f2ddca63309a9dccf8ccf6158be35a3ac4d8171e2ad5d86ef141d930427a24ddf782fb211e65f4df78c6442e15057f778be3b6ec6e038f88
7
+ data.tar.gz: 164566be1c5e2a2f94f44ee79b32f57f594bf5712d6845632f9468f76695baf3f1a19bedb77ea0a59669bb1f3fbfa2203b918cb8252662539624be8743c44fd2
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ env:
3
+ - RUBYLIB=lib
4
+ script: bundle exec mspec
5
+ rvm:
6
+ - 1.8.7
7
+ - rbx-nightly-18mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rubysl-stringio.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2013, Brian Shirai
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ 3. Neither the name of the library nor the names of its contributors may be
13
+ used to endorse or promote products derived from this software without
14
+ specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
20
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Rubysl::Stringio
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rubysl-stringio'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rubysl-stringio
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,2 @@
1
+ require "rubysl/stringio/version"
2
+ require "rubysl/stringio/stringio"
@@ -0,0 +1,611 @@
1
+ class StringIO
2
+
3
+ include Enumerable
4
+
5
+ DEFAULT_RECORD_SEPARATOR = "\n" unless defined?(::DEFAULT_RECORD_SEPARATOR)
6
+
7
+ # This is why we need undefined in Ruby
8
+ Undefined = Object.new
9
+
10
+ class Data
11
+ attr_accessor :string, :pos, :lineno
12
+
13
+ def initialize(string)
14
+ @string = string
15
+ @pos = @lineno = 0
16
+ end
17
+ end
18
+
19
+ def self.open(*args)
20
+ io = new(*args)
21
+ return io unless block_given?
22
+
23
+ begin
24
+ yield io
25
+ ensure
26
+ io.close
27
+ io.__data__.string = nil
28
+ self
29
+ end
30
+ end
31
+
32
+ attr_reader :__data__
33
+
34
+ def initialize(string="", mode=nil)
35
+ string = Rubinius::Type.coerce_to string, String, :to_str
36
+ @__data__ = Data.new string
37
+
38
+ if mode
39
+ if mode.is_a?(Integer)
40
+ mode_from_integer(mode)
41
+ else
42
+ mode = StringValue(mode)
43
+ mode_from_string(mode)
44
+ end
45
+ else
46
+ mode_from_string(string.frozen? ? "r" : "r+")
47
+ end
48
+
49
+ self
50
+ end
51
+
52
+ def initialize_copy(from)
53
+ from = Rubinius::Type.coerce_to(from, StringIO, :to_strio)
54
+
55
+ taint if from.tainted?
56
+
57
+ @append = from.instance_variable_get(:@append)
58
+ @readable = from.instance_variable_get(:@readable)
59
+ @writable = from.instance_variable_get(:@writable)
60
+ @__data__ = from.instance_variable_get(:@__data__)
61
+
62
+ self
63
+ end
64
+
65
+ def check_readable
66
+ raise IOError, "not opened for reading" unless @readable
67
+ end
68
+
69
+ private :check_readable
70
+
71
+ def check_writable
72
+ raise IOError, "not opened for writing" unless @writable
73
+ raise IOError, "unable to modify data" if @__data__.string.frozen?
74
+ end
75
+
76
+ private :check_writable
77
+
78
+ def each_byte
79
+ return to_enum :each_byte unless block_given?
80
+ check_readable
81
+
82
+ d = @__data__
83
+ string = d.string
84
+
85
+ while d.pos < string.length
86
+ byte = string.getbyte d.pos
87
+ d.pos += 1
88
+ yield byte
89
+ end
90
+
91
+ self
92
+ end
93
+
94
+ alias_method :bytes, :each_byte
95
+
96
+ def each_char
97
+ return to_enum :each_char unless block_given?
98
+ if $KCODE == "UTF8"
99
+ lookup = 7.downto(4)
100
+ while c = read(1) do
101
+ n = c[0]
102
+ leftmost_zero_bit = lookup.find{|i| n[i].zero? }
103
+ case leftmost_zero_bit
104
+ when 7 # ASCII
105
+ yield c
106
+ when 6 # UTF 8 complementary characters
107
+ next # Encoding error, ignore
108
+ else
109
+ more = read(6-leftmost_zero_bit)
110
+ break unless more
111
+ yield c+more
112
+ end
113
+ end
114
+ else
115
+ while s = read(1)
116
+ yield s
117
+ end
118
+ end
119
+
120
+ self
121
+ end
122
+
123
+ alias_method :chars, :each_char
124
+
125
+ def each(sep = $/)
126
+ return to_enum :each, sep unless block_given?
127
+ check_readable
128
+
129
+ while line = getline(sep)
130
+ yield line
131
+ end
132
+
133
+ self
134
+ end
135
+
136
+ alias_method :each_line, :each
137
+ alias_method :lines, :each
138
+
139
+ def <<(str)
140
+ write(str)
141
+ self
142
+ end
143
+
144
+ def binmode
145
+ self
146
+ end
147
+
148
+ def write(str)
149
+ check_writable
150
+
151
+ str = String(str)
152
+
153
+ return 0 if str.empty?
154
+
155
+ d = @__data__
156
+ pos = d.pos
157
+ string = d.string
158
+
159
+ if @append || pos == string.length
160
+ string << str
161
+ d.pos = string.length
162
+ elsif pos > string.bytesize
163
+ string[string.bytesize..pos] = "\000" * (pos - string.bytesize)
164
+ string << str
165
+ d.pos = string.bytesize
166
+ else
167
+ string[pos, str.length] = str
168
+ d.pos += str.length
169
+ string.taint if str.tainted?
170
+ end
171
+
172
+ return str.length
173
+ end
174
+ alias_method :syswrite, :write
175
+
176
+ def close
177
+ raise IOError, "closed stream" if closed?
178
+ @readable = @writable = nil
179
+ end
180
+
181
+ def closed?
182
+ !@readable && !@writable
183
+ end
184
+
185
+ def close_read
186
+ check_readable
187
+ @readable = nil
188
+ end
189
+
190
+ def closed_read?
191
+ !@readable
192
+ end
193
+
194
+ def close_write
195
+ check_writable
196
+ @writable = nil
197
+ end
198
+
199
+ def closed_write?
200
+ !@writable
201
+ end
202
+
203
+ def eof?
204
+ d = @__data__
205
+ d.pos >= d.string.bytesize
206
+ end
207
+ alias_method :eof, :eof?
208
+
209
+ def fcntl
210
+ raise NotImplementedError, "StringIO#fcntl is not implemented"
211
+ end
212
+
213
+ def fileno
214
+ nil
215
+ end
216
+
217
+ def flush
218
+ self
219
+ end
220
+
221
+ def fsync
222
+ 0
223
+ end
224
+
225
+ def getc
226
+ check_readable
227
+ d = @__data__
228
+
229
+ char = d.string[d.pos]
230
+ d.pos += 1 unless eof?
231
+ char
232
+ end
233
+
234
+ def getbyte
235
+ check_readable
236
+ d = @__data__
237
+
238
+ return nil if eof?
239
+
240
+ byte = d.string.getbyte(d.pos)
241
+ d.pos += 1
242
+ byte
243
+ end
244
+
245
+ def gets(sep = $/)
246
+ check_readable
247
+
248
+ $_ = getline(sep)
249
+ end
250
+
251
+ def isatty
252
+ false
253
+ end
254
+ alias_method :tty?, :isatty
255
+
256
+ def length
257
+ @string.length
258
+ end
259
+ alias_method :size, :length
260
+
261
+ def lineno
262
+ @__data__.lineno
263
+ end
264
+
265
+ def lineno=(line)
266
+ @__data__.lineno = line
267
+ end
268
+
269
+ def path
270
+ nil
271
+ end
272
+
273
+ def pid
274
+ nil
275
+ end
276
+
277
+ def pos
278
+ @__data__.pos
279
+ end
280
+
281
+ def pos=(pos)
282
+ raise Errno::EINVAL if pos < 0
283
+ @__data__.pos = pos
284
+ end
285
+
286
+ def print(*args)
287
+ check_writable
288
+ args << $_ if args.empty?
289
+ args.map! { |x| x.nil? ? "nil" : x }
290
+ write((args << $\).flatten.join)
291
+ nil
292
+ end
293
+
294
+ def printf(*args)
295
+ check_writable
296
+
297
+ if args.size > 1
298
+ write(args.shift % args)
299
+ else
300
+ write(args.first)
301
+ end
302
+
303
+ nil
304
+ end
305
+
306
+ def putc(obj)
307
+ check_writable
308
+
309
+ if obj.is_a?(String)
310
+ char = obj[0]
311
+ else
312
+ char = Rubinius::Type.coerce_to obj, Integer, :to_int
313
+ end
314
+
315
+ d = @__data__
316
+ pos = d.pos
317
+ string = d.string
318
+
319
+ if @append || pos == string.length
320
+ string << char
321
+ d.pos = string.length
322
+ elsif pos > string.length
323
+ string[string.length..pos] = "\000" * (pos - string.length)
324
+ string << char
325
+ d.pos = string.length
326
+ else
327
+ string[pos] = char
328
+ d.pos += 1
329
+ end
330
+
331
+ obj
332
+ end
333
+
334
+ def puts(*args)
335
+ if args.empty?
336
+ write(DEFAULT_RECORD_SEPARATOR)
337
+ else
338
+ args.each do |arg|
339
+ if arg.nil?
340
+ line = "nil"
341
+ elsif Thread.guarding? arg
342
+ line = "[...]"
343
+ else
344
+ begin
345
+ arg = Rubinius::Type.coerce_to(arg, Array, :to_ary)
346
+ Thread.recursion_guard arg do
347
+ arg.each { |a| puts a }
348
+ end
349
+ next
350
+ rescue
351
+ line = arg.to_s
352
+ end
353
+ end
354
+
355
+ write(line)
356
+ write(DEFAULT_RECORD_SEPARATOR) unless line[-1] == ?\n
357
+ end
358
+ end
359
+
360
+ nil
361
+ end
362
+
363
+ def read(length = nil, buffer = "")
364
+ check_readable
365
+ d = @__data__
366
+ pos = d.pos
367
+ string = d.string
368
+
369
+ buffer = StringValue(buffer)
370
+
371
+ if length
372
+ return nil if eof?
373
+ length = Rubinius::Type.coerce_to length, Integer, :to_int
374
+ raise ArgumentError if length < 0
375
+ buffer.replace(string[pos, length])
376
+ d.pos += buffer.length
377
+ else
378
+ return "" if eof?
379
+ buffer.replace(string[pos..-1])
380
+ d.pos = string.size
381
+ end
382
+
383
+ return buffer
384
+ end
385
+
386
+ def readchar
387
+ raise IO::EOFError, "end of file reached" if eof?
388
+ getc
389
+ end
390
+
391
+ alias_method :readbyte, :readchar
392
+
393
+ def readline(sep=$/)
394
+ raise IO::EOFError, "end of file reached" if eof?
395
+ check_readable
396
+
397
+ $_ = getline(sep)
398
+ end
399
+
400
+ def readlines(sep=$/)
401
+ check_readable
402
+
403
+ ary = []
404
+ while line = getline(sep)
405
+ ary << line
406
+ end
407
+
408
+ ary
409
+ end
410
+
411
+ def reopen(string=nil, mode=Undefined)
412
+ if string and not string.kind_of? String and mode.equal? Undefined
413
+ stringio = Rubinius::Type.coerce_to(string, StringIO, :to_strio)
414
+
415
+ taint if stringio.tainted?
416
+ initialize_copy stringio
417
+ else
418
+ mode = nil if mode.equal? Undefined
419
+ string = "" unless string
420
+
421
+ initialize string, mode
422
+ end
423
+
424
+ self
425
+ end
426
+
427
+ def rewind
428
+ d = @__data__
429
+ d.pos = d.lineno = 0
430
+ end
431
+
432
+ def seek(to, whence = IO::SEEK_SET)
433
+ raise IOError, "closed stream" if self.closed?
434
+ to = Rubinius::Type.coerce_to to, Integer, :to_int
435
+
436
+ case whence
437
+ when IO::SEEK_CUR
438
+ to += @__data__.pos
439
+ when IO::SEEK_END
440
+ to += @__data__.string.size
441
+ when IO::SEEK_SET, nil
442
+ else
443
+ raise Errno::EINVAL, "invalid whence"
444
+ end
445
+
446
+ raise Errno::EINVAL if to < 0
447
+
448
+ @__data__.pos = to
449
+
450
+ return 0
451
+ end
452
+
453
+ def size
454
+ @__data__.string.bytesize
455
+ end
456
+ alias_method :length, :size
457
+
458
+ def string
459
+ @__data__.string
460
+ end
461
+
462
+ def string=(string)
463
+ d = @__data__
464
+ d.string = StringValue(string)
465
+ d.pos = 0
466
+ d.lineno = 0
467
+ end
468
+
469
+ def sync
470
+ true
471
+ end
472
+
473
+ def sync=(val)
474
+ val
475
+ end
476
+
477
+ def sysread(length=nil, buffer="")
478
+ str = read(length, buffer)
479
+ raise IO::EOFError, "end of file reached" if str.nil?
480
+ str
481
+ end
482
+
483
+ def tell
484
+ @__data__.pos
485
+ end
486
+
487
+ def truncate(length)
488
+ check_writable
489
+ len = Rubinius::Type.coerce_to length, Integer, :to_int
490
+ raise Errno::EINVAL, "negative length" if len < 0
491
+ string = @__data__.string
492
+
493
+ if len < string.size
494
+ string[len..string.size] = ""
495
+ else
496
+ string << "\000" * (len - string.size)
497
+ end
498
+ return length
499
+ end
500
+
501
+ def ungetc(char)
502
+ check_readable
503
+
504
+ d = @__data__
505
+ pos = d.pos
506
+ string = d.string
507
+
508
+ char = Rubinius::Type.coerce_to char, Integer, :to_int
509
+
510
+ if pos > string.bytesize
511
+ string[string.bytesize..pos] = "\000" * (pos - string.bytesize)
512
+ d.pos -= 1
513
+ string[d.pos] = char
514
+ elsif pos > 0
515
+ d.pos -= 1
516
+ string[d.pos] = char
517
+ end
518
+
519
+ nil
520
+ end
521
+
522
+ def to_yaml_properties
523
+ []
524
+ end
525
+
526
+ def yaml_initialize(type, val)
527
+ @__data__ = Data.new("")
528
+ end
529
+
530
+ protected
531
+
532
+ def mode_from_string(mode)
533
+ @append = truncate = false
534
+
535
+ if mode[0] == ?r
536
+ @readable = true
537
+ @writable = mode[-1] == ?+ ? true : false
538
+ end
539
+
540
+ if mode[0] == ?w
541
+ @writable = truncate = true
542
+ @readable = mode[-1] == ?+ ? true : false
543
+ end
544
+
545
+ if mode[0] == ?a
546
+ @append = @writable = true
547
+ @readable = mode[-1] == ?+ ? true : false
548
+ end
549
+
550
+ d = @__data__
551
+ raise Errno::EACCES, "Permission denied" if @writable && d.string.frozen?
552
+ d.string.replace("") if truncate
553
+ end
554
+
555
+ def mode_from_integer(mode)
556
+ @readable = @writable = @append = false
557
+ d = @__data__
558
+
559
+ if mode == 0 or mode & IO::RDWR != 0
560
+ @readable = true
561
+ end
562
+
563
+ if mode & (IO::WRONLY | IO::RDWR) != 0
564
+ raise Errno::EACCES, "Permission denied" if d.string.frozen?
565
+ @writable = true
566
+ end
567
+
568
+ @append = true if (mode & IO::APPEND) != 0
569
+ d.string.replace("") if (mode & IO::TRUNC) != 0
570
+ end
571
+
572
+ def getline(sep = $/)
573
+ sep = StringValue(sep) unless sep.nil?
574
+
575
+ return nil if eof?
576
+
577
+ d = @__data__
578
+ pos = d.pos
579
+ string = d.string
580
+
581
+ if sep.nil?
582
+ line = string[pos..-1]
583
+ d.pos = string.size
584
+ elsif sep.empty?
585
+ if stop = string.index("\n\n", pos)
586
+ stop += 2
587
+ line = string[pos...stop]
588
+ while string[stop] == ?\n
589
+ stop += 1
590
+ end
591
+ d.pos = stop
592
+ else
593
+ line = string[pos..-1]
594
+ d.pos = string.size
595
+ end
596
+ else
597
+ if stop = string.index(sep, pos)
598
+ stop += sep.length
599
+ line = string[pos...stop]
600
+ d.pos = stop
601
+ else
602
+ line = string[pos..-1]
603
+ d.pos = string.size
604
+ end
605
+ end
606
+
607
+ d.lineno += 1
608
+
609
+ return line
610
+ end
611
+ end