stringio 0.0.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of stringio might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9593fa26bcf926ea907d5e261a5fe847c2d5ec28f114344e9698adc877a70bd8
4
- data.tar.gz: 334c3def4bbbb508503fcd2956e8d084a6183ba4c3a9d0680012c1b905950c1e
3
+ metadata.gz: 41c6ce121bb7eb707f594272b5665080732c7eb7d5ae868f95bb633dc83711ae
4
+ data.tar.gz: d7c1e9260fa0095a95a31e7170264d0d40b4e0093b6bccd0ee84fc80e3c4f005
5
5
  SHA512:
6
- metadata.gz: a2b7616e5b07ed4eef3637a3d4ebee48e5eca030927803bf7d60c80084061de42150cf3df930a90fe45eac2b5ee29a62dce8938b7d34d96c601083c5ed2dbb14
7
- data.tar.gz: 44a4c20f3c58e437d79724330ac023d4ccbd383900296c76a4687fc1cd641d1b0845203d55b0e5bfcbc75d884b38d8e7cd4ce102732183353d338aea8012eb70
6
+ metadata.gz: c19e3fa54ab666fe1ac76a398637e7181ca7e5948bb3576a2504e3a79253ab995dbf515bbaa52f01a6aec112f28102c002353038eced204ddeba0b15ea930544
7
+ data.tar.gz: 3d67ea8a7975013bdf361bf8ab80cd208187b6f4396a118fd16f1d6e9134ab0b596d4b7453b5bdaa0a7f232e08c0103ae3da638258f98baf2e4bd5bcaf5e35f8
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # StringIO
2
2
 
