stringio 3.1.7 → 3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d32a3b9eb5ecb12a5c78c7a79418ed351272fe49a2fc1bbde837880a8e6a2a53
4
- data.tar.gz: 8f965cb4f731147e7d6da44db5acbeda3a08ac51df419445d8001f35b17a1dc9
3
+ metadata.gz: 7c1acfcaec0e05165de2f55e7519bc0c5a732d9e00787843daade47fb287726e
4
+ data.tar.gz: 02eda2070ab8b4a9bc125de803c68de0a01845227c5e4f15359931f9fece7bbd
5
5
  SHA512:
6
- metadata.gz: 6c3f11fa1dee2b8e00269cad5e99db7014ecdc7b1b7d99f5086d15fb3f04d17105dabd838887e5f87af817851e2a8a59260c7c7af26a5ea40f2ce103ad830775
7
- data.tar.gz: c9e2afe1c8104c27591454cfeefdc71926c76196d3afc343f76052b9e465566f62df19ae25baaa1217839684910b0c94e4d05b7b08723f1960065f0c2d0844df
6
+ metadata.gz: f86b9853126abe79c1b801c2854cb606d532617218fa2a26dcc0c55c2c0ef457bee707e1d9ce08e6bfaf93c09411a175d244773b23ad0970c91ad3d068ba5718
7
+ data.tar.gz: 76083aecab40178e6c7296351c6cb66f128188000d925062d210cc938917ad8e8316074843e1fc7da295e67d391b1be2bded0409c076700a8e15a16f9dc8cd23
data/.rdoc_options CHANGED
@@ -1,2 +1,5 @@
1
1
  ---
2
2
  main_page: README.md
3
+ rdoc_include:
4
+ - doc
5
+ op_dir: html
data/NEWS.md CHANGED
@@ -1,5 +1,88 @@
1
1
  # News
2
2
 
3
+ ## 3.2.0 - 2025-12-17
4
+
5
+ ### Improvements
6
+
7
+ * Improved documents.
8
+ * GH-179
9
+ * GH-188
10
+ * GH-189
11
+ * GH-190
12
+ * GH-191
13
+ * GH-192
14
+ * GH-193
15
+ * GH-194
16
+ * Patch by Burdette Lamar
17
+
18
+ ### Thanks
19
+
20
+ * Burdette Lamar
21
+
22
+ ## 3.1.9 - 2025-12-01
23
+
24
+ ### Improvements
25
+
26
+ * [DOC] Tweaks for StringIO#each_line
27
+ * GH-165
28
+
29
+ * [DOC] Doc for StringIO.size
30
+ * GH-175
31
+
32
+ * [DOC] Tweaks for StringIO#fsync
33
+ * GH-173
34
+
35
+ * [DOC] Fix #seek link
36
+ * GH-174
37
+
38
+ * Add a note about chilled string support to 3.1.8 release note
39
+ * GH-180 fixes GH-179
40
+
41
+ ### Fixes
42
+
43
+ * JRuby: Removed use of RubyBasicObject.flags
44
+ * GH-182
45
+
46
+ ### Thanks
47
+
48
+ * Burdette Lamar
49
+
50
+ * Charles Oliver Nutter
51
+
52
+ ## 3.1.8 - 2025-11-12
53
+
54
+ ### Improvements
55
+
56
+ * Improved documents
57
+ * Patch by Burdette Lamar
58
+
59
+ * Improved chilled string support
60
+ * GH-128
61
+
62
+ ### Fixes
63
+
64
+ * Fixed SEGV in `StringIO#seek` with `SEEK_END` on `StringIO.new(nil)`
65
+ * GH-137
66
+ * Patch by koh-sh
67
+
68
+ * Fixed SEGV in `StringIO#read` on `StringIO.new(nil)`
69
+
70
+ * Fixed SEGV in `StringIO#pread` on `StringIO.new(nil)`
71
+
72
+ * Fixed SEGV in `StringIO#eof?` on `StringIO.new(nil)`
73
+
74
+ * JRuby: Fixed a bug that `StringIO#read` doesn't clear code range
75
+ * GH-156
76
+ * Patch by Karol Bucek
77
+
78
+ ### Thanks
79
+
80
+ * koh-sh
81
+
82
+ * Burdette Lamar
83
+
84
+ * Karol Bucek
85
+
3
86
  ## 3.1.7 - 2025-04-21
