Ruby  2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)
stringio.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  stringio.c -
4 
5  $Author$
6  $RoughId: stringio.c,v 1.13 2002/03/14 03:24:18 nobu Exp $
7  created at: Tue Feb 19 04:10:38 JST 2002
8 
9  All the files in this distribution are covered under the Ruby's
10  license (see the file COPYING).
11 
12 **********************************************************************/
13 
14 #define STRINGIO_VERSION "0.1.0"
15 
16 #include "ruby.h"
17 #include "ruby/io.h"
18 #include "ruby/encoding.h"
19 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
20 #include <fcntl.h>
21 #elif defined(HAVE_SYS_FCNTL_H)
22 #include <sys/fcntl.h>
23 #endif
24 
25 #ifndef RB_INTEGER_TYPE_P
26 # define RB_INTEGER_TYPE_P(c) (FIXNUM_P(c) || RB_TYPE_P(c, T_BIGNUM))
27 #endif
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)) {
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;
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 
109 struct StringIO {
112  long pos;
113  long lineno;
114  int flags;
115  int count;
116 };
117 
118 static VALUE strio_init(int, VALUE *, struct StringIO *, VALUE);
119 static VALUE strio_unget_bytes(struct StringIO *, const char *, long);
120 static long strio_write(VALUE self, VALUE str);
121 
122 #define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
123 #define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
124 #define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string))
125 
126 static struct StringIO *
127 strio_alloc(void)
128 {
129  struct StringIO *ptr = ALLOC(struct StringIO);
130  ptr->string = Qnil;
131  ptr->pos = 0;
132  ptr->lineno = 0;
133  ptr->flags = 0;
134  ptr->count = 1;
135  return ptr;
136 }
137 
138 static void
139 strio_mark(void *p)
140 {
141  struct StringIO *ptr = p;
142 
143  rb_gc_mark(ptr->string);
144 }
145 
146 static void
147 strio_free(void *p)
148 {
149  struct StringIO *ptr = p;
150  if (--ptr->count <= 0) {
151  xfree(ptr);
152  }
153 }
154 
155 static size_t
156 strio_memsize(const void *p)
157 {
158  return sizeof(struct StringIO);
159 }
160 
161 static const rb_data_type_t strio_data_type = {
162  "strio",
163  {
164  strio_mark,
165  strio_free,
166  strio_memsize,
167  },
169 };
170 
171 #define check_strio(self) ((struct StringIO*)rb_check_typeddata((self), &strio_data_type))
172 
173 static struct StringIO*
174 get_strio(VALUE self)
175 {
176  struct StringIO *ptr = check_strio(rb_io_taint_check(self));
177 
178  if (!ptr) {
179  rb_raise(rb_eIOError, "uninitialized stream");
180  }
181  return ptr;
182 }
183 
184 static VALUE
185 enc_subseq(VALUE str, long pos, long len, rb_encoding *enc)
186 {
187  str = rb_str_subseq(str, pos, len);
189  return str;
190 }
191 
192 static VALUE
193 strio_substr(struct StringIO *ptr, long pos, long len, rb_encoding *enc)
194 {
195  VALUE str = ptr->string;
196  long rlen = RSTRING_LEN(str) - pos;
197 
198  if (len > rlen) len = rlen;
199  if (len < 0) len = 0;
200  if (len == 0) return rb_enc_str_new(0, 0, enc);
201  return enc_subseq(str, pos, len, enc);
202 }
203 
204 #define StringIO(obj) get_strio(obj)
205 
206 #define STRIO_READABLE FL_USER4
207 #define STRIO_WRITABLE FL_USER5
208 #define STRIO_READWRITE (STRIO_READABLE|STRIO_WRITABLE)
210 #define STRIO_MODE_SET_P(strio, mode) \
211  ((RBASIC(strio)->flags & STRIO_##mode) && \
212  ((struct StringIO*)DATA_PTR(strio))->flags & FMODE_##mode)
213 #define CLOSED(strio) (!STRIO_MODE_SET_P(strio, READWRITE))
214 #define READABLE(strio) STRIO_MODE_SET_P(strio, READABLE)
215 #define WRITABLE(strio) STRIO_MODE_SET_P(strio, WRITABLE)
216 
217 static VALUE sym_exception;
218 
219 static struct StringIO*
220 readable(VALUE strio)
221 {
222  struct StringIO *ptr = StringIO(strio);
223  if (!READABLE(strio)) {
224  rb_raise(rb_eIOError, "not opened for reading");
225  }
226  return ptr;
227 }
228 
229 static struct StringIO*
230 writable(VALUE strio)
231 {
232  struct StringIO *ptr = StringIO(strio);
233  if (!WRITABLE(strio)) {
234  rb_raise(rb_eIOError, "not opened for writing");
235  }
236  return ptr;
237 }
238 
239 static void
240 check_modifiable(struct StringIO *ptr)
241 {
242  if (OBJ_FROZEN(ptr->string)) {
243  rb_raise(rb_eIOError, "not modifiable string");
244  }
245 }
246 
247 static VALUE
248 strio_s_allocate(VALUE klass)
249 {
250  return TypedData_Wrap_Struct(klass, &strio_data_type, 0);
251 }
252 
253 /*
254  * call-seq: StringIO.new(string=""[, mode])
255  *
256  * Creates new StringIO instance from with _string_ and _mode_.
257  */
258 static VALUE
259 strio_initialize(int argc, VALUE *argv, VALUE self)
260 {
261  struct StringIO *ptr = check_strio(self);
262 
263  if (!ptr) {
264  DATA_PTR(self) = ptr = strio_alloc();
265  }
266  rb_call_super(0, 0);
267  return strio_init(argc, argv, ptr, self);
268 }
269 
270 static int
271 detect_bom(VALUE str, int *bomlen)
272 {
273  const char *p;
274  long len;
275 
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  }
286  }
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");
294  }
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");
306  }
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");
314  }
315  break;
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) {
347  StringValue(string);
348  }
349  else {
350  string = rb_enc_str_new("", 0, rb_default_external_encoding());
351  }
352  if (OBJ_FROZEN_RAW(string)) {
353  if (ptr->flags & FMODE_WRITABLE) {
355  }
356  }
357  else {
358  if (NIL_P(vmode)) {
360  }
361  }
362  if (ptr->flags & FMODE_TRUNC) {
363  rb_str_resize(string, 0);
364  }
365  ptr->string = string;
366  ptr->enc = convconfig.enc;
367  ptr->pos = 0;
368  ptr->lineno = 0;
369  if (ptr->flags & FMODE_SETENC_BY_BOM) set_encoding_by_bom(ptr);
370  RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE);
371  return self;
372 }
373 
374 static VALUE
375 strio_finalize(VALUE self)
376 {
377  struct StringIO *ptr = StringIO(self);
378  ptr->string = Qnil;
380  return self;
381 }
382 
383 /*
384  * call-seq: StringIO.open(string=""[, mode]) {|strio| ...}
385  *
386  * Equivalent to StringIO.new except that when it is called with a block, it
387  * yields with the new instance and closes it, and returns the result which
388  * returned from the block.
389  */
390 static VALUE
391 strio_s_open(int argc, VALUE *argv, VALUE klass)
392 {
394  if (!rb_block_given_p()) return obj;
395  return rb_ensure(rb_yield, obj, strio_finalize, obj);
396 }
397 
398 /* :nodoc: */
399 static VALUE
400 strio_s_new(int argc, VALUE *argv, VALUE klass)
401 {
402  if (rb_block_given_p()) {
403  VALUE cname = rb_obj_as_string(klass);
404 
405  rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
406  cname, cname);
407  }
409 }
410 
411 /*
412  * Returns +false+. Just for compatibility to IO.
413  */
414 static VALUE
415 strio_false(VALUE self)
416 {
417  StringIO(self);
418  return Qfalse;
419 }
420 
421 /*
422  * Returns +nil+. Just for compatibility to IO.
423  */
424 static VALUE
425 strio_nil(VALUE self)
426 {
427  StringIO(self);
428  return Qnil;
429 }
430 
431 /*
432  * Returns an object itself. Just for compatibility to IO.
433  */
434 static VALUE
435 strio_self(VALUE self)
436 {
437  StringIO(self);
438  return self;
439 }
440 
441 /*
442  * Returns 0. Just for compatibility to IO.
443  */
444 static VALUE
445 strio_0(VALUE self)
446 {
447  StringIO(self);
448  return INT2FIX(0);
449 }
450 
451 /*
452  * Returns the argument unchanged. Just for compatibility to IO.
453  */
454 static VALUE
455 strio_first(VALUE self, VALUE arg)
456 {
457  StringIO(self);
458  return arg;
459 }
460 
461 /*
462  * Raises NotImplementedError.
463  */
464 static VALUE
465 strio_unimpl(int argc, VALUE *argv, VALUE self)
466 {
467  StringIO(self);
468  rb_notimplement();
469 
470  UNREACHABLE;
471 }
472 
473 /*
474  * call-seq: strio.string -> string
475  *
476  * Returns underlying String object, the subject of IO.
477  */
478 static VALUE
479 strio_get_string(VALUE self)
480 {
481  return StringIO(self)->string;
482 }
483 
484 /*
485  * call-seq:
486  * strio.string = string -> string
487  *
488  * Changes underlying String object, the subject of IO.
489  */
490 static VALUE
491 strio_set_string(VALUE self, VALUE string)
492 {
493  struct StringIO *ptr = StringIO(self);
494 
495  rb_io_taint_check(self);
497  StringValue(string);
499  ptr->pos = 0;
500  ptr->lineno = 0;
501  return ptr->string = string;
502 }
503 
504 /*
505  * call-seq:
506  * strio.close -> nil
507  *
508  * Closes a StringIO. The stream is unavailable for any further data
509  * operations; an +IOError+ is raised if such an attempt is made.
510  */
511 static VALUE
512 strio_close(VALUE self)
513 {
514  StringIO(self);
515  RBASIC(self)->flags &= ~STRIO_READWRITE;
516  return Qnil;
517 }
518 
519 /*
520  * call-seq:
521  * strio.close_read -> nil
522  *
523  * Closes the read end of a StringIO. Will raise an +IOError+ if the
524  * receiver is not readable.
525  */
526 static VALUE
527 strio_close_read(VALUE self)
528 {
529  struct StringIO *ptr = StringIO(self);
530  if (!(ptr->flags & FMODE_READABLE)) {
531  rb_raise(rb_eIOError, "closing non-duplex IO for reading");
532  }
533  RBASIC(self)->flags &= ~STRIO_READABLE;
534  return Qnil;
535 }
536 
537 /*
538  * call-seq:
539  * strio.close_write -> nil
540  *
541  * Closes the write end of a StringIO. Will raise an +IOError+ if the
542  * receiver is not writeable.
543  */
544 static VALUE
545 strio_close_write(VALUE self)
546 {
547  struct StringIO *ptr = StringIO(self);
548  if (!(ptr->flags & FMODE_WRITABLE)) {
549  rb_raise(rb_eIOError, "closing non-duplex IO for writing");
550  }
551  RBASIC(self)->flags &= ~STRIO_WRITABLE;
552  return Qnil;
553 }
554 
555 /*
556  * call-seq:
557  * strio.closed? -> true or false
558  *
559  * Returns +true+ if the stream is completely closed, +false+ otherwise.
560  */
561 static VALUE
562 strio_closed(VALUE self)
563 {
564  StringIO(self);
565  if (!CLOSED(self)) return Qfalse;
566  return Qtrue;
567 }
568 
569 /*
570  * call-seq:
571  * strio.closed_read? -> true or false
572  *
573  * Returns +true+ if the stream is not readable, +false+ otherwise.
574  */
575 static VALUE
576 strio_closed_read(VALUE self)
577 {
578  StringIO(self);
579  if (READABLE(self)) return Qfalse;
580  return Qtrue;
581 }
582 
583 /*
584  * call-seq:
585  * strio.closed_write? -> true or false
586  *
587  * Returns +true+ if the stream is not writable, +false+ otherwise.
588  */
589 static VALUE
590 strio_closed_write(VALUE self)
591 {
592  StringIO(self);
593  if (WRITABLE(self)) return Qfalse;
594  return Qtrue;
595 }
596 
597 /*
598  * call-seq:
599  * strio.eof -> true or false
600  * strio.eof? -> true or false
601  *
602  * Returns true if the stream is at the end of the data (underlying string).
603  * The stream must be opened for reading or an +IOError+ will be raised.
604  */
605 static VALUE
606 strio_eof(VALUE self)
607 {
608  struct StringIO *ptr = readable(self);
609  if (ptr->pos < RSTRING_LEN(ptr->string)) return Qfalse;
610  return Qtrue;
611 }
612 
613 /* :nodoc: */
614 static VALUE
615 strio_copy(VALUE copy, VALUE orig)
616 {
617  struct StringIO *ptr;
618 
619  orig = rb_convert_type(orig, T_DATA, "StringIO", "to_strio");
620  if (copy == orig) return copy;
621  ptr = StringIO(orig);
622  if (check_strio(copy)) {
623  strio_free(DATA_PTR(copy));
624  }
625  DATA_PTR(copy) = ptr;
626  RBASIC(copy)->flags &= ~STRIO_READWRITE;
627  RBASIC(copy)->flags |= RBASIC(orig)->flags & STRIO_READWRITE;
628  ++ptr->count;
629  return copy;
630 }
631 
632 /*
633  * call-seq:
634  * strio.lineno -> integer
635  *
636  * Returns the current line number. The stream must be
637  * opened for reading. +lineno+ counts the number of times +gets+ is
638  * called, rather than the number of newlines encountered. The two
639  * values will differ if +gets+ is called with a separator other than
640  * newline. See also the <code>$.</code> variable.
641  */
642 static VALUE
643 strio_get_lineno(VALUE self)
644 {
645  return LONG2NUM(StringIO(self)->lineno);
646 }
647 
648 /*
649  * call-seq:
650  * strio.lineno = integer -> integer
651  *
652  * Manually sets the current line number to the given value.
653  * <code>$.</code> is updated only on the next read.
654  */
655 static VALUE
656 strio_set_lineno(VALUE self, VALUE lineno)
657 {
658  StringIO(self)->lineno = NUM2LONG(lineno);
659  return lineno;
660 }
661 
662 /*
663  * call-seq:
664  * strio.binmode -> stringio
665  *
666  * Puts stream into binary mode. See IO#binmode.
667  *
668  */
669 static VALUE
670 strio_binmode(VALUE self)
671 {
672  struct StringIO *ptr = StringIO(self);
674 
675  ptr->enc = enc;
676  if (WRITABLE(self)) {
677  rb_enc_associate(ptr->string, enc);
678  }
679  return self;
680 }
681 
682 #define strio_fcntl strio_unimpl
683 
684 #define strio_flush strio_self
685 
686 #define strio_fsync strio_0
687 
688 /*
689  * call-seq:
690  * strio.reopen(other_StrIO) -> strio
691  * strio.reopen(string, mode) -> strio
692  *
693  * Reinitializes the stream with the given <i>other_StrIO</i> or _string_
694  * and _mode_ (see StringIO#new).
695  */
696 static VALUE
697 strio_reopen(int argc, VALUE *argv, VALUE self)
698 {
699  rb_io_taint_check(self);
700  if (argc == 1 && !RB_TYPE_P(*argv, T_STRING)) {
701  return strio_copy(self, *argv);
702  }
703  return strio_init(argc, argv, StringIO(self), self);
704 }
705 
706 /*
707  * call-seq:
708  * strio.pos -> integer
709  * strio.tell -> integer
710  *
711  * Returns the current offset (in bytes).
712  */
713 static VALUE
714 strio_get_pos(VALUE self)
715 {
716  return LONG2NUM(StringIO(self)->pos);
717 }
718 
719 /*
720  * call-seq:
721  * strio.pos = integer -> integer
722  *
723  * Seeks to the given position (in bytes).
724  */
725 static VALUE
726 strio_set_pos(VALUE self, VALUE pos)
727 {
728  struct StringIO *ptr = StringIO(self);
729  long p = NUM2LONG(pos);
730  if (p < 0) {
731  error_inval(0);
732  }
733  ptr->pos = p;
734  return pos;
735 }
736 
737 /*
738  * call-seq:
739  * strio.rewind -> 0
740  *
741  * Positions the stream to the beginning of input, resetting
742  * +lineno+ to zero.
743  */
744 static VALUE
745 strio_rewind(VALUE self)
746 {
747  struct StringIO *ptr = StringIO(self);
748  ptr->pos = 0;
749  ptr->lineno = 0;
750  return INT2FIX(0);
751 }
752 
753 /*
754  * call-seq:
755  * strio.seek(amount, whence=SEEK_SET) -> 0
756  *
757  * Seeks to a given offset _amount_ in the stream according to
758  * the value of _whence_ (see IO#seek).
759  */
760 static VALUE
761 strio_seek(int argc, VALUE *argv, VALUE self)
762 {
763  VALUE whence;
764  struct StringIO *ptr = StringIO(self);
765  long amount, offset;
766 
767  rb_scan_args(argc, argv, "11", NULL, &whence);
768  amount = NUM2LONG(argv[0]);
769  if (CLOSED(self)) {
770  rb_raise(rb_eIOError, "closed stream");
771  }
772  switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
773  case 0:
774  offset = 0;
775  break;
776  case 1:
777  offset = ptr->pos;
778  break;
779  case 2:
780  offset = RSTRING_LEN(ptr->string);
781  break;
782  default:
783  error_inval("invalid whence");
784  }
785  if (amount > LONG_MAX - offset || amount + offset < 0) {
786  error_inval(0);
787  }
788  ptr->pos = amount + offset;
789  return INT2FIX(0);
790 }
791 
792 /*
793  * call-seq:
794  * strio.sync -> true
795  *
796  * Returns +true+ always.
797  */
798 static VALUE
799 strio_get_sync(VALUE self)
800 {
801  StringIO(self);
802  return Qtrue;
803 }
804 
805 #define strio_set_sync strio_first
806 
807 #define strio_tell strio_get_pos
808 
809 /*
810  * call-seq:
811  * strio.each_byte {|byte| block } -> strio
812  * strio.each_byte -> anEnumerator
813  *
814  * See IO#each_byte.
815  */
816 static VALUE
817 strio_each_byte(VALUE self)
818 {
819  struct StringIO *ptr = readable(self);
820 
821  RETURN_ENUMERATOR(self, 0, 0);
822 
823  while (ptr->pos < RSTRING_LEN(ptr->string)) {
824  char c = RSTRING_PTR(ptr->string)[ptr->pos++];
825  rb_yield(CHR2FIX(c));
826  }
827  return self;
828 }
829 
830 /*
831  * This is a deprecated alias for #each_byte.
832  */
833 static VALUE
834 strio_bytes(VALUE self)
835 {
836  rb_warn("StringIO#bytes is deprecated; use #each_byte instead");
837  if (!rb_block_given_p())
838  return rb_enumeratorize(self, ID2SYM(rb_intern("each_byte")), 0, 0);
839  return strio_each_byte(self);
840 }
841 
842 /*
843  * call-seq:
844  * strio.getc -> string or nil
845  *
846  * See IO#getc.
847  */
848 static VALUE
849 strio_getc(VALUE self)
850 {
851  struct StringIO *ptr = readable(self);
853  VALUE str = ptr->string;
854  long pos = ptr->pos;
855  int len;
856  char *p;
857 
858  if (pos >= RSTRING_LEN(str)) {
859  return Qnil;
860  }
861  p = RSTRING_PTR(str)+pos;
863  ptr->pos += len;
864  return enc_subseq(str, pos, len, enc);
865 }
866 
867 /*
868  * call-seq:
869  * strio.getbyte -> fixnum or nil
870  *
871  * See IO#getbyte.
872  */
873 static VALUE
874 strio_getbyte(VALUE self)
875 {
876  struct StringIO *ptr = readable(self);
877  int c;
878  if (ptr->pos >= RSTRING_LEN(ptr->string)) {
879  return Qnil;
880  }
881  c = RSTRING_PTR(ptr->string)[ptr->pos++];
882  return CHR2FIX(c);
883 }
884 
885 static void
886 strio_extend(struct StringIO *ptr, long pos, long len)
887 {
888  long olen;
889 
890  if (len > LONG_MAX - pos)
891  rb_raise(rb_eArgError, "string size too big");
892 
893  check_modifiable(ptr);
894  olen = RSTRING_LEN(ptr->string);
895  if (pos + len > olen) {
896  rb_str_resize(ptr->string, pos + len);
897  if (pos > olen)
898  MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen);
899  }
900  else {
901  rb_str_modify(ptr->string);
902  }
903 }
904 
905 /*
906  * call-seq:
907  * strio.ungetc(string) -> nil
908  *
909  * Pushes back one character (passed as a parameter)
910  * such that a subsequent buffered read will return it. There is no
911  * limitation for multiple pushbacks including pushing back behind the
912  * beginning of the buffer string.
913  */
914 static VALUE
915 strio_ungetc(VALUE self, VALUE c)
916 {
917  struct StringIO *ptr = readable(self);
918  rb_encoding *enc, *enc2;
919 
920  check_modifiable(ptr);
921  if (NIL_P(c)) return Qnil;
922  if (RB_INTEGER_TYPE_P(c)) {
923  int len, cc = NUM2INT(c);
924  char buf[16];
925 
926  enc = rb_enc_get(ptr->string);
927  len = rb_enc_codelen(cc, enc);
928  if (len <= 0) rb_enc_uint_chr(cc, enc);
929  rb_enc_mbcput(cc, buf, enc);
930  return strio_unget_bytes(ptr, buf, len);
931  }
932  else {
933  SafeStringValue(c);
934  enc = rb_enc_get(ptr->string);
935  enc2 = rb_enc_get(c);
936  if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
937  c = rb_str_conv_enc(c, enc2, enc);
938  }
939  strio_unget_bytes(ptr, RSTRING_PTR(c), RSTRING_LEN(c));
940  RB_GC_GUARD(c);
941  return Qnil;
942  }
943 }
944 
945 /*
946  * call-seq:
947  * strio.ungetbyte(fixnum) -> nil
948  *
949  * See IO#ungetbyte
950  */
951 static VALUE
952 strio_ungetbyte(VALUE self, VALUE c)
953 {
954  struct StringIO *ptr = readable(self);
955 
956  check_modifiable(ptr);
957  if (NIL_P(c)) return Qnil;
958  if (RB_INTEGER_TYPE_P(c)) {
959  /* rb_int_and() not visible from exts */
960  VALUE v = rb_funcall(c, '&', 1, INT2FIX(0xff));
961  const char cc = NUM2INT(v) & 0xFF;
962  strio_unget_bytes(ptr, &cc, 1);
963  }
964  else {
965  long cl;
966  SafeStringValue(c);
967  cl = RSTRING_LEN(c);
968  if (cl > 0) {
969  strio_unget_bytes(ptr, RSTRING_PTR(c), cl);
970  RB_GC_GUARD(c);
971  }
972  }
973  return Qnil;
974 }
975 
976 static VALUE
977 strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
978 {
979  long pos = ptr->pos, len, rest;
980  VALUE str = ptr->string;
981  char *s;
982 
983  len = RSTRING_LEN(str);
984  rest = pos - len;
985  if (cl > pos) {
986  long ex = (rest < 0 ? cl-pos : cl+rest);
988  rb_str_set_len(str, len + ex);
989  s = RSTRING_PTR(str);
990  if (rest < 0) memmove(s + cl, s + pos, -rest);
991  pos = 0;
992  }
993  else {
994  if (rest > 0) {
995  rb_str_modify_expand(str, rest);
996  rb_str_set_len(str, len + rest);
997  }
998  s = RSTRING_PTR(str);
999  if (rest > cl) memset(s + len, 0, rest - cl);
1000  pos -= cl;
1001  }
1002  memcpy(s + pos, cp, cl);
1003  ptr->pos = pos;
1004  return Qnil;
1005 }
1006 
1007 /*
1008  * call-seq:
1009  * strio.readchar -> string
1010  *
1011  * See IO#readchar.
1012  */
1013 static VALUE
1014 strio_readchar(VALUE self)
1015 {
1016  VALUE c = rb_funcallv(self, rb_intern("getc"), 0, 0);
1017  if (NIL_P(c)) rb_eof_error();
1018  return c;
1019 }
1020 
1021 /*
1022  * call-seq:
1023  * strio.readbyte -> fixnum
1024  *
1025  * See IO#readbyte.
1026  */
1027 static VALUE
1028 strio_readbyte(VALUE self)
1029 {
1030  VALUE c = rb_funcallv(self, rb_intern("getbyte"), 0, 0);
1031  if (NIL_P(c)) rb_eof_error();
1032  return c;
1033 }
1034 
1035 /*
1036  * call-seq:
1037  * strio.each_char {|char| block } -> strio
1038  * strio.each_char -> anEnumerator
1039  *
1040  * See IO#each_char.
1041  */
1042 static VALUE
1043 strio_each_char(VALUE self)
1044 {
1045  VALUE c;
1046 
1047  RETURN_ENUMERATOR(self, 0, 0);
1048 
1049  while (!NIL_P(c = strio_getc(self))) {
1050  rb_yield(c);
1051  }
1052  return self;
1053 }
1054 
1055 /*
1056  * This is a deprecated alias for #each_char.
1057  */
1058 static VALUE
1059 strio_chars(VALUE self)
1060 {
1061  rb_warn("StringIO#chars is deprecated; use #each_char instead");
1062  if (!rb_block_given_p())
1063  return rb_enumeratorize(self, ID2SYM(rb_intern("each_char")), 0, 0);
1064  return strio_each_char(self);
1065 }
1066 
1067 /*
1068  * call-seq:
1069  * strio.each_codepoint {|c| block } -> strio
1070  * strio.each_codepoint -> anEnumerator
1071  *
1072  * See IO#each_codepoint.
1073  */
1074 static VALUE
1075 strio_each_codepoint(VALUE self)
1076 {
1077  struct StringIO *ptr;
1078  rb_encoding *enc;
1079  unsigned int c;
1080  int n;
1081 
1082  RETURN_ENUMERATOR(self, 0, 0);
1083 
1084  ptr = readable(self);
1085  enc = get_enc(ptr);
1086  for (;;) {
1087  if (ptr->pos >= RSTRING_LEN(ptr->string)) {
1088  return self;
1089  }
1090 
1091  c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
1092  RSTRING_END(ptr->string), &n, enc);
1093  rb_yield(UINT2NUM(c));
1094  ptr->pos += n;
1095  }
1096  return self;
1097 }
1098 
1099 /*
1100  * This is a deprecated alias for #each_codepoint.
1101  */
1102 static VALUE
1103 strio_codepoints(VALUE self)
1104 {
1105  rb_warn("StringIO#codepoints is deprecated; use #each_codepoint instead");
1106  if (!rb_block_given_p())
1107  return rb_enumeratorize(self, ID2SYM(rb_intern("each_codepoint")), 0, 0);
1108  return strio_each_codepoint(self);
1109 }
1110 
1111 /* Boyer-Moore search: copied from regex.c */
1112 static void
1113 bm_init_skip(long *skip, const char *pat, long m)
1114 {
1115  int c;
1116 
1117  for (c = 0; c < (1 << CHAR_BIT); c++) {
1118  skip[c] = m;
1119  }
1120  while (--m) {
1121  skip[(unsigned char)*pat++] = m;
1122  }
1123 }
1124 
1125 static long
1126 bm_search(const char *little, long llen, const char *big, long blen, const long *skip)
1127 {
1128  long i, j, k;
1129 
1130  i = llen - 1;
1131  while (i < blen) {
1132  k = i;
1133  j = llen - 1;
1134  while (j >= 0 && big[k] == little[j]) {
1135  k--;
1136  j--;
1137  }
1138  if (j < 0) return k + 1;
1139  i += skip[(unsigned char)big[i]];
1140  }
1141  return -1;
1142 }
1143 
1144 struct getline_arg {
1146  long limit;
1147  unsigned int chomp: 1;
1148 };
1149 
1150 static struct getline_arg *
1151 prepare_getline_args(struct getline_arg *arg, int argc, VALUE *argv)
1152 {
1153  VALUE str, lim, opts;
1154  long limit = -1;
1155 
1156  argc = rb_scan_args(argc, argv, "02:", &str, &lim, &opts);
1157  switch (argc) {
1158  case 0:
1159  str = rb_rs;
1160  break;
1161 
1162  case 1:
1163  if (!NIL_P(str) && !RB_TYPE_P(str, T_STRING)) {
1165  if (NIL_P(tmp)) {
1166  limit = NUM2LONG(str);
1167  str = rb_rs;
1168  }
1169  else {
1170  str = tmp;
1171  }
1172  }
1173  break;
1174 
1175  case 2:
1176  if (!NIL_P(str)) StringValue(str);
1177  if (!NIL_P(lim)) limit = NUM2LONG(lim);
1178  break;
1179  }
1180  arg->rs = str;
1181  arg->limit = limit;
1182  arg->chomp = 0;
1183  if (!NIL_P(opts)) {
1184  static ID keywords[1];
1185  VALUE vchomp;
1186  if (!keywords[0]) {
1187  keywords[0] = rb_intern_const("chomp");
1188  }
1189  rb_get_kwargs(opts, keywords, 0, 1, &vchomp);
1190  arg->chomp = (vchomp != Qundef) && RTEST(vchomp);
1191  }
1192  return arg;
1193 }
1194 
1195 static inline int
1196 chomp_newline_width(const char *s, const char *e)
1197 {
1198  if (e > s && *--e == '\n') {
1199  if (e > s && *--e == '\r') return 2;
1200  return 1;
1201  }
1202  return 0;
1203 }
1204 
1205 static VALUE
1206 strio_getline(struct getline_arg *arg, struct StringIO *ptr)
1207 {
1208  const char *s, *e, *p;
1209  long n, limit = arg->limit;
1210  VALUE str = arg->rs;
1211  int w = 0;
1212  rb_encoding *enc = get_enc(ptr);
1213 
1214  if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
1215  return Qnil;
1216  }
1217  s = RSTRING_PTR(ptr->string);
1218  e = s + RSTRING_LEN(ptr->string);
1219  s += ptr->pos;
1220  if (limit > 0 && (size_t)limit < (size_t)(e - s)) {
1221  e = rb_enc_right_char_head(s, s + limit, e, get_enc(ptr));
1222  }
1223  if (NIL_P(str)) {
1224  if (arg->chomp) {
1225  w = chomp_newline_width(s, e);
1226  }
1227  str = strio_substr(ptr, ptr->pos, e - s - w, enc);
1228  }
1229  else if ((n = RSTRING_LEN(str)) == 0) {
1230  p = s;
1231  while (p[(p + 1 < e) && (*p == '\r') && 0] == '\n') {
1232  p += *p == '\r';
1233  if (++p == e) {
1234  return Qnil;
1235  }
1236  }
1237  s = p;
1238  while ((p = memchr(p, '\n', e - p)) && (p != e)) {
1239  if (*++p == '\n') {
1240  e = p + 1;
1241  w = (arg->chomp ? 1 : 0);
1242  break;
1243  }
1244  else if (*p == '\r' && p < e && p[1] == '\n') {
1245  e = p + 2;
1246  w = (arg->chomp ? 2 : 0);
1247  break;
1248  }
1249  }
1250  if (!w && arg->chomp) {
1251  w = chomp_newline_width(s, e);
1252  }
1253  str = strio_substr(ptr, s - RSTRING_PTR(ptr->string), e - s - w, enc);
1254  }
1255  else if (n == 1) {
1256  if ((p = memchr(s, RSTRING_PTR(str)[0], e - s)) != 0) {
1257  e = p + 1;
1258  w = (arg->chomp ? (p > s && *(p-1) == '\r') + 1 : 0);
1259  }
1260  str = strio_substr(ptr, ptr->pos, e - s - w, enc);
1261  }
1262  else {
1263  if (n < e - s) {
1264  if (e - s < 1024) {
1265  for (p = s; p + n <= e; ++p) {
1266  if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
1267  e = p + (arg->chomp ? 0 : n);
1268  break;
1269  }
1270  }
1271  }
1272  else {
1273  long skip[1 << CHAR_BIT], pos;
1274  p = RSTRING_PTR(str);
1275  bm_init_skip(skip, p, n);
1276  if ((pos = bm_search(p, n, s, e - s, skip)) >= 0) {
1277  e = s + pos + (arg->chomp ? 0 : n);
1278  }
1279  }
1280  }
1281  str = strio_substr(ptr, ptr->pos, e - s - w, enc);
1282  }
1283  ptr->pos = e - RSTRING_PTR(ptr->string);
1284  ptr->lineno++;
1285  return str;
1286 }
1287 
1288 /*
1289  * call-seq:
1290  * strio.gets(sep=$/, chomp: false) -> string or nil
1291  * strio.gets(limit, chomp: false) -> string or nil
1292  * strio.gets(sep, limit, chomp: false) -> string or nil
1293  *
1294  * See IO#gets.
1295  */
1296 static VALUE
1297 strio_gets(int argc, VALUE *argv, VALUE self)
1298 {
1299  struct getline_arg arg;
1300  VALUE str;
1301 
1302  if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
1303  struct StringIO *ptr = readable(self);
1304  return rb_enc_str_new(0, 0, get_enc(ptr));
1305  }
1306 
1307  str = strio_getline(&arg, readable(self));
1309  return str;
1310 }
1311 
1312 /*
1313  * call-seq:
1314  * strio.readline(sep=$/, chomp: false) -> string
1315  * strio.readline(limit, chomp: false) -> string or nil
1316  * strio.readline(sep, limit, chomp: false) -> string or nil
1317  *
1318  * See IO#readline.
1319  */
1320 static VALUE
1321 strio_readline(int argc, VALUE *argv, VALUE self)
1322 {
1324  if (NIL_P(line)) rb_eof_error();
1325  return line;
1326 }
1327 
1328 /*
1329  * call-seq:
1330  * strio.each(sep=$/, chomp: false) {|line| block } -> strio
1331  * strio.each(limit, chomp: false) {|line| block } -> strio
1332  * strio.each(sep, limit, chomp: false) {|line| block } -> strio
1333  * strio.each(...) -> anEnumerator
1334  *
1335  * strio.each_line(sep=$/, chomp: false) {|line| block } -> strio
1336  * strio.each_line(limit, chomp: false) {|line| block } -> strio
1337  * strio.each_line(sep, limit, chomp: false) {|line| block } -> strio
1338  * strio.each_line(...) -> anEnumerator
1339  *
1340  * See IO#each.
1341  */
1342 static VALUE
1343 strio_each(int argc, VALUE *argv, VALUE self)
1344 {
1345  VALUE line;
1346  struct getline_arg arg;
1347 
1348  StringIO(self);
1349  RETURN_ENUMERATOR(self, argc, argv);
1350 
1351  if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
1352  rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
1353  }
1354 
1355  while (!NIL_P(line = strio_getline(&arg, readable(self)))) {
1356  rb_yield(line);
1357  }
1358  return self;
1359 }
1360 
1361 /*
1362  * This is a deprecated alias for #each_line.
1363  */
1364 static VALUE
1365 strio_lines(int argc, VALUE *argv, VALUE self)
1366 {
1367  rb_warn("StringIO#lines is deprecated; use #each_line instead");
1368  if (!rb_block_given_p())
1369  return rb_enumeratorize(self, ID2SYM(rb_intern("each_line")), argc, argv);
1370  return strio_each(argc, argv, self);
1371 }
1372 
1373 /*
1374  * call-seq:
1375  * strio.readlines(sep=$/, chomp: false) -> array
1376  * strio.readlines(limit, chomp: false) -> array
1377  * strio.readlines(sep, limit, chomp: false) -> array
1378  *
1379  * See IO#readlines.
1380  */
1381 static VALUE
1382 strio_readlines(int argc, VALUE *argv, VALUE self)
1383 {
1384  VALUE ary, line;
1385  struct getline_arg arg;
1386 
1387  StringIO(self);
1388  ary = rb_ary_new();
1389  if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
1390  rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
1391  }
1392 
1393  while (!NIL_P(line = strio_getline(&arg, readable(self)))) {
1394  rb_ary_push(ary, line);
1395  }
1396  return ary;
1397 }
1398 
1399 /*
1400  * call-seq:
1401  * strio.write(string, ...) -> integer
1402  * strio.syswrite(string) -> integer
1403  *
1404  * Appends the given string to the underlying buffer string.
1405  * The stream must be opened for writing. If the argument is not a
1406  * string, it will be converted to a string using <code>to_s</code>.
1407  * Returns the number of bytes written. See IO#write.
1408  */
1409 static VALUE
1410 strio_write_m(int argc, VALUE *argv, VALUE self)
1411 {
1412  long len = 0;
1413  while (argc-- > 0) {
1414  /* StringIO can't exceed long limit */
1415  len += strio_write(self, *argv++);
1416  }
1417  return LONG2NUM(len);
1418 }
1419 
1420 static long
1421 strio_write(VALUE self, VALUE str)
1422 {
1423  struct StringIO *ptr = writable(self);
1424  long len, olen;
1425  rb_encoding *enc, *enc2;
1426  rb_encoding *const ascii8bit = rb_ascii8bit_encoding();
1427 
1428  if (!RB_TYPE_P(str, T_STRING))
1430  enc = get_enc(ptr);
1431  enc2 = rb_enc_get(str);
1432  if (enc != enc2 && enc != ascii8bit) {
1433  str = rb_str_conv_enc(str, enc2, enc);
1434  }
1435  len = RSTRING_LEN(str);
1436  if (len == 0) return 0;
1437  check_modifiable(ptr);
1438  olen = RSTRING_LEN(ptr->string);
1439  if (ptr->flags & FMODE_APPEND) {
1440  ptr->pos = olen;
1441  }
1442  if (ptr->pos == olen) {
1443  if (enc == ascii8bit || enc2 == ascii8bit) {
1445  }
1446  else {
1447  rb_str_buf_append(ptr->string, str);
1448  }
1449  }
1450  else {
1451  strio_extend(ptr, ptr->pos, len);
1452  memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
1453  }
1454  RB_GC_GUARD(str);
1455  ptr->pos += len;
1456  return len;
1457 }
1458 
1459 /*
1460  * call-seq:
1461  * strio << obj -> strio
1462  *
1463  * See IO#<<.
1464  */
1465 #define strio_addstr rb_io_addstr
1466 
1467 /*
1468  * call-seq:
1469  * strio.print() -> nil
1470  * strio.print(obj, ...) -> nil
1471  *
1472  * See IO#print.
1473  */
1474 #define strio_print rb_io_print
1475 
1476 /*
1477  * call-seq:
1478  * strio.printf(format_string [, obj, ...] ) -> nil
1479  *
1480  * See IO#printf.
1481  */
1482 #define strio_printf rb_io_printf
1483 
1484 /*
1485  * call-seq:
1486  * strio.putc(obj) -> obj
1487  *
1488  * See IO#putc.
1489  */
1490 static VALUE
1491 strio_putc(VALUE self, VALUE ch)
1492 {
1493  struct StringIO *ptr = writable(self);
1494  VALUE str;
1495 
1496  check_modifiable(ptr);
1497  if (RB_TYPE_P(ch, T_STRING)) {
1498  str = rb_str_substr(ch, 0, 1);
1499  }
1500  else {
1501  char c = NUM2CHR(ch);
1502  str = rb_str_new(&c, 1);
1503  }
1504  strio_write(self, str);
1505  return ch;
1506 }
1507 
1508 /*
1509  * call-seq:
1510  * strio.puts(obj, ...) -> nil
1511  *
1512  * See IO#puts.
1513  */
1514 #define strio_puts rb_io_puts
1515 
1516 /*
1517  * call-seq:
1518  * strio.read([length [, outbuf]]) -> string, outbuf, or nil
1519  *
1520  * See IO#read.
1521  */
1522 static VALUE
1523 strio_read(int argc, VALUE *argv, VALUE self)
1524 {
1525  struct StringIO *ptr = readable(self);
1526  VALUE str = Qnil;
1527  long len;
1528  int binary = 0;
1529 
1530  rb_check_arity(argc, 0, 2);
1531  switch (argc) {
1532  case 2:
1533  str = argv[1];
1534  if (!NIL_P(str)) {
1535  StringValue(str);
1536  rb_str_modify(str);
1537  }
1538  /* fall through */
1539  case 1:
1540  if (!NIL_P(argv[0])) {
1541  len = NUM2LONG(argv[0]);
1542  if (len < 0) {
1543  rb_raise(rb_eArgError, "negative length %ld given", len);
1544  }
1545  if (len > 0 && ptr->pos >= RSTRING_LEN(ptr->string)) {
1546  if (!NIL_P(str)) rb_str_resize(str, 0);
1547  return Qnil;
1548  }
1549  binary = 1;
1550  break;
1551  }
1552  /* fall through */
1553  case 0:
1554  len = RSTRING_LEN(ptr->string);
1555  if (len <= ptr->pos) {
1556  rb_encoding *enc = get_enc(ptr);
1557  if (NIL_P(str)) {
1558  str = rb_str_new(0, 0);
1559  }
1560  else {
1561  rb_str_resize(str, 0);
1562  }
1564  return str;
1565  }
1566  else {
1567  len -= ptr->pos;
1568  }
1569  break;
1570  }
1571  if (NIL_P(str)) {
1572  rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
1573  str = strio_substr(ptr, ptr->pos, len, enc);
1574  }
1575  else {
1576  long rest = RSTRING_LEN(ptr->string) - ptr->pos;
1577  if (len > rest) len = rest;
1578  rb_str_resize(str, len);
1579  MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
1580  if (binary)
1582  else
1583  rb_enc_copy(str, ptr->string);
1584  }
1585  ptr->pos += RSTRING_LEN(str);
1586  return str;
1587 }
1588 
1589 /*
1590  * call-seq:
1591  * strio.sysread(integer[, outbuf]) -> string
1592  * strio.readpartial(integer[, outbuf]) -> string
1593  *
1594  * Similar to #read, but raises +EOFError+ at end of string instead of
1595  * returning +nil+, as well as IO#sysread does.
1596  */
1597 static VALUE
1598 strio_sysread(int argc, VALUE *argv, VALUE self)
1599 {
1601  if (NIL_P(val)) {
1602  rb_eof_error();
1603  }
1604  return val;
1605 }
1606 
1607 /*
1608  * call-seq:
1609  * strio.read_nonblock(integer[, outbuf [, opts]]) -> string
1610  *
1611  * Similar to #read, but raises +EOFError+ at end of string unless the
1612  * +exception: false+ option is passed in.
1613  */
1614 static VALUE
1615 strio_read_nonblock(int argc, VALUE *argv, VALUE self)
1616 {
1617  VALUE opts = Qnil, val;
1618 
1619  rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
1620 
1621  if (!NIL_P(opts)) {
1622  argc--;
1623  }
1624 
1625  val = strio_read(argc, argv, self);
1626  if (NIL_P(val)) {
1627  if (!NIL_P(opts) &&
1628  rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
1629  return Qnil;
1630  else
1631  rb_eof_error();
1632  }
1633 
1634  return val;
1635 }
1636 
1637 #define strio_syswrite rb_io_write
1638 
1639 static VALUE
1640 strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
1641 {
1642  VALUE str;
1643 
1644  rb_scan_args(argc, argv, "10:", &str, NULL);
1645  return strio_syswrite(self, str);
1646 }
1647 
1648 #define strio_isatty strio_false
1649 
1650 #define strio_pid strio_nil
1651 
1652 #define strio_fileno strio_nil
1653 
1654 /*
1655  * call-seq:
1656  * strio.length -> integer
1657  * strio.size -> integer
1658  *
1659  * Returns the size of the buffer string.
1660  */
1661 static VALUE
1662 strio_size(VALUE self)
1663 {
1664  VALUE string = StringIO(self)->string;
1665  if (NIL_P(string)) {
1666  rb_raise(rb_eIOError, "not opened");
1667  }
1668  return ULONG2NUM(RSTRING_LEN(string));
1669 }
1670 
1671 /*
1672  * call-seq:
1673  * strio.truncate(integer) -> 0
1674  *
1675  * Truncates the buffer string to at most _integer_ bytes. The stream
1676  * must be opened for writing.
1677  */
1678 static VALUE
1679 strio_truncate(VALUE self, VALUE len)
1680 {
1681  VALUE string = writable(self)->string;
1682  long l = NUM2LONG(len);
1683  long plen = RSTRING_LEN(string);
1684  if (l < 0) {
1685  error_inval("negative length");
1686  }
1687  rb_str_resize(string, l);
1688  if (plen < l) {
1689  MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
1690  }
1691  return len;
1692 }
1693 
1694 /*
1695  * call-seq:
1696  * strio.external_encoding => encoding
1697  *
1698  * Returns the Encoding object that represents the encoding of the file.
1699  * If the stream is write mode and no encoding is specified, returns
1700  * +nil+.
1701  */
1702 
1703 static VALUE
1704 strio_external_encoding(VALUE self)
1705 {
1706  struct StringIO *ptr = StringIO(self);
1707  return rb_enc_from_encoding(get_enc(ptr));
1708 }
1709 
1710 /*
1711  * call-seq:
1712  * strio.internal_encoding => encoding
1713  *
1714  * Returns the Encoding of the internal string if conversion is
1715  * specified. Otherwise returns +nil+.
1716  */
1717 
1718 static VALUE
1719 strio_internal_encoding(VALUE self)
1720 {
1721  return Qnil;
1722 }
1723 
1724 /*
1725  * call-seq:
1726  * strio.set_encoding(ext_enc, [int_enc[, opt]]) => strio
1727  *
1728  * Specify the encoding of the StringIO as <i>ext_enc</i>.
1729  * Use the default external encoding if <i>ext_enc</i> is nil.
1730  * 2nd argument <i>int_enc</i> and optional hash <i>opt</i> argument
1731  * are ignored; they are for API compatibility to IO.
1732  */
1733 
1734 static VALUE
1735 strio_set_encoding(int argc, VALUE *argv, VALUE self)
1736 {
1737  rb_encoding* enc;
1738  struct StringIO *ptr = StringIO(self);
1739  VALUE ext_enc, int_enc, opt;
1740 
1741  argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt);
1742 
1743  if (NIL_P(ext_enc)) {
1745  }
1746  else {
1747  enc = rb_to_encoding(ext_enc);
1748  }
1749  ptr->enc = enc;
1750  if (WRITABLE(self)) {
1751  rb_enc_associate(ptr->string, enc);
1752  }
1753 
1754  return self;
1755 }
1756 
1757 static VALUE
1758 strio_set_encoding_by_bom(VALUE self)
1759 {
1760  struct StringIO *ptr = StringIO(self);
1761 
1762  if (ptr->enc) {
1763  rb_raise(rb_eArgError, "encoding conversion is set");
1764  }
1765  if (!set_encoding_by_bom(ptr)) return Qnil;
1766  return rb_enc_from_encoding(ptr->enc);
1767 }
1768 
1769 /*
1770  * Pseudo I/O on String object, with interface corresponding to IO.
1771  *
1772  * Commonly used to simulate <code>$stdio</code> or <code>$stderr</code>
1773  *
1774  * === Examples
1775  *
1776  * require 'stringio'
1777  *
1778  * # Writing stream emulation
1779  * io = StringIO.new
1780  * io.puts "Hello World"
1781  * io.string #=> "Hello World\n"
1782  *
1783  * # Reading stream emulation
1784  * io = StringIO.new "first\nsecond\nlast\n"
1785  * io.getc #=> "f"
1786  * io.gets #=> "irst\n"
1787  * io.read #=> "second\nlast\n"
1788  */
1789 void
1791 {
1792 #undef rb_intern
1793  VALUE StringIO = rb_define_class("StringIO", rb_cData);
1794 
1796 
1798  rb_define_alloc_func(StringIO, strio_s_allocate);
1799  rb_define_singleton_method(StringIO, "new", strio_s_new, -1);
1800  rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
1801  rb_define_method(StringIO, "initialize", strio_initialize, -1);
1802  rb_define_method(StringIO, "initialize_copy", strio_copy, 1);
1803  rb_define_method(StringIO, "reopen", strio_reopen, -1);
1804 
1805  rb_define_method(StringIO, "string", strio_get_string, 0);
1806  rb_define_method(StringIO, "string=", strio_set_string, 1);
1807  rb_define_method(StringIO, "lineno", strio_get_lineno, 0);
1808  rb_define_method(StringIO, "lineno=", strio_set_lineno, 1);
1809 
1810 
1811  /* call-seq: strio.binmode -> true */
1812  rb_define_method(StringIO, "binmode", strio_binmode, 0);
1813  rb_define_method(StringIO, "close", strio_close, 0);
1814  rb_define_method(StringIO, "close_read", strio_close_read, 0);
1815  rb_define_method(StringIO, "close_write", strio_close_write, 0);
1816  rb_define_method(StringIO, "closed?", strio_closed, 0);
1817  rb_define_method(StringIO, "closed_read?", strio_closed_read, 0);
1818  rb_define_method(StringIO, "closed_write?", strio_closed_write, 0);
1819  rb_define_method(StringIO, "eof", strio_eof, 0);
1820  rb_define_method(StringIO, "eof?", strio_eof, 0);
1821  /* call-seq: strio.fcntl */
1822  rb_define_method(StringIO, "fcntl", strio_fcntl, -1);
1823  /* call-seq: strio.flush -> strio */
1824  rb_define_method(StringIO, "flush", strio_flush, 0);
1825  /* call-seq: strio.fsync -> 0 */
1826  rb_define_method(StringIO, "fsync", strio_fsync, 0);
1827  rb_define_method(StringIO, "pos", strio_get_pos, 0);
1828  rb_define_method(StringIO, "pos=", strio_set_pos, 1);
1829  rb_define_method(StringIO, "rewind", strio_rewind, 0);
1830  rb_define_method(StringIO, "seek", strio_seek, -1);
1831  rb_define_method(StringIO, "sync", strio_get_sync, 0);
1832  /* call-seq: strio.sync = boolean -> boolean */
1834  rb_define_method(StringIO, "tell", strio_tell, 0);
1835 
1836  rb_define_method(StringIO, "each", strio_each, -1);
1837  rb_define_method(StringIO, "each_line", strio_each, -1);
1838  rb_define_method(StringIO, "lines", strio_lines, -1);
1839  rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
1840  rb_define_method(StringIO, "bytes", strio_bytes, 0);
1841  rb_define_method(StringIO, "each_char", strio_each_char, 0);
1842  rb_define_method(StringIO, "chars", strio_chars, 0);
1843  rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0);
1844  rb_define_method(StringIO, "codepoints", strio_codepoints, 0);
1845  rb_define_method(StringIO, "getc", strio_getc, 0);
1846  rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
1847  rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
1848  rb_define_method(StringIO, "getbyte", strio_getbyte, 0);
1849  rb_define_method(StringIO, "gets", strio_gets, -1);
1850  rb_define_method(StringIO, "readlines", strio_readlines, -1);
1851  rb_define_method(StringIO, "read", strio_read, -1);
1852 
1853  rb_define_method(StringIO, "write", strio_write_m, -1);
1854  rb_define_method(StringIO, "putc", strio_putc, 1);
1855 
1856  /*
1857  * call-seq:
1858  * strio.isatty -> nil
1859  * strio.tty? -> nil
1860  *
1861  */
1862  rb_define_method(StringIO, "isatty", strio_isatty, 0);
1863  rb_define_method(StringIO, "tty?", strio_isatty, 0);
1864 
1865  /* call-seq: strio.pid -> nil */
1866  rb_define_method(StringIO, "pid", strio_pid, 0);
1867 
1868  /* call-seq: strio.fileno -> nil */
1869  rb_define_method(StringIO, "fileno", strio_fileno, 0);
1870  rb_define_method(StringIO, "size", strio_size, 0);
1871  rb_define_method(StringIO, "length", strio_size, 0);
1872  rb_define_method(StringIO, "truncate", strio_truncate, 1);
1873 
1874  rb_define_method(StringIO, "external_encoding", strio_external_encoding, 0);
1875  rb_define_method(StringIO, "internal_encoding", strio_internal_encoding, 0);
1876  rb_define_method(StringIO, "set_encoding", strio_set_encoding, -1);
1877  rb_define_method(StringIO, "set_encoding_by_bom", strio_set_encoding_by_bom, 0);
1878 
1879  {
1880  VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
1881  rb_define_method(mReadable, "readchar", strio_readchar, 0);
1882  rb_define_method(mReadable, "readbyte", strio_readbyte, 0);
1883  rb_define_method(mReadable, "readline", strio_readline, -1);
1884  rb_define_method(mReadable, "sysread", strio_sysread, -1);
1885  rb_define_method(mReadable, "readpartial", strio_sysread, -1);
1886  rb_define_method(mReadable, "read_nonblock", strio_read_nonblock, -1);
1887  rb_include_module(StringIO, mReadable);
1888  }
1889  {
1890  VALUE mWritable = rb_define_module_under(rb_cIO, "generic_writable");
1891  rb_define_method(mWritable, "<<", strio_addstr, 1);
1892  rb_define_method(mWritable, "print", strio_print, -1);
1893  rb_define_method(mWritable, "printf", strio_printf, -1);
1894  rb_define_method(mWritable, "puts", strio_puts, -1);
1895  rb_define_method(mWritable, "syswrite", strio_syswrite, 1);
1896  rb_define_method(mWritable, "write_nonblock", strio_syswrite_nonblock, -1);
1897  rb_include_module(StringIO, mWritable);
1898  }
1899 
1900  sym_exception = ID2SYM(rb_intern("exception"));
1901 }
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
ID
unsigned long ID
Definition: ruby.h:103
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
strio_set_sync
#define strio_set_sync
Definition: stringio.c:805
strio_fileno
#define strio_fileno
Definition: stringio.c:1652
RSTRING_GETMEM
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:1018
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
rb_enc_str_buf_cat
VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc)
Definition: string.c:2919
getline_arg
Definition: stringio.c:1144
rb_cData
RUBY_EXTERN VALUE rb_cData
Definition: ruby.h:2018
LONG_MAX
#define LONG_MAX
Definition: ruby.h:220
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Definition: ruby.h:1980
rb_enc_mbclen
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
rb_enc_mbcput
#define rb_enc_mbcput(c, buf, enc)
Definition: encoding.h:217
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
memset
void * memset(void *, int, size_t)
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:897
strio_syswrite
#define strio_syswrite
Definition: stringio.c:1637
rb_funcallv_kw
VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE *, int)
Definition: vm_eval.c:962
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
rb_io_oflags_fmode
int rb_io_oflags_fmode(int oflags)
Definition: io.c:5519
StringIO::enc
rb_encoding * enc
Definition: stringio.c:111
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
strchr
char * strchr(char *, char)
strio_flush
#define strio_flush
Definition: stringio.c:684
rb_enc_uint_chr
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:3375
StringIO::lineno
long lineno
Definition: stringio.c:113
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_str_substr
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:2584
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_class_new_instance_kw
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:1964
rb_utf8_encindex
int rb_utf8_encindex(void)
Definition: encoding.c:1334
rb_default_external_encoding
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1427
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
STRINGIO_VERSION
#define STRINGIO_VERSION
Definition: stringio.c:14
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
encoding.h
rb_intern
#define rb_intern(str)
FMODE_TRUNC
#define FMODE_TRUNC
Definition: io.h:119
getline_arg::limit
long limit
Definition: stringio.c:1146
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
strio_addstr
#define strio_addstr
Definition: stringio.c:1465
rb_intern_const
#define rb_intern_const(str)
Definition: ruby.h:1879
rb_io_extract_modeenc
#define rb_io_extract_modeenc
Definition: stringio.c:35
STRIO_READWRITE
#define STRIO_READWRITE
Definition: stringio.c:208
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
rb_call_super
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:306
UINT2NUM
#define UINT2NUM(x)
Definition: ruby.h:1610
rb_lastline_set
void rb_lastline_set(VALUE)
Definition: vm.c:1322
StringValue
use StringValue() instead")))
get_enc
#define get_enc(ptr)
Definition: stringio.c:124
StringIO::count
int count
Definition: stringio.c:115
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:1977
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
strio_fcntl
#define strio_fcntl
Definition: stringio.c:682
CHAR_BIT
#define CHAR_BIT
Definition: ruby.h:227
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:2114
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
strio_print
#define strio_print
Definition: stringio.c:1474
rb_eIOError
RUBY_EXTERN VALUE rb_eIOError
Definition: ruby.h:2064
ptr
struct RIMemo * ptr
Definition: debug.c:74
rb_io_enc_t
struct rb_io_enc_t rb_io_enc_t
Definition: io.h:104
T_DATA
#define T_DATA
Definition: ruby.h:538
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_io_taint_check
VALUE rb_io_taint_check(VALUE)
Definition: io.c:703
rb_enc_right_char_head
#define rb_enc_right_char_head(s, p, e, enc)
Definition: encoding.h:223
RIMemo::flags
VALUE flags
Definition: internal.h:1125
NULL
#define NULL
Definition: _sdbm.c:101
SafeStringValue
#define SafeStringValue(v)
Definition: ruby.h:607
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
rb_enc_from_encoding
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:116
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
strlen
size_t strlen(const char *)
rb_eof_error
void rb_eof_error(void)
Definition: io.c:697
CHR2FIX
#define CHR2FIX(x)
Definition: ruby.h:1648
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
error_inval
#define error_inval(msg)
Definition: stringio.c:123
ENCODING_MAXNAMELEN
#define ENCODING_MAXNAMELEN
Definition: encoding.h:64
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.0.h:7899
cc
const struct rb_call_cache * cc
Definition: rb_mjit_min_header-2.7.0.h:13228
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_notimplement
void rb_notimplement(void)
Definition: error.c:2712
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
NUM2CHR
#define NUM2CHR(x)
Definition: ruby.h:1647
ULONG2NUM
#define ULONG2NUM(x)
Definition: ruby.h:1645
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
StringIO
Definition: stringio.c:109
rb_syserr_fail
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:2781
FMODE_READABLE
#define FMODE_READABLE
Definition: io.h:108
rb_ascii8bit_encoding
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1316
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:1175
rb_encoding
const typedef OnigEncodingType rb_encoding
Definition: encoding.h:115
memmove
#define memmove(dst, src, len)
Definition: rb_mjit_min_header-2.7.0.h:2848
rb_enc_from_index
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:609
fmode
#define fmode
strio_tell
#define strio_tell
Definition: stringio.c:807
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:2999
EACCES
#define EACCES
Definition: rb_mjit_min_header-2.7.0.h:10950
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
ruby.h
FMODE_SETENC_BY_BOM
#define FMODE_SETENC_BY_BOM
Definition: io.h:122
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1231
StringIO::pos
long pos
Definition: stringio.c:112
ALLOC
#define ALLOC(type)
Definition: ruby.h:1664
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:279
StringIO::string
VALUE string
Definition: stringio.c:110
rb_enc_copy
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:990
FMODE_READWRITE
#define FMODE_READWRITE
Definition: io.h:110
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
WRITABLE
#define WRITABLE(strio)
Definition: stringio.c:215
strio_pid
#define strio_pid
Definition: stringio.c:1650
strio_flags_check
char strio_flags_check[(STRIO_READABLE/FMODE_READABLE==STRIO_WRITABLE/FMODE_WRITABLE) *2 - 1]
Definition: stringio.c:209
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1752
MEMCMP
#define MEMCMP(p1, p2, type, n)
Definition: ruby.h:1755
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:6117
strio_printf
#define strio_printf
Definition: stringio.c:1482
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1841
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
strio_puts
#define strio_puts
Definition: stringio.c:1514
rb_str_buf_append
VALUE rb_str_buf_append(VALUE, VALUE)
Definition: string.c:2950
strio_fsync
#define strio_fsync
Definition: stringio.c:686
char
#define char
Definition: rb_mjit_min_header-2.7.0.h:2876
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
StringIO::flags
int flags
Definition: stringio.c:114
getline_arg::chomp
unsigned int chomp
Definition: stringio.c:1147
rb_to_encoding
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:245
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:63
rb_io_extract_encoding_option
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5744
rb_enc_find
rb_encoding * rb_enc_find(const char *name)
Definition: encoding.c:728
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
FMODE_APPEND
#define FMODE_APPEND
Definition: io.h:115
rb_str_subseq
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2474
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
rb_enc_find_index
int rb_enc_find_index(const char *name)
Definition: encoding.c:693
strio_isatty
#define strio_isatty
Definition: stringio.c:1648
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
Definition: object.c:2900
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
check_strio
#define check_strio(self)
Definition: stringio.c:171
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
rb_io_modestr_fmode
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:5465
CLOSED
#define CLOSED(strio)
Definition: stringio.c:213
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
rb_str_modify_expand
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2122
io.h
argc
int argc
Definition: ruby.c:222
STRIO_WRITABLE
#define STRIO_WRITABLE
Definition: stringio.c:207
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
STRIO_READABLE
#define STRIO_READABLE
Definition: stringio.c:206
rb_data_type_struct
Definition: ruby.h:1148
xfree
#define xfree
Definition: defines.h:216
Init_stringio
void Init_stringio(void)
Definition: stringio.c:1790
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
OBJ_FROZEN_RAW
#define OBJ_FROZEN_RAW(x)
Definition: ruby.h:1374
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5212
rb_rs
RUBY_EXTERN VALUE rb_rs
Definition: intern.h:585
READABLE
#define READABLE(strio)
Definition: stringio.c:214
Qtrue
#define Qtrue
Definition: ruby.h:468
OBJ_FROZEN
#define OBJ_FROZEN(x)
Definition: ruby.h:1375
FMODE_WRITABLE
#define FMODE_WRITABLE
Definition: io.h:109
len
uint8_t len
Definition: escape.c:17
rb_enumeratorize
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, const VALUE *argv)
Definition: enumerator.c:516
rb_enc_codelen
int rb_enc_codelen(int c, rb_encoding *enc)
Definition: encoding.c:1089
T_STRING
#define T_STRING
Definition: ruby.h:528
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1114
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
rb_str_conv_enc
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
Definition: string.c:1030
StringIO
#define StringIO(obj)
Definition: stringio.c:204
rb_enc_codepoint_len
unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
Definition: encoding.c:1068
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:796
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
RTEST
#define RTEST(v)
Definition: ruby.h:481
getline_arg::rs
VALUE rs
Definition: stringio.c:1145
rb_cIO
RUBY_EXTERN VALUE rb_cIO
Definition: ruby.h:2030
rb_enc_associate_index
VALUE rb_enc_associate_index(VALUE obj, int idx)
Definition: encoding.c:838
RSTRING_END
#define RSTRING_END(str)
Definition: ruby.h:1013
memchr
void * memchr(const void *, int, size_t)