3
+ ![ubuntu](https://github.com/ruby/stringio/workflows/ubuntu/badge.svg?branch=master&event=push)
4
+ ![macos](https://github.com/ruby/stringio/workflows/macos/badge.svg?branch=master&event=push)
5
+ ![windows](https://github.com/ruby/stringio/workflows/windows/badge.svg?branch=master&event=push)
6
+
3
7
  Pseudo `IO` class from/to `String`.
4
8
 
5
9
  This library is based on MoonWolf version written in Ruby. Thanks a lot.
@@ -8,3 +12,33 @@ This library is based on MoonWolf version written in Ruby. Thanks a lot.
8
12
 
9
13
  * `fileno` raises `NotImplementedError`.
10
14
  * encoding conversion is not implemented, and ignored silently.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'stringio'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install stringio
31
+
32
+ ## Development
33
+
34
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
35
+
36
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
37
+
38
+ ## Contributing
39
+
40
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/stringio.
41
+
42
+ ## License
43
+
44
+ The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: false
2
2
  require 'mkmf'
3
+ have_func("rb_io_extract_modeenc", "ruby/io.h")
3
4
  create_makefile('stringio')
@@ -11,6 +11,8 @@
11
11
 
12
12
  **********************************************************************/
13
13
 
14
+ #define STRINGIO_VERSION "3.0.0"
15
+
14
16
  #include "ruby.h"
15
17
  #include "ruby/io.h"
16
18
  #include "ruby/encoding.h"
@@ -24,6 +26,86 @@
24
26
  # define RB_INTEGER_TYPE_P(c) (FIXNUM_P(c) || RB_TYPE_P(c, T_BIGNUM))
25
27
  #endif
26
28
 
29
+ #ifndef RB_PASS_CALLED_KEYWORDS
30
+ # define rb_funcallv_kw(recv, mid, arg, argv, kw_splat) rb_funcallv(recv, mid, arg, argv)
31
+ # define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
32
+ #endif
33
+
34
+ #ifndef HAVE_RB_IO_EXTRACT_MODEENC
35
+ #define rb_io_extract_modeenc strio_extract_modeenc
36
+ static void
37
+ strio_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
38
+ int *oflags_p, int *fmode_p, struct rb_io_enc_t *convconfig_p)
39
+ {
40
+ VALUE mode = *vmode_p;
41
+ VALUE intmode;
42
+ int fmode;
43
+ int has_enc = 0, has_vmode = 0;
44
+
45
+ convconfig_p->enc = convconfig_p->enc2 = 0;
46
+
47
+ vmode_handle:
48
+ if (NIL_P(mode)) {
49
+ fmode = FMODE_READABLE;
50
+ }
51
+ else if (!NIL_P(intmode = rb_check_to_integer(mode, "to_int"))) {
52
+ int flags = NUM2INT(intmode);
53
+ fmode = rb_io_oflags_fmode(flags);
54
+ }
55
+ else {
56
+ const char *m = StringValueCStr(mode), *n, *e;
57
+ fmode = rb_io_modestr_fmode(m);
58
+ n = strchr(m, ':');
59
+ if (n) {
60
+ long len;
61
+ char encname[ENCODING_MAXNAMELEN+1];
62
+ has_enc = 1;
63
+ if (fmode & FMODE_SETENC_BY_BOM) {
64
+ n = strchr(n, '|');
65
+ }
66
+ e = strchr(++n, ':');
67
+ len = e ? e - n : strlen(n);
68
+ if (len > 0 && len <= ENCODING_MAXNAMELEN) {
69
+ if (e) {
70
+ memcpy(encname, n, len);
71
+ encname[len] = '\0';
72
+ n = encname;
73
+ }
74
+ convconfig_p->enc = rb_enc_find(n);
75
+ }
76
+ if (e && (len = strlen(++e)) > 0 && len <= ENCODING_MAXNAMELEN) {
77
+ convconfig_p->enc2 = rb_enc_find(e);
78
+ }
79
+ }
80
+ }
81
+
82
+ if (!NIL_P(opthash)) {
83
+ rb_encoding *extenc = 0, *intenc = 0;
84
+ VALUE v;
85
+ if (!has_vmode) {
86
+ ID id_mode;
87
+ CONST_ID(id_mode, "mode");
88
+ v = rb_hash_aref(opthash, ID2SYM(id_mode));
89
+ if (!NIL_P(v)) {
90
+ if (!NIL_P(mode)) {
91
+ rb_raise(rb_eArgError, "mode specified twice");
92
+ }
93
+ has_vmode = 1;
94
+ mode = v;
95
+ goto vmode_handle;
96
+ }
97
+ }
98
+
99
+ if (rb_io_extract_encoding_option(opthash, &extenc, &intenc, &fmode)) {
100
+ if (has_enc) {
101
+ rb_raise(rb_eArgError, "encoding specified twice");
102
+ }
103
+ }
104
+ }
105
+ *fmode_p = fmode;
106
+ }
107
+ #endif
108
+
27
109
  struct StringIO {
28
110
  VALUE string;
29
111
  rb_encoding *enc;
@@ -185,45 +267,111 @@ strio_initialize(int argc, VALUE *argv, VALUE self)
185
267
  return strio_init(argc, argv, ptr, self);
186
268
  }
187
269
 
188
- static VALUE
189
- strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
270
+ static int
271
+ detect_bom(VALUE str, int *bomlen)
190
272
  {
191
- VALUE string, mode;
192
- int trunc = 0;
273
+ const char *p;
274
+ long len;
193
275
 
194
- switch (rb_scan_args(argc, argv, "02", &string, &mode)) {
195
- case 2:
196
- if (FIXNUM_P(mode)) {
197
- int flags = FIX2INT(mode);
198
- ptr->flags = rb_io_oflags_fmode(flags);
199
- trunc = flags & O_TRUNC;
276
+ RSTRING_GETMEM(str, p, len);
277
+ if (len < 1) return 0;
278
+ switch ((unsigned char)p[0]) {
279
+ case 0xEF:
280
+ if (len < 2) break;
281
+ if ((unsigned char)p[1] == 0xBB && len > 2) {
282
+ if ((unsigned char)p[2] == 0xBF) {
283
+ *bomlen = 3;
284
+ return rb_utf8_encindex();
285
+ }
200
286
  }
201
- else {
202
- const char *m = StringValueCStr(mode);
203
- ptr->flags = rb_io_modestr_fmode(m);
204
- trunc = *m == 'w';
287
+ break;
288
+
289
+ case 0xFE:
290
+ if (len < 2) break;
291
+ if ((unsigned char)p[1] == 0xFF) {
292
+ *bomlen = 2;
293
+ return rb_enc_find_index("UTF-16BE");
205
294
  }
206
- StringValue(string);
207
- if ((ptr->flags & FMODE_WRITABLE) && OBJ_FROZEN(string)) {
208
- rb_syserr_fail(EACCES, 0);
295
+ break;
296
+
297
+ case 0xFF:
298
+ if (len < 2) break;
299
+ if ((unsigned char)p[1] == 0xFE) {
300
+ if (len >= 4 && (unsigned char)p[2] == 0 && (unsigned char)p[3] == 0) {
301
+ *bomlen = 4;
302
+ return rb_enc_find_index("UTF-32LE");
303
+ }
304
+ *bomlen = 2;
305
+ return rb_enc_find_index("UTF-16LE");
209
306
  }
210
- if (trunc) {
211
- rb_str_resize(string, 0);
307
+ break;
308
+
309
+ case 0:
310
+ if (len < 4) break;
311
+ if ((unsigned char)p[1] == 0 && (unsigned char)p[2] == 0xFE && (unsigned char)p[3] == 0xFF) {
312
+ *bomlen = 4;
313
+ return rb_enc_find_index("UTF-32BE");
212
314
  }
213
315
  break;
214
- case 1:
316
+ }
317
+ return 0;
318
+ }
319
+
320
+ static rb_encoding *
321
+ set_encoding_by_bom(struct StringIO *ptr)
322
+ {
323
+ int bomlen, idx = detect_bom(ptr->string, &bomlen);
324
+ rb_encoding *extenc = NULL;
325
+
326
+ if (idx) {
327
+ extenc = rb_enc_from_index(idx);
328
+ ptr->pos = bomlen;
329
+ if (ptr->flags & FMODE_WRITABLE) {
330
+ rb_enc_associate_index(ptr->string, idx);
331
+ }
332
+ }
333
+ ptr->enc = extenc;
334
+ return extenc;
335
+ }
336
+
337
+ static VALUE
338
+ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
339
+ {
340
+ VALUE string, vmode, opt;
341
+ int oflags;
342
+ struct rb_io_enc_t convconfig;
343
+
344
+ argc = rb_scan_args(argc, argv, "02:", &string, &vmode, &opt);
345
+ rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &ptr->flags, &convconfig);
346
+ if (argc) {
215
347
  StringValue(string);
216
- ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
217
- break;
218
- case 0:
348
+ }
349
+ else {
219
350
  string = rb_enc_str_new("", 0, rb_default_external_encoding());
220
- ptr->flags = FMODE_READWRITE;
221
- break;
351
+ }
352
+ if (OBJ_FROZEN_RAW(string)) {
353
+ if (ptr->flags & FMODE_WRITABLE) {
354
+ rb_syserr_fail(EACCES, 0);
355
+ }
356
+ }
357
+ else {
358
+ if (NIL_P(vmode)) {
359
+ ptr->flags |= FMODE_WRITABLE;
360
+ }
361
+ }
362
+ if (ptr->flags & FMODE_TRUNC) {
363
+ rb_str_resize(string, 0);
222
364
  }
223
365
  ptr->string = string;
224
- ptr->enc = 0;
366
+ if (argc == 1) {
367
+ ptr->enc = rb_enc_get(string);
368
+ }
369
+ else {
370
+ ptr->enc = convconfig.enc;
371
+ }
225
372
  ptr->pos = 0;
226
373
  ptr->lineno = 0;
374
+ if (ptr->flags & FMODE_SETENC_BY_BOM) set_encoding_by_bom(ptr);
227
375
  RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE);
228
376
  return self;
229
377
  }
@@ -247,7 +395,7 @@ strio_finalize(VALUE self)
247
395
  static VALUE
248
396
  strio_s_open(int argc, VALUE *argv, VALUE klass)
249
397
  {
250
- VALUE obj = rb_class_new_instance(argc, argv, klass);
398
+ VALUE obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
251
399
  if (!rb_block_given_p()) return obj;
252
400
  return rb_ensure(rb_yield, obj, strio_finalize, obj);
253
401
  }
@@ -262,7 +410,7 @@ strio_s_new(int argc, VALUE *argv, VALUE klass)
262
410
  rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
263
411
  cname, cname);
264
412
  }
265
- return rb_class_new_instance(argc, argv, klass);
413
+ return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
266
414
  }
267
415
 
268
416
  /*
@@ -286,7 +434,7 @@ strio_nil(VALUE self)
286
434
  }
287
435
 
288
436
  /*
289
- * Returns *strio* itself. Just for compatibility to IO.
437
+ * Returns an object itself. Just for compatibility to IO.
290
438
  */
291
439
  static VALUE
292
440
  strio_self(VALUE self)
@@ -362,7 +510,7 @@ strio_set_string(VALUE self, VALUE string)
362
510
  * call-seq:
363
511
  * strio.close -> nil
364
512
  *
365
- * Closes strio. The *strio* is unavailable for any further data
513
+ * Closes a StringIO. The stream is unavailable for any further data
366
514
  * operations; an +IOError+ is raised if such an attempt is made.
367
515
  */
368
516
  static VALUE
@@ -378,7 +526,7 @@ strio_close(VALUE self)
378
526
  * strio.close_read -> nil
379
527
  *
380
528
  * Closes the read end of a StringIO. Will raise an +IOError+ if the
381
- * *strio* is not readable.
529
+ * receiver is not readable.
382
530
  */
383
531
  static VALUE
384
532
  strio_close_read(VALUE self)
@@ -396,7 +544,7 @@ strio_close_read(VALUE self)
396
544
  * strio.close_write -> nil
397
545
  *
398
546
  * Closes the write end of a StringIO. Will raise an +IOError+ if the
399
- * *strio* is not writeable.
547
+ * receiver is not writeable.
400
548
  */
401
549
  static VALUE
402
550
  strio_close_write(VALUE self)
@@ -413,7 +561,7 @@ strio_close_write(VALUE self)
413
561
  * call-seq:
414
562
  * strio.closed? -> true or false
415
563
  *
416
- * Returns +true+ if *strio* is completely closed, +false+ otherwise.
564
+ * Returns +true+ if the stream is completely closed, +false+ otherwise.
417
565
  */
418
566
  static VALUE
419
567
  strio_closed(VALUE self)
@@ -427,7 +575,7 @@ strio_closed(VALUE self)
427
575
  * call-seq:
428
576
  * strio.closed_read? -> true or false
429
577
  *
430
- * Returns +true+ if *strio* is not readable, +false+ otherwise.
578
+ * Returns +true+ if the stream is not readable, +false+ otherwise.
431
579
  */
432
580
  static VALUE
433
581
  strio_closed_read(VALUE self)
@@ -441,7 +589,7 @@ strio_closed_read(VALUE self)
441
589
  * call-seq:
442
590
  * strio.closed_write? -> true or false
443
591
  *
444
- * Returns +true+ if *strio* is not writable, +false+ otherwise.
592
+ * Returns +true+ if the stream is not writable, +false+ otherwise.
445
593
  */
446
594
  static VALUE
447
595
  strio_closed_write(VALUE self)
@@ -456,8 +604,8 @@ strio_closed_write(VALUE self)
456
604
  * strio.eof -> true or false
457
605
  * strio.eof? -> true or false
458
606
  *
459
- * Returns true if *strio* is at end of file. The stringio must be
460
- * opened for reading or an +IOError+ will be raised.
607
+ * Returns true if the stream is at the end of the data (underlying string).
608
+ * The stream must be opened for reading or an +IOError+ will be raised.
461
609
  */
462
610
  static VALUE
463
611
  strio_eof(VALUE self)
@@ -480,7 +628,6 @@ strio_copy(VALUE copy, VALUE orig)
480
628
  strio_free(DATA_PTR(copy));
481
629
  }
482
630
  DATA_PTR(copy) = ptr;
483
- OBJ_INFECT(copy, orig);
484
631
  RBASIC(copy)->flags &= ~STRIO_READWRITE;
485
632
  RBASIC(copy)->flags |= RBASIC(orig)->flags & STRIO_READWRITE;
486
633
  ++ptr->count;
@@ -491,7 +638,7 @@ strio_copy(VALUE copy, VALUE orig)
491
638
  * call-seq:
492
639
  * strio.lineno -> integer
493
640
  *
494
- * Returns the current line number in *strio*. The stringio must be
641
+ * Returns the current line number. The stream must be
495
642
  * opened for reading. +lineno+ counts the number of times +gets+ is
496
643
  * called, rather than the number of newlines encountered. The two
497
644
  * values will differ if +gets+ is called with a separator other than
@@ -517,6 +664,13 @@ strio_set_lineno(VALUE self, VALUE lineno)
517
664
  return lineno;
518
665
  }