4
87
 
5
88
  ### Improvements
data/docs/io.rb CHANGED
@@ -1,8 +1,3 @@
1
- # :stopdoc:
1
+ # The {built-in class for I/O}[https://docs.ruby-lang.org/en/master/IO.html].
2
2
  class IO
3
- module generic_readable
4
- end
5
- module generic_writable
6
- end
7
3
  end
8
- # :startdoc:
@@ -13,13 +13,14 @@
13
13
  **********************************************************************/
14
14
 
15
15
  static const char *const
16
- STRINGIO_VERSION = "3.1.7";
16
+ STRINGIO_VERSION = "3.2.0";
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,6 +36,19 @@ STRINGIO_VERSION = "3.1.7";
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
+
38
52
  #ifndef HAVE_TYPE_RB_IO_MODE_T
39
53
  typedef int rb_io_mode_t;
40
54
  #endif
@@ -189,6 +203,18 @@ check_modifiable(struct StringIO *ptr)
189
203
  }
190
204
  }
191
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
+
192
218
  static VALUE
193
219
  strio_s_allocate(VALUE klass)
194
220
  {
@@ -199,17 +225,32 @@ strio_s_allocate(VALUE klass)
199
225
  * call-seq:
200
226
  * StringIO.new(string = '', mode = 'r+') -> new_stringio
201
227
  *
202
- * Note that +mode+ defaults to <tt>'r'</tt> if +string+ is frozen.
203
- *
204
228
  * Returns a new \StringIO instance formed from +string+ and +mode+;
205
- * see {Access Modes}[rdoc-ref:File@Access+Modes]:
229
+ * the instance should be closed when no longer needed:
206
230
  *
207
- * strio = StringIO.new # => #<StringIO>
231
+ * strio = StringIO.new
232
+ * strio.string # => ""
233
+ * strio.closed_read? # => false
234
+ * strio.closed_write? # => false
208
235
  * strio.close
209
236
  *
210
- * The instance should be closed when no longer needed.
237
+ * If +string+ is frozen, the default +mode+ is <tt>'r'</tt>:
211
238
  *
212
- * Related: StringIO.open (accepts block; closes automatically).
239
+ * strio = StringIO.new('foo'.freeze)
240
+ * strio.string # => "foo"
241
+ * strio.closed_read? # => false
242
+ * strio.closed_write? # => true
243
+ * strio.close
244
+ *
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)
251
+ *
252
+ * Related: StringIO.open
253
+ * (passes the \StringIO object to the block; closes the object automatically on block exit).
213
254
  */
214
255
  static VALUE
215
256
  strio_initialize(int argc, VALUE *argv, VALUE self)
@@ -344,23 +385,20 @@ strio_finalize(VALUE self)
344
385
 
345
386
  /*
346
387
  * call-seq:
347
- * StringIO.open(string = '', mode = 'r+') {|strio| ... }
388
+ * StringIO.open(string = '', mode = 'r+') -> new_stringio
389
+ * StringIO.open(string = '', mode = 'r+') {|strio| ... } -> object
348
390
  *
349
- * Note that +mode+ defaults to <tt>'r'</tt> if +string+ is frozen.
391
+ * Creates new \StringIO instance by calling <tt>StringIO.new(string, mode)</tt>.
350
392
  *
351
- * Creates a new \StringIO instance formed from +string+ and +mode+;
352
- * see {Access Modes}[rdoc-ref:File@Access+Modes].
353
- *
354
- * With no block, returns the new instance:
393
+ * With no block given, returns the new instance:
355
394
  *
356
395
  * strio = StringIO.open # => #<StringIO>
357
396
  *
358
- * With a block, calls the block with the new instance
397
+ * With a block given, calls the block with the new instance
359
398
  * and returns the block's value;
360
- * closes the instance on block exit.
399
+ * closes the instance on block exit:
361
400
  *
362
- * StringIO.open {|strio| p strio }
363
- * # => #<StringIO>
401
+ * StringIO.open('foo') {|strio| strio.string.upcase } # => "FOO"
364
402
  *
365
403
  * Related: StringIO.new.
366
404
  */
