stringio 3.1.0 → 3.1.2

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: 67351f85af240c4189d6d1eaf805bfade85b9aae65d930326ec1c6930c5ba9c9
4
- data.tar.gz: 51016af4762d130788a7f80798fafd346225f67c86096f95e7f3f2f5244d8b17
3
+ metadata.gz: 89f7a19f0a8689e3fa7ceae8a0139eab614a14f64f2d1f5831c0d012d3b49dac
4
+ data.tar.gz: 71b2022cc337d594566c0dfcb215bc1f3d4949747c97ffb984ea0613f67d58aa
5
5
  SHA512:
6
- metadata.gz: 6e15df64d01a1592cf7ca5f0024cdd693494c5db5c5cfcf9e7d4662c3f8a8c8cdadf2032e72c80d1baa2110c6310f4e6e0fdc96926eee53095ddf443caab9b5c
7
- data.tar.gz: 50dafc1b4c0de2e659860b00b6d6e6ef43eedba1cf059956d86acc9f9bb6c28c3924ef5ff3e5b7ba8719afc5366bf1cebf9a0e67b1e1a918a1347aa28f18ea0c
6
+ metadata.gz: e6aa9ba1567fe2ea15f973a81ef8ae215be4ea7b88013dd9a4d9e8cbd8d1d0381dd70980ffb049d8b4283e0b1e6e586ef840618c8f129f1182c71bfa95847824
7
+ data.tar.gz: ed2fd455cbe0f072ef020f2b6a114ae192a8a86509cebcb927fb4c7b9754551bdda8519ebc7aa21b6cbf2b3c0cab4170e5017c0468ad4431ea4b9eaf9c473825
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ COPYING
2
+ *.md
3
+ *.txt
4
+ docs/
5
+ ext/stringio/
data/.rdoc_options ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ main_page: README.md
data/COPYING 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.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
data/NEWS.md ADDED
@@ -0,0 +1,185 @@
1
+ # News
2
+
3
+ ## 3.1.2 - 2024-11-07
4
+
5
+ ### Improvements
6
+
7
+ * JRuby: Added support for detecting encoding by BOM.
8
+ * GH-100
9
+ * GH-101
10
+
11
+ ### Fixes
12
+
13
+ * CRuby: Fixed a bug that unknown memory may be used by
14
+ `StringIO#ungetc`/`StringIO#ungetbyte`.
15
+ * https://hackerone.com/reports/2805165
16
+ * Reported by manun.
17
+
18
+ ### Thanks
19
+
20
+ * manun
21
+
22
+ ## 3.1.1 - 2024-06-13
23
+
24
+ ### Improvements
25
+
26
+ * JRuby: Improved.
27
+ * GH-83
28
+ * GH-84
29
+ * GH-85
30
+
31
+ * Added `StringIO::MAX_LENGTH`.
32
+
33
+ * Added support for NULL `StringIO` by `StringIO.new(nil)`.
34
+
35
+ * Improved IO compatibility for partial read.
36
+ * GH-95
37
+ * https://bugs.ruby-lang.org/issues/20418
38
+
39
+ ### Fixes
40
+
41
+ * Fixed a bug that coderange isn't updated after overwrite.
42
+ * Reported by Tiago Cardoso.
43
+ * https://bugs.ruby-lang.org/issues/20185
44
+ * GH-77
45
+ * GH-79
46
+
47
+ ### Thanks
48
+
49
+ * Tiago Cardoso
50
+
51
+ ## 3.1.0 - 2023-11-28
52
+
53
+ ### Fixes
54
+
55
+ * TruffleRuby: Do not compile the C extension
56
+
57
+ GH-71
58
+
59
+ ## 3.0.9 - 2023-11-08
60
+
61
+ ### Improvements
62
+
63
+ * JRuby: Aligned `StringIO#gets` behavior with the C implementation.
64
+
65
+ GH-61
66
+
67
+ ### Fixes
68
+
69
+ * CRuby: Fixed `StringIO#pread` with the length 0.
70
+
71
+ Patch by Jean byroot Boussier.
72
+
73
+ GH-67
74
+
75
+ * CRuby: Fixed a bug that `StringIO#gets` with non ASCII compatible
76
+ encoding such as UTF-16 doesn't detect correct new line characters.
77
+
78
+ Reported by IWAMOTO Kouichi.
79
+
80
+ GH-68
81
+
82
+ ### Thanks
83
+
84
+ * Jean byroot Boussier
85
+
86
+ * IWAMOTO Kouichi
87
+
88
+ ## 3.0.8 - 2023-08-10
89
+
90
+ ### Improvements
91
+
92
+ * Added `StringIO#pread`.
93
+
94
+ Patch by Jean byroot Boussier.
95
+
96
+ GH-56
97
+
98
+ * JRuby: Added `StringIO::VERSION`.
99
+
100
+ GH-57 GH-59
101
+
102
+ ### Thanks
103
+
104
+ * Jean byroot Boussier
105
+
106
+ ## 3.0.7 - 2023-06-02
107
+
108
+ * CRuby: Avoid direct struct usage. This change is for supporting
109
+ Ruby 3.3.
110
+
111
+ GH-54
112
+
113
+ ## 3.0.6 - 2023-04-14
114
+
115
+ ### Improvements
116
+
117
+ * CRuby: Added support for write barrier.
118
+
119
+ * JRuby: Added missing arty-checking.
120
+
121
+ GH-48
122
+
123
+ * JRuby: Added support for `StringIO.new(encoding:)`.
124
+
125
+ GH-45
126
+
127
+ ## 3.0.5 - 2023-02-02
128
+
129
+ ### Improvements
130
+
131
+ ### Fixes
132
+
133
+ * Fixed a bug that `StringIO#gets("2+ character", chomp: true)` did not
134
+ remove the separator at the end.
135
+ [[Bug #19389](https://bugs.ruby-lang.org/issues/19389)]
136
+
137
+ ## 3.0.4 - 2022-12-09
138
+
139
+ ### Improvements
140
+
141
+ * JRuby: Changed to use flag registry.
142
+ [[GitHub#33](https://github.com/ruby/stringio/pull/26)]
143
+
144
+ ## 3.0.3 - 2022-12-08
145
+
146
+ ### Improvements
147
+
148
+ * Improved documents.
149
+ [[GitHub#33](https://github.com/ruby/stringio/pull/33)]
150
+ [[GitHub#34](https://github.com/ruby/stringio/pull/34)]
151
+ [[GitHub#35](https://github.com/ruby/stringio/pull/35)]
152
+ [[GitHub#36](https://github.com/ruby/stringio/pull/36)]
153
+ [[GitHub#37](https://github.com/ruby/stringio/pull/37)]
154
+ [Patch by Burdette Lamar]
155
+
156
+ ### Fixes
157
+
158
+ * Fixed a bug that large `StringIO#ungetc`/`StringIO#ungetbyte`
159
+ break internal buffer.
160
+
161
+ * Fixed a bug that `StringIO#each("2+ character", chomp: true)` cause
162
+ infinite loop.
163
+ [[Bug #18769](https://bugs.ruby-lang.org/issues/18769)]
164
+
165
+ * Fixed a bug that `StringIO#each(nil, chomp: true)` chomps.
166
+ [[Bug #18770](https://bugs.ruby-lang.org/issues/18770)]
167
+
168
+ * Fixed a bug that `StringIO#each("", chomp: true)` isn't compatible
169
+ with `IO#each("", chomp: true)`.
170
+ [[Bug #18768](https://bugs.ruby-lang.org/issues/18768)]
171
+
172
+ * Fixed a bug that `StringIO#set_encoding` doesn't accept external
173
+ and internal encodings pairo.
174
+ [[GitHub#16](https://github.com/ruby/stringio/issues/16)]
175
+ [Reported by Kenta Murata]
176
+
177
+ * Fixed a bug that `StringIO#truncate` isn't compatible with
178
+ `File#truncate`.
179
+
180
+ ### Thanks
181
+
182
+ * Kenta Murata
183
+
184
+ * Burdette Lamar
185
+
data/README.md CHANGED
@@ -12,7 +12,7 @@ This library is based on MoonWolf version written in Ruby. Thanks a lot.
12
12
 
13
13
  * `fileno` raises `NotImplementedError`.
14
14
  * encoding conversion is not implemented, and ignored silently.
15
- * there is no `#to_io` method because this is not an `IO.
15
+ * there is no `#to_io` method because this is not an `IO`.
16
16
 
17
17
  ## Installation
18
18
 
data/docs/io.rb ADDED
@@ -0,0 +1,8 @@
1
+ # :stopdoc:
2
+ class IO
3
+ module generic_readable
4
+ end
5
+ module generic_writable
6
+ end
7
+ end
8
+ # :startdoc:
@@ -0,0 +1 @@
1
+ *.[ch]
@@ -13,7 +13,9 @@
13
13
  **********************************************************************/
14
14
 
15
15
  static const char *const
16
- STRINGIO_VERSION = "3.1.0";
16
+ STRINGIO_VERSION = "3.1.2";
17
+
18
+ #include <stdbool.h>
17
19
 
18
20
  #include "ruby.h"
19
21
  #include "ruby/io.h"
@@ -48,7 +50,13 @@ static long strio_write(VALUE self, VALUE str);
48
50
 
49
51
  #define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
50
52
  #define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
51
- #define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string))
53
+ #define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : !NIL_P((ptr)->string) ? rb_enc_get((ptr)->string) : NULL)
54
+
55
+ static bool
56
+ readonly_string_p(VALUE string)
57
+ {
58
+ return OBJ_FROZEN_RAW(string);
59
+ }
52
60
 
53
61
  static struct StringIO *
54
62
  strio_alloc(void)
@@ -166,7 +174,10 @@ writable(VALUE strio)
166
174
  static void
167
175
  check_modifiable(struct StringIO *ptr)
168
176
  {
169
- if (OBJ_FROZEN(ptr->string)) {
177
+ if (NIL_P(ptr->string)) {
178
+ /* Null device StringIO */
179
+ }
180
+ else if (OBJ_FROZEN_RAW(ptr->string)) {
170
181
  rb_raise(rb_eIOError, "not modifiable string");
171
182
  }
172
183
  }
@@ -281,13 +292,14 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
281
292
 
282
293
  argc = rb_scan_args(argc, argv, "02:", &string, &vmode, &opt);
283
294
  rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &ptr->flags, &convconfig);
284
- if (argc) {
295
+ if (!NIL_P(string)) {
285
296
  StringValue(string);
286
297
  }
287
- else {
298
+ else if (!argc) {
288
299
  string = rb_enc_str_new("", 0, rb_default_external_encoding());
289
300
  }
290
- if (OBJ_FROZEN_RAW(string)) {
301
+
302
+ if (!NIL_P(string) && readonly_string_p(string)) {
291
303
  if (ptr->flags & FMODE_WRITABLE) {
292
304
  rb_syserr_fail(EACCES, 0);
293
305
  }
@@ -297,11 +309,11 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
297
309
  ptr->flags |= FMODE_WRITABLE;
298
310
  }
299
311
  }
300
- if (ptr->flags & FMODE_TRUNC) {
312
+ if (!NIL_P(string) && (ptr->flags & FMODE_TRUNC)) {
301
313
  rb_str_resize(string, 0);
302
314
  }
303
315
  RB_OBJ_WRITE(self, &ptr->string, string);
304
- if (argc == 1) {
316
+ if (argc == 1 && !NIL_P(string)) {
305
317
  ptr->enc = rb_enc_get(string);
306
318
  }
307
319
  else {
@@ -481,7 +493,7 @@ strio_set_string(VALUE self, VALUE string)
481
493
  rb_io_taint_check(self);
482
494
  ptr->flags &= ~FMODE_READWRITE;
483
495
  StringValue(string);
484
- ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
496
+ ptr->flags = readonly_string_p(string) ? FMODE_READABLE : FMODE_READWRITE;
485
497
  ptr->pos = 0;
486
498
  ptr->lineno = 0;
487
499
  RB_OBJ_WRITE(self, &ptr->string, string);
@@ -595,6 +607,7 @@ static struct StringIO *
595
607
  strio_to_read(VALUE self)
596
608
  {
597
609
  struct StringIO *ptr = readable(self);
610
+ if (NIL_P(ptr->string)) return NULL;
598
611
  if (ptr->pos < RSTRING_LEN(ptr->string)) return ptr;
599
612
  return NULL;
600
613
  }
@@ -872,7 +885,7 @@ strio_getc(VALUE self)
872
885
  int len;
873
886
  char *p;
874
887
 
875
- if (pos >= RSTRING_LEN(str)) {
888
+ if (NIL_P(str) || pos >= RSTRING_LEN(str)) {
876
889
  return Qnil;
877
890
  }
878
891
  p = RSTRING_PTR(str)+pos;
@@ -893,7 +906,7 @@ strio_getbyte(VALUE self)
893
906
  {
894
907
  struct StringIO *ptr = readable(self);
895
908
  int c;
896
- if (ptr->pos >= RSTRING_LEN(ptr->string)) {
909
+ if (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string)) {
897
910
  return Qnil;
898
911
  }
899
912
  c = RSTRING_PTR(ptr->string)[ptr->pos++];
@@ -915,8 +928,17 @@ strio_extend(struct StringIO *ptr, long pos, long len)
915
928
  if (pos > olen)
916
929
  MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen);
917
930
  }
918
- else {
919
- rb_str_modify(ptr->string);
931
+ }
932
+
933
+ static void
934
+ strio_unget_string(struct StringIO *ptr, VALUE c)
935
+ {
936
+ const char *cp = NULL;
937
+ long cl = RSTRING_LEN(c);
938
+ if (cl > 0) {
939
+ if (c != ptr->string) cp = RSTRING_PTR(c);
940
+ strio_unget_bytes(ptr, cp, cl);
941
+ RB_GC_GUARD(c);
920
942
  }
921
943
  }
922
944
 
@@ -934,6 +956,7 @@ strio_ungetc(VALUE self, VALUE c)
934
956
  rb_encoding *enc, *enc2;
935
957
 
936
958
  check_modifiable(ptr);
959
+ if (NIL_P(ptr->string)) return Qnil;
937
960
  if (NIL_P(c)) return Qnil;
938
961
  if (RB_INTEGER_TYPE_P(c)) {
939
962
  int len, cc = NUM2INT(c);
@@ -941,19 +964,22 @@ strio_ungetc(VALUE self, VALUE c)
941
964
 
942
965
  enc = rb_enc_get(ptr->string);
943
966
  len = rb_enc_codelen(cc, enc);
944
- if (len <= 0) rb_enc_uint_chr(cc, enc);
967
+ if (len <= 0) {
968
+ rb_enc_uint_chr(cc, enc); /* to raise an exception */
969
+ UNREACHABLE;
970
+ }
945
971
  rb_enc_mbcput(cc, buf, enc);
946
972
  return strio_unget_bytes(ptr, buf, len);
947
973
  }
948
974
  else {
949
- SafeStringValue(c);
975
+ StringValue(c);
976
+ if (RSTRING_LEN(c) == 0) return Qnil;
950
977
  enc = rb_enc_get(ptr->string);
951
978
  enc2 = rb_enc_get(c);
952
979
  if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
953
980
  c = rb_str_conv_enc(c, enc2, enc);
954
981
  }
955
- strio_unget_bytes(ptr, RSTRING_PTR(c), RSTRING_LEN(c));
956
- RB_GC_GUARD(c);
982
+ strio_unget_string(ptr, c);
957
983
  return Qnil;
958
984
  }
959
985
  }
@@ -971,21 +997,17 @@ strio_ungetbyte(VALUE self, VALUE c)
971
997
  struct StringIO *ptr = readable(self);
972
998
 
973
999
  check_modifiable(ptr);
1000
+ if (NIL_P(ptr->string)) return Qnil;
974
1001
  if (NIL_P(c)) return Qnil;
975
1002
  if (RB_INTEGER_TYPE_P(c)) {
976
- /* rb_int_and() not visible from exts */
977
- VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
978
- const char cc = NUM2INT(v) & 0xFF;
979
- strio_unget_bytes(ptr, &cc, 1);
1003
+ /* rb_int_and() not visible from exts */
1004
+ VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
1005
+ const char cc = NUM2INT(v) & 0xFF;
1006
+ strio_unget_bytes(ptr, &cc, 1);
980
1007
  }
981
1008
  else {
982
- long cl;
983
- SafeStringValue(c);
984
- cl = RSTRING_LEN(c);
985
- if (cl > 0) {
986
- strio_unget_bytes(ptr, RSTRING_PTR(c), cl);
987
- RB_GC_GUARD(c);
988
- }
1009
+ StringValue(c);
1010
+ strio_unget_string(ptr, c);
989
1011
  }
990
1012
  return Qnil;
991
1013
  }
@@ -1016,7 +1038,7 @@ strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
1016
1038
  if (rest > cl) memset(s + len, 0, rest - cl);
1017
1039
  pos -= cl;
1018
1040
  }
1019
- memcpy(s + pos, cp, cl);
1041
+ memcpy(s + pos, (cp ? cp : s), cl);
1020
1042
  ptr->pos = pos;
1021
1043
  return Qnil;
1022
1044
  }
@@ -1157,41 +1179,41 @@ prepare_getline_args(struct StringIO *ptr, struct getline_arg *arg, int argc, VA
1157
1179
  break;
1158
1180
 
1159
1181
  case 1:
1160
- if (!NIL_P(rs) && !RB_TYPE_P(rs, T_STRING)) {
1161
- VALUE tmp = rb_check_string_type(rs);
1182
+ if (!NIL_P(rs) && !RB_TYPE_P(rs, T_STRING)) {
1183
+ VALUE tmp = rb_check_string_type(rs);
1162
1184
  if (NIL_P(tmp)) {
1163
- limit = NUM2LONG(rs);
1164
- rs = rb_rs;
1185
+ limit = NUM2LONG(rs);
1186
+ rs = rb_rs;
1165
1187
  }
1166
1188
  else {
1167
- rs = tmp;
1189
+ rs = tmp;
1168
1190
  }
1169
1191
  }
1170
1192
  break;
1171
1193
 
1172
1194
  case 2:
1173
- if (!NIL_P(rs)) StringValue(rs);
1195
+ if (!NIL_P(rs)) StringValue(rs);
1174
1196
  if (!NIL_P(lim)) limit = NUM2LONG(lim);
1175
1197
  break;
1176
1198
  }
1177
- if (!NIL_P(rs)) {
1178
- rb_encoding *enc_rs, *enc_io;
1179
- enc_rs = rb_enc_get(rs);
1180
- enc_io = get_enc(ptr);
1181
- if (enc_rs != enc_io &&
1182
- (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
1183
- (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
1184
- if (rs == rb_rs) {
1185
- rs = rb_enc_str_new(0, 0, enc_io);
1186
- rb_str_buf_cat_ascii(rs, "\n");
1187
- rs = rs;
1188
- }
1189
- else {
1190
- rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
1191
- rb_enc_name(enc_io),
1192
- rb_enc_name(enc_rs));
1193
- }
1194
- }
1199
+ if (!NIL_P(ptr->string) && !NIL_P(rs)) {
1200
+ rb_encoding *enc_rs, *enc_io;
1201
+ enc_rs = rb_enc_get(rs);
1202
+ enc_io = get_enc(ptr);
1203
+ if (enc_rs != enc_io &&
1204
+ (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
1205
+ (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
1206
+ if (rs == rb_rs) {
1207
+ rs = rb_enc_str_new(0, 0, enc_io);
1208
+ rb_str_buf_cat_ascii(rs, "\n");
1209
+ rs = rs;
1210
+ }
1211
+ else {
1212
+ rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
1213
+ rb_enc_name(enc_io),
1214
+ rb_enc_name(enc_rs));
1215
+ }
1216
+ }
1195
1217
  }
1196
1218
  arg->rs = rs;
1197
1219
  arg->limit = limit;
@@ -1203,9 +1225,9 @@ prepare_getline_args(struct StringIO *ptr, struct getline_arg *arg, int argc, VA
1203
1225
  keywords[0] = rb_intern_const("chomp");
1204
1226
  }
1205
1227
  rb_get_kwargs(opts, keywords, 0, 1, &vchomp);
1206
- if (respect_chomp) {
1228
+ if (respect_chomp) {
1207
1229
  arg->chomp = (vchomp != Qundef) && RTEST(vchomp);
1208
- }
1230
+ }
1209
1231
  }
1210
1232
  return arg;
1211
1233
  }
@@ -1229,7 +1251,7 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
1229
1251
  long w = 0;
1230
1252
  rb_encoding *enc = get_enc(ptr);
1231
1253
 
1232
- if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
1254
+ if (NIL_P(ptr->string) || ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
1233
1255
  return Qnil;
1234
1256
  }
1235
1257
  s = RSTRING_PTR(ptr->string);
@@ -1245,7 +1267,7 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
1245
1267
  str = strio_substr(ptr, ptr->pos, e - s - w, enc);
1246
1268
  }
1247
1269
  else if ((n = RSTRING_LEN(str)) == 0) {
1248
- const char *paragraph_end = NULL;
1270
+ const char *paragraph_end = NULL;
1249
1271
  p = s;
1250
1272
  while (p[(p + 1 < e) && (*p == '\r') && 0] == '\n') {
1251
1273
  p += *p == '\r';
@@ -1255,18 +1277,18 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
1255
1277
  }
1256
1278
  s = p;
1257
1279
  while ((p = memchr(p, '\n', e - p)) && (p != e)) {
1258
- p++;
1259
- if (!((p < e && *p == '\n') ||
1260
- (p + 1 < e && *p == '\r' && *(p+1) == '\n'))) {
1261
- continue;
1262
- }
1263
- paragraph_end = p - ((*(p-2) == '\r') ? 2 : 1);
1264
- while ((p < e && *p == '\n') ||
1265
- (p + 1 < e && *p == '\r' && *(p+1) == '\n')) {
1266
- p += (*p == '\r') ? 2 : 1;
1267
- }
1268
- e = p;
1269
- break;
1280
+ p++;
1281
+ if (!((p < e && *p == '\n') ||
1282
+ (p + 1 < e && *p == '\r' && *(p+1) == '\n'))) {
1283
+ continue;
1284
+ }
1285
+ paragraph_end = p - ((*(p-2) == '\r') ? 2 : 1);
1286
+ while ((p < e && *p == '\n') ||
1287
+ (p + 1 < e && *p == '\r' && *(p+1) == '\n')) {
1288
+ p += (*p == '\r') ? 2 : 1;
1289
+ }
1290
+ e = p;
1291
+ break;
1270
1292
  }
1271
1293
  if (arg->chomp && paragraph_end) {
1272
1294
  w = e - paragraph_end;
@@ -1326,6 +1348,7 @@ strio_gets(int argc, VALUE *argv, VALUE self)
1326
1348
  VALUE str;
1327
1349
 
1328
1350
  if (prepare_getline_args(ptr, &arg, argc, argv)->limit == 0) {
1351
+ if (NIL_P(ptr->string)) return Qnil;
1329
1352
  return rb_enc_str_new(0, 0, get_enc(ptr));
1330
1353
  }
1331
1354
 
@@ -1440,6 +1463,7 @@ strio_write(VALUE self, VALUE str)
1440
1463
  if (!RB_TYPE_P(str, T_STRING))
1441
1464
  str = rb_obj_as_string(str);
1442
1465
  enc = get_enc(ptr);
1466
+ if (!enc) return 0;
1443
1467
  enc2 = rb_enc_get(str);
1444
1468
  if (enc != enc2 && enc != ascii8bit && enc != (usascii = rb_usascii_encoding())) {
1445
1469
  VALUE converted = rb_str_conv_enc(str, enc2, enc);
@@ -1465,6 +1489,7 @@ strio_write(VALUE self, VALUE str)
1465
1489
  }
1466
1490
  else {
1467
1491
  strio_extend(ptr, ptr->pos, len);
1492
+ rb_str_modify(ptr->string);
1468
1493
  memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
1469
1494
  }
1470
1495
  RB_GC_GUARD(str);
@@ -1511,10 +1536,12 @@ strio_putc(VALUE self, VALUE ch)
1511
1536
 
1512
1537
  check_modifiable(ptr);
1513
1538
  if (RB_TYPE_P(ch, T_STRING)) {
1539
+ if (NIL_P(ptr->string)) return ch;
1514
1540
  str = rb_str_substr(ch, 0, 1);
1515
1541
  }
1516
1542
  else {
1517
1543
  char c = NUM2CHR(ch);
1544
+ if (NIL_P(ptr->string)) return ch;
1518
1545
  str = rb_str_new(&c, 1);
1519
1546
  }
1520
1547
  strio_write(self, str);
@@ -1557,7 +1584,8 @@ strio_read(int argc, VALUE *argv, VALUE self)
1557
1584
  if (len < 0) {
1558
1585
  rb_raise(rb_eArgError, "negative length %ld given", len);
1559
1586
  }
1560
- if (len > 0 && ptr->pos >= RSTRING_LEN(ptr->string)) {
1587
+ if (len > 0 &&
1588
+ (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string))) {
1561
1589
  if (!NIL_P(str)) rb_str_resize(str, 0);
1562
1590
  return Qnil;
1563
1591
  }
@@ -1566,6 +1594,7 @@ strio_read(int argc, VALUE *argv, VALUE self)
1566
1594
  }
1567
1595
  /* fall through */
1568
1596
  case 0:
1597
+ if (NIL_P(ptr->string)) return Qnil;
1569
1598
  len = RSTRING_LEN(ptr->string);
1570
1599
  if (len <= ptr->pos) {
1571
1600
  rb_encoding *enc = get_enc(ptr);
@@ -1583,7 +1612,7 @@ strio_read(int argc, VALUE *argv, VALUE self)
1583
1612
  }
1584
1613
  break;
1585
1614
  default:
1586
- rb_error_arity(argc, 0, 2);
1615
+ rb_error_arity(argc, 0, 2);
1587
1616
  }
1588
1617
  if (NIL_P(str)) {
1589
1618
  rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
@@ -1594,10 +1623,9 @@ strio_read(int argc, VALUE *argv, VALUE self)
1594
1623
  if (len > rest) len = rest;
1595
1624
  rb_str_resize(str, len);
1596
1625
  MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
1597
- if (binary)
1598
- rb_enc_associate(str, rb_ascii8bit_encoding());
1599
- else
1626
+ if (!binary) {
1600
1627
  rb_enc_copy(str, ptr->string);
1628
+ }
1601
1629
  }
1602
1630
  ptr->pos += RSTRING_LEN(str);
1603
1631
  return str;
@@ -1619,28 +1647,28 @@ strio_pread(int argc, VALUE *argv, VALUE self)
1619
1647
  long offset = NUM2LONG(rb_offset);
1620
1648
 
1621
1649
  if (len < 0) {
1622
- rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);
1650
+ rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len);
1623
1651
  }
1624
1652
 
1625
1653
  if (len == 0) {
1626
- if (NIL_P(rb_buf)) {
1627
- return rb_str_new("", 0);
1628
- }
1629
- return rb_buf;
1654
+ if (NIL_P(rb_buf)) {
1655
+ return rb_str_new("", 0);
1656
+ }
1657
+ return rb_buf;
1630
1658
  }
1631
1659
 
1632
1660
  if (offset < 0) {
1633
- rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));
1661
+ rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset));
1634
1662
  }
1635
1663
 
1636
1664
  struct StringIO *ptr = readable(self);
1637
1665
 
1638
1666
  if (offset >= RSTRING_LEN(ptr->string)) {
1639
- rb_eof_error();
1667
+ rb_eof_error();
1640
1668
  }
1641
1669
 
1642
1670
  if (NIL_P(rb_buf)) {
1643
- return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());
1671
+ return strio_substr(ptr, offset, len, rb_ascii8bit_encoding());
1644
1672
  }
1645
1673
 
1646
1674
  long rest = RSTRING_LEN(ptr->string) - offset;
@@ -1700,8 +1728,14 @@ strio_read_nonblock(int argc, VALUE *argv, VALUE self)
1700
1728
  return val;
1701
1729
  }
1702
1730
 
1731
+ /*
1732
+ * See IO#write
1733
+ */
1703
1734
  #define strio_syswrite rb_io_write
1704
1735
 
1736
+ /*
1737
+ * See IO#write_nonblock
1738
+ */
1705
1739
  static VALUE
1706
1740
  strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
1707
1741
  {
@@ -1729,7 +1763,7 @@ strio_size(VALUE self)
1729
1763
  {
1730
1764
  VALUE string = StringIO(self)->string;
1731
1765
  if (NIL_P(string)) {
1732
- rb_raise(rb_eIOError, "not opened");
1766
+ return INT2FIX(0);
1733
1767
  }
1734
1768
  return ULONG2NUM(RSTRING_LEN(string));
1735
1769
  }
@@ -1746,10 +1780,12 @@ strio_truncate(VALUE self, VALUE len)
1746
1780
  {
1747
1781
  VALUE string = writable(self)->string;
1748
1782
  long l = NUM2LONG(len);
1749
- long plen = RSTRING_LEN(string);
1783
+ long plen;
1750
1784
  if (l < 0) {
1751
1785
  error_inval("negative length");
1752
1786
  }
1787
+ if (NIL_P(string)) return 0;
1788
+ plen = RSTRING_LEN(string);
1753
1789
  rb_str_resize(string, l);
1754
1790
  if (plen < l) {
1755
1791
  MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
@@ -1820,13 +1856,22 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self)
1820
1856
  }
1821
1857
  }
1822
1858
  ptr->enc = enc;
1823
- if (WRITABLE(self)) {
1859
+ if (!NIL_P(ptr->string) && WRITABLE(self)) {
1824
1860
  rb_enc_associate(ptr->string, enc);
1825
1861
  }
1826
1862
 
1827
1863
  return self;
1828
1864
  }
1829
1865
 
1866
+ /*
1867
+ * call-seq:
1868
+ * strio.set_encoding_by_bom => strio or nil
1869
+ *
1870
+ * Sets the encoding according to the BOM (Byte Order Mark) in the
1871
+ * string.
1872
+ *
1873
+ * Returns +self+ if the BOM is found, otherwise +nil.
1874
+ */
1830
1875
  static VALUE
1831
1876
  strio_set_encoding_by_bom(VALUE self)
1832
1877
  {
@@ -1859,10 +1904,15 @@ Init_stringio(void)
1859
1904
 
1860
1905
  VALUE StringIO = rb_define_class("StringIO", rb_cObject);
1861
1906
 
1907
+ /* The version string */
1862
1908
  rb_define_const(StringIO, "VERSION", rb_str_new_cstr(STRINGIO_VERSION));
1863
1909
 
1864
1910
  rb_include_module(StringIO, rb_mEnumerable);
1865
1911
  rb_define_alloc_func(StringIO, strio_s_allocate);
1912
+
1913
+ /* Maximum length that a StringIO instance can hold */
1914
+ rb_define_const(StringIO, "MAX_LENGTH", LONG2NUM(LONG_MAX));
1915
+
1866
1916
  rb_define_singleton_method(StringIO, "new", strio_s_new, -1);
1867
1917
  rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
1868
1918
  rb_define_method(StringIO, "initialize", strio_initialize, -1);
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stringio
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nobu Nakada
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-11-28 00:00:00.000000000 Z
12
+ date: 2024-11-07 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Pseudo `IO` class from/to `String`.
15
15
  email:
@@ -18,9 +18,24 @@ email:
18
18
  executables: []
19
19
  extensions:
20
20
  - ext/stringio/extconf.rb
21
- extra_rdoc_files: []
21
+ extra_rdoc_files:
22
+ - ".document"
23
+ - ".rdoc_options"
24
+ - COPYING
25
+ - LICENSE.txt
26
+ - NEWS.md
27
+ - README.md
28
+ - docs/io.rb
29
+ - ext/stringio/.document
22
30
  files:
31
+ - ".document"
32
+ - ".rdoc_options"
33
+ - COPYING
34
+ - LICENSE.txt
35
+ - NEWS.md
23
36
  - README.md
37
+ - docs/io.rb
38
+ - ext/stringio/.document
24
39
  - ext/stringio/extconf.rb
25
40
  - ext/stringio/stringio.c
26
41
  homepage: https://github.com/ruby/stringio
@@ -43,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
58
  - !ruby/object:Gem::Version
44
59
  version: '0'
45
60
  requirements: []
46
- rubygems_version: 3.4.10
61
+ rubygems_version: 3.5.22
47
62
  signing_key:
48
63
  specification_version: 4
49
64
  summary: Pseudo IO on String