rubysl-stringio 2.0.0 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad4377f000371c4db7fcc555b58556ead4b61005
4
- data.tar.gz: 2928739f7801ab5da1d9aee92165ef42c49ab5fb
3
+ metadata.gz: e9b77f8e9cdd0225371244cf238863376dbc7340
4
+ data.tar.gz: 104eda2562feb6b7e27608046b7b2786d86ce8f3
5
5
  SHA512:
6
- metadata.gz: f31db2a4d211f5bd2c576ace419d0a5a79aa2537a3d01c499be3225308043a5b189db2f8c69fb76036bd7f8fc1b6e9808ace694e3f5196336e946d6867d441ac
7
- data.tar.gz: 2f3fcf1b00557c2e78af268b8781adbbd3279c25af76d0d094147f3d25738cb4f28deda3e1a245cd6e994a173f62fe83947b21c16d97ab7747c999cbd8980f47
6
+ metadata.gz: c333dea3b14ba64a76d94c934f316f7afb18a2cb3b88112b9d95e205a1df17099821c3631f59e5ffa81791131d2ad91cc9b48ccc36aa9fd553ba229c84f76329
7
+ data.tar.gz: b686ef987c87441e1a13c1f290f73c4fde5ff8c50f0548448fd06e27cca44b215d1426aa39e6e2efb4d98b26b8a8cbce449ce3fa0c2570fdb3b663a49e4f09b9
data/.travis.yml CHANGED
@@ -1,7 +1,11 @@
1
1
  language: ruby
2
2
  env:
3
- - RUBYLIB=lib
4
- script: bundle exec mspec
3
+ - RUBYLIB=lib:.
4
+ script: mspec spec
5
+ branches:
6
+ only:
7
+ - 1.0
8
+ - 2.0
5
9
  rvm:
6
- - 1.9.3
7
- - rbx-nightly-19mode
10
+ - 2.1.0
11
+ - rbx-2
data/MRI_LICENSE ADDED
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
@@ -1,2 +1,3 @@
1
1
  require "rubysl/stringio/version"
2
2
  require "rubysl/stringio/stringio"
3
+ require "stringio"
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module StringIO
3
- VERSION = "2.0.0"
3
+ VERSION = "2.1"
4
4
  end
5
5
  end