519
666
 
667
+ /*
668
+ * call-seq:
669
+ * strio.binmode -> stringio
670
+ *
671
+ * Puts stream into binary mode. See IO#binmode.
672
+ *
673
+ */
520
674
  static VALUE
521
675
  strio_binmode(VALUE self)
522
676
  {
@@ -541,7 +695,7 @@ strio_binmode(VALUE self)
541
695
  * strio.reopen(other_StrIO) -> strio
542
696
  * strio.reopen(string, mode) -> strio
543
697
  *
544
- * Reinitializes *strio* with the given <i>other_StrIO</i> or _string_
698
+ * Reinitializes the stream with the given <i>other_StrIO</i> or _string_
545
699
  * and _mode_ (see StringIO#new).
546
700
  */
547
701
  static VALUE
@@ -559,7 +713,7 @@ strio_reopen(int argc, VALUE *argv, VALUE self)
559
713
  * strio.pos -> integer
560
714
  * strio.tell -> integer
561
715
  *
562
- * Returns the current offset (in bytes) of *strio*.
716
+ * Returns the current offset (in bytes).
563
717
  */
564
718
  static VALUE
565
719
  strio_get_pos(VALUE self)
@@ -571,7 +725,7 @@ strio_get_pos(VALUE self)
571
725
  * call-seq:
572
726
  * strio.pos = integer -> integer
573
727
  *
574
- * Seeks to the given position (in bytes) in *strio*.
728
+ * Seeks to the given position (in bytes).
575
729
  */
576
730
  static VALUE
577
731
  strio_set_pos(VALUE self, VALUE pos)
@@ -589,7 +743,7 @@ strio_set_pos(VALUE self, VALUE pos)
589
743
  * call-seq:
590
744
  * strio.rewind -> 0
591
745
  *
592
- * Positions *strio* to the beginning of input, resetting
746
+ * Positions the stream to the beginning of input, resetting
593
747
  * +lineno+ to zero.
594
748
  */
595
749
  static VALUE
@@ -678,18 +832,6 @@ strio_each_byte(VALUE self)
678
832
  return self;
679
833
  }
680
834
 
681
- /*
682
- * This is a deprecated alias for #each_byte.
683
- */
684
- static VALUE
685
- strio_bytes(VALUE self)
686
- {
687
- rb_warn("StringIO#bytes is deprecated; use #each_byte instead");
688
- if (!rb_block_given_p())
689
- return rb_enumeratorize(self, ID2SYM(rb_intern("each_byte")), 0, 0);
690
- return strio_each_byte(self);
691
- }
692
-
693
835
  /*
694
836
  * call-seq:
695
837
  * strio.getc -> string or nil
@@ -757,7 +899,7 @@ strio_extend(struct StringIO *ptr, long pos, long len)
757
899
  * call-seq:
758
900
  * strio.ungetc(string) -> nil
759
901
  *
760
- * Pushes back one character (passed as a parameter) onto *strio*
902
+ * Pushes back one character (passed as a parameter)
761
903
  * such that a subsequent buffered read will return it. There is no
762
904
  * limitation for multiple pushbacks including pushing back behind the
763
905
  * beginning of the buffer string.
@@ -803,24 +945,25 @@ static VALUE
803
945
  strio_ungetbyte(VALUE self, VALUE c)
804
946
  {
805
947
  struct StringIO *ptr = readable(self);
806
- char buf[1], *cp = buf;
807
- long cl = 1;
808
948
 
809
949
  check_modifiable(ptr);
810
950
  if (NIL_P(c)) return Qnil;
811
- if (FIXNUM_P(c)) {
812
- buf[0] = (char)FIX2INT(c);
813
- return strio_unget_bytes(ptr, buf, 1);
951
+ if (RB_INTEGER_TYPE_P(c)) {
952
+ /* rb_int_and() not visible from exts */
953
+ VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
954
+ const char cc = NUM2INT(v) & 0xFF;
955
+ strio_unget_bytes(ptr, &cc, 1);
814
956
  }