@@ -386,7 +424,7 @@ strio_s_new(int argc, VALUE *argv, VALUE klass)
386
424
  }
387
425
 
388
426
  /*
389
- * Returns +false+. Just for compatibility to IO.
427
+ * Returns +false+; for compatibility with IO.
390
428
  */
391
429
  static VALUE
392
430
  strio_false(VALUE self)
@@ -396,7 +434,7 @@ strio_false(VALUE self)
396
434
  }
397
435
 
398
436
  /*
399
- * Returns +nil+. Just for compatibility to IO.
437
+ * Returns +nil+; for compatibility with IO.
400
438
  */
401
439
  static VALUE
402
440
  strio_nil(VALUE self)
@@ -406,7 +444,7 @@ strio_nil(VALUE self)
406
444
  }
407
445
 
408
446
  /*
409
- * Returns an object itself. Just for compatibility to IO.
447
+ * Returns +self+; for compatibility with IO.
410
448
  */
411
449
  static VALUE
412
450
  strio_self(VALUE self)
@@ -416,7 +454,7 @@ strio_self(VALUE self)
416
454
  }
417
455
 
418
456
  /*
419
- * Returns 0. Just for compatibility to IO.
457
+ * Returns 0; for compatibility with IO.
420
458
  */
421
459
  static VALUE
422
460
  strio_0(VALUE self)
@@ -476,7 +514,7 @@ strio_get_string(VALUE self)
476
514
  * call-seq:
477
515
  * string = other_string -> other_string
478
516
  *
479
- * Assigns the underlying string as +other_string+, and sets position to zero;
517
+ * Replaces the stored string with +other_string+, and sets the position to zero;
480
518
  * returns +other_string+:
481
519
  *
482
520
  * StringIO.open('foo') do |strio|
@@ -490,7 +528,7 @@ strio_get_string(VALUE self)
490
528
  * "foo"
491
529
  * "bar"
492
530
  *
493
- * Related: StringIO#string (returns the underlying string).
531
+ * Related: StringIO#string (returns the stored string).
494
532
  */
495
533
  static VALUE
496
534
  strio_set_string(VALUE self, VALUE string)
@@ -511,11 +549,16 @@ strio_set_string(VALUE self, VALUE string)
511
549
  * call-seq:
512
550
  * close -> nil
513
551
  *
514
- * Closes +self+ for both reading and writing.
552
+ * Closes +self+ for both reading and writing; returns +nil+:
515
553
  *
516
- * Raises IOError if reading or writing is attempted.
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
517
560
  *
518
- * Related: StringIO#close_read, StringIO#close_write.
561
+ * Related: StringIO#close_read, StringIO#close_write, StringIO.closed?.
519
562
  */
520
563
  static VALUE
521
564
  strio_close(VALUE self)
@@ -529,9 +572,16 @@ strio_close(VALUE self)
529
572
  * call-seq:
530
573
  * close_read -> nil
531
574
  *
532
- * Closes +self+ for reading; closed-write setting remains unchanged.
575
+ * Closes +self+ for reading;
576
+ * closed-write setting remains unchanged;
577
+ * returns +nil+:
533
578
  *
534
- * Raises IOError if reading is attempted.
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
535
585
  *
536
586
  * Related: StringIO#close, StringIO#close_write.
537
587
  */
@@ -550,11 +600,16 @@ strio_close_read(VALUE self)
550
600
  * call-seq:
551
601
  * close_write -> nil
552
602
  *
553
- * Closes +self+ for writing; closed-read setting remains unchanged.
603
+ * Closes +self+ for writing; closed-read setting remains unchanged; returns +nil+:
554
604
  *
555
- * Raises IOError if writing is attempted.
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
556
611
  *
557
- * Related: StringIO#close, StringIO#close_read.
612
+ * Related: StringIO#close, StringIO#close_read, StringIO#closed_write?.
558
613
  */
559
614
  static VALUE
560
615
  strio_close_write(VALUE self)
@@ -571,8 +626,16 @@ strio_close_write(VALUE self)
571
626
  * call-seq:
572
627
  * closed? -> true or false
573
628
  *
574
- * Returns +true+ if +self+ is closed for both reading and writing,
575
- * +false+ otherwise.
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?.
576
639
  */
577
640
  static VALUE
