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)) {
49 fmode = FMODE_READABLE;
50 }
51 else if (!NIL_P(intmode = rb_check_to_integer(mode, "to_int"))) {
52 int flags = NUM2INT(intmode);
53 fmode = rb_io_oflags_fmode(flags);
54 }
55 else {
56 const char *m = StringValueCStr(mode), *n, *e;
57 fmode = rb_io_modestr_fmode(m);
58 n = strchr(m, ':');
59 if (n) {
60 long len;
61 char encname[ENCODING_MAXNAMELEN+1];
62 has_enc = 1;
63 if (fmode & FMODE_SETENC_BY_BOM) {
64 n = strchr(n, '|');
65 }
66 e = strchr(++n, ':');
67 len = e ? e - n : strlen(n);
68 if (len > 0 && len <= ENCODING_MAXNAMELEN) {
69 if (e) {
70 memcpy(encname, n, len);
71 encname[len] = '\0';
72 n = encname;
73 }
74 convconfig_p->enc = rb_enc_find(n);
75 }
76 if (e && (len = strlen(++e)) > 0 && len <= ENCODING_MAXNAMELEN) {
77 convconfig_p->enc2 = rb_enc_find(e);
78 }
79 }
80 }
81
82 if (!NIL_P(opthash)) {
83 rb_encoding *extenc = 0, *intenc = 0;
84 VALUE v;
85 if (!has_vmode) {
86 ID id_mode;
87 CONST_ID(id_mode, "mode");
88 v = rb_hash_aref(opthash, ID2SYM(id_mode));
89 if (!NIL_P(v)) {
90 if (!NIL_P(mode)) {
91 rb_raise(rb_eArgError, "mode specified twice");
92 }
93 has_vmode = 1;
94 mode = v;
95 goto vmode_handle;
96 }
97 }
98
99 if (rb_io_extract_encoding_option(opthash, &extenc, &intenc, &fmode)) {
100 if (has_enc) {
101 rb_raise(rb_eArgError, "encoding specified twice");
102 }
103 }
104 }
105 *fmode_p = fmode;
106 }
107 #endif
108
109 struct StringIO {
110 VALUE string;
111 rb_encoding *enc;
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 },
168 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
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);
188 rb_enc_associate(str, enc);
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)
209 typedef char strio_flags_check[(STRIO_READABLE/FMODE_READABLE == STRIO_WRITABLE/FMODE_WRITABLE) * 2 - 1];
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) {
354 rb_syserr_fail(EACCES, 0);
355 }
356 }
357 else {
358 if (NIL_P(vmode)) {
359 ptr->flags |= FMODE_WRITABLE;
360 }
361 }
362 if (ptr->flags & FMODE_TRUNC) {
363 rb_str_resize(string, 0);
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;
379 ptr->flags &= ~FMODE_READWRITE;
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 {
393 VALUE obj = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
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 }
408 return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
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);
496 ptr->flags &= ~FMODE_READWRITE;
497 StringValue(string);
498 ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
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);
673 rb_encoding *enc = rb_ascii8bit_encoding();
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);
852 rb_encoding *enc = get_enc(ptr);
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;
862 len = rb_enc_mbclen(p, RSTRING_END(str), enc);
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);
987 rb_str_modify_expand(str, ex);
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 {
1145 VALUE rs;
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)) {
1164 VALUE tmp = rb_check_string_type(str);
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));
1308 rb_lastline_set(str);
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 {
1323 VALUE line = rb_funcallv_kw(self, rb_intern("gets"), argc, argv, RB_PASS_CALLED_KEYWORDS);
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))
1429 str = rb_obj_as_string(str);
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) {
1444 rb_enc_str_buf_cat(ptr->string, RSTRING_PTR(str), len, enc);
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 }
1563 rb_enc_associate(str, enc);
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)
1581 rb_enc_associate(str, rb_ascii8bit_encoding());
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 {
1600 VALUE val = rb_funcallv_kw(self, rb_intern("read"), argc, argv, RB_PASS_CALLED_KEYWORDS);
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)) {
1744 enc = rb_default_external_encoding();
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
1790 Init_stringio(void)
1791 {
1792 #undef rb_intern
1793 VALUE StringIO = rb_define_class("StringIO", rb_cData);
1794
1795 rb_define_const(StringIO, "VERSION", rb_str_new_cstr(STRINGIO_VERSION));
1796
1797 rb_include_module(StringIO, rb_mEnumerable);
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 */
1833 rb_define_method(StringIO, "sync=", strio_set_sync, 1);
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)