DEFINITIONS
This source file includes following functions.
- strio_alloc
- strio_mark
- strio_free
- check_strio
- get_strio
- readable
- writable
- check_modifiable
- strio_s_allocate
- strio_s_open
- strio_initialize
- strio_finalize
- strio_false
- strio_nil
- strio_self
- strio_0
- strio_first
- strio_unimpl
- strio_get_string
- strio_set_string
- strio_close
- strio_close_read
- strio_close_write
- strio_closed
- strio_closed_read
- strio_closed_write
- strio_eof
- strio_become
- strio_get_lineno
- strio_set_lineno
- strio_reopen
- strio_get_pos
- strio_set_pos
- strio_rewind
- strio_seek
- strio_get_sync
- strio_each_byte
- strio_getc
- strio_ungetc
- strio_readchar
- bm_init_skip
- bm_search
- strio_gets_internal
- strio_gets
- strio_readline
- strio_each
- strio_readlines
- strio_write
- strio_putc
- strio_read
- strio_sysread
- strio_size
- strio_truncate
- Init_stringio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include "ruby.h"
16 #include "rubyio.h"
17
18 #define STRIO_APPEND 4
19
20 struct StringIO {
21 VALUE string;
22 long pos;
23 long lineno;
24 int flags;
25 int count;
26 };
27
28 static struct StringIO* strio_alloc _((void));
29 static void strio_mark _((struct StringIO *));
30 static void strio_free _((struct StringIO *));
31 static struct StringIO* check_strio _((VALUE));
32 static struct StringIO* get_strio _((VALUE));
33 static struct StringIO* readable _((struct StringIO *));
34 static struct StringIO* writable _((struct StringIO *));
35 static void check_modifiable _((struct StringIO *));
36
37 #define IS_STRIO(obj) (RDATA(obj)->dmark == (RUBY_DATA_FUNC)strio_mark)
38 #define error_inval(msg) (errno = EINVAL, rb_sys_fail(msg))
39
40 static struct StringIO *
41 strio_alloc()
42 {
43 struct StringIO *ptr = ALLOC(struct StringIO);
44 ptr->string = Qnil;
45 ptr->pos = 0;
46 ptr->lineno = 0;
47 ptr->flags = 0;
48 ptr->count = 1;
49 return ptr;
50 }
51
52 static void
53 strio_mark(ptr)
54 struct StringIO *ptr;
55 {
56 if (ptr) {
57 rb_gc_mark(ptr->string);
58 }
59 }
60
61 static void
62 strio_free(ptr)
63 struct StringIO *ptr;
64 {
65 if (--ptr->count <= 0) {
66 xfree(ptr);
67 }
68 }
69
70 static struct StringIO*
71 check_strio(self)
72 VALUE self;
73 {
74 Check_Type(self, T_DATA);
75 if (!IS_STRIO(self)) {
76 rb_raise(rb_eTypeError, "wrong argument type %s (expected String::IO)",
77 rb_class2name(CLASS_OF(self)));
78 }
79 return DATA_PTR(self);
80 }
81
82 static struct StringIO*
83 get_strio(self)
84 VALUE self;
85 {
86 struct StringIO *ptr = check_strio(self);
87
88 if (!ptr) {
89 rb_raise(rb_eIOError, "uninitialized stream");
90 }
91 return ptr;
92 }
93
94 #define StringIO(obj) get_strio(obj)
95
96 #define CLOSED(ptr) NIL_P((ptr)->string)
97 #define READABLE(ptr) (!CLOSED(ptr) && ((ptr)->flags & FMODE_READABLE))
98 #define WRITABLE(ptr) (!CLOSED(ptr) && ((ptr)->flags & FMODE_WRITABLE))
99
100 static struct StringIO*
101 readable(ptr)
102 struct StringIO *ptr;
103 {
104 if (!READABLE(ptr)) {
105 rb_raise(rb_eIOError, "not opened for reading");
106 }
107 return ptr;
108 }
109
110 static struct StringIO*
111 writable(ptr)
112 struct StringIO *ptr;
113 {
114 if (!WRITABLE(ptr)) {
115 rb_raise(rb_eIOError, "not opened for writing");
116 }
117 if (!OBJ_TAINTED(ptr->string)) {
118 rb_secure(4);
119 }
120 return ptr;
121 }
122
123 static void
124 check_modifiable(ptr)
125 struct StringIO *ptr;
126 {
127 if (OBJ_FROZEN(ptr->string)) {
128 rb_raise(rb_eIOError, "not modifiable string");
129 }
130 }
131
132 static VALUE strio_s_allocate _((VALUE));
133 static VALUE strio_s_open _((int, VALUE *, VALUE));
134 static VALUE strio_initialize _((int, VALUE *, VALUE));
135 static VALUE strio_finalize _((VALUE));
136 static VALUE strio_self _((VALUE));
137 static VALUE strio_false _((VALUE));
138 static VALUE strio_nil _((VALUE));
139 static VALUE strio_0 _((VALUE));
140 static VALUE strio_first _((VALUE, VALUE));
141 static VALUE strio_unimpl _((int, VALUE *, VALUE));
142 static VALUE strio_get_string _((VALUE));
143 static VALUE strio_set_string _((VALUE, VALUE));
144 static VALUE strio_close _((VALUE));
145 static VALUE strio_close_read _((VALUE));
146 static VALUE strio_close_write _((VALUE));
147 static VALUE strio_closed _((VALUE));
148 static VALUE strio_closed_read _((VALUE));
149 static VALUE strio_closed_write _((VALUE));
150 static VALUE strio_eof _((VALUE));
151 static VALUE strio_become _((VALUE, VALUE));
152 static VALUE strio_get_lineno _((VALUE));
153 static VALUE strio_set_lineno _((VALUE, VALUE));
154 static VALUE strio_get_pos _((VALUE));
155 static VALUE strio_set_pos _((VALUE, VALUE));
156 static VALUE strio_rewind _((VALUE));
157 static VALUE strio_seek _((int, VALUE *, VALUE));
158 static VALUE strio_get_sync _((VALUE));
159 static VALUE strio_set_sync _((VALUE, VALUE));
160 static VALUE strio_each_byte _((VALUE));
161 static VALUE strio_getc _((VALUE));
162 static VALUE strio_ungetc _((VALUE, VALUE));
163 static VALUE strio_readchar _((VALUE));
164 static VALUE strio_gets_internal _((int, VALUE *, struct StringIO *));
165 static VALUE strio_gets _((int, VALUE *, VALUE));
166 static VALUE strio_readline _((int, VALUE *, VALUE));
167 static VALUE strio_each _((int, VALUE *, VALUE));
168 static VALUE strio_readlines _((int, VALUE *, VALUE));
169 static VALUE strio_write _((VALUE, VALUE));
170 static VALUE strio_print _((int, VALUE *, VALUE));
171 static VALUE strio_printf _((int, VALUE *, VALUE));
172 static VALUE strio_putc _((VALUE, VALUE));
173 static VALUE strio_read _((int, VALUE *, VALUE));
174 static VALUE strio_size _((VALUE));
175 static VALUE strio_truncate _((VALUE, VALUE));
176 void Init_stringio _((void));
177
178
179 static void bm_init_skip _((long *, const char *, long));
180 static long bm_search _((const char *, long, const char *, long, const long *));
181
182 static VALUE
183 strio_s_allocate(klass)
184 VALUE klass;
185 {
186 return Data_Wrap_Struct(klass, strio_mark, strio_free, 0);
187 }
188
189 static VALUE
190 strio_s_open(argc, argv, klass)
191 int argc;
192 VALUE *argv;
193 VALUE klass;
194 {
195 VALUE obj = rb_class_new_instance(argc, argv, klass);
196 if (!rb_block_given_p()) return obj;
197 return rb_ensure(rb_yield, obj, strio_finalize, obj);
198 }
199
200 static VALUE
201 strio_initialize(argc, argv, self)
202 int argc;
203 VALUE *argv;
204 VALUE self;
205 {
206 struct StringIO *ptr = check_strio(self);
207 VALUE string, mode;
208 const char* m;
209
210 if (!ptr) {
211 DATA_PTR(self) = ptr = strio_alloc();
212 }
213 rb_call_super(0, 0);
214 switch (rb_scan_args(argc, argv, "02", &string, &mode)) {
215 case 2:
216 StringValue(mode);
217 StringValue(string);
218 if (!(m = RSTRING(mode)->ptr)) m = "";
219 ptr->flags = rb_io_mode_flags(m);
220 if ((ptr->flags & FMODE_WRITABLE) && OBJ_FROZEN(string)) {
221 errno = EACCES;
222 rb_sys_fail(0);
223 }
224 switch (*m) {
225 case 'a':
226 ptr->flags |= STRIO_APPEND;
227 break;
228 case 'w':
229 rb_str_resize(string, 0);
230 break;
231 }
232 break;
233 case 1:
234 StringValue(string);
235 ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
236 break;
237 case 0:
238 string = rb_str_new("", 0);
239 ptr->flags = FMODE_READWRITE;
240 break;
241 }
242 ptr->string = string;
243 return self;
244 }
245
246 static VALUE
247 strio_finalize(self)
248 VALUE self;
249 {
250 struct StringIO *ptr = StringIO(self);
251 ptr->string = Qnil;
252 ptr->flags &= ~FMODE_READWRITE;
253 return self;
254 }
255
256 static VALUE
257 strio_false(self)
258 VALUE self;
259 {
260 StringIO(self);
261 return Qfalse;
262 }
263
264 static VALUE
265 strio_nil(self)
266 VALUE self;
267 {
268 StringIO(self);
269 return Qnil;
270 }
271
272 static VALUE
273 strio_self(self)
274 VALUE self;
275 {
276 StringIO(self);
277 return self;
278 }
279
280 static VALUE
281 strio_0(self)
282 VALUE self;
283 {
284 StringIO(self);
285 return INT2FIX(0);
286 }
287
288 static VALUE
289 strio_first(self, arg)
290 VALUE self, arg;
291 {
292 StringIO(self);
293 return arg;
294 }
295
296 static VALUE
297 strio_unimpl(argc, argv, self)
298 int argc;
299 VALUE *argv;
300 VALUE self;
301 {
302 StringIO(self);
303 rb_notimplement();
304 return Qnil;
305 }
306
307 static VALUE
308 strio_get_string(self)
309 VALUE self;
310 {
311 return StringIO(self)->string;
312 }
313
314 static VALUE
315 strio_set_string(self, string)
316 VALUE self, string;
317 {
318 struct StringIO *ptr = StringIO(self);
319
320 ptr->flags &= ~FMODE_READWRITE;
321 if (!NIL_P(string)) {
322 StringValue(string);
323 ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
324 }
325 ptr->pos = 0;
326 ptr->lineno = 0;
327 return ptr->string = string;
328 }
329
330 static VALUE
331 strio_close(self)
332 VALUE self;
333 {
334 struct StringIO *ptr = StringIO(self);
335 if (CLOSED(ptr)) {
336 rb_raise(rb_eIOError, "closed stream");
337 }
338 ptr->string = Qnil;
339 ptr->flags &= ~FMODE_READWRITE;
340 return self;
341 }
342
343 static VALUE
344 strio_close_read(self)
345 VALUE self;
346 {
347 struct StringIO *ptr = StringIO(self);
348 if (!READABLE(ptr)) {
349 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
350 }
351 if (!((ptr->flags &= ~FMODE_READABLE) & FMODE_READWRITE)) {
352 ptr->string = Qnil;
353 }
354 return self;
355 }
356
357 static VALUE
358 strio_close_write(self)
359 VALUE self;
360 {
361 struct StringIO *ptr = StringIO(self);
362 if (!WRITABLE(ptr)) {
363 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
364 }
365 if (!((ptr->flags &= ~FMODE_WRITABLE) & FMODE_READWRITE)) {
366 ptr->string = Qnil;
367 }
368 return self;
369 }
370
371 static VALUE
372 strio_closed(self)
373 VALUE self;
374 {
375 struct StringIO *ptr = StringIO(self);
376 if (!CLOSED(ptr)) return Qfalse;
377 return Qtrue;
378 }
379
380 static VALUE
381 strio_closed_read(self)
382 VALUE self;
383 {
384 struct StringIO *ptr = StringIO(self);
385 if (READABLE(ptr)) return Qfalse;
386 return Qtrue;
387 }
388
389 static VALUE
390 strio_closed_write(self)
391 VALUE self;
392 {
393 struct StringIO *ptr = StringIO(self);
394 if (WRITABLE(ptr)) return Qfalse;
395 return Qtrue;
396 }
397
398 static VALUE
399 strio_eof(self)
400 VALUE self;
401 {
402 struct StringIO *ptr = readable(StringIO(self));
403 if (ptr->pos < RSTRING(ptr->string)->len) return Qfalse;
404 return Qtrue;
405 }
406
407 static VALUE
408 strio_become(copy, orig)
409 VALUE copy, orig;
410 {
411 struct StringIO *ptr;
412
413 orig = rb_convert_type(orig, T_DATA, "StringIO", "to_strio");
414 if (copy == orig) return copy;
415 ptr = StringIO(orig);
416 if (check_strio(copy)) {
417 strio_free(DATA_PTR(copy));
418 }
419 DATA_PTR(copy) = ptr;
420 ++ptr->count;
421 return copy;
422 }
423
424 static VALUE
425 strio_get_lineno(self)
426 VALUE self;
427 {
428 return LONG2NUM(StringIO(self)->lineno);
429 }
430
431 static VALUE
432 strio_set_lineno(self, lineno)
433 VALUE self, lineno;
434 {
435 StringIO(self)->lineno = NUM2LONG(lineno);
436 return lineno;
437 }
438
439 #define strio_binmode strio_self
440
441 #define strio_fcntl strio_unimpl
442
443 #define strio_flush strio_self
444
445 #define strio_fsync strio_0
446
447 static VALUE
448 strio_reopen(argc, argv, self)
449 int argc;
450 VALUE *argv;
451 VALUE self;
452 {
453 rb_secure(4);
454 if (argc == 1 && TYPE(*argv) != T_STRING) {
455 return strio_become(self, *argv);
456 }
457 return strio_initialize(argc, argv, self);
458 }
459
460 static VALUE
461 strio_get_pos(self)
462 VALUE self;
463 {
464 return LONG2NUM(StringIO(self)->pos);
465 }
466
467 static VALUE
468 strio_set_pos(self, pos)
469 VALUE self;
470 VALUE pos;
471 {
472 struct StringIO *ptr = StringIO(self);
473 long p = NUM2LONG(pos);
474 if (p < 0) {
475 error_inval(0);
476 }
477 ptr->pos = p;
478 return pos;
479 }
480
481 static VALUE
482 strio_rewind(self)
483 VALUE self;
484 {
485 struct StringIO *ptr = StringIO(self);
486 ptr->pos = 0;
487 ptr->lineno = 0;
488 return INT2FIX(0);
489 }
490
491 static VALUE
492 strio_seek(argc, argv, self)
493 int argc;
494 VALUE *argv;
495 VALUE self;
496 {
497 VALUE whence;
498 struct StringIO *ptr = StringIO(self);
499 long offset;
500
501 rb_scan_args(argc, argv, "11", NULL, &whence);
502 offset = NUM2LONG(argv[0]);
503 switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
504 case 0:
505 break;
506 case 1:
507 offset += ptr->pos;
508 break;
509 case 2:
510 offset += RSTRING(ptr->string)->len;
511 break;
512 default:
513 rb_raise(rb_eArgError, "invalid whence %ld", NUM2LONG(whence));
514 }
515 if (offset < 0) {
516 error_inval(0);
517 }
518 ptr->pos = offset;
519 return INT2FIX(0);
520 }
521
522 static VALUE
523 strio_get_sync(self)
524 VALUE self;
525 {
526 StringIO(self);
527 return Qtrue;
528 }
529
530 #define strio_set_sync strio_first
531
532 #define strio_tell strio_get_pos
533
534 static VALUE
535 strio_each_byte(self)
536 VALUE self;
537 {
538 struct StringIO *ptr = readable(StringIO(self));
539 while (ptr->pos < RSTRING(ptr->string)->len) {
540 char c = RSTRING(ptr->string)->ptr[ptr->pos++];
541 rb_yield(CHR2FIX(c));
542 }
543 return Qnil;
544 }
545
546 static VALUE
547 strio_getc(self)
548 VALUE self;
549 {
550 struct StringIO *ptr = readable(StringIO(self));
551 int c;
552 if (ptr->pos >= RSTRING(ptr->string)->len) {
553 return Qnil;
554 }
555 c = RSTRING(ptr->string)->ptr[ptr->pos++];
556 return CHR2FIX(c);
557 }
558
559 static VALUE
560 strio_ungetc(self, ch)
561 VALUE self, ch;
562 {
563 struct StringIO *ptr = readable(StringIO(self));
564 int cc = NUM2INT(ch);
565 long len, pos = ptr->pos;
566
567 if (cc != EOF && pos > 0) {
568 if ((len = RSTRING(ptr->string)->len) < pos ||
569 (unsigned char)RSTRING(ptr->string)->ptr[pos - 1] !=
570 (unsigned char)cc) {
571 check_modifiable(ptr);
572 if (len < pos) {
573 rb_str_resize(ptr->string, pos);
574 MEMZERO(RSTRING(ptr->string)->ptr + len, char, pos - len - 1);
575 }
576 else {
577 rb_str_modify(ptr->string);
578 }
579 RSTRING(ptr->string)->ptr[pos - 1] = cc;
580 }
581 --ptr->pos;
582 }
583 return Qnil;
584 }
585
586 static VALUE
587 strio_readchar(self)
588 VALUE self;
589 {
590 VALUE c = strio_getc(self);
591 if (NIL_P(c)) rb_eof_error();
592 return c;
593 }
594
595 static void
596 bm_init_skip(skip, pat, m)
597 long *skip;
598 const char *pat;
599 long m;
600 {
601 int c;
602
603 for (c = 0; c < (1 << CHAR_BIT); c++) {
604 skip[c] = m;
605 }
606 while (--m) {
607 skip[(unsigned char)*pat++] = m;
608 }
609 }
610
611 static long
612 bm_search(little, llen, big, blen, skip)
613 const char *little;
614 long llen;
615 const char *big;
616 long blen;
617 const long *skip;
618 {
619 long i, j, k;
620
621 i = llen - 1;
622 while (i < blen) {
623 k = i;
624 j = llen - 1;
625 while (j >= 0 && big[k] == little[j]) {
626 k--;
627 j--;
628 }
629 if (j < 0) return k + 1;
630 i += skip[(unsigned char)big[i]];
631 }
632 return -1;
633 }
634
635 static VALUE
636 strio_gets_internal(argc, argv, ptr)
637 int argc;
638 VALUE *argv;
639 struct StringIO *ptr;
640 {
641 const char *s, *e, *p;
642 long n;
643 VALUE str;
644
645 if (argc == 0) {
646 str = rb_rs;
647 }
648 else {
649 rb_scan_args(argc, argv, "1", &str);
650 if (!NIL_P(str)) StringValue(str);
651 }
652
653 if (ptr->pos >= (n = RSTRING(ptr->string)->len)) return Qnil;
654 s = RSTRING(ptr->string)->ptr;
655 e = s + RSTRING(ptr->string)->len;
656 s += ptr->pos;
657 if (NIL_P(str)) {
658 str = rb_str_substr(ptr->string, ptr->pos, e - s);
659 }
660 else if ((n = RSTRING(str)->len) == 0) {
661 p = s;
662 while (*p == '\n') {
663 if (++p == e) return Qnil;
664 }
665 s = p;
666 while (p = memchr(p, '\n', e - p)) {
667 if (p == e) break;
668 if (*++p == '\n') {
669 e = p;
670 break;
671 }
672 }
673 str = rb_str_substr(ptr->string, s - RSTRING(ptr->string)->ptr, e - s);
674 }
675 else if (n == 1) {
676 if (p = memchr(s, RSTRING(str)->ptr[0], e - s)) {
677 e = p + 1;
678 }
679 str = rb_str_substr(ptr->string, ptr->pos, e - s);
680 }
681 else {
682 if (n < e - s) {
683 if (e - s < 1024) {
684 for (p = s; p + n <= e; ++p) {
685 if (MEMCMP(p, RSTRING(str)->ptr, char, n) == 0) {
686 e = p + n;
687 break;
688 }
689 }
690 }
691 else {
692 long skip[1 << CHAR_BIT], pos;
693 p = RSTRING(str)->ptr;
694 bm_init_skip(skip, p, n);
695 if ((pos = bm_search(p, n, s, e - s, skip)) >= 0) {
696 e = s + pos + n;
697 }
698 }
699 }
700 str = rb_str_substr(ptr->string, ptr->pos, e - s);
701 }
702 ptr->pos = e - RSTRING(ptr->string)->ptr;
703 ptr->lineno++;
704 rb_lastline_set(str);
705 return str;
706 }
707
708 static VALUE
709 strio_gets(argc, argv, self)
710 int argc;
711 VALUE *argv;
712 VALUE self;
713 {
714 return strio_gets_internal(argc, argv, readable(StringIO(self)));
715 }
716
717 static VALUE
718 strio_readline(argc, argv, self)
719 int argc;
720 VALUE *argv;
721 VALUE self;
722 {
723 VALUE line = strio_gets_internal(argc, argv, readable(StringIO(self)));
724 if (NIL_P(line)) rb_eof_error();
725 return line;
726 }
727
728 static VALUE
729 strio_each(argc, argv, self)
730 int argc;
731 VALUE *argv;
732 VALUE self;
733 {
734 struct StringIO *ptr = StringIO(self);
735 VALUE line;
736
737 while (!NIL_P(line = strio_gets_internal(argc, argv, readable(ptr)))) {
738 rb_yield(line);
739 }
740 return self;
741 }
742
743 static VALUE
744 strio_readlines(argc, argv, self)
745 int argc;
746 VALUE *argv;
747 VALUE self;
748 {
749 struct StringIO *ptr = StringIO(self);
750 VALUE ary = rb_ary_new(), line;
751 while (!NIL_P(line = strio_gets_internal(argc, argv, readable(ptr)))) {
752 rb_ary_push(ary, line);
753 }
754 return ary;
755 }
756
757 static VALUE
758 strio_write(self, str)
759 VALUE self, str;
760 {
761 struct StringIO *ptr = writable(StringIO(self));
762 long len;
763
764 if (TYPE(str) != T_STRING)
765 str = rb_obj_as_string(str);
766 len = RSTRING(str)->len;
767 if (!len) return INT2FIX(0);
768 check_modifiable(ptr);
769 if (ptr->flags & STRIO_APPEND) {
770 ptr->pos = RSTRING(ptr->string)->len;
771 }
772 if (ptr->pos == RSTRING(ptr->string)->len) {
773 rb_str_cat(ptr->string, RSTRING(str)->ptr, len);
774 }
775 else {
776 if (ptr->pos + len > RSTRING(ptr->string)->len) {
777 rb_str_resize(ptr->string, ptr->pos + len);
778 }
779 else {
780 rb_str_modify(ptr->string);
781 }
782 rb_str_update(ptr->string, ptr->pos, len, str);
783 }
784 ptr->pos += len;
785 return LONG2NUM(len);
786 }
787
788 #define strio_addstr rb_io_addstr
789
790 #define strio_print rb_io_print
791
792 #define strio_printf rb_io_printf
793
794 static VALUE
795 strio_putc(self, ch)
796 VALUE self, ch;
797 {
798 struct StringIO *ptr = writable(StringIO(self));
799 int c = NUM2CHR(ch);
800
801 check_modifiable(ptr);
802 if (ptr->flags & STRIO_APPEND) {
803 ptr->pos = RSTRING(ptr->string)->len;
804 }
805 if (ptr->pos >= RSTRING(ptr->string)->len) {
806 rb_str_resize(ptr->string, ptr->pos + 1);
807 }
808 else {
809 rb_str_modify(ptr->string);
810 }
811 RSTRING(ptr->string)->ptr[ptr->pos++] = c;
812 return ch;
813 }
814
815 #define strio_puts rb_io_puts
816
817 static VALUE
818 strio_read(argc, argv, self)
819 int argc;
820 VALUE *argv;
821 VALUE self;
822 {
823 struct StringIO *ptr = readable(StringIO(self));
824 VALUE str;
825 long len;
826
827 if (ptr->pos >= RSTRING(ptr->string)->len) {
828 return Qnil;
829 }
830 switch (argc) {
831 case 1:
832 if (!NIL_P(argv[0])) {
833 len = NUM2LONG(argv[0]);
834 break;
835 }
836
837 case 0:
838 len = RSTRING(ptr->string)->len - ptr->pos;
839 break;
840 default:
841 rb_raise(rb_eArgError, "wrong number arguments (%d for 0)", argc);
842 }
843 str = rb_str_substr(ptr->string, ptr->pos, len);
844 ptr->pos += len;
845 return str;
846 }
847
848 static VALUE
849 strio_sysread(argc, argv, self)
850 int argc;
851 VALUE *argv;
852 VALUE self;
853 {
854 VALUE val = strio_read(argc, argv, self);
855 if (NIL_P(val)) {
856 rb_eof_error();
857 }
858 return val;
859 }
860
861 #define strio_syswrite strio_write
862
863 #define strio_path rb_inspect
864
865 #define strio_isatty strio_false
866
867 #define strio_pid strio_nil
868
869 #define strio_fileno strio_nil
870
871 static VALUE
872 strio_size(self)
873 VALUE self;
874 {
875 VALUE string = StringIO(self)->string;
876 if (NIL_P(string)) {
877 rb_raise(rb_eIOError, "not opened");
878 }
879 return ULONG2NUM(RSTRING(string)->len);
880 }
881
882 static VALUE
883 strio_truncate(self, len)
884 VALUE self, len;
885 {
886 VALUE string = writable(StringIO(self))->string;
887 long l = NUM2LONG(len);
888 if (l < 0) {
889 error_inval("negative legnth");
890 }
891 rb_str_resize(string, l);
892 return len;
893 }
894
895 void
896 Init_stringio()
897 {
898 VALUE StringIO = rb_define_class("StringIO", rb_cData);
899 rb_define_singleton_method(StringIO, "allocate", strio_s_allocate, 0);
900 rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
901 rb_define_method(StringIO, "initialize", strio_initialize, -1);
902 rb_enable_super(StringIO, "initialize");
903 rb_define_method(StringIO, "become", strio_become, 1);
904 rb_define_method(StringIO, "reopen", strio_reopen, -1);
905
906 rb_define_method(StringIO, "string", strio_get_string, 0);
907 rb_define_method(StringIO, "string=", strio_set_string, 1);
908 rb_define_method(StringIO, "lineno", strio_get_lineno, 0);
909 rb_define_method(StringIO, "lineno=", strio_set_lineno, 1);
910
911 rb_define_method(StringIO, "binmode", strio_binmode, 0);
912 rb_define_method(StringIO, "close", strio_close, 0);
913 rb_define_method(StringIO, "close_read", strio_close_read, 0);
914 rb_define_method(StringIO, "close_write", strio_close_write, 0);
915 rb_define_method(StringIO, "closed?", strio_closed, 0);
916 rb_define_method(StringIO, "closed_read?", strio_closed_read, 0);
917 rb_define_method(StringIO, "closed_write?", strio_closed_write, 0);
918 rb_define_method(StringIO, "eof", strio_eof, 0);
919 rb_define_method(StringIO, "eof?", strio_eof, 0);
920 rb_define_method(StringIO, "fcntl", strio_fcntl, -1);
921 rb_define_method(StringIO, "flush", strio_flush, 0);
922 rb_define_method(StringIO, "fsync", strio_fsync, 0);
923 rb_define_method(StringIO, "pos", strio_get_pos, 0);
924 rb_define_method(StringIO, "pos=", strio_set_pos, 1);
925 rb_define_method(StringIO, "rewind", strio_rewind, 0);
926 rb_define_method(StringIO, "seek", strio_seek, -1);
927 rb_define_method(StringIO, "sync", strio_get_sync, 0);
928 rb_define_method(StringIO, "sync=", strio_set_sync, 1);
929 rb_define_method(StringIO, "tell", strio_tell, 0);
930 rb_define_method(StringIO, "path", strio_path, 0);
931
932 rb_define_method(StringIO, "each", strio_each, -1);
933 rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
934 rb_define_method(StringIO, "each_line", strio_each, -1);
935 rb_define_method(StringIO, "getc", strio_getc, 0);
936 rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
937 rb_define_method(StringIO, "readchar", strio_readchar, 0);
938 rb_define_method(StringIO, "gets", strio_gets, -1);
939 rb_define_method(StringIO, "readline", strio_readline, -1);
940 rb_define_method(StringIO, "readlines", strio_readlines, -1);
941 rb_define_method(StringIO, "read", strio_read, -1);
942 rb_define_method(StringIO, "sysread", strio_sysread, -1);
943
944 rb_define_method(StringIO, "write", strio_write, 1);
945 rb_define_method(StringIO, "<<", strio_addstr, 1);
946 rb_define_method(StringIO, "print", strio_print, -1);
947 rb_define_method(StringIO, "printf", strio_printf, -1);
948 rb_define_method(StringIO, "putc", strio_putc, 1);
949 rb_define_method(StringIO, "puts", strio_puts, -1);
950 rb_define_method(StringIO, "syswrite", strio_syswrite, 1);
951
952 rb_define_method(StringIO, "isatty", strio_isatty, 0);
953 rb_define_method(StringIO, "tty?", strio_isatty, 0);
954 rb_define_method(StringIO, "pid", strio_pid, 0);
955 rb_define_method(StringIO, "fileno", strio_fileno, 0);
956 rb_define_method(StringIO, "size", strio_size, 0);
957 rb_define_method(StringIO, "length", strio_size, 0);
958 rb_define_method(StringIO, "truncate", strio_truncate, 1);
959 }