578
641
  strio_closed(VALUE self)
@@ -586,7 +649,14 @@ strio_closed(VALUE self)
586
649
  * call-seq:
587
650
  * closed_read? -> true or false
588
651
  *
589
- * Returns +true+ if +self+ is closed for reading, +false+ otherwise.
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.
590
660
  */
591
661
  static VALUE
592
662
  strio_closed_read(VALUE self)
@@ -600,7 +670,14 @@ strio_closed_read(VALUE self)
600
670
  * call-seq:
601
671
  * closed_write? -> true or false
602
672
  *
603
- * Returns +true+ if +self+ is closed for writing, +false+ otherwise.
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?.
604
681
  */
605
682
  static VALUE
606
683
  strio_closed_write(VALUE self)
@@ -614,19 +691,26 @@ static struct StringIO *
614
691
  strio_to_read(VALUE self)
615
692
  {
616
693
  struct StringIO *ptr = readable(self);
617
- if (NIL_P(ptr->string)) return NULL;
618
- if (ptr->pos < RSTRING_LEN(ptr->string)) return ptr;
619
- return NULL;
694
+ if (eos_p(ptr)) return NULL;
695
+ return ptr;
620
696
  }
621
697
 
622
698
  /*
623
699
  * call-seq:
624
700
  * eof? -> true or false
625
701
  *
626
- * Returns +true+ if positioned at end-of-stream, +false+ otherwise;
627
- * see {Position}[rdoc-ref:IO@Position].
702
+ * Returns whether +self+ is positioned at end-of-stream:
628
703
  *
629
- * Raises IOError if the stream is not opened for reading.
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
712
+ *
713
+ * Related: StringIO#pos.
630
714
  */
631
715
  static VALUE
632
716
  strio_eof(VALUE self)
@@ -663,7 +747,7 @@ strio_copy(VALUE copy, VALUE orig)
663
747
  * lineno -> current_line_number
664
748
  *
665
749
  * Returns the current line number in +self+;
666
- * see {Line Number}[rdoc-ref:IO@Line+Number].
750
+ * see {Line Number}[rdoc-ref:StringIO@Line+Number].
667
751
  */
668
752
  static VALUE
669
753
  strio_get_lineno(VALUE self)
@@ -676,7 +760,7 @@ strio_get_lineno(VALUE self)
676
760
  * lineno = new_line_number -> new_line_number
677
761
  *
678
762
  * Sets the current line number in +self+ to the given +new_line_number+;
679
- * see {Line Number}[rdoc-ref:IO@Line+Number].
763
+ * see {Line Number}[rdoc-ref:StringIO@Line+Number].
680
764
  */
681
765
  static VALUE
682
766
  strio_set_lineno(VALUE self, VALUE lineno)
@@ -690,7 +774,7 @@ strio_set_lineno(VALUE self, VALUE lineno)
690
774
  * binmode -> self
691
775
  *
692
776
  * Sets the data mode in +self+ to binary mode;
693
- * see {Data Mode}[rdoc-ref:File@Data+Mode].
777
+ * see {Data Mode}[rdoc-ref:StringIO@Data+Mode].
694
778
  *
695
779
  */
696
780
  static VALUE
@@ -751,7 +835,7 @@ strio_reopen(int argc, VALUE *argv, VALUE self)
751
835
  * pos -> stream_position
752
836
  *
753
837
  * Returns the current position (in bytes);
754
- * see {Position}[rdoc-ref:IO@Position].
838
+ * see {Position}[rdoc-ref:StringIO@Position].
755
839
  */
756
840
  static VALUE
757
841
  strio_get_pos(VALUE self)
@@ -764,7 +848,7 @@ strio_get_pos(VALUE self)
764
848
  * pos = new_position -> new_position
765
849
  *
766
850
  * Sets the current position (in bytes);
767
- * see {Position}[rdoc-ref:IO@Position].
851
+ * see {Position}[rdoc-ref:StringIO@Position].
768
852
  */
769
853
  static VALUE
770
854
  strio_set_pos(VALUE self, VALUE pos)
@@ -799,9 +883,9 @@ strio_rewind(VALUE self)
799
883
  * call-seq:
800
884
  * seek(offset, whence = SEEK_SET) -> 0
