stringio 3.1.7 → 3.1.9

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: 82c38ce8a492167984eccc4291f550ec4f16c82708e9a11412e6636b5d8c0f3a
4
+ data.tar.gz: 78853fef7518aafb4fbdec810923d4ba6c05149cf03e9e998a93c98e2de1a82e
5
5
  SHA512:
6
- metadata.gz: 6c3f11fa1dee2b8e00269cad5e99db7014ecdc7b1b7d99f5086d15fb3f04d17105dabd838887e5f87af817851e2a8a59260c7c7af26a5ea40f2ce103ad830775
7
- data.tar.gz: c9e2afe1c8104c27591454cfeefdc71926c76196d3afc343f76052b9e465566f62df19ae25baaa1217839684910b0c94e4d05b7b08723f1960065f0c2d0844df
6
+ metadata.gz: 3015bd4fa76347c286fc9da21ff751ebc17dcbf6980440c4247ad946901a435c4a31b63085ab5c74d9d55893e43f0e15d11acf34872cd2e16f49591961834cf5
7
+ data.tar.gz: 07a0567e7ef8e667c979cedcc6af3a26934100df077b8054b578b1632593a0a0f490c03c54c447844380bca39ec6fabbb4be837eb3961a9363078e41e38ff763
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,69 @@
1
1
  # News
2
2
 
3
+ ## 3.1.9 - 2025-12-01
4
+
5
+ ### Improvements
6
+
7
+ * [DOC] Tweaks for StringIO#each_line
8
+ * GH-165
9
+
10
+ * [DOC] Doc for StringIO.size
11
+ * GH-175
12
+
13
+ * [DOC] Tweaks for StringIO#fsync
14
+ * GH-173
15
+
16
+ * [DOC] Fix #seek link
17
+ * GH-174
18
+
19
+ * Add a note about chilled string support to 3.1.8 release note
20
+ * GH-180 fixes GH-179
21
+
22
+ ### Fixes
23
+
24
+ * JRuby: Removed use of RubyBasicObject.flags
25
+ * GH-182
26
+
27
+ ### Thanks
28
+
29
+ * Burdette Lamar
30
+
31
+ * Charles Oliver Nutter
32
+
33
+ ## 3.1.8 - 2025-11-12
34
+
35
+ ### Improvements
36
+
37
+ * Improved documents
38
+ * Patch by Burdette Lamar
39
+
40
+ * Improved chilled string support
41
+ * GH-128
42
+
43
+ ### Fixes
44
+
45
+ * Fixed SEGV in `StringIO#seek` with `SEEK_END` on `StringIO.new(nil)`
46
+ * GH-137
47
+ * Patch by koh-sh
48
+
49
+ * Fixed SEGV in `StringIO#read` on `StringIO.new(nil)`
50
+
51
+ * Fixed SEGV in `StringIO#pread` on `StringIO.new(nil)`
52
+
53
+ * Fixed SEGV in `StringIO#eof?` on `StringIO.new(nil)`
54
+
55
+ * JRuby: Fixed a bug that `StringIO#read` doesn't clear code range
56
+ * GH-156
57
+ * Patch by Karol Bucek
58
+
59
+ ### Thanks
60
+
61
+ * koh-sh
62
+
63
+ * Burdette Lamar
64
+
65
+ * Karol Bucek
66
+
3
67
  ## 3.1.7 - 2025-04-21
4
68
 
5
69
  ### 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.1.9";
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:
230
+ *
231
+ * strio = StringIO.new
232
+ * strio.string # => ""
233
+ * strio.closed_read? # => false
234
+ * strio.closed_write? # => false
235
+ * strio.close
236
+ *
237
+ * If +string+ is frozen, the default +mode+ is <tt>'r'</tt>:
206
238
  *
207
- * strio = StringIO.new # => #<StringIO>
239
+ * strio = StringIO.new('foo'.freeze)
240
+ * strio.string # => "foo"
241
+ * strio.closed_read? # => false
242
+ * strio.closed_write? # => true
208
243
  * strio.close
209
244
  *
210
- * The instance should be closed when no longer needed.
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)
211
251
  *
212
- * Related: StringIO.open (accepts block; closes automatically).
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)
@@ -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}[https://docs.ruby-lang.org/en/master/File.html#class-File-label-Data+Mode].
694
778
  *
695
779
  */
696
780
  static VALUE
@@ -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 {Encoding}[https://docs.ruby-lang.org/en/master/Encoding.html]:
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.1.9
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-02 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.1.9
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: []