815
957
  else {
958
+ long cl;
816
959
  SafeStringValue(c);
817
- cp = RSTRING_PTR(c);
818
960
  cl = RSTRING_LEN(c);
819
- if (cl == 0) return Qnil;
820
- strio_unget_bytes(ptr, cp, cl);
821
- RB_GC_GUARD(c);
822
- return Qnil;
961
+ if (cl > 0) {
962
+ strio_unget_bytes(ptr, RSTRING_PTR(c), cl);
963
+ RB_GC_GUARD(c);
964
+ }
823
965
  }
966
+ return Qnil;
824
967
  }
825
968
 
826
969
  static VALUE
@@ -863,7 +1006,7 @@ strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
863
1006
  static VALUE
864
1007
  strio_readchar(VALUE self)
865
1008
  {
866
- VALUE c = rb_funcall2(self, rb_intern("getc"), 0, 0);
1009
+ VALUE c = rb_funcallv(self, rb_intern("getc"), 0, 0);
867
1010
  if (NIL_P(c)) rb_eof_error();
868
1011
  return c;
869
1012
  }
@@ -877,7 +1020,7 @@ strio_readchar(VALUE self)
877
1020
  static VALUE
878
1021
  strio_readbyte(VALUE self)
879
1022
  {
880
- VALUE c = rb_funcall2(self, rb_intern("getbyte"), 0, 0);
1023
+ VALUE c = rb_funcallv(self, rb_intern("getbyte"), 0, 0);
881
1024
  if (NIL_P(c)) rb_eof_error();
882
1025
  return c;
883
1026
  }
