stringio 3.1.0 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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