801
885
  *
802
- * Sets the current position to the given integer +offset+ (in bytes),
886
+ * Sets the position to the given integer +offset+ (in bytes),
803
887
  * with respect to a given constant +whence+;
804
- * see {Position}[rdoc-ref:IO@Position].
888
+ * see {IO#seek}[https://docs.ruby-lang.org/en/master/IO.html#method-i-seek].
805
889
  */
806
890
  static VALUE
807
891
  strio_seek(int argc, VALUE *argv, VALUE self)
@@ -823,7 +907,11 @@ strio_seek(int argc, VALUE *argv, VALUE self)
823
907
  offset = ptr->pos;
824
908
  break;
825
909
  case 2:
826
- offset = RSTRING_LEN(ptr->string);
910
+ if (NIL_P(ptr->string)) {
911
+ offset = 0;
912
+ } else {
913
+ offset = RSTRING_LEN(ptr->string);
914
+ }
827
915
  break;
828
916
  default:
829
917
  error_inval("invalid whence");
@@ -856,10 +944,9 @@ strio_get_sync(VALUE self)
856
944
  * call-seq:
857
945
  * each_byte {|byte| ... } -> self
858
946
  *
859
- * With a block given, calls the block with each remaining byte in the stream;
860
- * see {Byte IO}[rdoc-ref:IO@Byte+IO].
947
+ * :include: stringio/each_byte.rdoc
861
948
  *
862
- * With no block given, returns an enumerator.
949
+ * Related: StringIO#each_char, StringIO#each_codepoint, StringIO#each_line.
863
950
  */
864
951
  static VALUE
865
952
  strio_each_byte(VALUE self)
@@ -877,10 +964,10 @@ strio_each_byte(VALUE self)
877
964
 
878
965
  /*
879
966
  * call-seq:
880
- * getc -> character or nil
967
+ * getc -> character, byte, or nil
968
+ *
969
+ * :include: stringio/getc.rdoc
881
970
  *
882
- * Reads and returns the next character from the stream;
883
- * see {Character IO}[rdoc-ref:IO@Character+IO].
884
971
  */
885
972
  static VALUE
886
973
  strio_getc(VALUE self)
@@ -892,7 +979,7 @@ strio_getc(VALUE self)
892
979
  int len;
893
980
  char *p;
894
981
 
895
- if (NIL_P(str) || pos >= RSTRING_LEN(str)) {
982
+ if (eos_p(ptr)) {
896
983
  return Qnil;
897
984
  }
898
985
  p = RSTRING_PTR(str)+pos;
@@ -903,17 +990,17 @@ strio_getc(VALUE self)
903
990
 
904
991
  /*
905
992
  * call-seq:
906
- * getbyte -> byte or nil
993
+ * getbyte -> integer or nil
994
+ *
995
+ * :include: stringio/getbyte.rdoc
907
996
  *
908
- * Reads and returns the next 8-bit byte from the stream;
909
- * see {Byte IO}[rdoc-ref:IO@Byte+IO].
910
997
  */
911
998
  static VALUE
912
999
  strio_getbyte(VALUE self)
913
1000
  {
914
1001
  struct StringIO *ptr = readable(self);
915
1002
  int c;
916
- if (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string)) {
1003
+ if (eos_p(ptr)) {
917
1004
  return Qnil;
918
1005
  }
919
1006
  c = RSTRING_PTR(ptr->string)[ptr->pos++];
@@ -1082,12 +1169,11 @@ strio_readbyte(VALUE self)
1082
1169
 
1083
1170
  /*
1084
1171
  * call-seq:
1085
- * each_char {|c| ... } -> self
1172
+ * each_char {|char| ... } -> self
1086
1173
  *
1087
- * With a block given, calls the block with each remaining character in the stream;
1088
- * see {Character IO}[rdoc-ref:IO@Character+IO].
1174
+ * :include: stringio/each_char.rdoc
1089
1175
  *
1090
- * With no block given, returns an enumerator.
1176
+ * Related: StringIO#each_byte, StringIO#each_codepoint, StringIO#each_line.
1091
1177
  */
1092
1178
  static VALUE
1093
1179
  strio_each_char(VALUE self)
@@ -1106,10 +1192,9 @@ strio_each_char(VALUE self)
1106
1192
  * call-seq:
1107
1193
  * each_codepoint {|codepoint| ... } -> self
1108
1194
  *
1109
- * With a block given, calls the block with each remaining codepoint in the stream;
1110
- * see {Codepoint IO}[rdoc-ref:IO@Codepoint+IO].
1195
+ * :include: stringio/each_codepoint.rdoc
1111
1196
  *
1112
- * With no block given, returns an enumerator.
1197
+ * Related: StringIO#each_byte, StringIO#each_char, StringIO#each_line.
1113
1198
  */
1114
1199
  static VALUE
1115
1200
  strio_each_codepoint(VALUE self)
@@ -1343,9 +1428,8 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
1343
1428
  * gets(limit, chomp: false) -> string or nil
1344
1429
  * gets(sep, limit, chomp: false) -> string or nil
1345
1430
  *
1346
- * Reads and returns a line from the stream;
1347
- * assigns the return value to <tt>$_</tt>;
1348
- * see {Line IO}[rdoc-ref:IO@Line+IO].
1431
+ * :include: stringio/gets.rdoc
1432
+ *
1349
1433
  */
1350
1434
  static VALUE
1351
1435
  strio_gets(int argc, VALUE *argv, VALUE self)
@@ -1382,15 +1466,15 @@ strio_readline(int argc, VALUE *argv, VALUE self)
1382
1466
  }
1383
1467
 
1384
1468
  /*
1469
+ * :markup: markdown
1470
+ *
1385
1471
  * call-seq:
1386
1472
  * each_line(sep = $/, chomp: false) {|line| ... } -> self
1387
1473
  * each_line(limit, chomp: false) {|line| ... } -> self
1388
1474
  * each_line(sep, limit, chomp: false) {|line| ... } -> self
1389
1475
  *
1390
- * Calls the block with each remaining line read from the stream;
1391
- * does nothing if already at end-of-file;
1392
- * returns +self+.
1393
- * See {Line IO}[rdoc-ref:IO@Line+IO].
1476
+ * :include: stringio/each_line.md
1477
+ *
1394
1478
  */
1395
1479
  static VALUE
1396
1480
  strio_each(int argc, VALUE *argv, VALUE self)
@@ -1591,10 +1675,9 @@ strio_read(int argc, VALUE *argv, VALUE self)
1591
1675
  if (len < 0) {
1592
1676
  rb_raise(rb_eArgError, "negative length %ld given", len);
1593
1677
  }
1594
- if (len > 0 &&
1595
- (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string))) {
1678
+ if (eos_p(ptr)) {
1596
1679
  if (!NIL_P(str)) rb_str_resize(str, 0);
1597
- return Qnil;
1680
+ return len > 0 ? Qnil : rb_str_new(0, 0);
1598
1681
  }
1599
1682
  binary = 1;
1600
1683
  break;
@@ -1670,7 +1753,7 @@ strio_pread(int argc, VALUE *argv, VALUE self)
1670
1753
 
1671
1754
  struct StringIO *ptr = readable(self);
1672
1755
 
1673
- if (offset >= RSTRING_LEN(ptr->string)) {
1756
+ if (outside_p(ptr, offset)) {
1674
1757
  rb_eof_error();
1675
1758
  }
1676
1759
 
@@ -1760,10 +1843,10 @@ strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
1760
1843
 
1761
1844
  /*
1762
1845
  * call-seq:
1763
- * strio.length -> integer
1764
- * strio.size -> integer
1846
+ * size -> integer
1847
+ *
1848
+ * :include: stringio/size.rdoc
1765
1849
  *
1766
- * Returns the size of the buffer string.
1767
1850
  */
1768
1851
  static VALUE
1769
1852
  strio_size(VALUE self)
@@ -1801,12 +1884,20 @@ strio_truncate(VALUE self, VALUE len)
1801
1884
  }
1802
1885
 
1803
1886
  /*
1804
- * call-seq:
1805
- * strio.external_encoding => encoding
1887
+ * call-seq:
1888
+ * external_encoding -> encoding or nil
1889
+ *
1890
+ * Returns an Encoding object that represents the encoding of the string;
1891
+ * see {Encodings}[rdoc-ref:StringIO@Encodings]:
1892
+ *
1893
+ * strio = StringIO.new('foo')
1894
+ * strio.external_encoding # => #<Encoding:UTF-8>
1895
+ *
1896
+ * Returns +nil+ if +self+ has no string and is in write mode:
1897
+ *
1898
+ * strio = StringIO.new(nil, 'w+')
1899
+ * strio.external_encoding # => nil
1806
1900
  *
1807
- * Returns the Encoding object that represents the encoding of the file.
1808
- * If the stream is write mode and no encoding is specified, returns
1809
- * +nil+.
1810
1901
  */
1811
1902
 
1812
1903
  static VALUE
@@ -1818,10 +1909,9 @@ strio_external_encoding(VALUE self)
1818
1909
 
1819
1910
  /*
1820
1911
  * call-seq:
1821
- * strio.internal_encoding => encoding
1912
+ * internal_encoding -> nil
1822
1913
  *
1823
- * Returns the Encoding of the internal string if conversion is
1824
- * specified. Otherwise returns +nil+.
1914
+ * Returns +nil+; for compatibility with IO.
1825
1915
  */
1826
1916
 
1827
1917
  static VALUE
@@ -1864,7 +1954,7 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self)
1864
1954
  }