@@ -902,18 +1045,6 @@ strio_each_char(VALUE self)
902
1045
  return self;
903
1046
  }
904
1047
 
905
- /*
906
- * This is a deprecated alias for <code>each_char</code>.
907
- */
908
- static VALUE
909
- strio_chars(VALUE self)
910
- {
911
- rb_warn("StringIO#chars is deprecated; use #each_char instead");
912
- if (!rb_block_given_p())
913
- return rb_enumeratorize(self, ID2SYM(rb_intern("each_char")), 0, 0);
914
- return strio_each_char(self);
915
- }
916
-
917
1048
  /*
918
1049
  * call-seq:
919
1050
  * strio.each_codepoint {|c| block } -> strio
@@ -940,24 +1071,12 @@ strio_each_codepoint(VALUE self)
940
1071
 
941
1072
  c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
942
1073
  RSTRING_END(ptr->string), &n, enc);
943
- rb_yield(UINT2NUM(c));
944
1074
  ptr->pos += n;
1075
+ rb_yield(UINT2NUM(c));
945
1076
  }
946
1077
  return self;
947
1078
  }
948
1079
 
949
- /*
950
- * This is a deprecated alias for <code>each_codepoint</code>.
951
- */
952
- static VALUE
953
- strio_codepoints(VALUE self)
954
- {
955
- rb_warn("StringIO#codepoints is deprecated; use #each_codepoint instead");
956
- if (!rb_block_given_p())
957
- return rb_enumeratorize(self, ID2SYM(rb_intern("each_codepoint")), 0, 0);
958
- return strio_each_codepoint(self);
959
- }
960
-
961
1080
  /* Boyer-Moore search: copied from regex.c */
962
1081
  static void
963
1082
  bm_init_skip(long *skip, const char *pat, long m)
@@ -1137,9 +1256,9 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
1137
1256
 
1138
1257
  /*
1139
1258
  * call-seq:
1140
- * strio.gets(sep=$/) -> string or nil
1141
- * strio.gets(limit) -> string or nil
1142
- * strio.gets(sep, limit) -> string or nil
1259
+ * strio.gets(sep=$/, chomp: false) -> string or nil
1260
+ * strio.gets(limit, chomp: false) -> string or nil
1261
+ * strio.gets(sep, limit, chomp: false) -> string or nil
1143
1262
  *
1144
1263
  * See IO#gets.
1145
1264
  */
@@ -1161,31 +1280,31 @@ strio_gets(int argc, VALUE *argv, VALUE self)
1161
1280
 
1162
1281
  /*
1163
1282
  * call-seq:
1164
- * strio.readline(sep=$/) -> string
1165
- * strio.readline(limit) -> string or nil
1166
- * strio.readline(sep, limit) -> string or nil
1283
+ * strio.readline(sep=$/, chomp: false) -> string
1284
+ * strio.readline(limit, chomp: false) -> string or nil
1285
+ * strio.readline(sep, limit, chomp: false) -> string or nil
1167
1286
  *
1168
1287
  * See IO#readline.
1169
1288
  */
1170
1289
  static VALUE
