stringio 3.1.6 → 3.1.8
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.
- checksums.yaml +4 -4
- data/.rdoc_options +3 -0
- data/NEWS.md +44 -0
- data/docs/io.rb +1 -6
- data/ext/stringio/extconf.rb +2 -0
- data/ext/stringio/stringio.c +347 -93
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7955baf0f07b14461ca7f88b4c2f97383d9cf1114e07fd7408e1e332f974c139
|
|
4
|
+
data.tar.gz: 4169d5e9055f8ce90725fc374030ff97b8473734741c3cb741527f7e0aefd865
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e91d6fa5462e3afec46f4e709dd746e8bb275198825eca723634b2837207270c05973f224884525da256fd1ad17b1da7659046f78135ba958651715c7a34b5f7
|
|
7
|
+
data.tar.gz: 673e6b9e4e59a31b708963893bcc9ea80e01351b272b82992467b72e8c7a074eb9f2f8f854cbdc2767ca826c5d9351cfaa82ce721e8a32dca41ca6ad9a47f883
|
data/.rdoc_options
CHANGED
data/NEWS.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# News
|
|
2
2
|
|
|
3
|
+
## 3.1.8 - 2025-11-12
|
|
4
|
+
|
|
5
|
+
### Improvements
|
|
6
|
+
|
|
7
|
+
* Improved documents
|
|
8
|
+
* Patch by Burdette Lamar
|
|
9
|
+
|
|
10
|
+
### Fixes
|
|
11
|
+
|
|
12
|
+
* Fixed SEGV in `StringIO#seek` with `SEEK_END` on `StringIO.new(nil)`
|
|
13
|
+
* GH-137
|
|
14
|
+
* Patch by koh-sh
|
|
15
|
+
|
|
16
|
+
* Fixed SEGV in `StringIO#read` on `StringIO.new(nil)`
|
|
17
|
+
|
|
18
|
+
* Fixed SEGV in `StringIO#pread` on `StringIO.new(nil)`
|
|
19
|
+
|
|
20
|
+
* Fixed SEGV in `StringIO#eof?` on `StringIO.new(nil)`
|
|
21
|
+
|
|
22
|
+
* JRuby: Fixed a bug that `StringIO#read` doesn't clear code range
|
|
23
|
+
* GH-156
|
|
24
|
+
* Patch by Karol Bucek
|
|
25
|
+
|
|
26
|
+
### Thanks
|
|
27
|
+
|
|
28
|
+
* koh-sh
|
|
29
|
+
|
|
30
|
+
* Burdette Lamar
|
|
31
|
+
|
|
32
|
+
* Karol Bucek
|
|
33
|
+
|
|
34
|
+
## 3.1.7 - 2025-04-21
|
|
35
|
+
|
|
36
|
+
### Improvements
|
|
37
|
+
|
|
38
|
+
* CRuby: Added support for `rb_io_mode_t` that will be introduced in
|
|
39
|
+
Ruby 3.5 or later.
|
|
40
|
+
* GH-129
|
|
41
|
+
* Patch by Samuel Williams
|
|
42
|
+
|
|
43
|
+
### Thanks
|
|
44
|
+
|
|
45
|
+
* Samuel Williams
|
|
46
|
+
|
|
3
47
|
## 3.1.6 - 2025-03-25
|
|
4
48
|
|
|
5
49
|
### Fixes
|
data/docs/io.rb
CHANGED
data/ext/stringio/extconf.rb
CHANGED
data/ext/stringio/stringio.c
CHANGED
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
**********************************************************************/
|
|
14
14
|
|
|
15
15
|
static const char *const
|
|
16
|
-
STRINGIO_VERSION = "3.1.
|
|
16
|
+
STRINGIO_VERSION = "3.1.8";
|
|
17
17
|
|
|
18
18
|
#include <stdbool.h>
|
|
19
19
|
|
|
20
20
|
#include "ruby.h"
|
|
21
21
|
#include "ruby/io.h"
|
|
22
22
|
#include "ruby/encoding.h"
|
|
23
|
+
#include "ruby/version.h"
|
|
23
24
|
#if defined(HAVE_FCNTL_H) || defined(_WIN32)
|
|
24
25
|
#include <fcntl.h>
|
|
25
26
|
#elif defined(HAVE_SYS_FCNTL_H)
|
|
@@ -35,12 +36,29 @@ STRINGIO_VERSION = "3.1.6";
|
|
|
35
36
|
# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
|
|
36
37
|
#endif
|
|
37
38
|
|
|
39
|
+
static inline bool
|
|
40
|
+
str_chilled_p(VALUE str)
|
|
41
|
+
{
|
|
42
|
+
#if (RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 4) || RUBY_API_VERSION_MAJOR >= 4
|
|
43
|
+
// Do not attempt to modify chilled strings on Ruby 3.4+
|
|
44
|
+
// RUBY_FL_USER2 == STR_CHILLED_LITERAL
|
|
45
|
+
// RUBY_FL_USER3 == STR_CHILLED_SYMBOL_TO_S
|
|
46
|
+
return FL_TEST_RAW(str, RUBY_FL_USER2 | RUBY_FL_USER3);
|
|
47
|
+
#else
|
|
48
|
+
return false;
|
|
49
|
+
#endif
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#ifndef HAVE_TYPE_RB_IO_MODE_T
|
|
53
|
+
typedef int rb_io_mode_t;
|
|
54
|
+
#endif
|
|
55
|
+
|
|
38
56
|
struct StringIO {
|
|
39
57
|
VALUE string;
|
|
40
58
|
rb_encoding *enc;
|
|
41
59
|
long pos;
|
|
42
60
|
long lineno;
|
|
43
|
-
|
|
61
|
+
rb_io_mode_t flags;
|
|
44
62
|
int count;
|
|
45
63
|
};
|
|
46
64
|
|
|
@@ -185,6 +203,18 @@ check_modifiable(struct StringIO *ptr)
|
|
|
185
203
|
}
|
|
186
204
|
}
|
|
187
205
|
|
|
206
|
+
static inline bool
|
|
207
|
+
outside_p(struct StringIO *ptr, long pos)
|
|
208
|
+
{
|
|
209
|
+
return NIL_P(ptr->string) || pos >= RSTRING_LEN(ptr->string);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
static inline bool
|
|
213
|
+
eos_p(struct StringIO *ptr)
|
|
214
|
+
{
|
|
215
|
+
return outside_p(ptr, ptr->pos);
|
|
216
|
+
}
|
|
217
|
+
|
|
188
218
|
static VALUE
|
|
189
219
|
strio_s_allocate(VALUE klass)
|
|
190
220
|
{
|
|
@@ -195,17 +225,32 @@ strio_s_allocate(VALUE klass)
|
|
|
195
225
|
* call-seq:
|
|
196
226
|
* StringIO.new(string = '', mode = 'r+') -> new_stringio
|
|
197
227
|
*
|
|
198
|
-
* Note that +mode+ defaults to <tt>'r'</tt> if +string+ is frozen.
|
|
199
|
-
*
|
|
200
228
|
* Returns a new \StringIO instance formed from +string+ and +mode+;
|
|
201
|
-
*
|
|
229
|
+
* the instance should be closed when no longer needed:
|
|
230
|
+
*
|
|
231
|
+
* strio = StringIO.new
|
|
232
|
+
* strio.string # => ""
|
|
233
|
+
* strio.closed_read? # => false
|
|
234
|
+
* strio.closed_write? # => false
|
|
235
|
+
* strio.close
|
|
202
236
|
*
|
|
203
|
-
*
|
|
237
|
+
* If +string+ is frozen, the default +mode+ is <tt>'r'</tt>:
|
|
238
|
+
*
|
|
239
|
+
* strio = StringIO.new('foo'.freeze)
|
|
240
|
+
* strio.string # => "foo"
|
|
241
|
+
* strio.closed_read? # => false
|
|
242
|
+
* strio.closed_write? # => true
|
|
204
243
|
* strio.close
|
|
205
244
|
*
|
|
206
|
-
*
|
|
245
|
+
* Argument +mode+ must be a valid
|
|
246
|
+
* {Access Mode}[https://docs.ruby-lang.org/en/master/File.html#class-File-label-Access+Modes],
|
|
247
|
+
* which may be a string or an integer constant:
|
|
248
|
+
*
|
|
249
|
+
* StringIO.new('foo', 'w+')
|
|
250
|
+
* StringIO.new('foo', File::RDONLY)
|
|
207
251
|
*
|
|
208
|
-
* Related: StringIO.open
|
|
252
|
+
* Related: StringIO.open
|
|
253
|
+
* (passes the \StringIO object to the block; closes the object automatically on block exit).
|
|
209
254
|
*/
|
|
210
255
|
static VALUE
|
|
211
256
|
strio_initialize(int argc, VALUE *argv, VALUE self)
|
|
@@ -340,23 +385,20 @@ strio_finalize(VALUE self)
|
|
|
340
385
|
|
|
341
386
|
/*
|
|
342
387
|
* call-seq:
|
|
343
|
-
* StringIO.open(string = '', mode = 'r+')
|
|
344
|
-
*
|
|
345
|
-
* Note that +mode+ defaults to <tt>'r'</tt> if +string+ is frozen.
|
|
388
|
+
* StringIO.open(string = '', mode = 'r+') -> new_stringio
|
|
389
|
+
* StringIO.open(string = '', mode = 'r+') {|strio| ... } -> object
|
|
346
390
|
*
|
|
347
|
-
* Creates
|
|
348
|
-
* see {Access Modes}[rdoc-ref:File@Access+Modes].
|
|
391
|
+
* Creates new \StringIO instance by calling <tt>StringIO.new(string, mode)</tt>.
|
|
349
392
|
*
|
|
350
|
-
* With no block, returns the new instance:
|
|
393
|
+
* With no block given, returns the new instance:
|
|
351
394
|
*
|
|
352
395
|
* strio = StringIO.open # => #<StringIO>
|
|
353
396
|
*
|
|
354
|
-
* With a block, calls the block with the new instance
|
|
397
|
+
* With a block given, calls the block with the new instance
|
|
355
398
|
* and returns the block's value;
|
|
356
|
-
* closes the instance on block exit
|
|
399
|
+
* closes the instance on block exit:
|
|
357
400
|
*
|
|
358
|
-
* StringIO.open {|strio|
|
|
359
|
-
* # => #<StringIO>
|
|
401
|
+
* StringIO.open('foo') {|strio| strio.string.upcase } # => "FOO"
|
|
360
402
|
*
|
|
361
403
|
* Related: StringIO.new.
|
|
362
404
|
*/
|
|
@@ -382,7 +424,7 @@ strio_s_new(int argc, VALUE *argv, VALUE klass)
|
|
|
382
424
|
}
|
|
383
425
|
|
|
384
426
|
/*
|
|
385
|
-
* Returns +false
|
|
427
|
+
* Returns +false+; for compatibility with IO.
|
|
386
428
|
*/
|
|
387
429
|
static VALUE
|
|
388
430
|
strio_false(VALUE self)
|
|
@@ -392,7 +434,7 @@ strio_false(VALUE self)
|
|
|
392
434
|
}
|
|
393
435
|
|
|
394
436
|
/*
|
|
395
|
-
* Returns +nil
|
|
437
|
+
* Returns +nil+; for compatibility with IO.
|
|
396
438
|
*/
|
|
397
439
|
static VALUE
|
|
398
440
|
strio_nil(VALUE self)
|
|
@@ -402,7 +444,7 @@ strio_nil(VALUE self)
|
|
|
402
444
|
}
|
|
403
445
|
|
|
404
446
|
/*
|
|
405
|
-
* Returns
|
|
447
|
+
* Returns +self+; for compatibility with IO.
|
|
406
448
|
*/
|
|
407
449
|
static VALUE
|
|
408
450
|
strio_self(VALUE self)
|
|
@@ -412,7 +454,7 @@ strio_self(VALUE self)
|
|
|
412
454
|
}
|
|
413
455
|
|
|
414
456
|
/*
|
|
415
|
-
* Returns 0
|
|
457
|
+
* Returns 0; for compatibility with IO.
|
|
416
458
|
*/
|
|
417
459
|
static VALUE
|
|
418
460
|
strio_0(VALUE self)
|
|
@@ -472,7 +514,7 @@ strio_get_string(VALUE self)
|
|
|
472
514
|
* call-seq:
|
|
473
515
|
* string = other_string -> other_string
|
|
474
516
|
*
|
|
475
|
-
*
|
|
517
|
+
* Replaces the stored string with +other_string+, and sets the position to zero;
|
|
476
518
|
* returns +other_string+:
|
|
477
519
|
*
|
|
478
520
|
* StringIO.open('foo') do |strio|
|
|
@@ -486,7 +528,7 @@ strio_get_string(VALUE self)
|
|
|
486
528
|
* "foo"
|
|
487
529
|
* "bar"
|
|
488
530
|
*
|
|
489
|
-
* Related: StringIO#string (returns the
|
|
531
|
+
* Related: StringIO#string (returns the stored string).
|
|
490
532
|
*/
|
|
491
533
|
static VALUE
|
|
492
534
|
strio_set_string(VALUE self, VALUE string)
|
|
@@ -507,11 +549,16 @@ strio_set_string(VALUE self, VALUE string)
|
|
|
507
549
|
* call-seq:
|
|
508
550
|
* close -> nil
|
|
509
551
|
*
|
|
510
|
-
* Closes +self+ for both reading and writing
|
|
552
|
+
* Closes +self+ for both reading and writing; returns +nil+:
|
|
511
553
|
*
|
|
512
|
-
*
|
|
554
|
+
* strio = StringIO.new
|
|
555
|
+
* strio.closed? # => false
|
|
556
|
+
* strio.close # => nil
|
|
557
|
+
* strio.closed? # => true
|
|
558
|
+
* strio.read # Raises IOError: not opened for reading
|
|
559
|
+
* strio.write # Raises IOError: not opened for writing
|
|
513
560
|
*
|
|
514
|
-
* Related: StringIO#close_read, StringIO#close_write.
|
|
561
|
+
* Related: StringIO#close_read, StringIO#close_write, StringIO.closed?.
|
|
515
562
|
*/
|
|
516
563
|
static VALUE
|
|
517
564
|
strio_close(VALUE self)
|
|
@@ -525,9 +572,16 @@ strio_close(VALUE self)
|
|
|
525
572
|
* call-seq:
|
|
526
573
|
* close_read -> nil
|
|
527
574
|
*
|
|
528
|
-
* Closes +self+ for reading;
|
|
575
|
+
* Closes +self+ for reading;
|
|
576
|
+
* closed-write setting remains unchanged;
|
|
577
|
+
* returns +nil+:
|
|
529
578
|
*
|
|
530
|
-
*
|
|
579
|
+
* strio = StringIO.new
|
|
580
|
+
* strio.closed_read? # => false
|
|
581
|
+
* strio.close_read # => nil
|
|
582
|
+
* strio.closed_read? # => true
|
|
583
|
+
* strio.closed_write? # => false
|
|
584
|
+
* strio.read # Raises IOError: not opened for reading
|
|
531
585
|
*
|
|
532
586
|
* Related: StringIO#close, StringIO#close_write.
|
|
533
587
|
*/
|
|
@@ -546,11 +600,16 @@ strio_close_read(VALUE self)
|
|
|
546
600
|
* call-seq:
|
|
547
601
|
* close_write -> nil
|
|
548
602
|
*
|
|
549
|
-
* Closes +self+ for writing; closed-read setting remains unchanged
|
|
603
|
+
* Closes +self+ for writing; closed-read setting remains unchanged; returns +nil+:
|
|
550
604
|
*
|
|
551
|
-
*
|
|
605
|
+
* strio = StringIO.new
|
|
606
|
+
* strio.closed_write? # => false
|
|
607
|
+
* strio.close_write # => nil
|
|
608
|
+
* strio.closed_write? # => true
|
|
609
|
+
* strio.closed_read? # => false
|
|
610
|
+
* strio.write('foo') # Raises IOError: not opened for writing
|
|
552
611
|
*
|
|
553
|
-
* Related: StringIO#close, StringIO#close_read
|
|
612
|
+
* Related: StringIO#close, StringIO#close_read, StringIO#closed_write?.
|
|
554
613
|
*/
|
|
555
614
|
static VALUE
|
|
556
615
|
strio_close_write(VALUE self)
|
|
@@ -567,8 +626,16 @@ strio_close_write(VALUE self)
|
|
|
567
626
|
* call-seq:
|
|
568
627
|
* closed? -> true or false
|
|
569
628
|
*
|
|
570
|
-
* Returns
|
|
571
|
-
*
|
|
629
|
+
* Returns whether +self+ is closed for both reading and writing:
|
|
630
|
+
*
|
|
631
|
+
* strio = StringIO.new
|
|
632
|
+
* strio.closed? # => false # Open for reading and writing.
|
|
633
|
+
* strio.close_read
|
|
634
|
+
* strio.closed? # => false # Still open for writing.
|
|
635
|
+
* strio.close_write
|
|
636
|
+
* strio.closed? # => true # Now closed for both.
|
|
637
|
+
*
|
|
638
|
+
* Related: StringIO.closed_read?, StringIO.closed_write?.
|
|
572
639
|
*/
|
|
573
640
|
static VALUE
|
|
574
641
|
strio_closed(VALUE self)
|
|
@@ -582,7 +649,14 @@ strio_closed(VALUE self)
|
|
|
582
649
|
* call-seq:
|
|
583
650
|
* closed_read? -> true or false
|
|
584
651
|
*
|
|
585
|
-
* Returns
|
|
652
|
+
* Returns whether +self+ is closed for reading:
|
|
653
|
+
*
|
|
654
|
+
* strio = StringIO.new
|
|
655
|
+
* strio.closed_read? # => false
|
|
656
|
+
* strio.close_read
|
|
657
|
+
* strio.closed_read? # => true
|
|
658
|
+
*
|
|
659
|
+
* Related: StringIO#closed?, StringIO#closed_write?, StringIO#close_read.
|
|
586
660
|
*/
|
|
587
661
|
static VALUE
|
|
588
662
|
strio_closed_read(VALUE self)
|
|
@@ -596,7 +670,14 @@ strio_closed_read(VALUE self)
|
|
|
596
670
|
* call-seq:
|
|
597
671
|
* closed_write? -> true or false
|
|
598
672
|
*
|
|
599
|
-
* Returns
|
|
673
|
+
* Returns whether +self+ is closed for writing:
|
|
674
|
+
*
|
|
675
|
+
* strio = StringIO.new
|
|
676
|
+
* strio.closed_write? # => false
|
|
677
|
+
* strio.close_write
|
|
678
|
+
* strio.closed_write? # => true
|
|
679
|
+
*
|
|
680
|
+
* Related: StringIO#close_write, StringIO#closed?, StringIO#closed_read?.
|
|
600
681
|
*/
|
|
601
682
|
static VALUE
|
|
602
683
|
strio_closed_write(VALUE self)
|
|
@@ -610,19 +691,26 @@ static struct StringIO *
|
|
|
610
691
|
strio_to_read(VALUE self)
|
|
611
692
|
{
|
|
612
693
|
struct StringIO *ptr = readable(self);
|
|
613
|
-
if (
|
|
614
|
-
|
|
615
|
-
return NULL;
|
|
694
|
+
if (eos_p(ptr)) return NULL;
|
|
695
|
+
return ptr;
|
|
616
696
|
}
|
|
617
697
|
|
|
618
698
|
/*
|
|
619
699
|
* call-seq:
|
|
620
700
|
* eof? -> true or false
|
|
621
701
|
*
|
|
622
|
-
* Returns +
|
|
623
|
-
*
|
|
702
|
+
* Returns whether +self+ is positioned at end-of-stream:
|
|
703
|
+
*
|
|
704
|
+
* strio = StringIO.new('foo')
|
|
705
|
+
* strio.pos # => 0
|
|
706
|
+
* strio.eof? # => false
|
|
707
|
+
* strio.read # => "foo"
|
|
708
|
+
* strio.pos # => 3
|
|
709
|
+
* strio.eof? # => true
|
|
710
|
+
* strio.close_read
|
|
711
|
+
* strio.eof? # Raises IOError: not opened for reading
|
|
624
712
|
*
|
|
625
|
-
*
|
|
713
|
+
* Related: StringIO#pos.
|
|
626
714
|
*/
|
|
627
715
|
static VALUE
|
|
628
716
|
strio_eof(VALUE self)
|
|
@@ -686,7 +774,7 @@ strio_set_lineno(VALUE self, VALUE lineno)
|
|
|
686
774
|
* binmode -> self
|
|
687
775
|
*
|
|
688
776
|
* Sets the data mode in +self+ to binary mode;
|
|
689
|
-
* see {Data Mode}[
|
|
777
|
+
* see {Data Mode}[https://docs.ruby-lang.org/en/master/File.html#class-File-label-Data+Mode].
|
|
690
778
|
*
|
|
691
779
|
*/
|
|
692
780
|
static VALUE
|
|
@@ -819,7 +907,11 @@ strio_seek(int argc, VALUE *argv, VALUE self)
|
|
|
819
907
|
offset = ptr->pos;
|
|
820
908
|
break;
|
|
821
909
|
case 2:
|
|
822
|
-
|
|
910
|
+
if (NIL_P(ptr->string)) {
|
|
911
|
+
offset = 0;
|
|
912
|
+
} else {
|
|
913
|
+
offset = RSTRING_LEN(ptr->string);
|
|
914
|
+
}
|
|
823
915
|
break;
|
|
824
916
|
default:
|
|
825
917
|
error_inval("invalid whence");
|
|
@@ -852,10 +944,9 @@ strio_get_sync(VALUE self)
|
|
|
852
944
|
* call-seq:
|
|
853
945
|
* each_byte {|byte| ... } -> self
|
|
854
946
|
*
|
|
855
|
-
*
|
|
856
|
-
* see {Byte IO}[rdoc-ref:IO@Byte+IO].
|
|
947
|
+
* :include: stringio/each_byte.rdoc
|
|
857
948
|
*
|
|
858
|
-
*
|
|
949
|
+
* Related: StringIO#each_char, StringIO#each_codepoint, StringIO#each_line.
|
|
859
950
|
*/
|
|
860
951
|
static VALUE
|
|
861
952
|
strio_each_byte(VALUE self)
|
|
@@ -873,10 +964,10 @@ strio_each_byte(VALUE self)
|
|
|
873
964
|
|
|
874
965
|
/*
|
|
875
966
|
* call-seq:
|
|
876
|
-
* getc -> character or nil
|
|
967
|
+
* getc -> character, byte, or nil
|
|
968
|
+
*
|
|
969
|
+
* :include: stringio/getc.rdoc
|
|
877
970
|
*
|
|
878
|
-
* Reads and returns the next character from the stream;
|
|
879
|
-
* see {Character IO}[rdoc-ref:IO@Character+IO].
|
|
880
971
|
*/
|
|
881
972
|
static VALUE
|
|
882
973
|
strio_getc(VALUE self)
|
|
@@ -888,7 +979,7 @@ strio_getc(VALUE self)
|
|
|
888
979
|
int len;
|
|
889
980
|
char *p;
|
|
890
981
|
|
|
891
|
-
if (
|
|
982
|
+
if (eos_p(ptr)) {
|
|
892
983
|
return Qnil;
|
|
893
984
|
}
|
|
894
985
|
p = RSTRING_PTR(str)+pos;
|
|
@@ -899,17 +990,17 @@ strio_getc(VALUE self)
|
|
|
899
990
|
|
|
900
991
|
/*
|
|
901
992
|
* call-seq:
|
|
902
|
-
* getbyte ->
|
|
993
|
+
* getbyte -> integer or nil
|
|
994
|
+
*
|
|
995
|
+
* :include: stringio/getbyte.rdoc
|
|
903
996
|
*
|
|
904
|
-
* Reads and returns the next 8-bit byte from the stream;
|
|
905
|
-
* see {Byte IO}[rdoc-ref:IO@Byte+IO].
|
|
906
997
|
*/
|
|
907
998
|
static VALUE
|
|
908
999
|
strio_getbyte(VALUE self)
|
|
909
1000
|
{
|
|
910
1001
|
struct StringIO *ptr = readable(self);
|
|
911
1002
|
int c;
|
|
912
|
-
if (
|
|
1003
|
+
if (eos_p(ptr)) {
|
|
913
1004
|
return Qnil;
|
|
914
1005
|
}
|
|
915
1006
|
c = RSTRING_PTR(ptr->string)[ptr->pos++];
|
|
@@ -1078,12 +1169,11 @@ strio_readbyte(VALUE self)
|
|
|
1078
1169
|
|
|
1079
1170
|
/*
|
|
1080
1171
|
* call-seq:
|
|
1081
|
-
* each_char {|
|
|
1172
|
+
* each_char {|char| ... } -> self
|
|
1082
1173
|
*
|
|
1083
|
-
*
|
|
1084
|
-
* see {Character IO}[rdoc-ref:IO@Character+IO].
|
|
1174
|
+
* :include: stringio/each_char.rdoc
|
|
1085
1175
|
*
|
|
1086
|
-
*
|
|
1176
|
+
* Related: StringIO#each_byte, StringIO#each_codepoint, StringIO#each_line.
|
|
1087
1177
|
*/
|
|
1088
1178
|
static VALUE
|
|
1089
1179
|
strio_each_char(VALUE self)
|
|
@@ -1102,10 +1192,9 @@ strio_each_char(VALUE self)
|
|
|
1102
1192
|
* call-seq:
|
|
1103
1193
|
* each_codepoint {|codepoint| ... } -> self
|
|
1104
1194
|
*
|
|
1105
|
-
*
|
|
1106
|
-
* see {Codepoint IO}[rdoc-ref:IO@Codepoint+IO].
|
|
1195
|
+
* :include: stringio/each_codepoint.rdoc
|
|
1107
1196
|
*
|
|
1108
|
-
*
|
|
1197
|
+
* Related: StringIO#each_byte, StringIO#each_char, StringIO#each_line.
|
|
1109
1198
|
*/
|
|
1110
1199
|
static VALUE
|
|
1111
1200
|
strio_each_codepoint(VALUE self)
|
|
@@ -1339,9 +1428,8 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
|
|
|
1339
1428
|
* gets(limit, chomp: false) -> string or nil
|
|
1340
1429
|
* gets(sep, limit, chomp: false) -> string or nil
|
|
1341
1430
|
*
|
|
1342
|
-
*
|
|
1343
|
-
*
|
|
1344
|
-
* see {Line IO}[rdoc-ref:IO@Line+IO].
|
|
1431
|
+
* :include: stringio/gets.rdoc
|
|
1432
|
+
*
|
|
1345
1433
|
*/
|
|
1346
1434
|
static VALUE
|
|
1347
1435
|
strio_gets(int argc, VALUE *argv, VALUE self)
|
|
@@ -1378,15 +1466,177 @@ strio_readline(int argc, VALUE *argv, VALUE self)
|
|
|
1378
1466
|
}
|
|
1379
1467
|
|
|
1380
1468
|
/*
|
|
1469
|
+
* :markup: markdown
|
|
1470
|
+
*
|
|
1381
1471
|
* call-seq:
|
|
1382
1472
|
* each_line(sep = $/, chomp: false) {|line| ... } -> self
|
|
1383
1473
|
* each_line(limit, chomp: false) {|line| ... } -> self
|
|
1384
1474
|
* each_line(sep, limit, chomp: false) {|line| ... } -> self
|
|
1385
1475
|
*
|
|
1386
|
-
*
|
|
1387
|
-
*
|
|
1388
|
-
*
|
|
1389
|
-
*
|
|
1476
|
+
* With a block given calls the block with each remaining line (see "Position" below) in the stream;
|
|
1477
|
+
* returns `self`.
|
|
1478
|
+
*
|
|
1479
|
+
* Leaves stream position as end-of-stream.
|
|
1480
|
+
*
|
|
1481
|
+
* **No Arguments**
|
|
1482
|
+
*
|
|
1483
|
+
* With no arguments given,
|
|
1484
|
+
* reads lines using the default record separator global variable `$/`, whose initial value is `"\n"`.
|
|
1485
|
+
*
|
|
1486
|
+
* ```
|
|
1487
|
+
* strio = StringIO.new(TEXT)
|
|
1488
|
+
* strio.each_line {|line| p line }
|
|
1489
|
+
* strio.eof? # => true
|
|
1490
|
+
* ```
|
|
1491
|
+
*
|
|
1492
|
+
* Output:
|
|
1493
|
+
*
|
|
1494
|
+
* ```
|
|
1495
|
+
* "First line\n"
|
|
1496
|
+
* "Second line\n"
|
|
1497
|
+
* "\n"
|
|
1498
|
+
* "Fourth line\n"
|
|
1499
|
+
* "Fifth line\n"
|
|
1500
|
+
* ```
|
|
1501
|
+
*
|
|
1502
|
+
* **Argument `sep`**
|
|
1503
|
+
*
|
|
1504
|
+
* With only string argument `sep` given,
|
|
1505
|
+
* reads lines using that string as the record separator:
|
|
1506
|
+
*
|
|
1507
|
+
* ```
|
|
1508
|
+
* strio = StringIO.new(TEXT)
|
|
1509
|
+
* strio.each_line(' ') {|line| p line }
|
|
1510
|
+
* ```
|
|
1511
|
+
*
|
|
1512
|
+
* Output:
|
|
1513
|
+
*
|
|
1514
|
+
* ```
|
|
1515
|
+
* "First "
|
|
1516
|
+
* "line\nSecond "
|
|
1517
|
+
* "line\n\nFourth "
|
|
1518
|
+
* "line\nFifth "
|
|
1519
|
+
* "line\n"
|
|
1520
|
+
* ```
|
|
1521
|
+
*
|
|
1522
|
+
* **Argument `limit`**
|
|
1523
|
+
*
|
|
1524
|
+
* With only integer argument `limit` given,
|
|
1525
|
+
* reads lines using the default record separator global variable `$/`, whose initial value is `"\n"`;
|
|
1526
|
+
* also limits the size (in characters) of each line to the given limit:
|
|
1527
|
+
*
|
|
1528
|
+
* ```
|
|
1529
|
+
* strio = StringIO.new(TEXT)
|
|
1530
|
+
* strio.each_line(10) {|line| p line }
|
|
1531
|
+
* ```
|
|
1532
|
+
*
|
|
1533
|
+
* Output:
|
|
1534
|
+
*
|
|
1535
|
+
* ```
|
|
1536
|
+
* "First line"
|
|
1537
|
+
* "\n"
|
|
1538
|
+
* "Second lin"
|
|
1539
|
+
* "e\n"
|
|
1540
|
+
* "\n"
|
|
1541
|
+
* "Fourth lin"
|
|
1542
|
+
* "e\n"
|
|
1543
|
+
* "Fifth line"
|
|
1544
|
+
* "\n"
|
|
1545
|
+
* ```
|
|
1546
|
+
* **Arguments `sep` and `limit`**
|
|
1547
|
+
*
|
|
1548
|
+
* With arguments `sep` and `limit` both given,
|
|
1549
|
+
* honors both:
|
|
1550
|
+
*
|
|
1551
|
+
* ```
|
|
1552
|
+
* strio = StringIO.new(TEXT)
|
|
1553
|
+
* strio.each_line(' ', 10) {|line| p line }
|
|
1554
|
+
* ```
|
|
1555
|
+
*
|
|
1556
|
+
* Output:
|
|
1557
|
+
*
|
|
1558
|
+
* ```
|
|
1559
|
+
* "First "
|
|
1560
|
+
* "line\nSecon"
|
|
1561
|
+
* "d "
|
|
1562
|
+
* "line\n\nFour"
|
|
1563
|
+
* "th "
|
|
1564
|
+
* "line\nFifth"
|
|
1565
|
+
* " "
|
|
1566
|
+
* "line\n"
|
|
1567
|
+
* ```
|
|
1568
|
+
*
|
|
1569
|
+
* **Position**
|
|
1570
|
+
*
|
|
1571
|
+
* As stated above, method `each` _remaining_ line in the stream.
|
|
1572
|
+
*
|
|
1573
|
+
* In the examples above each `strio` object starts with its position at beginning-of-stream;
|
|
1574
|
+
* but in other cases the position may be anywhere (see StringIO#pos):
|
|
1575
|
+
*
|
|
1576
|
+
* ```
|
|
1577
|
+
* strio = StringIO.new(TEXT)
|
|
1578
|
+
* strio.pos = 30 # Set stream position to character 30.
|
|
1579
|
+
* strio.each_line {|line| p line }
|
|
1580
|
+
* ```
|
|
1581
|
+
*
|
|
1582
|
+
* Output:
|
|
1583
|
+
*
|
|
1584
|
+
* ```
|
|
1585
|
+
* " line\n"
|
|
1586
|
+
* "Fifth line\n"
|
|
1587
|
+
* ```
|
|
1588
|
+
*
|
|
1589
|
+
* **Special Record Separators**
|
|
1590
|
+
*
|
|
1591
|
+
* Like some methds in class `IO`, StringIO.each honors two special record separators;
|
|
1592
|
+
* see {Special Line Separators}[https://docs.ruby-lang.org/en/master/IO.html#class-IO-label-Special+Line+Separator+Values].
|
|
1593
|
+
*
|
|
1594
|
+
* ```
|
|
1595
|
+
* strio = StringIO.new(TEXT)
|
|
1596
|
+
* strio.each_line('') {|line| p line } # Read as paragraphs (separated by blank lines).
|
|
1597
|
+
* ```
|
|
1598
|
+
*
|
|
1599
|
+
* Output:
|
|
1600
|
+
*
|
|
1601
|
+
* ```
|
|
1602
|
+
* "First line\nSecond line\n\n"
|
|
1603
|
+
* "Fourth line\nFifth line\n"
|
|
1604
|
+
* ```
|
|
1605
|
+
*
|
|
1606
|
+
* ```
|
|
1607
|
+
* strio = StringIO.new(TEXT)
|
|
1608
|
+
* strio.each_line(nil) {|line| p line } # "Slurp"; read it all.
|
|
1609
|
+
* ```
|
|
1610
|
+
*
|
|
1611
|
+
* Output:
|
|
1612
|
+
*
|
|
1613
|
+
* ```
|
|
1614
|
+
* "First line\nSecond line\n\nFourth line\nFifth line\n"
|
|
1615
|
+
* ```
|
|
1616
|
+
*
|
|
1617
|
+
* **Keyword Argument `chomp`**
|
|
1618
|
+
*
|
|
1619
|
+
* With keyword argument `chomp` given as `true` (the default is `false`),
|
|
1620
|
+
* removes trailing newline (if any) from each line:
|
|
1621
|
+
*
|
|
1622
|
+
* ```
|
|
1623
|
+
* strio = StringIO.new(TEXT)
|
|
1624
|
+
* strio.each_line(chomp: true) {|line| p line }
|
|
1625
|
+
* ```
|
|
1626
|
+
*
|
|
1627
|
+
* Output:
|
|
1628
|
+
*
|
|
1629
|
+
* ```
|
|
1630
|
+
* "First line"
|
|
1631
|
+
* "Second line"
|
|
1632
|
+
* ""
|
|
1633
|
+
* "Fourth line"
|
|
1634
|
+
* "Fifth line"
|
|
1635
|
+
* ```
|
|
1636
|
+
*
|
|
1637
|
+
* With no block given, returns a new {Enumerator}[https://docs.ruby-lang.org/en/master/Enumerator.html].
|
|
1638
|
+
*
|
|
1639
|
+
* Related: StringIO.each_byte, StringIO.each_char, StringIO.each_codepoint.
|
|
1390
1640
|
*/
|
|
1391
1641
|
static VALUE
|
|
1392
1642
|
strio_each(int argc, VALUE *argv, VALUE self)
|
|
@@ -1587,10 +1837,9 @@ strio_read(int argc, VALUE *argv, VALUE self)
|
|
|
1587
1837
|
if (len < 0) {
|
|
1588
1838
|
rb_raise(rb_eArgError, "negative length %ld given", len);
|
|
1589
1839
|
}
|
|
1590
|
-
if (
|
|
1591
|
-
(NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string))) {
|
|
1840
|
+
if (eos_p(ptr)) {
|
|
1592
1841
|
if (!NIL_P(str)) rb_str_resize(str, 0);
|
|
1593
|
-
return Qnil;
|
|
1842
|
+
return len > 0 ? Qnil : rb_str_new(0, 0);
|
|
1594
1843
|
}
|
|
1595
1844
|
binary = 1;
|
|
1596
1845
|
break;
|
|
@@ -1666,7 +1915,7 @@ strio_pread(int argc, VALUE *argv, VALUE self)
|
|
|
1666
1915
|
|
|
1667
1916
|
struct StringIO *ptr = readable(self);
|
|
1668
1917
|
|
|
1669
|
-
if (
|
|
1918
|
+
if (outside_p(ptr, offset)) {
|
|
1670
1919
|
rb_eof_error();
|
|
1671
1920
|
}
|
|
1672
1921
|
|
|
@@ -1797,12 +2046,20 @@ strio_truncate(VALUE self, VALUE len)
|
|
|
1797
2046
|
}
|
|
1798
2047
|
|
|
1799
2048
|
/*
|
|
1800
|
-
*
|
|
1801
|
-
*
|
|
2049
|
+
* call-seq:
|
|
2050
|
+
* external_encoding -> encoding or nil
|
|
2051
|
+
*
|
|
2052
|
+
* Returns an Encoding object that represents the encoding of the string;
|
|
2053
|
+
* see {Encoding}[https://docs.ruby-lang.org/en/master/Encoding.html]:
|
|
2054
|
+
*
|
|
2055
|
+
* strio = StringIO.new('foo')
|
|
2056
|
+
* strio.external_encoding # => #<Encoding:UTF-8>
|
|
2057
|
+
*
|
|
2058
|
+
* Returns +nil+ if +self+ has no string and is in write mode:
|
|
2059
|
+
*
|
|
2060
|
+
* strio = StringIO.new(nil, 'w+')
|
|
2061
|
+
* strio.external_encoding # => nil
|
|
1802
2062
|
*
|
|
1803
|
-
* Returns the Encoding object that represents the encoding of the file.
|
|
1804
|
-
* If the stream is write mode and no encoding is specified, returns
|
|
1805
|
-
* +nil+.
|
|
1806
2063
|
*/
|
|
1807
2064
|
|
|
1808
2065
|
static VALUE
|
|
@@ -1814,10 +2071,9 @@ strio_external_encoding(VALUE self)
|
|
|
1814
2071
|
|
|
1815
2072
|
/*
|
|
1816
2073
|
* call-seq:
|
|
1817
|
-
*
|
|
2074
|
+
* internal_encoding -> nil
|
|
1818
2075
|
*
|
|
1819
|
-
* Returns
|
|
1820
|
-
* specified. Otherwise returns +nil+.
|
|
2076
|
+
* Returns +nil+; for compatibility with IO.
|
|
1821
2077
|
*/
|
|
1822
2078
|
|
|
1823
2079
|
static VALUE
|
|
@@ -1852,14 +2108,15 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self)
|
|
|
1852
2108
|
enc = rb_find_encoding(ext_enc);
|
|
1853
2109
|
if (!enc) {
|
|
1854
2110
|
rb_io_enc_t convconfig;
|
|
1855
|
-
int oflags
|
|
2111
|
+
int oflags;
|
|
2112
|
+
rb_io_mode_t fmode;
|
|
1856
2113
|
VALUE vmode = rb_str_append(rb_str_new_cstr("r:"), ext_enc);
|
|
1857
2114
|
rb_io_extract_modeenc(&vmode, 0, Qnil, &oflags, &fmode, &convconfig);
|
|
1858
2115
|
enc = convconfig.enc2;
|
|
1859
2116
|
}
|
|
1860
2117
|
}
|
|
1861
2118
|
ptr->enc = enc;
|
|
1862
|
-
if (!NIL_P(ptr->string) && WRITABLE(self)) {
|
|
2119
|
+
if (!NIL_P(ptr->string) && WRITABLE(self) && !str_chilled_p(ptr->string)) {
|
|
1863
2120
|
rb_enc_associate(ptr->string, enc);
|
|
1864
2121
|
}
|
|
1865
2122
|
|
|
@@ -1885,16 +2142,9 @@ strio_set_encoding_by_bom(VALUE self)
|
|
|
1885
2142
|
}
|
|
1886
2143
|
|
|
1887
2144
|
/*
|
|
1888
|
-
*
|
|
1889
|
-
* {IO}[rdoc-ref:IO];
|
|
1890
|
-
* see {IO}[rdoc-ref:IO].
|
|
1891
|
-
*
|
|
1892
|
-
* === About the Examples
|
|
1893
|
-
*
|
|
1894
|
-
* Examples on this page assume that \StringIO has been required:
|
|
1895
|
-
*
|
|
1896
|
-
* require 'stringio'
|
|
2145
|
+
* :markup: markdown
|
|
1897
2146
|
*
|
|
2147
|
+
* :include: stringio/stringio.md
|
|
1898
2148
|
*/
|
|
1899
2149
|
void
|
|
1900
2150
|
Init_stringio(void)
|
|
@@ -1902,7 +2152,7 @@ Init_stringio(void)
|
|
|
1902
2152
|
#undef rb_intern
|
|
1903
2153
|
|
|
1904
2154
|
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
1905
|
-
|
|
2155
|
+
rb_ext_ractor_safe(true);
|
|
1906
2156
|
#endif
|
|
1907
2157
|
|
|
1908
2158
|
VALUE StringIO = rb_define_class("StringIO", rb_cObject);
|
|
@@ -1994,7 +2244,9 @@ Init_stringio(void)
|
|
|
1994
2244
|
rb_define_method(StringIO, "set_encoding_by_bom", strio_set_encoding_by_bom, 0);
|
|
1995
2245
|
|
|
1996
2246
|
{
|
|
2247
|
+
/* :stopdoc: */
|
|
1997
2248
|
VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
|
|
2249
|
+
/* :startdoc: */
|
|
1998
2250
|
rb_define_method(mReadable, "readchar", strio_readchar, 0);
|
|
1999
2251
|
rb_define_method(mReadable, "readbyte", strio_readbyte, 0);
|
|
2000
2252
|
rb_define_method(mReadable, "readline", strio_readline, -1);
|
|
@@ -2004,7 +2256,9 @@ Init_stringio(void)
|
|
|
2004
2256
|
rb_include_module(StringIO, mReadable);
|
|
2005
2257
|
}
|
|
2006
2258
|
{
|
|
2259
|
+
/* :stopdoc: */
|
|
2007
2260
|
VALUE mWritable = rb_define_module_under(rb_cIO, "generic_writable");
|
|
2261
|
+
/* :startdoc: */
|
|
2008
2262
|
rb_define_method(mWritable, "<<", strio_addstr, 1);
|
|
2009
2263
|
rb_define_method(mWritable, "print", strio_print, -1);
|
|
2010
2264
|
rb_define_method(mWritable, "printf", strio_printf, -1);
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stringio
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.1.
|
|
4
|
+
version: 3.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nobu Nakada
|
|
8
8
|
- Charles Oliver Nutter
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-11-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Pseudo `IO` class from/to `String`.
|
|
14
14
|
email:
|
|
@@ -42,7 +42,7 @@ licenses:
|
|
|
42
42
|
- Ruby
|
|
43
43
|
- BSD-2-Clause
|
|
44
44
|
metadata:
|
|
45
|
-
changelog_uri: https://github.com/ruby/stringio/releases/tag/v3.1.
|
|
45
|
+
changelog_uri: https://github.com/ruby/stringio/releases/tag/v3.1.8
|
|
46
46
|
rdoc_options: []
|
|
47
47
|
require_paths:
|
|
48
48
|
- lib
|
|
@@ -57,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
57
57
|
- !ruby/object:Gem::Version
|
|
58
58
|
version: '0'
|
|
59
59
|
requirements: []
|
|
60
|
-
rubygems_version: 3.6.
|
|
60
|
+
rubygems_version: 3.6.9
|
|
61
61
|
specification_version: 4
|
|
62
62
|
summary: Pseudo IO on String
|
|
63
63
|
test_files: []
|