1865
1955
  }
1866
1956
  ptr->enc = enc;
1867
- if (!NIL_P(ptr->string) && WRITABLE(self)) {
1957
+ if (!NIL_P(ptr->string) && WRITABLE(self) && !str_chilled_p(ptr->string)) {
1868
1958
  rb_enc_associate(ptr->string, enc);
1869
1959
  }
1870
1960
 
@@ -1890,16 +1980,9 @@ strio_set_encoding_by_bom(VALUE self)
1890
1980
  }
1891
1981
 
1892
1982
  /*
1893
- * \IO streams for strings, with access similar to
1894
- * {IO}[rdoc-ref:IO];
1895
- * see {IO}[rdoc-ref:IO].
1896
- *
1897
- * === About the Examples
1898
- *
1899
- * Examples on this page assume that \StringIO has been required:
1900
- *
1901
- * require 'stringio'
1983
+ * :markup: markdown
1902
1984
  *
1985
+ * :include: stringio/stringio.md
1903
1986
  */
1904
1987
  void
1905
1988
  Init_stringio(void)
@@ -1907,7 +1990,7 @@ Init_stringio(void)
1907
1990
  #undef rb_intern
1908
1991
 
1909
1992
  #ifdef HAVE_RB_EXT_RACTOR_SAFE
