1 /**********************************************************************
2 
3   stringio.c -
4 
5   $Author: naruse $
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 #include "ruby.h"
15 #include "ruby/io.h"
16 #include "ruby/encoding.h"
17 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
18 #include <fcntl.h>
19 #elif defined(HAVE_SYS_FCNTL_H)
20 #include <sys/fcntl.h>
21 #endif
22 
23 #ifndef RB_INTEGER_TYPE_P
24 # define RB_INTEGER_TYPE_P(c) (FIXNUM_P(c) || RB_TYPE_P(c, T_BIGNUM))
25 #endif
26 
27 struct StringIO {
28     VALUE string;
29     rb_encoding *enc;
30     long pos;
31     long lineno;
32     int flags;
33     int count;
34 };
35 
36 static VALUE strio_init(int, VALUE *, struct StringIO *, VALUE);
37 static VALUE strio_unget_bytes(struct StringIO *, const char *, long);
38 static long strio_write(VALUE self, VALUE str);
39 
40 #define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
41 #define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
42 #define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string))
43 
44 static struct StringIO *
strio_alloc(void)45 strio_alloc(void)
46 {
47     struct StringIO *ptr = ALLOC(struct StringIO);
48     ptr->string = Qnil;
49     ptr->pos = 0;
50     ptr->lineno = 0;
51     ptr->flags = 0;
52     ptr->count = 1;
53     return ptr;
54 }
55 
56 static void
strio_mark(void * p)57 strio_mark(void *p)
58 {
59     struct StringIO *ptr = p;
60 
61     rb_gc_mark(ptr->string);
62 }
63 
64 static void
strio_free(void * p)65 strio_free(void *p)
66 {
67     struct StringIO *ptr = p;
68     if (--ptr->count <= 0) {
69 	xfree(ptr);
70     }
71 }
72 
73 static size_t
strio_memsize(const void * p)74 strio_memsize(const void *p)
75 {
76     return sizeof(struct StringIO);
77 }
78 
79 static const rb_data_type_t strio_data_type = {
80     "strio",
81     {
82 	strio_mark,
83 	strio_free,
84 	strio_memsize,
85     },
86     0, 0, RUBY_TYPED_FREE_IMMEDIATELY
87 };
88 
89 #define check_strio(self) ((struct StringIO*)rb_check_typeddata((self), &strio_data_type))
90 
91 static struct StringIO*
get_strio(VALUE self)92 get_strio(VALUE self)
93 {
94     struct StringIO *ptr = check_strio(rb_io_taint_check(self));
95 
96     if (!ptr) {
97 	rb_raise(rb_eIOError, "uninitialized stream");
98     }
99     return ptr;
100 }
101 
102 static VALUE
enc_subseq(VALUE str,long pos,long len,rb_encoding * enc)103 enc_subseq(VALUE str, long pos, long len, rb_encoding *enc)
104 {
105     str = rb_str_subseq(str, pos, len);
106     rb_enc_associate(str, enc);
107     return str;
108 }
109 
110 static VALUE
strio_substr(struct StringIO * ptr,long pos,long len,rb_encoding * enc)111 strio_substr(struct StringIO *ptr, long pos, long len, rb_encoding *enc)
112 {
113     VALUE str = ptr->string;
114     long rlen = RSTRING_LEN(str) - pos;
115 
116     if (len > rlen) len = rlen;
117     if (len < 0) len = 0;
118     if (len == 0) return rb_enc_str_new(0, 0, enc);
119     return enc_subseq(str, pos, len, enc);
120 }
121 
122 #define StringIO(obj) get_strio(obj)
123 
124 #define STRIO_READABLE FL_USER4
125 #define STRIO_WRITABLE FL_USER5
126 #define STRIO_READWRITE (STRIO_READABLE|STRIO_WRITABLE)
127 typedef char strio_flags_check[(STRIO_READABLE/FMODE_READABLE == STRIO_WRITABLE/FMODE_WRITABLE) * 2 - 1];
128 #define STRIO_MODE_SET_P(strio, mode) \
129     ((RBASIC(strio)->flags & STRIO_##mode) && \
130      ((struct StringIO*)DATA_PTR(strio))->flags & FMODE_##mode)
131 #define CLOSED(strio) (!STRIO_MODE_SET_P(strio, READWRITE))
132 #define READABLE(strio) STRIO_MODE_SET_P(strio, READABLE)
133 #define WRITABLE(strio) STRIO_MODE_SET_P(strio, WRITABLE)
134 
135 static VALUE sym_exception;
136 
137 static struct StringIO*
readable(VALUE strio)138 readable(VALUE strio)
139 {
140     struct StringIO *ptr = StringIO(strio);
141     if (!READABLE(strio)) {
142 	rb_raise(rb_eIOError, "not opened for reading");
143     }
144     return ptr;
145 }
146 
147 static struct StringIO*
writable(VALUE strio)148 writable(VALUE strio)
149 {
150     struct StringIO *ptr = StringIO(strio);
151     if (!WRITABLE(strio)) {
152 	rb_raise(rb_eIOError, "not opened for writing");
153     }
154     return ptr;
155 }
156 
157 static void
check_modifiable(struct StringIO * ptr)158 check_modifiable(struct StringIO *ptr)
159 {
160     if (OBJ_FROZEN(ptr->string)) {
161 	rb_raise(rb_eIOError, "not modifiable string");
162     }
163 }
164 
165 static VALUE
strio_s_allocate(VALUE klass)166 strio_s_allocate(VALUE klass)
167 {
168     return TypedData_Wrap_Struct(klass, &strio_data_type, 0);
169 }
170 
171 /*
172  * call-seq: StringIO.new(string=""[, mode])
173  *
174  * Creates new StringIO instance from with _string_ and _mode_.
175  */
176 static VALUE
strio_initialize(int argc,VALUE * argv,VALUE self)177 strio_initialize(int argc, VALUE *argv, VALUE self)
178 {
179     struct StringIO *ptr = check_strio(self);
180 
181     if (!ptr) {
182 	DATA_PTR(self) = ptr = strio_alloc();
183     }
184     rb_call_super(0, 0);
185     return strio_init(argc, argv, ptr, self);
186 }
187 
188 static VALUE
strio_init(int argc,VALUE * argv,struct StringIO * ptr,VALUE self)189 strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
190 {
191     VALUE string, mode;
192     int trunc = 0;
193 
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;
200 	}
201 	else {
202 	    const char *m = StringValueCStr(mode);
203 	    ptr->flags = rb_io_modestr_fmode(m);
204 	    trunc = *m == 'w';
205 	}
206 	StringValue(string);
207 	if ((ptr->flags & FMODE_WRITABLE) && OBJ_FROZEN(string)) {
208 	    rb_syserr_fail(EACCES, 0);
209 	}
210 	if (trunc) {
211 	    rb_str_resize(string, 0);
212 	}
213 	break;
214       case 1:
215 	StringValue(string);
216 	ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
217 	break;
218       case 0:
219 	string = rb_enc_str_new("", 0, rb_default_external_encoding());
220 	ptr->flags = FMODE_READWRITE;
221 	break;
222     }
223     ptr->string = string;
224     ptr->enc = 0;
225     ptr->pos = 0;
226     ptr->lineno = 0;
227     RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE);
228     return self;
229 }
230 
231 static VALUE
strio_finalize(VALUE self)232 strio_finalize(VALUE self)
233 {
234     struct StringIO *ptr = StringIO(self);
235     ptr->string = Qnil;
236     ptr->flags &= ~FMODE_READWRITE;
237     return self;
238 }
239 
240 /*
241  * call-seq: StringIO.open(string=""[, mode]) {|strio| ...}
242  *
243  * Equivalent to StringIO.new except that when it is called with a block, it
244  * yields with the new instance and closes it, and returns the result which
245  * returned from the block.
246  */
247 static VALUE
strio_s_open(int argc,VALUE * argv,VALUE klass)248 strio_s_open(int argc, VALUE *argv, VALUE klass)
249 {
250     VALUE obj = rb_class_new_instance(argc, argv, klass);
251     if (!rb_block_given_p()) return obj;
252     return rb_ensure(rb_yield, obj, strio_finalize, obj);
253 }
254 
255 /* :nodoc: */
256 static VALUE
strio_s_new(int argc,VALUE * argv,VALUE klass)257 strio_s_new(int argc, VALUE *argv, VALUE klass)
258 {
259     if (rb_block_given_p()) {
260 	VALUE cname = rb_obj_as_string(klass);
261 
262 	rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
263 		cname, cname);
264     }
265     return rb_class_new_instance(argc, argv, klass);
266 }
267 
268 /*
269  * Returns +false+.  Just for compatibility to IO.
270  */
271 static VALUE
strio_false(VALUE self)272 strio_false(VALUE self)
273 {
274     StringIO(self);
275     return Qfalse;
276 }
277 
278 /*
279  * Returns +nil+.  Just for compatibility to IO.
280  */
281 static VALUE
strio_nil(VALUE self)282 strio_nil(VALUE self)
283 {
284     StringIO(self);
285     return Qnil;
286 }
287 
288 /*
289  * Returns *strio* itself.  Just for compatibility to IO.
290  */
291 static VALUE
strio_self(VALUE self)292 strio_self(VALUE self)
293 {
294     StringIO(self);
295     return self;
296 }
297 
298 /*
299  * Returns 0.  Just for compatibility to IO.
300  */
301 static VALUE
strio_0(VALUE self)302 strio_0(VALUE self)
303 {
304     StringIO(self);
305     return INT2FIX(0);
306 }
307 
308 /*
309  * Returns the argument unchanged.  Just for compatibility to IO.
310  */
311 static VALUE
strio_first(VALUE self,VALUE arg)312 strio_first(VALUE self, VALUE arg)
313 {
314     StringIO(self);
315     return arg;
316 }
317 
318 /*
319  * Raises NotImplementedError.
320  */
321 static VALUE
strio_unimpl(int argc,VALUE * argv,VALUE self)322 strio_unimpl(int argc, VALUE *argv, VALUE self)
323 {
324     StringIO(self);
325     rb_notimplement();
326 
327     UNREACHABLE;
328 }
329 
330 /*
331  * call-seq: strio.string     -> string
332  *
333  * Returns underlying String object, the subject of IO.
334  */
335 static VALUE
strio_get_string(VALUE self)336 strio_get_string(VALUE self)
337 {
338     return StringIO(self)->string;
339 }
340 
341 /*
342  * call-seq:
343  *   strio.string = string  -> string
344  *
345  * Changes underlying String object, the subject of IO.
346  */
347 static VALUE
strio_set_string(VALUE self,VALUE string)348 strio_set_string(VALUE self, VALUE string)
349 {
350     struct StringIO *ptr = StringIO(self);
351 
352     rb_io_taint_check(self);
353     ptr->flags &= ~FMODE_READWRITE;
354     StringValue(string);
355     ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
356     ptr->pos = 0;
357     ptr->lineno = 0;
358     return ptr->string = string;
359 }
360 
361 /*
362  * call-seq:
363  *   strio.close  -> nil
364  *
365  * Closes strio.  The *strio* is unavailable for any further data
366  * operations; an +IOError+ is raised if such an attempt is made.
367  */
368 static VALUE
strio_close(VALUE self)369 strio_close(VALUE self)
370 {
371     StringIO(self);
372     RBASIC(self)->flags &= ~STRIO_READWRITE;
373     return Qnil;
374 }
375 
376 /*
377  * call-seq:
378  *   strio.close_read    -> nil
379  *
380  * Closes the read end of a StringIO.  Will raise an +IOError+ if the
381  * *strio* is not readable.
382  */
383 static VALUE
strio_close_read(VALUE self)384 strio_close_read(VALUE self)
385 {
386     struct StringIO *ptr = StringIO(self);
387     if (!(ptr->flags & FMODE_READABLE)) {
388 	rb_raise(rb_eIOError, "closing non-duplex IO for reading");
389     }
390     RBASIC(self)->flags &= ~STRIO_READABLE;
391     return Qnil;
392 }
393 
394 /*
395  * call-seq:
396  *   strio.close_write    -> nil
397  *
398  * Closes the write end of a StringIO.  Will raise an  +IOError+ if the
399  * *strio* is not writeable.
400  */
401 static VALUE
strio_close_write(VALUE self)402 strio_close_write(VALUE self)
403 {
404     struct StringIO *ptr = StringIO(self);
405     if (!(ptr->flags & FMODE_WRITABLE)) {
406 	rb_raise(rb_eIOError, "closing non-duplex IO for writing");
407     }
408     RBASIC(self)->flags &= ~STRIO_WRITABLE;
409     return Qnil;
410 }
411 
412 /*
413  * call-seq:
414  *   strio.closed?    -> true or false
415  *
416  * Returns +true+ if *strio* is completely closed, +false+ otherwise.
417  */
418 static VALUE
strio_closed(VALUE self)419 strio_closed(VALUE self)
420 {
421     StringIO(self);
422     if (!CLOSED(self)) return Qfalse;
423     return Qtrue;
424 }
425 
426 /*
427  * call-seq:
428  *   strio.closed_read?    -> true or false
429  *
430  * Returns +true+ if *strio* is not readable, +false+ otherwise.
431  */
432 static VALUE
strio_closed_read(VALUE self)433 strio_closed_read(VALUE self)
434 {
435     StringIO(self);
436     if (READABLE(self)) return Qfalse;
437     return Qtrue;
438 }
439 
440 /*
441  * call-seq:
442  *   strio.closed_write?    -> true or false
443  *
444  * Returns +true+ if *strio* is not writable, +false+ otherwise.
445  */
446 static VALUE
strio_closed_write(VALUE self)447 strio_closed_write(VALUE self)
448 {
449     StringIO(self);
450     if (WRITABLE(self)) return Qfalse;
451     return Qtrue;
452 }
453 
454 /*
455  * call-seq:
456  *   strio.eof     -> true or false
457  *   strio.eof?    -> true or false
458  *
459  * Returns true if *strio* is at end of file. The stringio must be
460  * opened for reading or an +IOError+ will be raised.
461  */
462 static VALUE
strio_eof(VALUE self)463 strio_eof(VALUE self)
464 {
465     struct StringIO *ptr = readable(self);
466     if (ptr->pos < RSTRING_LEN(ptr->string)) return Qfalse;
467     return Qtrue;
468 }
469 
470 /* :nodoc: */
471 static VALUE
strio_copy(VALUE copy,VALUE orig)472 strio_copy(VALUE copy, VALUE orig)
473 {
474     struct StringIO *ptr;
475 
476     orig = rb_convert_type(orig, T_DATA, "StringIO", "to_strio");
477     if (copy == orig) return copy;
478     ptr = StringIO(orig);
479     if (check_strio(copy)) {
480 	strio_free(DATA_PTR(copy));
481     }
482     DATA_PTR(copy) = ptr;
483     OBJ_INFECT(copy, orig);
484     RBASIC(copy)->flags &= ~STRIO_READWRITE;
485     RBASIC(copy)->flags |= RBASIC(orig)->flags & STRIO_READWRITE;
486     ++ptr->count;
487     return copy;
488 }
489 
490 /*
491  * call-seq:
492  *   strio.lineno    -> integer
493  *
494  * Returns the current line number in *strio*. The stringio must be
495  * opened for reading. +lineno+ counts the number of times  +gets+ is
496  * called, rather than the number of newlines  encountered. The two
497  * values will differ if +gets+ is  called with a separator other than
498  * newline.  See also the  <code>$.</code> variable.
499  */
500 static VALUE
strio_get_lineno(VALUE self)501 strio_get_lineno(VALUE self)
502 {
503     return LONG2NUM(StringIO(self)->lineno);
504 }
505 
506 /*
507  * call-seq:
508  *   strio.lineno = integer    -> integer
509  *
510  * Manually sets the current line number to the given value.
511  * <code>$.</code> is updated only on the next read.
512  */
513 static VALUE
strio_set_lineno(VALUE self,VALUE lineno)514 strio_set_lineno(VALUE self, VALUE lineno)
515 {
516     StringIO(self)->lineno = NUM2LONG(lineno);
517     return lineno;
518 }
519 
520 static VALUE
strio_binmode(VALUE self)521 strio_binmode(VALUE self)
522 {
523     struct StringIO *ptr = StringIO(self);
524     rb_encoding *enc = rb_ascii8bit_encoding();
525 
526     ptr->enc = enc;
527     if (WRITABLE(self)) {
528 	rb_enc_associate(ptr->string, enc);
529     }
530     return self;
531 }
532 
533 #define strio_fcntl strio_unimpl
534 
535 #define strio_flush strio_self
536 
537 #define strio_fsync strio_0
538 
539 /*
540  * call-seq:
541  *   strio.reopen(other_StrIO)     -> strio
542  *   strio.reopen(string, mode)    -> strio
543  *
544  * Reinitializes *strio* with the given <i>other_StrIO</i> or _string_
545  * and _mode_ (see StringIO#new).
546  */
547 static VALUE
strio_reopen(int argc,VALUE * argv,VALUE self)548 strio_reopen(int argc, VALUE *argv, VALUE self)
549 {
550     rb_io_taint_check(self);
551     if (argc == 1 && !RB_TYPE_P(*argv, T_STRING)) {
552 	return strio_copy(self, *argv);
553     }
554     return strio_init(argc, argv, StringIO(self), self);
555 }
556 
557 /*
558  * call-seq:
559  *   strio.pos     -> integer
560  *   strio.tell    -> integer
561  *
562  * Returns the current offset (in bytes) of *strio*.
563  */
564 static VALUE
strio_get_pos(VALUE self)565 strio_get_pos(VALUE self)
566 {
567     return LONG2NUM(StringIO(self)->pos);
568 }
569 
570 /*
571  * call-seq:
572  *   strio.pos = integer    -> integer
573  *
574  * Seeks to the given position (in bytes) in *strio*.
575  */
576 static VALUE
strio_set_pos(VALUE self,VALUE pos)577 strio_set_pos(VALUE self, VALUE pos)
578 {
579     struct StringIO *ptr = StringIO(self);
580     long p = NUM2LONG(pos);
581     if (p < 0) {
582 	error_inval(0);
583     }
584     ptr->pos = p;
585     return pos;
586 }
587 
588 /*
589  * call-seq:
590  *   strio.rewind    -> 0
591  *
592  * Positions *strio* to the beginning of input, resetting
593  * +lineno+ to zero.
594  */
595 static VALUE
strio_rewind(VALUE self)596 strio_rewind(VALUE self)
597 {
598     struct StringIO *ptr = StringIO(self);
599     ptr->pos = 0;
600     ptr->lineno = 0;
601     return INT2FIX(0);
602 }
603 
604 /*
605  * call-seq:
606  *   strio.seek(amount, whence=SEEK_SET) -> 0
607  *
608  * Seeks to a given offset _amount_ in the stream according to
609  * the value of _whence_ (see IO#seek).
610  */
611 static VALUE
strio_seek(int argc,VALUE * argv,VALUE self)612 strio_seek(int argc, VALUE *argv, VALUE self)
613 {
614     VALUE whence;
615     struct StringIO *ptr = StringIO(self);
616     long amount, offset;
617 
618     rb_scan_args(argc, argv, "11", NULL, &whence);
619     amount = NUM2LONG(argv[0]);
620     if (CLOSED(self)) {
621 	rb_raise(rb_eIOError, "closed stream");
622     }
623     switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
624       case 0:
625 	offset = 0;
626 	break;
627       case 1:
628 	offset = ptr->pos;
629 	break;
630       case 2:
631 	offset = RSTRING_LEN(ptr->string);
632 	break;
633       default:
634 	error_inval("invalid whence");
635     }
636     if (amount > LONG_MAX - offset || amount + offset < 0) {
637 	error_inval(0);
638     }
639     ptr->pos = amount + offset;
640     return INT2FIX(0);
641 }
642 
643 /*
644  * call-seq:
645  *   strio.sync    -> true
646  *
647  * Returns +true+ always.
648  */
649 static VALUE
strio_get_sync(VALUE self)650 strio_get_sync(VALUE self)
651 {
652     StringIO(self);
653     return Qtrue;
654 }
655 
656 #define strio_set_sync strio_first
657 
658 #define strio_tell strio_get_pos
659 
660 /*
661  * call-seq:
662  *   strio.each_byte {|byte| block }  -> strio
663  *   strio.each_byte                  -> anEnumerator
664  *
665  * See IO#each_byte.
666  */
667 static VALUE
strio_each_byte(VALUE self)668 strio_each_byte(VALUE self)
669 {
670     struct StringIO *ptr = readable(self);
671 
672     RETURN_ENUMERATOR(self, 0, 0);
673 
674     while (ptr->pos < RSTRING_LEN(ptr->string)) {
675 	char c = RSTRING_PTR(ptr->string)[ptr->pos++];
676 	rb_yield(CHR2FIX(c));
677     }
678     return self;
679 }
680 
681 /*
682  *  This is a deprecated alias for #each_byte.
683  */
684 static VALUE
strio_bytes(VALUE self)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 /*
694  * call-seq:
695  *   strio.getc   -> string or nil
696  *
697  * See IO#getc.
698  */
699 static VALUE
strio_getc(VALUE self)700 strio_getc(VALUE self)
701 {
702     struct StringIO *ptr = readable(self);
703     rb_encoding *enc = get_enc(ptr);
704     VALUE str = ptr->string;
705     long pos = ptr->pos;
706     int len;
707     char *p;
708 
709     if (pos >= RSTRING_LEN(str)) {
710 	return Qnil;
711     }
712     p = RSTRING_PTR(str)+pos;
713     len = rb_enc_mbclen(p, RSTRING_END(str), enc);
714     ptr->pos += len;
715     return enc_subseq(str, pos, len, enc);
716 }
717 
718 /*
719  * call-seq:
720  *   strio.getbyte   -> fixnum or nil
721  *
722  * See IO#getbyte.
723  */
724 static VALUE
strio_getbyte(VALUE self)725 strio_getbyte(VALUE self)
726 {
727     struct StringIO *ptr = readable(self);
728     int c;
729     if (ptr->pos >= RSTRING_LEN(ptr->string)) {
730 	return Qnil;
731     }
732     c = RSTRING_PTR(ptr->string)[ptr->pos++];
733     return CHR2FIX(c);
734 }
735 
736 static void
strio_extend(struct StringIO * ptr,long pos,long len)737 strio_extend(struct StringIO *ptr, long pos, long len)
738 {
739     long olen;
740 
741     if (len > LONG_MAX - pos)
742 	rb_raise(rb_eArgError, "string size too big");
743 
744     check_modifiable(ptr);
745     olen = RSTRING_LEN(ptr->string);
746     if (pos + len > olen) {
747 	rb_str_resize(ptr->string, pos + len);
748 	if (pos > olen)
749 	    MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen);
750     }
751     else {
752 	rb_str_modify(ptr->string);
753     }
754 }
755 
756 /*
757  * call-seq:
758  *   strio.ungetc(string)   -> nil
759  *
760  * Pushes back one character (passed as a parameter) onto *strio*
761  * such that a subsequent buffered read will return it.  There is no
762  * limitation for multiple pushbacks including pushing back behind the
763  * beginning of the buffer string.
764  */
765 static VALUE
strio_ungetc(VALUE self,VALUE c)766 strio_ungetc(VALUE self, VALUE c)
767 {
768     struct StringIO *ptr = readable(self);
769     rb_encoding *enc, *enc2;
770 
771     check_modifiable(ptr);
772     if (NIL_P(c)) return Qnil;
773     if (RB_INTEGER_TYPE_P(c)) {
774 	int len, cc = NUM2INT(c);
775 	char buf[16];
776 
777 	enc = rb_enc_get(ptr->string);
778 	len = rb_enc_codelen(cc, enc);
779 	if (len <= 0) rb_enc_uint_chr(cc, enc);
780 	rb_enc_mbcput(cc, buf, enc);
781 	return strio_unget_bytes(ptr, buf, len);
782     }
783     else {
784 	SafeStringValue(c);
785 	enc = rb_enc_get(ptr->string);
786 	enc2 = rb_enc_get(c);
787 	if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
788 	    c = rb_str_conv_enc(c, enc2, enc);
789 	}
790 	strio_unget_bytes(ptr, RSTRING_PTR(c), RSTRING_LEN(c));
791 	RB_GC_GUARD(c);
792 	return Qnil;
793     }
794 }
795 
796 /*
797  * call-seq:
798  *   strio.ungetbyte(fixnum)   -> nil
799  *
800  * See IO#ungetbyte
801  */
802 static VALUE
strio_ungetbyte(VALUE self,VALUE c)803 strio_ungetbyte(VALUE self, VALUE c)
804 {
805     struct StringIO *ptr = readable(self);
806 
807     check_modifiable(ptr);
808     switch (TYPE(c)) {
809       case T_NIL:
810         return Qnil;
811       case T_FIXNUM:
812       case T_BIGNUM: ;
813         /* rb_int_modulo() not visible from exts */
814         VALUE v = rb_funcall(c, rb_intern("modulo"), 1, INT2FIX(256));
815         unsigned char cc = NUM2INT(v) & 0xFF;
816         c = rb_str_new((const char *)&cc, 1);
817         break;
818       default:
819         SafeStringValue(c);
820     }
821 
822     const char *cp = RSTRING_PTR(c);
823     long cl = RSTRING_LEN(c);
824     if (cl == 0) return Qnil;
825     strio_unget_bytes(ptr, cp, cl);
826     RB_GC_GUARD(c);
827     return Qnil;
828 }
829 
830 static VALUE
strio_unget_bytes(struct StringIO * ptr,const char * cp,long cl)831 strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
832 {
833     long pos = ptr->pos, len, rest;
834     VALUE str = ptr->string;
835     char *s;
836 
837     len = RSTRING_LEN(str);
838     rest = pos - len;
839     if (cl > pos) {
840 	long ex = (rest < 0 ? cl-pos : cl+rest);
841 	rb_str_modify_expand(str, ex);
842 	rb_str_set_len(str, len + ex);
843 	s = RSTRING_PTR(str);
844 	if (rest < 0) memmove(s + cl, s + pos, -rest);
845 	pos = 0;
846     }
847     else {
848 	if (rest > 0) {
849 	    rb_str_modify_expand(str, rest);
850 	    rb_str_set_len(str, len + rest);
851 	}
852 	s = RSTRING_PTR(str);
853 	if (rest > cl) memset(s + len, 0, rest - cl);
854 	pos -= cl;
855     }
856     memcpy(s + pos, cp, cl);
857     ptr->pos = pos;
858     return Qnil;
859 }
860 
861 /*
862  * call-seq:
863  *   strio.readchar   -> string
864  *
865  * See IO#readchar.
866  */
867 static VALUE
strio_readchar(VALUE self)868 strio_readchar(VALUE self)
869 {
870     VALUE c = rb_funcall2(self, rb_intern("getc"), 0, 0);
871     if (NIL_P(c)) rb_eof_error();
872     return c;
873 }
874 
875 /*
876  * call-seq:
877  *   strio.readbyte   -> fixnum
878  *
879  * See IO#readbyte.
880  */
881 static VALUE
strio_readbyte(VALUE self)882 strio_readbyte(VALUE self)
883 {
884     VALUE c = rb_funcall2(self, rb_intern("getbyte"), 0, 0);
885     if (NIL_P(c)) rb_eof_error();
886     return c;
887 }
888 
889 /*
890  * call-seq:
891  *   strio.each_char {|char| block }  -> strio
892  *   strio.each_char                  -> anEnumerator
893  *
894  * See IO#each_char.
895  */
896 static VALUE
strio_each_char(VALUE self)897 strio_each_char(VALUE self)
898 {
899     VALUE c;
900 
901     RETURN_ENUMERATOR(self, 0, 0);
902 
903     while (!NIL_P(c = strio_getc(self))) {
904 	rb_yield(c);
905     }
906     return self;
907 }
908 
909 /*
910  *  This is a deprecated alias for <code>each_char</code>.
911  */
912 static VALUE
strio_chars(VALUE self)913 strio_chars(VALUE self)
914 {
915     rb_warn("StringIO#chars is deprecated; use #each_char instead");
916     if (!rb_block_given_p())
917 	return rb_enumeratorize(self, ID2SYM(rb_intern("each_char")), 0, 0);
918     return strio_each_char(self);
919 }
920 
921 /*
922  * call-seq:
923  *   strio.each_codepoint {|c| block }  -> strio
924  *   strio.each_codepoint               -> anEnumerator
925  *
926  * See IO#each_codepoint.
927  */
928 static VALUE
strio_each_codepoint(VALUE self)929 strio_each_codepoint(VALUE self)
930 {
931     struct StringIO *ptr;
932     rb_encoding *enc;
933     unsigned int c;
934     int n;
935 
936     RETURN_ENUMERATOR(self, 0, 0);
937 
938     ptr = readable(self);
939     enc = get_enc(ptr);
940     for (;;) {
941 	if (ptr->pos >= RSTRING_LEN(ptr->string)) {
942 	    return self;
943 	}
944 
945 	c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
946 				 RSTRING_END(ptr->string), &n, enc);
947 	rb_yield(UINT2NUM(c));
948 	ptr->pos += n;
949     }
950     return self;
951 }
952 
953 /*
954  *  This is a deprecated alias for <code>each_codepoint</code>.
955  */
956 static VALUE
strio_codepoints(VALUE self)957 strio_codepoints(VALUE self)
958 {
959     rb_warn("StringIO#codepoints is deprecated; use #each_codepoint instead");
960     if (!rb_block_given_p())
961 	return rb_enumeratorize(self, ID2SYM(rb_intern("each_codepoint")), 0, 0);
962     return strio_each_codepoint(self);
963 }
964 
965 /* Boyer-Moore search: copied from regex.c */
966 static void
bm_init_skip(long * skip,const char * pat,long m)967 bm_init_skip(long *skip, const char *pat, long m)
968 {
969     int c;
970 
971     for (c = 0; c < (1 << CHAR_BIT); c++) {
972 	skip[c] = m;
973     }
974     while (--m) {
975 	skip[(unsigned char)*pat++] = m;
976     }
977 }
978 
979 static long
bm_search(const char * little,long llen,const char * big,long blen,const long * skip)980 bm_search(const char *little, long llen, const char *big, long blen, const long *skip)
981 {
982     long i, j, k;
983 
984     i = llen - 1;
985     while (i < blen) {
986 	k = i;
987 	j = llen - 1;
988 	while (j >= 0 && big[k] == little[j]) {
989 	    k--;
990 	    j--;
991 	}
992 	if (j < 0) return k + 1;
993 	i += skip[(unsigned char)big[i]];
994     }
995     return -1;
996 }
997 
998 struct getline_arg {
999     VALUE rs;
1000     long limit;
1001     unsigned int chomp: 1;
1002 };
1003 
1004 static struct getline_arg *
prepare_getline_args(struct getline_arg * arg,int argc,VALUE * argv)1005 prepare_getline_args(struct getline_arg *arg, int argc, VALUE *argv)
1006 {
1007     VALUE str, lim, opts;
1008     long limit = -1;
1009 
1010     argc = rb_scan_args(argc, argv, "02:", &str, &lim, &opts);
1011     switch (argc) {
1012       case 0:
1013 	str = rb_rs;
1014 	break;
1015 
1016       case 1:
1017 	if (!NIL_P(str) && !RB_TYPE_P(str, T_STRING)) {
1018 	    VALUE tmp = rb_check_string_type(str);
1019 	    if (NIL_P(tmp)) {
1020 		limit = NUM2LONG(str);
1021 		str = rb_rs;
1022 	    }
1023 	    else {
1024 		str = tmp;
1025 	    }
1026 	}
1027 	break;
1028 
1029       case 2:
1030 	if (!NIL_P(str)) StringValue(str);
1031 	if (!NIL_P(lim)) limit = NUM2LONG(lim);
1032 	break;
1033     }
1034     arg->rs = str;
1035     arg->limit = limit;
1036     arg->chomp = 0;
1037     if (!NIL_P(opts)) {
1038 	static ID keywords[1];
1039 	VALUE vchomp;
1040 	if (!keywords[0]) {
1041 	    keywords[0] = rb_intern_const("chomp");
1042 	}
1043 	rb_get_kwargs(opts, keywords, 0, 1, &vchomp);
1044 	arg->chomp = (vchomp != Qundef) && RTEST(vchomp);
1045     }
1046     return arg;
1047 }
1048 
1049 static inline int
chomp_newline_width(const char * s,const char * e)1050 chomp_newline_width(const char *s, const char *e)
1051 {
1052     if (e > s && *--e == '\n') {
1053 	if (e > s && *--e == '\r') return 2;
1054 	return 1;
1055     }
1056     return 0;
1057 }
1058 
1059 static VALUE
strio_getline(struct getline_arg * arg,struct StringIO * ptr)1060 strio_getline(struct getline_arg *arg, struct StringIO *ptr)
1061 {
1062     const char *s, *e, *p;
1063     long n, limit = arg->limit;
1064     VALUE str = arg->rs;
1065     int w = 0;
1066     rb_encoding *enc = get_enc(ptr);
1067 
1068     if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
1069 	return Qnil;
1070     }
1071     s = RSTRING_PTR(ptr->string);
1072     e = s + RSTRING_LEN(ptr->string);
1073     s += ptr->pos;
1074     if (limit > 0 && (size_t)limit < (size_t)(e - s)) {
1075 	e = rb_enc_right_char_head(s, s + limit, e, get_enc(ptr));
1076     }
1077     if (NIL_P(str)) {
1078 	if (arg->chomp) {
1079 	    w = chomp_newline_width(s, e);
1080 	}
1081 	str = strio_substr(ptr, ptr->pos, e - s - w, enc);
1082     }
1083     else if ((n = RSTRING_LEN(str)) == 0) {
1084 	p = s;
1085 	while (p[(p + 1 < e) && (*p == '\r') && 0] == '\n') {
1086 	    p += *p == '\r';
1087 	    if (++p == e) {
1088 		return Qnil;
1089 	    }
1090 	}
1091 	s = p;
1092 	while ((p = memchr(p, '\n', e - p)) && (p != e)) {
1093 	    if (*++p == '\n') {
1094 		e = p + 1;
1095 		w = (arg->chomp ? 1 : 0);
1096 		break;
1097 	    }
1098 	    else if (*p == '\r' && p < e && p[1] == '\n') {
1099 		e = p + 2;
1100 		w = (arg->chomp ? 2 : 0);
1101 		break;
1102 	    }
1103 	}
1104 	if (!w && arg->chomp) {
1105 	    w = chomp_newline_width(s, e);
1106 	}
1107 	str = strio_substr(ptr, s - RSTRING_PTR(ptr->string), e - s - w, enc);
1108     }
1109     else if (n == 1) {
1110 	if ((p = memchr(s, RSTRING_PTR(str)[0], e - s)) != 0) {
1111 	    e = p + 1;
1112 	    w = (arg->chomp ? (p > s && *(p-1) == '\r') + 1 : 0);
1113 	}
1114 	str = strio_substr(ptr, ptr->pos, e - s - w, enc);
1115     }
1116     else {
1117 	if (n < e - s) {
1118 	    if (e - s < 1024) {
1119 		for (p = s; p + n <= e; ++p) {
1120 		    if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
1121 			e = p + (arg->chomp ? 0 : n);
1122 			break;
1123 		    }
1124 		}
1125 	    }
1126 	    else {
1127 		long skip[1 << CHAR_BIT], pos;
1128 		p = RSTRING_PTR(str);
1129 		bm_init_skip(skip, p, n);
1130 		if ((pos = bm_search(p, n, s, e - s, skip)) >= 0) {
1131 		    e = s + pos + (arg->chomp ? 0 : n);
1132 		}
1133 	    }
1134 	}
1135 	str = strio_substr(ptr, ptr->pos, e - s - w, enc);
1136     }
1137     ptr->pos = e - RSTRING_PTR(ptr->string);
1138     ptr->lineno++;
1139     return str;
1140 }
1141 
1142 /*
1143  * call-seq:
1144  *   strio.gets(sep=$/)     -> string or nil
1145  *   strio.gets(limit)      -> string or nil
1146  *   strio.gets(sep, limit) -> string or nil
1147  *
1148  * See IO#gets.
1149  */
1150 static VALUE
strio_gets(int argc,VALUE * argv,VALUE self)1151 strio_gets(int argc, VALUE *argv, VALUE self)
1152 {
1153     struct getline_arg arg;
1154     VALUE str;
1155 
1156     if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
1157 	struct StringIO *ptr = readable(self);
1158 	return rb_enc_str_new(0, 0, get_enc(ptr));
1159     }
1160 
1161     str = strio_getline(&arg, readable(self));
1162     rb_lastline_set(str);
1163     return str;
1164 }
1165 
1166 /*
1167  * call-seq:
1168  *   strio.readline(sep=$/)     -> string
1169  *   strio.readline(limit)      -> string or nil
1170  *   strio.readline(sep, limit) -> string or nil
1171  *
1172  * See IO#readline.
1173  */
1174 static VALUE
strio_readline(int argc,VALUE * argv,VALUE self)1175 strio_readline(int argc, VALUE *argv, VALUE self)
1176 {
1177     VALUE line = rb_funcall2(self, rb_intern("gets"), argc, argv);
1178     if (NIL_P(line)) rb_eof_error();
1179     return line;
1180 }
1181 
1182 /*
1183  * call-seq:
1184  *   strio.each(sep=$/) {|line| block }         -> strio
1185  *   strio.each(limit) {|line| block }          -> strio
1186  *   strio.each(sep, limit) {|line| block }     -> strio
1187  *   strio.each(...)                            -> anEnumerator
1188  *
1189  *   strio.each_line(sep=$/) {|line| block }    -> strio
1190  *   strio.each_line(limit) {|line| block }     -> strio
1191  *   strio.each_line(sep,limit) {|line| block } -> strio
1192  *   strio.each_line(...)                       -> anEnumerator
1193  *
1194  * See IO#each.
1195  */
1196 static VALUE
strio_each(int argc,VALUE * argv,VALUE self)1197 strio_each(int argc, VALUE *argv, VALUE self)
1198 {
1199     VALUE line;
1200     struct getline_arg arg;
1201 
1202     StringIO(self);
1203     RETURN_ENUMERATOR(self, argc, argv);
1204 
1205     if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
1206 	rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
1207     }
1208 
1209     while (!NIL_P(line = strio_getline(&arg, readable(self)))) {
1210 	rb_yield(line);
1211     }
1212     return self;
1213 }
1214 
1215 /*
1216  *  This is a deprecated alias for <code>each_line</code>.
1217  */
1218 static VALUE
strio_lines(int argc,VALUE * argv,VALUE self)1219 strio_lines(int argc, VALUE *argv, VALUE self)
1220 {
1221     rb_warn("StringIO#lines is deprecated; use #each_line instead");
1222     if (!rb_block_given_p())
1223 	return rb_enumeratorize(self, ID2SYM(rb_intern("each_line")), argc, argv);
1224     return strio_each(argc, argv, self);
1225 }
1226 
1227 /*
1228  * call-seq:
1229  *   strio.readlines(sep=$/)    ->   array
1230  *   strio.readlines(limit)     ->   array
1231  *   strio.readlines(sep,limit) ->   array
1232  *
1233  * See IO#readlines.
1234  */
1235 static VALUE
strio_readlines(int argc,VALUE * argv,VALUE self)1236 strio_readlines(int argc, VALUE *argv, VALUE self)
1237 {
1238     VALUE ary, line;
1239     struct getline_arg arg;
1240 
1241     StringIO(self);
1242     ary = rb_ary_new();
1243     if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
1244 	rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
1245     }
1246 
1247     while (!NIL_P(line = strio_getline(&arg, readable(self)))) {
1248 	rb_ary_push(ary, line);
1249     }
1250     return ary;
1251 }
1252 
1253 /*
1254  * call-seq:
1255  *   strio.write(string, ...) -> integer
1256  *   strio.syswrite(string)   -> integer
1257  *
1258  * Appends the given string to the underlying buffer string of *strio*.
1259  * The stream must be opened for writing.  If the argument is not a
1260  * string, it will be converted to a string using <code>to_s</code>.
1261  * Returns the number of bytes written.  See IO#write.
1262  */
1263 static VALUE
strio_write_m(int argc,VALUE * argv,VALUE self)1264 strio_write_m(int argc, VALUE *argv, VALUE self)
1265 {
1266     long len = 0;
1267     while (argc-- > 0) {
1268 	/* StringIO can't exceed long limit */
1269 	len += strio_write(self, *argv++);
1270     }
1271     return LONG2NUM(len);
1272 }
1273 
1274 static long
strio_write(VALUE self,VALUE str)1275 strio_write(VALUE self, VALUE str)
1276 {
1277     struct StringIO *ptr = writable(self);
1278     long len, olen;
1279     rb_encoding *enc, *enc2;
1280     rb_encoding *const ascii8bit = rb_ascii8bit_encoding();
1281 
1282     if (!RB_TYPE_P(str, T_STRING))
1283 	str = rb_obj_as_string(str);
1284     enc = get_enc(ptr);
1285     enc2 = rb_enc_get(str);
1286     if (enc != enc2 && enc != ascii8bit) {
1287 	str = rb_str_conv_enc(str, enc2, enc);
1288     }
1289     len = RSTRING_LEN(str);
1290     if (len == 0) return 0;
1291     check_modifiable(ptr);
1292     olen = RSTRING_LEN(ptr->string);
1293     if (ptr->flags & FMODE_APPEND) {
1294 	ptr->pos = olen;
1295     }
1296     if (ptr->pos == olen) {
1297 	if (enc == ascii8bit || enc2 == ascii8bit) {
1298 	    rb_enc_str_buf_cat(ptr->string, RSTRING_PTR(str), len, enc);
1299 	    OBJ_INFECT(ptr->string, str);
1300 	}
1301 	else {
1302 	    rb_str_buf_append(ptr->string, str);
1303 	}
1304     }
1305     else {
1306 	strio_extend(ptr, ptr->pos, len);
1307 	memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
1308 	OBJ_INFECT(ptr->string, str);
1309     }
1310     OBJ_INFECT(ptr->string, self);
1311     RB_GC_GUARD(str);
1312     ptr->pos += len;
1313     return len;
1314 }
1315 
1316 /*
1317  * call-seq:
1318  *   strio << obj     -> strio
1319  *
1320  * See IO#<<.
1321  */
1322 #define strio_addstr rb_io_addstr
1323 
1324 /*
1325  * call-seq:
1326  *   strio.print()             -> nil
1327  *   strio.print(obj, ...)     -> nil
1328  *
1329  * See IO#print.
1330  */
1331 #define strio_print rb_io_print
1332 
1333 /*
1334  * call-seq:
1335  *   strio.printf(format_string [, obj, ...] )   -> nil
1336  *
1337  * See IO#printf.
1338  */
1339 #define strio_printf rb_io_printf
1340 
1341 /*
1342  * call-seq:
1343  *   strio.putc(obj)    -> obj
1344  *
1345  * See IO#putc.
1346  */
1347 static VALUE
strio_putc(VALUE self,VALUE ch)1348 strio_putc(VALUE self, VALUE ch)
1349 {
1350     struct StringIO *ptr = writable(self);
1351     VALUE str;
1352 
1353     check_modifiable(ptr);
1354     if (RB_TYPE_P(ch, T_STRING)) {
1355 	str = rb_str_substr(ch, 0, 1);
1356     }
1357     else {
1358 	char c = NUM2CHR(ch);
1359 	str = rb_str_new(&c, 1);
1360     }
1361     strio_write(self, str);
1362     return ch;
1363 }
1364 
1365 /*
1366  * call-seq:
1367  *   strio.puts(obj, ...)    -> nil
1368  *
1369  * See IO#puts.
1370  */
1371 #define strio_puts rb_io_puts
1372 
1373 /*
1374  * call-seq:
1375  *   strio.read([length [, outbuf]])    -> string, outbuf, or nil
1376  *
1377  * See IO#read.
1378  */
1379 static VALUE
strio_read(int argc,VALUE * argv,VALUE self)1380 strio_read(int argc, VALUE *argv, VALUE self)
1381 {
1382     struct StringIO *ptr = readable(self);
1383     VALUE str = Qnil;
1384     long len;
1385     int binary = 0;
1386 
1387     rb_check_arity(argc, 0, 2);
1388     switch (argc) {
1389       case 2:
1390 	str = argv[1];
1391 	if (!NIL_P(str)) {
1392 	    StringValue(str);
1393 	    rb_str_modify(str);
1394 	}
1395 	/* fall through */
1396       case 1:
1397 	if (!NIL_P(argv[0])) {
1398 	    len = NUM2LONG(argv[0]);
1399 	    if (len < 0) {
1400 		rb_raise(rb_eArgError, "negative length %ld given", len);
1401 	    }
1402 	    if (len > 0 && ptr->pos >= RSTRING_LEN(ptr->string)) {
1403 		if (!NIL_P(str)) rb_str_resize(str, 0);
1404 		return Qnil;
1405 	    }
1406 	    binary = 1;
1407 	    break;
1408 	}
1409 	/* fall through */
1410       case 0:
1411 	len = RSTRING_LEN(ptr->string);
1412 	if (len <= ptr->pos) {
1413 	    rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
1414 	    if (NIL_P(str)) {
1415 		str = rb_str_new(0, 0);
1416 	    }
1417 	    else {
1418 		rb_str_resize(str, 0);
1419 	    }
1420 	    rb_enc_associate(str, enc);
1421 	    return str;
1422 	}
1423 	else {
1424 	    len -= ptr->pos;
1425 	}
1426 	break;
1427     }
1428     if (NIL_P(str)) {
1429 	rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
1430 	str = strio_substr(ptr, ptr->pos, len, enc);
1431     }
1432     else {
1433 	long rest = RSTRING_LEN(ptr->string) - ptr->pos;
1434 	if (len > rest) len = rest;
1435 	rb_str_resize(str, len);
1436 	MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
1437 	if (binary)
1438 	    rb_enc_associate(str, rb_ascii8bit_encoding());
1439 	else
1440 	    rb_enc_copy(str, ptr->string);
1441     }
1442     ptr->pos += RSTRING_LEN(str);
1443     return str;
1444 }
1445 
1446 /*
1447  * call-seq:
1448  *   strio.sysread(integer[, outbuf])    -> string
1449  *   strio.readpartial(integer[, outbuf])    -> string
1450  *
1451  * Similar to #read, but raises +EOFError+ at end of string instead of
1452  * returning +nil+, as well as IO#sysread does.
1453  */
1454 static VALUE
strio_sysread(int argc,VALUE * argv,VALUE self)1455 strio_sysread(int argc, VALUE *argv, VALUE self)
1456 {
1457     VALUE val = rb_funcall2(self, rb_intern("read"), argc, argv);
1458     if (NIL_P(val)) {
1459 	rb_eof_error();
1460     }
1461     return val;
1462 }
1463 
1464 /*
1465  * call-seq:
1466  *   strio.read_nonblock(integer[, outbuf [, opts]])    -> string
1467  *
1468  * Similar to #read, but raises +EOFError+ at end of string unless the
1469  * +exception: false+ option is passed in.
1470  */
1471 static VALUE
strio_read_nonblock(int argc,VALUE * argv,VALUE self)1472 strio_read_nonblock(int argc, VALUE *argv, VALUE self)
1473 {
1474     VALUE opts = Qnil, val;
1475 
1476     rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
1477 
1478     if (!NIL_P(opts)) {
1479 	argc--;
1480     }
1481 
1482     val = strio_read(argc, argv, self);
1483     if (NIL_P(val)) {
1484 	if (!NIL_P(opts) &&
1485 	      rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
1486 	    return Qnil;
1487 	else
1488 	    rb_eof_error();
1489     }
1490 
1491     return val;
1492 }
1493 
1494 #define strio_syswrite rb_io_write
1495 
1496 static VALUE
strio_syswrite_nonblock(int argc,VALUE * argv,VALUE self)1497 strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
1498 {
1499     VALUE str;
1500 
1501     rb_scan_args(argc, argv, "10:", &str, NULL);
1502     return strio_syswrite(self, str);
1503 }
1504 
1505 #define strio_isatty strio_false
1506 
1507 #define strio_pid strio_nil
1508 
1509 #define strio_fileno strio_nil
1510 
1511 /*
1512  * call-seq:
1513  *   strio.length -> integer
1514  *   strio.size   -> integer
1515  *
1516  * Returns the size of the buffer string.
1517  */
1518 static VALUE
strio_size(VALUE self)1519 strio_size(VALUE self)
1520 {
1521     VALUE string = StringIO(self)->string;
1522     if (NIL_P(string)) {
1523 	rb_raise(rb_eIOError, "not opened");
1524     }
1525     return ULONG2NUM(RSTRING_LEN(string));
1526 }
1527 
1528 /*
1529  * call-seq:
1530  *   strio.truncate(integer)    -> 0
1531  *
1532  * Truncates the buffer string to at most _integer_ bytes. The *strio*
1533  * must be opened for writing.
1534  */
1535 static VALUE
strio_truncate(VALUE self,VALUE len)1536 strio_truncate(VALUE self, VALUE len)
1537 {
1538     VALUE string = writable(self)->string;
1539     long l = NUM2LONG(len);
1540     long plen = RSTRING_LEN(string);
1541     if (l < 0) {
1542 	error_inval("negative length");
1543     }
1544     rb_str_resize(string, l);
1545     if (plen < l) {
1546 	MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
1547     }
1548     return len;
1549 }
1550 
1551 /*
1552  *  call-seq:
1553  *     strio.external_encoding   => encoding
1554  *
1555  *  Returns the Encoding object that represents the encoding of the file.
1556  *  If strio is write mode and no encoding is specified, returns <code>nil</code>.
1557  */
1558 
1559 static VALUE
strio_external_encoding(VALUE self)1560 strio_external_encoding(VALUE self)
1561 {
1562     struct StringIO *ptr = StringIO(self);
1563     return rb_enc_from_encoding(get_enc(ptr));
1564 }
1565 
1566 /*
1567  *  call-seq:
1568  *     strio.internal_encoding   => encoding
1569  *
1570  *  Returns the Encoding of the internal string if conversion is
1571  *  specified.  Otherwise returns nil.
1572  */
1573 
1574 static VALUE
strio_internal_encoding(VALUE self)1575 strio_internal_encoding(VALUE self)
1576 {
1577     return Qnil;
1578 }
1579 
1580 /*
1581  *  call-seq:
1582  *     strio.set_encoding(ext_enc, [int_enc[, opt]])  => strio
1583  *
1584  *  Specify the encoding of the StringIO as <i>ext_enc</i>.
1585  *  Use the default external encoding if <i>ext_enc</i> is nil.
1586  *  2nd argument <i>int_enc</i> and optional hash <i>opt</i> argument
1587  *  are ignored; they are for API compatibility to IO.
1588  */
1589 
1590 static VALUE
strio_set_encoding(int argc,VALUE * argv,VALUE self)1591 strio_set_encoding(int argc, VALUE *argv, VALUE self)
1592 {
1593     rb_encoding* enc;
1594     struct StringIO *ptr = StringIO(self);
1595     VALUE ext_enc, int_enc, opt;
1596 
1597     argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt);
1598 
1599     if (NIL_P(ext_enc)) {
1600 	enc = rb_default_external_encoding();
1601     }
1602     else {
1603 	enc = rb_to_encoding(ext_enc);
1604     }
1605     ptr->enc = enc;
1606     if (WRITABLE(self)) {
1607 	rb_enc_associate(ptr->string, enc);
1608     }
1609 
1610     return self;
1611 }
1612 
1613 /*
1614  * Pseudo I/O on String object.
1615  *
1616  * Commonly used to simulate `$stdio` or `$stderr`
1617  *
1618  * === Examples
1619  *
1620  *   require 'stringio'
1621  *
1622  *   io = StringIO.new
1623  *   io.puts "Hello World"
1624  *   io.string #=> "Hello World\n"
1625  */
1626 void
Init_stringio(void)1627 Init_stringio(void)
1628 {
1629 #undef rb_intern
1630     VALUE StringIO = rb_define_class("StringIO", rb_cData);
1631 
1632     rb_include_module(StringIO, rb_mEnumerable);
1633     rb_define_alloc_func(StringIO, strio_s_allocate);
1634     rb_define_singleton_method(StringIO, "new", strio_s_new, -1);
1635     rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
1636     rb_define_method(StringIO, "initialize", strio_initialize, -1);
1637     rb_define_method(StringIO, "initialize_copy", strio_copy, 1);
1638     rb_define_method(StringIO, "reopen", strio_reopen, -1);
1639 
1640     rb_define_method(StringIO, "string", strio_get_string, 0);
1641     rb_define_method(StringIO, "string=", strio_set_string, 1);
1642     rb_define_method(StringIO, "lineno", strio_get_lineno, 0);
1643     rb_define_method(StringIO, "lineno=", strio_set_lineno, 1);
1644 
1645 
1646     /* call-seq: strio.binmode -> true */
1647     rb_define_method(StringIO, "binmode", strio_binmode, 0);
1648     rb_define_method(StringIO, "close", strio_close, 0);
1649     rb_define_method(StringIO, "close_read", strio_close_read, 0);
1650     rb_define_method(StringIO, "close_write", strio_close_write, 0);
1651     rb_define_method(StringIO, "closed?", strio_closed, 0);
1652     rb_define_method(StringIO, "closed_read?", strio_closed_read, 0);
1653     rb_define_method(StringIO, "closed_write?", strio_closed_write, 0);
1654     rb_define_method(StringIO, "eof", strio_eof, 0);
1655     rb_define_method(StringIO, "eof?", strio_eof, 0);
1656     /* call-seq: strio.fcntl */
1657     rb_define_method(StringIO, "fcntl", strio_fcntl, -1);
1658     /* call-seq: strio.flush -> strio */
1659     rb_define_method(StringIO, "flush", strio_flush, 0);
1660     /* call-seq: strio.fsync -> 0 */
1661     rb_define_method(StringIO, "fsync", strio_fsync, 0);
1662     rb_define_method(StringIO, "pos", strio_get_pos, 0);
1663     rb_define_method(StringIO, "pos=", strio_set_pos, 1);
1664     rb_define_method(StringIO, "rewind", strio_rewind, 0);
1665     rb_define_method(StringIO, "seek", strio_seek, -1);
1666     rb_define_method(StringIO, "sync", strio_get_sync, 0);
1667     /* call-seq: strio.sync = boolean -> boolean */
1668     rb_define_method(StringIO, "sync=", strio_set_sync, 1);
1669     rb_define_method(StringIO, "tell", strio_tell, 0);
1670 
1671     rb_define_method(StringIO, "each", strio_each, -1);
1672     rb_define_method(StringIO, "each_line", strio_each, -1);
1673     rb_define_method(StringIO, "lines", strio_lines, -1);
1674     rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
1675     rb_define_method(StringIO, "bytes", strio_bytes, 0);
1676     rb_define_method(StringIO, "each_char", strio_each_char, 0);
1677     rb_define_method(StringIO, "chars", strio_chars, 0);
1678     rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0);
1679     rb_define_method(StringIO, "codepoints", strio_codepoints, 0);
1680     rb_define_method(StringIO, "getc", strio_getc, 0);
1681     rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
1682     rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
1683     rb_define_method(StringIO, "getbyte", strio_getbyte, 0);
1684     rb_define_method(StringIO, "gets", strio_gets, -1);
1685     rb_define_method(StringIO, "readlines", strio_readlines, -1);
1686     rb_define_method(StringIO, "read", strio_read, -1);
1687 
1688     rb_define_method(StringIO, "write", strio_write_m, -1);
1689     rb_define_method(StringIO, "putc", strio_putc, 1);
1690 
1691     /*
1692      * call-seq:
1693      *   strio.isatty -> nil
1694      *   strio.tty? -> nil
1695      *
1696      */
1697     rb_define_method(StringIO, "isatty", strio_isatty, 0);
1698     rb_define_method(StringIO, "tty?", strio_isatty, 0);
1699 
1700     /* call-seq: strio.pid -> nil */
1701     rb_define_method(StringIO, "pid", strio_pid, 0);
1702 
1703     /* call-seq: strio.fileno -> nil */
1704     rb_define_method(StringIO, "fileno", strio_fileno, 0);
1705     rb_define_method(StringIO, "size", strio_size, 0);
1706     rb_define_method(StringIO, "length", strio_size, 0);
1707     rb_define_method(StringIO, "truncate", strio_truncate, 1);
1708 
1709     rb_define_method(StringIO, "external_encoding", strio_external_encoding, 0);
1710     rb_define_method(StringIO, "internal_encoding", strio_internal_encoding, 0);
1711     rb_define_method(StringIO, "set_encoding", strio_set_encoding, -1);
1712 
1713     {
1714 	VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
1715 	rb_define_method(mReadable, "readchar", strio_readchar, 0);
1716 	rb_define_method(mReadable, "readbyte", strio_readbyte, 0);
1717 	rb_define_method(mReadable, "readline", strio_readline, -1);
1718 	rb_define_method(mReadable, "sysread", strio_sysread, -1);
1719 	rb_define_method(mReadable, "readpartial", strio_sysread, -1);
1720 	rb_define_method(mReadable, "read_nonblock", strio_read_nonblock, -1);
1721 	rb_include_module(StringIO, mReadable);
1722     }
1723     {
1724 	VALUE mWritable = rb_define_module_under(rb_cIO, "generic_writable");
1725 	rb_define_method(mWritable, "<<", strio_addstr, 1);
1726 	rb_define_method(mWritable, "print", strio_print, -1);
1727 	rb_define_method(mWritable, "printf", strio_printf, -1);
1728 	rb_define_method(mWritable, "puts", strio_puts, -1);
1729 	rb_define_method(mWritable, "syswrite", strio_syswrite, 1);
1730 	rb_define_method(mWritable, "write_nonblock", strio_syswrite_nonblock, -1);
1731 	rb_include_module(StringIO, mWritable);
1732     }
1733 
1734     sym_exception = ID2SYM(rb_intern("exception"));
1735 }
1736