data/lib/stringio.rb CHANGED
@@ -1 +1,742 @@
1
- require "rubysl/stringio"
1
+ class IO
2
+ module Writable
3
+ end
4
+ module Readable
5
+ end
6
+ end
7
+
8
+ class StringIO
9
+
10
+ include Enumerable
11
+ include IO::Writable
12
+ include IO::Readable
13
+
14
+ DEFAULT_RECORD_SEPARATOR = "\n" unless defined?(::DEFAULT_RECORD_SEPARATOR)
15
+
16
+ # This is why we need undefined in Ruby
17
+ Undefined = Object.new
18
+
19
+ class Data
20
+ attr_accessor :string, :pos, :lineno, :encoding
21
+
22
+ def initialize(string)
23
+ @string = string
24
+ @encoding = string.encoding
25
+ @pos = @lineno = 0
26
+ end
27
+ end
28
+
29
+ def self.open(*args)
30
+ io = new(*args)
31
+ return io unless block_given?
32
+
33
+ begin
34
+ yield io
35
+ ensure
36
+ io.close
37
+ io.__data__.string = nil
38
+ self
39
+ end
40
+ end
41
+
42
+ attr_reader :__data__
43
+
44
+ def initialize(string=nil, mode=nil)
45
+ if string.nil?
46
+ @__data__ = Data.new ""
47
+ set_encoding(nil)
48
+ mode = IO::RDWR
49
+ else
50
+ string = Rubinius::Type.coerce_to string, String, :to_str
51
+ @__data__ = Data.new string
52
+ end
53
+
54
+ if mode
55
+ if mode.is_a?(Integer)
56
+ mode_from_integer(mode)
57
+ else
58
+ mode = StringValue(mode)
59
+ mode_from_string(mode)
60
+ end
61
+ else
62
+ mode_from_string(string.frozen? ? "r" : "r+")
63
+ end
64
+
65
+ self
66
+ end
67
+
68
+ def initialize_copy(from)
69
+ from = Rubinius::Type.coerce_to(from, StringIO, :to_strio)
70
+
71
+ taint if from.tainted?
72
+
73
+ @append = from.instance_variable_get(:@append)
74
+ @readable = from.instance_variable_get(:@readable)
75
+ @writable = from.instance_variable_get(:@writable)
76
+ @__data__ = from.instance_variable_get(:@__data__)
77
+
78
+ self
79
+ end
80
+
81
+ def check_readable
82
+ raise IOError, "not opened for reading" unless @readable
83
+ end
84
+
85
+ private :check_readable
86
+
87
+ def check_writable
88
+ raise IOError, "not opened for writing" unless @writable
89
+ raise IOError, "unable to modify data" if @__data__.string.frozen?
90
+ end
91
+
92
+ private :check_writable
93
+
94
+ def set_encoding(external, internal=nil, options=nil)
95
+ encoding = external || Encoding.default_external
96
+ @__data__.encoding = encoding
97
+ @__data__.string.force_encoding(encoding)
98
+ self
99
+ end
100
+
101
+ def external_encoding
102
+ @__data__.encoding
103
+ end
104
+
105
+ def internal_encoding
106
+ nil
107
+ end
108
+
109
+ def each_byte
110
+ return to_enum :each_byte unless block_given?
111
+ check_readable
112
+
113
+ d = @__data__
114
+ string = d.string
115
+
116
+ while d.pos < string.length
117
+ byte = string.getbyte d.pos
118
+ d.pos += 1
119
+ yield byte
120
+ end
121
+
122
+ self
123
+ end
124
+
125
+ alias_method :bytes, :each_byte
126
+
127
+ def each_char
128
+ return to_enum :each_char unless block_given?
129
+ while s = getc
130
+ yield s
131
+ end
132
+
133
+ self
134
+ end
135
+
136
+ alias_method :chars, :each_char
137
+
138
+ def each_codepoint(&block)
139
+ return to_enum :each_codepoint unless block_given?
140
+ check_readable
141
+
142
+ d = @__data__
143
+ string = d.string
144
+
145
+ while d.pos < string.bytesize
146
+ char = string.chr_at d.pos
147
+
148
+ unless char
149
+ raise ArgumentError, "invalid byte sequence in #{d.encoding}"
150
+ end
151
+
152
+ d.pos += char.bytesize
153
+ yield char.ord
154
+ end
155
+
156
+ self
157
+ end
158
+
159
+ alias_method :codepoints, :each_codepoint
160
+
161
+ def each(sep=$/, limit=Undefined)
162
+ return to_enum :each, sep, limit unless block_given?
163
+ check_readable
164
+
165
+ while line = getline(true, sep, limit)
166
+ yield line
167
+ end
168
+
169
+ self
170
+ end
171
+
172
+ alias_method :each_line, :each
173
+ alias_method :lines, :each
174
+
175
+ def <<(str)
176
+ write(str)
177
+ self
178
+ end
179
+
180
+ def binmode
181
+ self
182
+ end
183
+
184
+ def write(str)
185
+ check_writable
186
+
187
+ str = String(str)
188
+ return 0 if str.empty?
189
+
190
+ d = @__data__
191
+ pos = d.pos
192
+ string = d.string
193
+
194
+ if @append || pos == string.bytesize
195
+ string.byte_append str
196
+ d.pos = string.bytesize
197
+ elsif pos > string.bytesize
198
+ m = Rubinius::Mirror.reflect string
199
+ m.splice string.bytesize, 0, "\000" * (pos - string.bytesize)
200
+ string.byte_append str
201
+ d.pos = string.bytesize
202
+ else
203
+ stop = string.bytesize - pos
204
+ if str.bytesize < stop
205
+ stop = str.bytesize
206
+ end
207
+ m = Rubinius::Mirror.reflect string
208
+ m.splice pos, stop, str
209
+ d.pos += str.bytesize
210
+ string.taint if str.tainted?
211
+ end
212
+
213
+ str.bytesize
214
+ end
215
+ alias_method :syswrite, :write
216
+ alias_method :write_nonblock, :write
217
+
218
+ def close
219
+ raise IOError, "closed stream" if closed?
220
+ @readable = @writable = nil
221
+ end
222
+
223
+ def closed?
224
+ !@readable && !@writable
225
+ end
226
+
227
+ def close_read
228
+ check_readable
229
+ @readable = nil
230
+ end
231
+
232
+ def closed_read?
233
+ !@readable
234
+ end
235
+
236
+ def close_write
237
+ check_writable
238
+ @writable = nil
239
+ end
240
+
241
+ def closed_write?
242
+ !@writable
243
+ end
244
+
245
+ def eof?
246
+ d = @__data__
247
+ d.pos >= d.string.bytesize
248
+ end
249
+ alias_method :eof, :eof?
250
+
251
+ def fcntl
252
+ raise NotImplementedError, "StringIO#fcntl is not implemented"
253
+ end
254
+
255
+ def fileno
256
+ nil
257
+ end
258
+
259
+ def flush
260
+ self
261
+ end
262
+
263
+ def fsync
264
+ 0
265
+ end
266
+
267
+ def getc
268
+ check_readable
269
+ d = @__data__
270
+
271
+ return nil if eof?
272
+
273
+ char = d.string.find_character(d.pos)
274
+ d.pos += char.bytesize
275
+ char
276
+ end
277
+
278
+ def getbyte
279
+ check_readable
280
+ d = @__data__
281
+
282
+ return nil if eof?
283
+
284
+ byte = d.string.getbyte(d.pos)
285
+ d.pos += 1
286
+ byte
287
+ end
288
+
289
+ def gets(sep=$/, limit=Undefined)
290
+ check_readable
291
+
292
+ $_ = getline(false, sep, limit)
293
+ end
294
+
295
+ def isatty
296
+ false
297
+ end
298
+ alias_method :tty?, :isatty
299
+
300
+ def lineno
301
+ @__data__.lineno
302
+ end
303
+
304
+ def lineno=(line)
305
+ @__data__.lineno = line
306
+ end
307
+
308
+ def pid
309
+ nil
310
+ end
311
+
312
+ def pos
313
+ @__data__.pos
314
+ end
315
+
316
+ def pos=(pos)
317
+ raise Errno::EINVAL if pos < 0
318
+ @__data__.pos = pos
319
+ end
320
+
321
+ def print(*args)
322
+ check_writable
323
+ args << $_ if args.empty?
324
+ write((args << $\).flatten.join)
325
+ nil
326
+ end
327
+
328
+ def printf(*args)
329
+ check_writable
330
+
331
+ if args.size > 1
332
+ write(args.shift % args)
333
+ else
334
+ write(args.first)
335
+ end
336
+
337
+ nil
338
+ end
339
+
340
+ def putc(obj)
341
+ check_writable
342
+
343
+ if obj.is_a?(String)
344
+ char = obj[0]
345
+ else
346
+ c = Rubinius::Type.coerce_to obj, Integer, :to_int
347
+ char = (c & 0xff).chr
348
+ end
349
+
350
+ d = @__data__
351
+ pos = d.pos
352
+ string = d.string
353
+
354
+ if @append || pos == string.bytesize
355
+ string.byte_append char
356
+ d.pos = string.bytesize
357
+ elsif pos > string.bytesize
358
+ m = Rubinius::Mirror.reflect string
359
+ m.splice string.bytesize, 0, "\000" * (pos - string.bytesize)
360
+ string.byte_append char
361
+ d.pos = string.bytesize
362
+ else
363
+ m = Rubinius::Mirror.reflect string
364
+ m.splice pos, char.bytesize, char
365
+ d.pos += char.bytesize
366
+ end
367
+
368
+ obj
369
+ end
370
+
371
+ def puts(*args)
372
+ if args.empty?
373
+ write(DEFAULT_RECORD_SEPARATOR)
374
+ else
375
+ args.each do |arg|
376
+ if arg.nil?
377
+ line = ""
378
+ elsif Thread.guarding? arg
379
+ line = "[...]"
380
+ else
381
+ begin
382
+ arg = Rubinius::Type.coerce_to(arg, Array, :to_ary)
383
+ Thread.recursion_guard arg do
384
+ arg.each { |a| puts a }
385
+ end
386
+ next
387
+ rescue
388
+ line = arg.to_s
389
+ end
390
+ end
391
+
392
+ write(line)
393
+ write(DEFAULT_RECORD_SEPARATOR) unless line[-1] == ?\n
394
+ end
395
+ end
396
+
397
+ nil
398
+ end
399
+
400
+ def read(length=nil, buffer=nil)
401
+ check_readable
402
+ d = @__data__
403
+ pos = d.pos
404
+ string = d.string
405
+
406
+ if length
407
+ length = Rubinius::Type.coerce_to length, Integer, :to_int
408
+ raise ArgumentError if length < 0
409
+
410
+ buffer = StringValue(buffer) if buffer
411
+
412
+ if eof?
413
+ buffer.clear if buffer
414
+ if length == 0
415
+ return "".force_encoding(Encoding::ASCII_8BIT)
416
+ else
417
+ return nil
418
+ end
419
+ end
420
+
421
+ str = string.byteslice(pos, length)
422
+ str.force_encoding Encoding::ASCII_8BIT
423
+
424
+ str = buffer.replace(str) if buffer
425
+ else
426
+ if eof?
427
+ buffer.clear if buffer
428
+ return "".force_encoding(Encoding::ASCII_8BIT)
429
+ end
430
+
431
+ str = string.byteslice(pos..-1)
432
+ buffer.replace str if buffer
433
+ end
434
+
435
+ d.pos += str.length
436
+ return str
437
+ end
438
+
439
+ def readchar
440
+ raise IO::EOFError, "end of file reached" if eof?
441
+ getc
442
+ end
443
+
444
+ def readbyte
445
+ readchar.getbyte(0)
446
+ end
447
+
448
+ def readline(sep=$/, limit=Undefined)
449
+ check_readable
450
+ raise IO::EOFError, "end of file reached" if eof?
451
+
452
+ $_ = getline(true, sep, limit)
453
+ end
454
+
455
+ def readlines(sep=$/, limit=Undefined)
456
+ check_readable
457
+
458
+ ary = []
459
+ while line = getline(true, sep, limit)
460
+ ary << line
461
+ end
462
+
463
+ ary
464
+ end
465
+
466
+ def reopen(string=nil, mode=Undefined)
467
+ if string and not string.kind_of? String and mode.equal? Undefined
468
+ stringio = Rubinius::Type.coerce_to(string, StringIO, :to_strio)
469
+
470
+ taint if stringio.tainted?
471
+ initialize_copy stringio
472
+ else
473
+ mode = nil if mode.equal? Undefined
474
+ string = "" unless string
475
+
476
+ initialize string, mode
477
+ end
478
+
479
+ self
480
+ end
481
+
482
+ def rewind
483
+ d = @__data__
484
+ d.pos = d.lineno = 0
485
+ end
486
+
487
+ def seek(to, whence = IO::SEEK_SET)
488
+ raise IOError, "closed stream" if self.closed?
489
+ to = Rubinius::Type.coerce_to to, Integer, :to_int
490
+
491
+ case whence
492
+ when IO::SEEK_CUR
493
+ to += @__data__.pos
494
+ when IO::SEEK_END
495
+ to += @__data__.string.bytesize
496
+ when IO::SEEK_SET, nil
497
+ else
498
+ raise Errno::EINVAL, "invalid whence"
499
+ end
500
+
501
+ raise Errno::EINVAL if to < 0
502
+
503
+ @__data__.pos = to
504
+
505
+ return 0
506
+ end
507
+
508
+ def size
509
+ @__data__.string.bytesize
510
+ end
511
+ alias_method :length, :size
512
+
513
+ def string
514
+ @__data__.string
515
+ end
516
+
517
+ def string=(string)
518
+ d = @__data__
519
+ d.string = StringValue(string)
520
+ d.pos = 0
521
+ d.lineno = 0
522
+ end
523
+
524
+ def sync
525
+ true
526
+ end
527
+
528
+ def sync=(val)
529
+ val
530
+ end
531
+
532
+ def sysread(length=nil, buffer="")
533
+ str = read(length, buffer)
534
+
535
+ if str.nil?
536
+ buffer.clear
537
+ raise IO::EOFError, "end of file reached"
538
+ end
539
+
540
+ str
541
+ end
542
+
543
+ alias_method :readpartial, :sysread
544
+ alias_method :read_nonblock, :sysread
545
+
546
+ def tell
547
+ @__data__.pos
548
+ end
549
+
550
+ def truncate(length)
551
+ check_writable
552
+ len = Rubinius::Type.coerce_to length, Integer, :to_int
553
+ raise Errno::EINVAL, "negative length" if len < 0
554
+ string = @__data__.string
555
+
556
+ if len < string.bytesize
557
+ string[len..string.bytesize] = ""
558
+ else
559
+ string << "\000" * (len - string.bytesize)
560
+ end
561
+ return length
562
+ end
563
+
564
+ def ungetc(char)
565
+ check_readable
566
+
567
+ d = @__data__
568
+ pos = d.pos
569
+ string = d.string
570
+
571
+ if char.kind_of? Integer
572
+ char = Rubinius::Type.coerce_to char, String, :chr
573
+ else
574
+ char = Rubinius::Type.coerce_to char, String, :to_str
575
+ end
576
+
577
+ if pos > string.bytesize
578
+ string[string.bytesize..pos] = "\000" * (pos - string.bytesize)
579
+ d.pos -= 1
580
+ string[d.pos] = char
581
+ elsif pos > 0
582
+ d.pos -= 1
583
+ string[d.pos] = char
584
+ end
585
+
586
+ nil
587
+ end
588
+
589
+ def ungetbyte(bytes)
590
+ check_readable
591
+
592
+ return unless bytes
593
+
594
+ if bytes.kind_of? Fixnum
595
+ bytes = "" << bytes
596
+ else
597
+ bytes = StringValue(bytes)
598
+ return if bytes.bytesize == 0
599
+ end
600
+
601
+ d = @__data__
602
+ pos = d.pos
603
+ string = d.string
604
+
605
+ enc = string.encoding
606
+
607
+ if d.pos == 0
608
+ d.string = "#{bytes}#{string}"
609
+ else
610
+ size = bytes.bytesize
611
+ a = string.byteslice(0, pos - size) if size < pos
612
+ b = string.byteslice(pos..-1)
613
+ d.string = "#{a}#{bytes}#{b}"
614
+ d.pos = pos > size ? pos - size : 0
615
+ end
616
+
617
+ d.string.force_encoding enc
618
+ nil
619
+ end
620
+
621
+ def encode_with(coder)
622
+ end
623
+
624
+ def init_with(coder)
625
+ @__data__ = Data.new("")
626
+ end
627
+
628
+ def to_yaml_properties
629
+ []
630
+ end
631
+
632
+ def yaml_initialize(type, val)
633
+ @__data__ = Data.new("")
634
+ end
635
+
636
+ protected
637
+
638
+ def mode_from_string(mode)
639
+ @append = truncate = false
640
+
641
+ if mode[0] == ?r
642
+ @readable = true
643
+ @writable = mode[-1] == ?+ ? true : false
644
+ end
645
+
646
+ if mode[0] == ?w
647
+ @writable = truncate = true
648
+ @readable = mode[-1] == ?+ ? true : false
649
+ end
650
+
651
+ if mode[0] == ?a
652
+ @append = @writable = true
653
+ @readable = mode[-1] == ?+ ? true : false
654
+ end
655
+
656
+ d = @__data__
657
+ raise Errno::EACCES, "Permission denied" if @writable && d.string.frozen?
658
+ d.string.replace("") if truncate
659
+ end
660
+
661
+ def mode_from_integer(mode)
662
+ @readable = @writable = @append = false
663
+ d = @__data__
664
+
665
+ if mode == 0 or mode & IO::RDWR != 0
666
+ @readable = true
667
+ end
668
+
669
+ if mode & (IO::WRONLY | IO::RDWR) != 0
670
+ raise Errno::EACCES, "Permission denied" if d.string.frozen?
671
+ @writable = true
672
+ end
673
+
674
+ @append = true if (mode & IO::APPEND) != 0
675
+ d.string.replace("") if (mode & IO::TRUNC) != 0
676
+ end
677
+
678
+ def getline(arg_error, sep, limit)
679
+ if limit != Undefined
680
+ limit = Rubinius::Type.coerce_to limit, Fixnum, :to_int if limit
681
+ sep = Rubinius::Type.coerce_to sep, String, :to_str if sep
682
+ else
683
+ limit = nil
684
+
685
+ unless sep == $/ or sep.nil?
686
+ osep = sep
687
+ sep = Rubinius::Type.check_convert_type sep, String, :to_str
688
+ limit = Rubinius::Type.coerce_to osep, Fixnum, :to_int unless sep
689
+ end
690
+ end
691
+
692
+ raise ArgumentError if arg_error and limit == 0
693
+
694
+ return nil if eof?
695
+
696
+ d = @__data__
697
+ pos = d.pos
698
+ string = d.string
699
+
700
+ if sep.nil?
701
+ if limit
702
+ line = string.byteslice(pos, limit)
703
+ else
704
+ line = string.byteslice(pos, string.bytesize - pos)
705
+ end
706
+ d.pos += line.bytesize
707
+ elsif sep.empty?
708
+ if stop = string.find_string("\n\n", pos)
709
+ stop += 2
710
+ line = string.byteslice(pos, stop - pos)
711
+ while string.getbyte(stop) == 10
712
+ stop += 1
713
+ end
714
+ d.pos = stop
715
+ else
716
+ line = string.byteslice(pos, string.bytesize - pos)
717
+ d.pos = string.bytesize
718
+ end
719
+ else
720
+ if stop = string.find_string(sep, pos)
721
+ if limit && stop - pos >= limit
722
+ stop = pos + limit
723
+ else
724
+ stop += sep.bytesize
725
+ end
726
+ line = string.byteslice(pos, stop - pos)
727
+ d.pos = stop
728
+ else
729
+ if limit
730
+ line = string.byteslice(pos, limit)
731
+ else
732
+ line = string.byteslice(pos, string.bytesize - pos)
733
+ end
734
+ d.pos += line.bytesize
735
+ end
736
+ end
737
+
738
+ d.lineno += 1
739
+
740
+ return line
741
+ end
742
+ end