1910
- rb_ext_ractor_safe(true);
1993
+ rb_ext_ractor_safe(true);
1911
1994
  #endif
1912
1995
 
1913
1996
  VALUE StringIO = rb_define_class("StringIO", rb_cObject);
@@ -1999,7 +2082,9 @@ Init_stringio(void)
1999
2082
  rb_define_method(StringIO, "set_encoding_by_bom", strio_set_encoding_by_bom, 0);
2000
2083
 
2001
2084
  {
2085
+ /* :stopdoc: */
2002
2086
  VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
2087
+ /* :startdoc: */
2003
2088
  rb_define_method(mReadable, "readchar", strio_readchar, 0);
2004
2089
  rb_define_method(mReadable, "readbyte", strio_readbyte, 0);
2005
2090
  rb_define_method(mReadable, "readline", strio_readline, -1);
@@ -2009,7 +2094,9 @@ Init_stringio(void)
2009
2094
  rb_include_module(StringIO, mReadable);
2010
2095
  }
2011
2096
  {
2097
+ /* :stopdoc: */
2012
2098
  VALUE mWritable = rb_define_module_under(rb_cIO, "generic_writable");
2099
+ /* :startdoc: */
2013
2100
  rb_define_method(mWritable, "<<", strio_addstr, 1);
2014
2101
  rb_define_method(mWritable, "print", strio_print, -1);
2015
2102
  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.7
4
+ version: 3.2.0
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-04-21 00:00:00.000000000 Z
11
+ date: 2025-12-17 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.7
45
+ changelog_uri: https://github.com/ruby/stringio/releases/tag/v3.2.0
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.7
60
+ rubygems_version: 3.6.9
61
61
  specification_version: 4
62
62
  summary: Pseudo IO on String
63
63
  test_files: []