1171
1290
  strio_readline(int argc, VALUE *argv, VALUE self)
1172
1291
  {
1173
- VALUE line = rb_funcall2(self, rb_intern("gets"), argc, argv);
1292
+ VALUE line = rb_funcallv_kw(self, rb_intern("gets"), argc, argv, RB_PASS_CALLED_KEYWORDS);
1174
1293
  if (NIL_P(line)) rb_eof_error();
1175
1294
  return line;
1176
1295
  }
1177
1296
 
1178
1297
  /*
1179
1298
  * call-seq:
1180
- * strio.each(sep=$/) {|line| block } -> strio
1181
- * strio.each(limit) {|line| block } -> strio
1182
- * strio.each(sep, limit) {|line| block } -> strio
1183
- * strio.each(...) -> anEnumerator
1299
+ * strio.each(sep=$/, chomp: false) {|line| block } -> strio
1300
+ * strio.each(limit, chomp: false) {|line| block } -> strio
1301
+ * strio.each(sep, limit, chomp: false) {|line| block } -> strio
1302
+ * strio.each(...) -> anEnumerator
1184
1303
  *
1185
- * strio.each_line(sep=$/) {|line| block } -> strio
1186
- * strio.each_line(limit) {|line| block } -> strio
1187
- * strio.each_line(sep,limit) {|line| block } -> strio
1188
- * strio.each_line(...) -> anEnumerator
1304
+ * strio.each_line(sep=$/, chomp: false) {|line| block } -> strio
1305
+ * strio.each_line(limit, chomp: false) {|line| block } -> strio
1306
+ * strio.each_line(sep, limit, chomp: false) {|line| block } -> strio
1307
+ * strio.each_line(...) -> anEnumerator
1189
1308
  *
1190
1309
  * See IO#each.
1191
1310
  */
@@ -1208,23 +1327,11 @@ strio_each(int argc, VALUE *argv, VALUE self)
1208
1327
  return self;
1209
1328
  }
1210
1329
 
1211
- /*
1212
- * This is a deprecated alias for <code>each_line</code>.
1213
- */
1214
- static VALUE
1215
- strio_lines(int argc, VALUE *argv, VALUE self)
1216
- {
1217
- rb_warn("StringIO#lines is deprecated; use #each_line instead");
1218
- if (!rb_block_given_p())
1219
- return rb_enumeratorize(self, ID2SYM(rb_intern("each_line")), argc, argv);
1220
- return strio_each(argc, argv, self);
1221
- }
1222
-
1223
1330
  /*
1224
1331
  * call-seq:
1225
- * strio.readlines(sep=$/) -> array
1226
- * strio.readlines(limit) -> array
1227
- * strio.readlines(sep,limit) -> array
1332
+ * strio.readlines(sep=$/, chomp: false) -> array
1333
+ * strio.readlines(limit, chomp: false) -> array
1334
+ * strio.readlines(sep, limit, chomp: false) -> array
1228
1335
  *
1229
1336
  * See IO#readlines.
1230
1337
  */
@@ -1251,7 +1358,7 @@ strio_readlines(int argc, VALUE *argv, VALUE self)
1251
1358
  * strio.write(string, ...) -> integer
1252
1359
  * strio.syswrite(string) -> integer
1253
1360
  *
1254
- * Appends the given string to the underlying buffer string of *strio*.
1361
+ * Appends the given string to the underlying buffer string.
1255
1362
  * The stream must be opened for writing. If the argument is not a
1256
1363
  * string, it will be converted to a string using <code>to_s</code>.
1257
1364
  * Returns the number of bytes written. See IO#write.
@@ -1274,13 +1381,18 @@ strio_write(VALUE self, VALUE str)
1274
1381
  long len, olen;
1275
1382
  rb_encoding *enc, *enc2;
1276
1383
  rb_encoding *const ascii8bit = rb_ascii8bit_encoding();
1384
+ rb_encoding *usascii = 0;
1277
1385
 
1278
1386
  if (!RB_TYPE_P(str, T_STRING))
1279
1387
  str = rb_obj_as_string(str);
1280
1388
  enc = get_enc(ptr);
1281
1389
  enc2 = rb_enc_get(str);
1282
- if (enc != enc2 && enc != ascii8bit) {
1283
- str = rb_str_conv_enc(str, enc2, enc);
1390
+ if (enc != enc2 && enc != ascii8bit && enc != (usascii = rb_usascii_encoding())) {
1391
+ VALUE converted = rb_str_conv_enc(str, enc2, enc);
1392
+ if (converted == str && enc2 != ascii8bit && enc2 != usascii) { /* conversion failed */
1393
+ rb_enc_check(rb_enc_from_encoding(enc), str);
1394
+ }
1395
+ str = converted;
1284
1396
  }
1285
1397
  len = RSTRING_LEN(str);
1286
1398
  if (len == 0) return 0;
@@ -1292,7 +1404,6 @@ strio_write(VALUE self, VALUE str)
1292
1404
  if (ptr->pos == olen) {
1293
1405
  if (enc == ascii8bit || enc2 == ascii8bit) {
1294
1406
  rb_enc_str_buf_cat(ptr->string, RSTRING_PTR(str), len, enc);
1295
- OBJ_INFECT(ptr->string, str);
1296
1407
  }
1297
1408
  else {
1298
1409
  rb_str_buf_append(ptr->string, str);
@@ -1301,9 +1412,7 @@ strio_write(VALUE self, VALUE str)
1301
1412
  else {
1302
1413
  strio_extend(ptr, ptr->pos, len);
1303
1414
  memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
1304
- OBJ_INFECT(ptr->string, str);
1305
1415
  }
1306
- OBJ_INFECT(ptr->string, self);
1307
1416
  RB_GC_GUARD(str);
1308
1417
  ptr->pos += len;
1309
1418
  return len;
@@ -1380,7 +1489,6 @@ strio_read(int argc, VALUE *argv, VALUE self)
1380
1489
  long len;
1381
1490
  int binary = 0;
1382
1491
 
1383
- rb_check_arity(argc, 0, 2);
1384
1492
  switch (argc) {
1385
1493
  case 2:
1386
1494
  str = argv[1];
@@ -1406,7 +1514,7 @@ strio_read(int argc, VALUE *argv, VALUE self)
1406
1514
  case 0:
1407
1515
  len = RSTRING_LEN(ptr->string);
1408
1516
  if (len <= ptr->pos) {
1409
- rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
1517
+ rb_encoding *enc = get_enc(ptr);
1410
1518
  if (NIL_P(str)) {
1411
1519
  str = rb_str_new(0, 0);
1412
1520
  }
@@ -1420,6 +1528,8 @@ strio_read(int argc, VALUE *argv, VALUE self)
1420
1528
  len -= ptr->pos;
1421
1529
  }
1422
1530
  break;
1531
+ default:
1532
+ rb_error_arity(argc, 0, 2);
1423
1533
  }
1424
1534
  if (NIL_P(str)) {
1425
1535
  rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
@@ -1450,7 +1560,7 @@ strio_read(int argc, VALUE *argv, VALUE self)
1450
1560
  static VALUE
1451
1561
  strio_sysread(int argc, VALUE *argv, VALUE self)
1452
1562
  {
1453
- VALUE val = rb_funcall2(self, rb_intern("read"), argc, argv);
1563
+ VALUE val = rb_funcallv_kw(self, rb_intern("read"), argc, argv, RB_PASS_CALLED_KEYWORDS);
1454
1564
  if (NIL_P(val)) {
1455
1565
  rb_eof_error();
1456
1566
  }
@@ -1525,7 +1635,7 @@ strio_size(VALUE self)
1525
1635
  * call-seq:
1526
1636
  * strio.truncate(integer) -> 0
1527
1637
  *
1528
- * Truncates the buffer string to at most _integer_ bytes. The *strio*
1638
+ * Truncates the buffer string to at most _integer_ bytes. The stream
1529
1639
  * must be opened for writing.
1530
1640
  */
1531
1641
  static VALUE
@@ -1549,7 +1659,8 @@ strio_truncate(VALUE self, VALUE len)
1549
1659
  * strio.external_encoding => encoding
1550
1660
  *
1551
1661
  * Returns the Encoding object that represents the encoding of the file.
1552
- * If strio is write mode and no encoding is specified, returns <code>nil</code>.
1662
+ * If the stream is write mode and no encoding is specified, returns
1663
+ * +nil+.
1553
1664
  */
1554
1665
 
1555
1666
  static VALUE
@@ -1564,7 +1675,7 @@ strio_external_encoding(VALUE self)
1564
1675
  * strio.internal_encoding => encoding
1565
1676
  *
1566
1677
  * Returns the Encoding of the internal string if conversion is
1567
- * specified. Otherwise returns nil.
1678
+ * specified. Otherwise returns +nil+.
1568
1679
  */
1569
1680
 
1570
1681
  static VALUE
@@ -1606,24 +1717,48 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self)
1606
1717
  return self;
1607
1718
  }
1608
1719
 
1720
+ static VALUE
1721
+ strio_set_encoding_by_bom(VALUE self)
1722
+ {
1723
+ struct StringIO *ptr = StringIO(self);
1724
+
1725
+ if (!set_encoding_by_bom(ptr)) return Qnil;
1726
+ return rb_enc_from_encoding(ptr->enc);
1727
+ }
1728
+
1609
1729
  /*
1610
- * Pseudo I/O on String object.
1730
+ * Pseudo I/O on String object, with interface corresponding to IO.
1611
1731
  *
1612
- * Commonly used to simulate `$stdio` or `$stderr`
1732
+ * Commonly used to simulate <code>$stdio</code> or <code>$stderr</code>
1613
1733
  *
1614
1734
  * === Examples
1615
1735
  *
1616
1736
  * require 'stringio'
1617
1737
  *
1738
+ * # Writing stream emulation
1618
1739
  * io = StringIO.new
1619
1740
  * io.puts "Hello World"
1620
1741
  * io.string #=> "Hello World\n"
1742
+ *
1743
+ * # Reading stream emulation
1744
+ * io = StringIO.new "first\nsecond\nlast\n"
1745
+ * io.getc #=> "f"
1746
+ * io.gets #=> "irst\n"
1747
+ * io.read #=> "second\nlast\n"
1621
1748
  */
1622
1749
  void
1623
1750
  Init_stringio(void)
1624
1751
  {
1752
+ #undef rb_intern
1753
+
1754
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
1755
+ rb_ext_ractor_safe(true);
1756
+ #endif
1757
+
1625
1758
  VALUE StringIO = rb_define_class("StringIO", rb_cData);
1626
1759
 
1760
+ rb_define_const(StringIO, "VERSION", rb_str_new_cstr(STRINGIO_VERSION));
1761
+
1627
1762
  rb_include_module(StringIO, rb_mEnumerable);
1628
1763
  rb_define_alloc_func(StringIO, strio_s_allocate);
1629
1764
  rb_define_singleton_method(StringIO, "new", strio_s_new, -1);
@@ -1665,13 +1800,9 @@ Init_stringio(void)
1665
1800
 
1666
1801
  rb_define_method(StringIO, "each", strio_each, -1);
1667
1802
  rb_define_method(StringIO, "each_line", strio_each, -1);
1668
- rb_define_method(StringIO, "lines", strio_lines, -1);
1669
1803
  rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
1670
- rb_define_method(StringIO, "bytes", strio_bytes, 0);
1671
1804
  rb_define_method(StringIO, "each_char", strio_each_char, 0);
1672
- rb_define_method(StringIO, "chars", strio_chars, 0);
1673
1805
  rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0);
1674
- rb_define_method(StringIO, "codepoints", strio_codepoints, 0);
1675
1806
  rb_define_method(StringIO, "getc", strio_getc, 0);
1676
1807
  rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
1677
1808
  rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
@@ -1704,6 +1835,7 @@ Init_stringio(void)
1704
1835
  rb_define_method(StringIO, "external_encoding", strio_external_encoding, 0);
1705
1836
  rb_define_method(StringIO, "internal_encoding", strio_internal_encoding, 0);
1706
1837
  rb_define_method(StringIO, "set_encoding", strio_set_encoding, -1);
1838
+ rb_define_method(StringIO, "set_encoding_by_bom", strio_set_encoding_by_bom, 0);
1707
1839
 
1708
1840
  {
1709
1841
  VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stringio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nobu Nakada
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain:
11
- - certs/nobu.pem
12
- date: 2016-06-09 00:00:00.000000000 Z
10
+ cert_chain: []
11
+ date: 2020-12-18 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake-compiler
@@ -25,19 +24,33 @@ dependencies:
25
24
  - - ">="
26
25
  - !ruby/object:Gem::Version
27
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: test-unit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
28
41
  description: Pseudo `IO` class from/to `String`.
29
42
  email: nobu@ruby-lang.org
30
43
  executables: []
31
44
  extensions:
32
- - extconf.rb
45
+ - ext/stringio/extconf.rb
33
46
  extra_rdoc_files: []
34
47
  files:
35
48
  - README.md
36
- - depend
37
- - extconf.rb
38
- - stringio.c
49
+ - ext/stringio/extconf.rb
50
+ - ext/stringio/stringio.c
39
51
  homepage: https://github.com/ruby/stringio
40
52
  licenses:
53
+ - Ruby
41
54
  - BSD-2-Clause
42
55
  metadata: {}
43
56
  post_install_message:
@@ -48,15 +61,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
48
61
  requirements:
49
62
  - - ">="
50
63
  - !ruby/object:Gem::Version
51
- version: '2.2'
64
+ version: '2.5'
52
65
  required_rubygems_version: !ruby/object:Gem::Requirement
53
66
  requirements:
54
67
  - - ">="
55
68
  - !ruby/object:Gem::Version
56
69
  version: '2.6'
57
70
  requirements: []
58
- rubyforge_project:
59
- rubygems_version: 2.7.6
71
+ rubygems_version: 3.1.4
60
72
  signing_key:
61
73
  specification_version: 4
62
74
  summary: Pseudo IO on String
data/depend DELETED
@@ -1,17 +0,0 @@
1
- # AUTOGENERATED DEPENDENCIES START
2
- stringio.o: $(RUBY_EXTCONF_H)
3
- stringio.o: $(arch_hdrdir)/ruby/config.h
4
- stringio.o: $(hdrdir)/ruby/backward.h
5
- stringio.o: $(hdrdir)/ruby/defines.h
6
- stringio.o: $(hdrdir)/ruby/encoding.h
7
- stringio.o: $(hdrdir)/ruby/intern.h
8
- stringio.o: $(hdrdir)/ruby/io.h
9
- stringio.o: $(hdrdir)/ruby/missing.h
10
- stringio.o: $(hdrdir)/ruby/onigmo.h
11
- stringio.o: $(hdrdir)/ruby/oniguruma.h
12
- stringio.o: $(hdrdir)/ruby/ruby.h
13
- stringio.o: $(hdrdir)/ruby/st.h
14
- stringio.o: $(hdrdir)/ruby/subst.h
15
- stringio.o: $(top_srcdir)/include/ruby.h
16
- stringio.o: stringio.c
17
- # AUTOGENERATED DEPENDENCIES END