00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ruby.h"
00015 #include "ruby/io.h"
00016 #include "ruby/encoding.h"
00017 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
00018 #include <fcntl.h>
00019 #elif defined(HAVE_SYS_FCNTL_H)
00020 #include <sys/fcntl.h>
00021 #endif
00022
00023 struct StringIO {
00024 VALUE string;
00025 long pos;
00026 long lineno;
00027 int flags;
00028 int count;
00029 };
00030
00031 static void strio_init(int, VALUE *, struct StringIO *, VALUE);
00032
00033 #define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
00034 #define error_inval(msg) (errno = EINVAL, rb_sys_fail(msg))
00035
00036 static struct StringIO *
00037 strio_alloc(void)
00038 {
00039 struct StringIO *ptr = ALLOC(struct StringIO);
00040 ptr->string = Qnil;
00041 ptr->pos = 0;
00042 ptr->lineno = 0;
00043 ptr->flags = 0;
00044 ptr->count = 1;
00045 return ptr;
00046 }
00047
00048 static void
00049 strio_mark(void *p)
00050 {
00051 struct StringIO *ptr = p;
00052 if (ptr) {
00053 rb_gc_mark(ptr->string);
00054 }
00055 }
00056
00057 static void
00058 strio_free(void *p)
00059 {
00060 struct StringIO *ptr = p;
00061 if (--ptr->count <= 0) {
00062 xfree(ptr);
00063 }
00064 }
00065
00066 static size_t
00067 strio_memsize(const void *p)
00068 {
00069 const struct StringIO *ptr = p;
00070 if (!ptr) return 0;
00071 return sizeof(struct StringIO);
00072 }
00073
00074 static const rb_data_type_t strio_data_type = {
00075 "strio",
00076 {
00077 strio_mark,
00078 strio_free,
00079 strio_memsize,
00080 },
00081 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
00082 };
00083
00084 #define check_strio(self) ((struct StringIO*)rb_check_typeddata((self), &strio_data_type))
00085
00086 static struct StringIO*
00087 get_strio(VALUE self)
00088 {
00089 struct StringIO *ptr = check_strio(rb_io_taint_check(self));
00090
00091 if (!ptr) {
00092 rb_raise(rb_eIOError, "uninitialized stream");
00093 }
00094 return ptr;
00095 }
00096
00097 static VALUE
00098 strio_substr(struct StringIO *ptr, long pos, long len)
00099 {
00100 VALUE str = ptr->string;
00101 rb_encoding *enc = rb_enc_get(str);
00102 long rlen = RSTRING_LEN(str) - pos;
00103
00104 if (len > rlen) len = rlen;
00105 if (len < 0) len = 0;
00106 if (len == 0) return rb_str_new(0,0);
00107 return rb_enc_str_new(RSTRING_PTR(str)+pos, len, enc);
00108 }
00109
00110 #define StringIO(obj) get_strio(obj)
00111
00112 #define STRIO_READABLE FL_USER4
00113 #define STRIO_WRITABLE FL_USER5
00114 #define STRIO_READWRITE (STRIO_READABLE|STRIO_WRITABLE)
00115 typedef char strio_flags_check[(STRIO_READABLE/FMODE_READABLE == STRIO_WRITABLE/FMODE_WRITABLE) * 2 - 1];
00116 #define STRIO_MODE_SET_P(strio, mode) \
00117 ((RBASIC(strio)->flags & STRIO_##mode) && \
00118 ((struct StringIO*)DATA_PTR(strio))->flags & FMODE_##mode)
00119 #define CLOSED(strio) (!STRIO_MODE_SET_P(strio, READWRITE))
00120 #define READABLE(strio) STRIO_MODE_SET_P(strio, READABLE)
00121 #define WRITABLE(strio) STRIO_MODE_SET_P(strio, WRITABLE)
00122
00123 static VALUE sym_exception;
00124
00125 static struct StringIO*
00126 readable(VALUE strio)
00127 {
00128 struct StringIO *ptr = StringIO(strio);
00129 if (!READABLE(strio)) {
00130 rb_raise(rb_eIOError, "not opened for reading");
00131 }
00132 return ptr;
00133 }
00134
00135 static struct StringIO*
00136 writable(VALUE strio)
00137 {
00138 struct StringIO *ptr = StringIO(strio);
00139 if (!WRITABLE(strio)) {
00140 rb_raise(rb_eIOError, "not opened for writing");
00141 }
00142 if (!OBJ_TAINTED(ptr->string)) {
00143 }
00144 return ptr;
00145 }
00146
00147 static void
00148 check_modifiable(struct StringIO *ptr)
00149 {
00150 if (OBJ_FROZEN(ptr->string)) {
00151 rb_raise(rb_eIOError, "not modifiable string");
00152 }
00153 }
00154
00155 static VALUE
00156 strio_s_allocate(VALUE klass)
00157 {
00158 return TypedData_Wrap_Struct(klass, &strio_data_type, 0);
00159 }
00160
00161
00162
00163
00164
00165
00166 static VALUE
00167 strio_initialize(int argc, VALUE *argv, VALUE self)
00168 {
00169 struct StringIO *ptr = check_strio(self);
00170
00171 if (!ptr) {
00172 DATA_PTR(self) = ptr = strio_alloc();
00173 }
00174 rb_call_super(0, 0);
00175 strio_init(argc, argv, ptr, self);
00176 return self;
00177 }
00178
00179 static void
00180 strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
00181 {
00182 VALUE string, mode;
00183 int trunc = 0;
00184
00185 switch (rb_scan_args(argc, argv, "02", &string, &mode)) {
00186 case 2:
00187 if (FIXNUM_P(mode)) {
00188 int flags = FIX2INT(mode);
00189 ptr->flags = rb_io_modenum_flags(flags);
00190 trunc = flags & O_TRUNC;
00191 }
00192 else {
00193 const char *m = StringValueCStr(mode);
00194 ptr->flags = rb_io_mode_flags(m);
00195 trunc = *m == 'w';
00196 }
00197 StringValue(string);
00198 if ((ptr->flags & FMODE_WRITABLE) && OBJ_FROZEN(string)) {
00199 errno = EACCES;
00200 rb_sys_fail(0);
00201 }
00202 if (trunc) {
00203 rb_str_resize(string, 0);
00204 }
00205 break;
00206 case 1:
00207 StringValue(string);
00208 ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
00209 break;
00210 case 0:
00211 string = rb_enc_str_new("", 0, rb_default_external_encoding());
00212 ptr->flags = FMODE_READWRITE;
00213 break;
00214 }
00215 ptr->string = string;
00216 ptr->pos = 0;
00217 ptr->lineno = 0;
00218 RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE);
00219 }
00220
00221 static VALUE
00222 strio_finalize(VALUE self)
00223 {
00224 struct StringIO *ptr = StringIO(self);
00225 ptr->string = Qnil;
00226 ptr->flags &= ~FMODE_READWRITE;
00227 return self;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237 static VALUE
00238 strio_s_open(int argc, VALUE *argv, VALUE klass)
00239 {
00240 VALUE obj = rb_class_new_instance(argc, argv, klass);
00241 if (!rb_block_given_p()) return obj;
00242 return rb_ensure(rb_yield, obj, strio_finalize, obj);
00243 }
00244
00245
00246
00247
00248 static VALUE
00249 strio_false(VALUE self)
00250 {
00251 StringIO(self);
00252 return Qfalse;
00253 }
00254
00255
00256
00257
00258 static VALUE
00259 strio_nil(VALUE self)
00260 {
00261 StringIO(self);
00262 return Qnil;
00263 }
00264
00265
00266
00267
00268 static VALUE
00269 strio_self(VALUE self)
00270 {
00271 StringIO(self);
00272 return self;
00273 }
00274
00275
00276
00277
00278 static VALUE
00279 strio_0(VALUE self)
00280 {
00281 StringIO(self);
00282 return INT2FIX(0);
00283 }
00284
00285
00286
00287
00288 static VALUE
00289 strio_first(VALUE self, VALUE arg)
00290 {
00291 StringIO(self);
00292 return arg;
00293 }
00294
00295
00296
00297
00298 static VALUE
00299 strio_unimpl(int argc, VALUE *argv, VALUE self)
00300 {
00301 StringIO(self);
00302 rb_notimplement();
00303
00304 UNREACHABLE;
00305 }
00306
00307
00308
00309
00310
00311
00312 static VALUE
00313 strio_get_string(VALUE self)
00314 {
00315 return StringIO(self)->string;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324 static VALUE
00325 strio_set_string(VALUE self, VALUE string)
00326 {
00327 struct StringIO *ptr = StringIO(self);
00328
00329 rb_io_taint_check(self);
00330 ptr->flags &= ~FMODE_READWRITE;
00331 StringValue(string);
00332 ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
00333 ptr->pos = 0;
00334 ptr->lineno = 0;
00335 return ptr->string = string;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345 static VALUE
00346 strio_close(VALUE self)
00347 {
00348 StringIO(self);
00349 if (CLOSED(self)) {
00350 rb_raise(rb_eIOError, "closed stream");
00351 }
00352 RBASIC(self)->flags &= ~STRIO_READWRITE;
00353 return Qnil;
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363 static VALUE
00364 strio_close_read(VALUE self)
00365 {
00366 StringIO(self);
00367 if (!READABLE(self)) {
00368 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
00369 }
00370 RBASIC(self)->flags &= ~STRIO_READABLE;
00371 return Qnil;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381 static VALUE
00382 strio_close_write(VALUE self)
00383 {
00384 StringIO(self);
00385 if (!WRITABLE(self)) {
00386 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
00387 }
00388 RBASIC(self)->flags &= ~STRIO_WRITABLE;
00389 return Qnil;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398 static VALUE
00399 strio_closed(VALUE self)
00400 {
00401 StringIO(self);
00402 if (!CLOSED(self)) return Qfalse;
00403 return Qtrue;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412 static VALUE
00413 strio_closed_read(VALUE self)
00414 {
00415 StringIO(self);
00416 if (READABLE(self)) return Qfalse;
00417 return Qtrue;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426 static VALUE
00427 strio_closed_write(VALUE self)
00428 {
00429 StringIO(self);
00430 if (WRITABLE(self)) return Qfalse;
00431 return Qtrue;
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 static VALUE
00443 strio_eof(VALUE self)
00444 {
00445 struct StringIO *ptr = readable(self);
00446 if (ptr->pos < RSTRING_LEN(ptr->string)) return Qfalse;
00447 return Qtrue;
00448 }
00449
00450
00451 static VALUE
00452 strio_copy(VALUE copy, VALUE orig)
00453 {
00454 struct StringIO *ptr;
00455
00456 orig = rb_convert_type(orig, T_DATA, "StringIO", "to_strio");
00457 if (copy == orig) return copy;
00458 ptr = StringIO(orig);
00459 if (check_strio(copy)) {
00460 strio_free(DATA_PTR(copy));
00461 }
00462 DATA_PTR(copy) = ptr;
00463 OBJ_INFECT(copy, orig);
00464 RBASIC(copy)->flags &= ~STRIO_READWRITE;
00465 RBASIC(copy)->flags |= RBASIC(orig)->flags & STRIO_READWRITE;
00466 ++ptr->count;
00467 return copy;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 static VALUE
00481 strio_get_lineno(VALUE self)
00482 {
00483 return LONG2NUM(StringIO(self)->lineno);
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493 static VALUE
00494 strio_set_lineno(VALUE self, VALUE lineno)
00495 {
00496 StringIO(self)->lineno = NUM2LONG(lineno);
00497 return lineno;
00498 }
00499
00500 #define strio_binmode strio_self
00501
00502 #define strio_fcntl strio_unimpl
00503
00504 #define strio_flush strio_self
00505
00506 #define strio_fsync strio_0
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 static VALUE
00517 strio_reopen(int argc, VALUE *argv, VALUE self)
00518 {
00519 rb_io_taint_check(self);
00520 if (argc == 1 && !RB_TYPE_P(*argv, T_STRING)) {
00521 return strio_copy(self, *argv);
00522 }
00523 strio_init(argc, argv, StringIO(self), self);
00524 return self;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534 static VALUE
00535 strio_get_pos(VALUE self)
00536 {
00537 return LONG2NUM(StringIO(self)->pos);
00538 }
00539
00540
00541
00542
00543
00544
00545
00546 static VALUE
00547 strio_set_pos(VALUE self, VALUE pos)
00548 {
00549 struct StringIO *ptr = StringIO(self);
00550 long p = NUM2LONG(pos);
00551 if (p < 0) {
00552 error_inval(0);
00553 }
00554 ptr->pos = p;
00555 return pos;
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565 static VALUE
00566 strio_rewind(VALUE self)
00567 {
00568 struct StringIO *ptr = StringIO(self);
00569 ptr->pos = 0;
00570 ptr->lineno = 0;
00571 return INT2FIX(0);
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581 static VALUE
00582 strio_seek(int argc, VALUE *argv, VALUE self)
00583 {
00584 VALUE whence;
00585 struct StringIO *ptr = StringIO(self);
00586 long offset;
00587
00588 rb_scan_args(argc, argv, "11", NULL, &whence);
00589 offset = NUM2LONG(argv[0]);
00590 if (CLOSED(self)) {
00591 rb_raise(rb_eIOError, "closed stream");
00592 }
00593 switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
00594 case 0:
00595 break;
00596 case 1:
00597 offset += ptr->pos;
00598 break;
00599 case 2:
00600 offset += RSTRING_LEN(ptr->string);
00601 break;
00602 default:
00603 error_inval("invalid whence");
00604 }
00605 if (offset < 0) {
00606 error_inval(0);
00607 }
00608 ptr->pos = offset;
00609 return INT2FIX(0);
00610 }
00611
00612
00613
00614
00615
00616
00617
00618 static VALUE
00619 strio_get_sync(VALUE self)
00620 {
00621 StringIO(self);
00622 return Qtrue;
00623 }
00624
00625 #define strio_set_sync strio_first
00626
00627 #define strio_tell strio_get_pos
00628
00629
00630
00631
00632
00633
00634
00635
00636 static VALUE
00637 strio_each_byte(VALUE self)
00638 {
00639 struct StringIO *ptr = readable(self);
00640
00641 RETURN_ENUMERATOR(self, 0, 0);
00642
00643 while (ptr->pos < RSTRING_LEN(ptr->string)) {
00644 char c = RSTRING_PTR(ptr->string)[ptr->pos++];
00645 rb_yield(CHR2FIX(c));
00646 }
00647 return self;
00648 }
00649
00650
00651
00652
00653 static VALUE
00654 strio_bytes(VALUE self)
00655 {
00656 rb_warn("StringIO#bytes is deprecated; use #each_byte instead");
00657 if (!rb_block_given_p())
00658 return rb_enumeratorize(self, ID2SYM(rb_intern("each_byte")), 0, 0);
00659 return strio_each_byte(self);
00660 }
00661
00662
00663
00664
00665
00666
00667
00668 static VALUE
00669 strio_getc(VALUE self)
00670 {
00671 struct StringIO *ptr = readable(self);
00672 rb_encoding *enc = rb_enc_get(ptr->string);
00673 int len;
00674 char *p;
00675
00676 if (ptr->pos >= RSTRING_LEN(ptr->string)) {
00677 return Qnil;
00678 }
00679 p = RSTRING_PTR(ptr->string)+ptr->pos;
00680 len = rb_enc_mbclen(p, RSTRING_END(ptr->string), enc);
00681 ptr->pos += len;
00682 return rb_enc_str_new(p, len, rb_enc_get(ptr->string));
00683 }
00684
00685
00686
00687
00688
00689
00690
00691 static VALUE
00692 strio_getbyte(VALUE self)
00693 {
00694 struct StringIO *ptr = readable(self);
00695 int c;
00696 if (ptr->pos >= RSTRING_LEN(ptr->string)) {
00697 return Qnil;
00698 }
00699 c = RSTRING_PTR(ptr->string)[ptr->pos++];
00700 return CHR2FIX(c);
00701 }
00702
00703 static void
00704 strio_extend(struct StringIO *ptr, long pos, long len)
00705 {
00706 long olen;
00707
00708 check_modifiable(ptr);
00709 olen = RSTRING_LEN(ptr->string);
00710 if (pos + len > olen) {
00711 rb_str_resize(ptr->string, pos + len);
00712 if (pos > olen)
00713 MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen);
00714 }
00715 else {
00716 rb_str_modify(ptr->string);
00717 }
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 static VALUE
00730 strio_ungetc(VALUE self, VALUE c)
00731 {
00732 struct StringIO *ptr = readable(self);
00733 long lpos, clen;
00734 char *p, *pend;
00735 rb_encoding *enc, *enc2;
00736
00737 if (NIL_P(c)) return Qnil;
00738 check_modifiable(ptr);
00739 if (FIXNUM_P(c)) {
00740 int cc = FIX2INT(c);
00741 char buf[16];
00742
00743 enc = rb_enc_get(ptr->string);
00744 rb_enc_mbcput(cc, buf, enc);
00745 c = rb_enc_str_new(buf, rb_enc_codelen(cc, enc), enc);
00746 }
00747 else {
00748 SafeStringValue(c);
00749 enc = rb_enc_get(ptr->string);
00750 enc2 = rb_enc_get(c);
00751 if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
00752 c = rb_str_conv_enc(c, enc2, enc);
00753 }
00754 }
00755 if (RSTRING_LEN(ptr->string) < ptr->pos) {
00756 long len = RSTRING_LEN(ptr->string);
00757 rb_str_resize(ptr->string, ptr->pos - 1);
00758 memset(RSTRING_PTR(ptr->string) + len, 0, ptr->pos - len - 1);
00759 rb_str_concat(ptr->string, c);
00760 ptr->pos--;
00761 }
00762 else {
00763
00764 lpos = 0; p = RSTRING_PTR(ptr->string); pend = p + ptr->pos;
00765 for (;;) {
00766 clen = rb_enc_mbclen(p, pend, enc);
00767 if (p+clen >= pend) break;
00768 p += clen;
00769 lpos++;
00770 }
00771 clen = p - RSTRING_PTR(ptr->string);
00772 rb_str_update(ptr->string, lpos, ptr->pos ? 1 : 0, c);
00773 ptr->pos = clen;
00774 }
00775
00776 return Qnil;
00777 }
00778
00779
00780
00781
00782
00783
00784
00785 static VALUE
00786 strio_ungetbyte(VALUE self, VALUE c)
00787 {
00788 struct StringIO *ptr = readable(self);
00789 char buf[1], *cp = buf;
00790 long pos = ptr->pos, cl = 1;
00791 VALUE str = ptr->string;
00792
00793 if (NIL_P(c)) return Qnil;
00794 if (FIXNUM_P(c)) {
00795 buf[0] = (char)FIX2INT(c);
00796 }
00797 else {
00798 SafeStringValue(c);
00799 cp = RSTRING_PTR(c);
00800 cl = RSTRING_LEN(c);
00801 if (cl == 0) return Qnil;
00802 }
00803 check_modifiable(ptr);
00804 rb_str_modify(str);
00805 if (cl > pos) {
00806 char *s;
00807 long rest = RSTRING_LEN(str) - pos;
00808 rb_str_resize(str, rest + cl);
00809 s = RSTRING_PTR(str);
00810 memmove(s + cl, s + pos, rest);
00811 pos = 0;
00812 }
00813 else {
00814 pos -= cl;
00815 }
00816 memcpy(RSTRING_PTR(str) + pos, cp, cl);
00817 ptr->pos = pos;
00818 RB_GC_GUARD(c);
00819 return Qnil;
00820 }
00821
00822
00823
00824
00825
00826
00827
00828 static VALUE
00829 strio_readchar(VALUE self)
00830 {
00831 VALUE c = rb_funcall2(self, rb_intern("getc"), 0, 0);
00832 if (NIL_P(c)) rb_eof_error();
00833 return c;
00834 }
00835
00836
00837
00838
00839
00840
00841
00842 static VALUE
00843 strio_readbyte(VALUE self)
00844 {
00845 VALUE c = rb_funcall2(self, rb_intern("getbyte"), 0, 0);
00846 if (NIL_P(c)) rb_eof_error();
00847 return c;
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857 static VALUE
00858 strio_each_char(VALUE self)
00859 {
00860 VALUE c;
00861
00862 RETURN_ENUMERATOR(self, 0, 0);
00863
00864 while (!NIL_P(c = strio_getc(self))) {
00865 rb_yield(c);
00866 }
00867 return self;
00868 }
00869
00870
00871
00872
00873 static VALUE
00874 strio_chars(VALUE self)
00875 {
00876 rb_warn("StringIO#chars is deprecated; use #each_char instead");
00877 if (!rb_block_given_p())
00878 return rb_enumeratorize(self, ID2SYM(rb_intern("each_char")), 0, 0);
00879 return strio_each_char(self);
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889 static VALUE
00890 strio_each_codepoint(VALUE self)
00891 {
00892 struct StringIO *ptr;
00893 rb_encoding *enc;
00894 unsigned int c;
00895 int n;
00896
00897 RETURN_ENUMERATOR(self, 0, 0);
00898
00899 ptr = readable(self);
00900 enc = rb_enc_get(ptr->string);
00901 for (;;) {
00902 if (ptr->pos >= RSTRING_LEN(ptr->string)) {
00903 return self;
00904 }
00905
00906 c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
00907 RSTRING_END(ptr->string), &n, enc);
00908 rb_yield(UINT2NUM(c));
00909 ptr->pos += n;
00910 }
00911 return self;
00912 }
00913
00914
00915
00916
00917 static VALUE
00918 strio_codepoints(VALUE self)
00919 {
00920 rb_warn("StringIO#codepoints is deprecated; use #each_codepoint instead");
00921 if (!rb_block_given_p())
00922 return rb_enumeratorize(self, ID2SYM(rb_intern("each_codepoint")), 0, 0);
00923 return strio_each_codepoint(self);
00924 }
00925
00926
00927 static void
00928 bm_init_skip(long *skip, const char *pat, long m)
00929 {
00930 int c;
00931
00932 for (c = 0; c < (1 << CHAR_BIT); c++) {
00933 skip[c] = m;
00934 }
00935 while (--m) {
00936 skip[(unsigned char)*pat++] = m;
00937 }
00938 }
00939
00940 static long
00941 bm_search(const char *little, long llen, const char *big, long blen, const long *skip)
00942 {
00943 long i, j, k;
00944
00945 i = llen - 1;
00946 while (i < blen) {
00947 k = i;
00948 j = llen - 1;
00949 while (j >= 0 && big[k] == little[j]) {
00950 k--;
00951 j--;
00952 }
00953 if (j < 0) return k + 1;
00954 i += skip[(unsigned char)big[i]];
00955 }
00956 return -1;
00957 }
00958
00959 static VALUE
00960 strio_getline(int argc, VALUE *argv, struct StringIO *ptr)
00961 {
00962 const char *s, *e, *p;
00963 long n, limit = 0;
00964 VALUE str, lim;
00965
00966 rb_scan_args(argc, argv, "02", &str, &lim);
00967 switch (argc) {
00968 case 0:
00969 str = rb_rs;
00970 break;
00971
00972 case 1:
00973 if (!NIL_P(str) && !RB_TYPE_P(str, T_STRING)) {
00974 VALUE tmp = rb_check_string_type(str);
00975 if (NIL_P(tmp)) {
00976 limit = NUM2LONG(str);
00977 if (limit == 0) return rb_str_new(0,0);
00978 str = rb_rs;
00979 }
00980 else {
00981 str = tmp;
00982 }
00983 }
00984 break;
00985
00986 case 2:
00987 if (!NIL_P(str)) StringValue(str);
00988 if (!NIL_P(lim)) limit = NUM2LONG(lim);
00989 break;
00990 }
00991
00992 if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
00993 return Qnil;
00994 }
00995 s = RSTRING_PTR(ptr->string);
00996 e = s + RSTRING_LEN(ptr->string);
00997 s += ptr->pos;
00998 if (limit > 0 && s + limit < e) {
00999 e = rb_enc_right_char_head(s, s + limit, e, rb_enc_get(ptr->string));
01000 }
01001 if (NIL_P(str)) {
01002 str = strio_substr(ptr, ptr->pos, e - s);
01003 }
01004 else if ((n = RSTRING_LEN(str)) == 0) {
01005 p = s;
01006 while (*p == '\n') {
01007 if (++p == e) {
01008 return Qnil;
01009 }
01010 }
01011 s = p;
01012 while ((p = memchr(p, '\n', e - p)) && (p != e)) {
01013 if (*++p == '\n') {
01014 e = p + 1;
01015 break;
01016 }
01017 }
01018 str = strio_substr(ptr, s - RSTRING_PTR(ptr->string), e - s);
01019 }
01020 else if (n == 1) {
01021 if ((p = memchr(s, RSTRING_PTR(str)[0], e - s)) != 0) {
01022 e = p + 1;
01023 }
01024 str = strio_substr(ptr, ptr->pos, e - s);
01025 }
01026 else {
01027 if (n < e - s) {
01028 if (e - s < 1024) {
01029 for (p = s; p + n <= e; ++p) {
01030 if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
01031 e = p + n;
01032 break;
01033 }
01034 }
01035 }
01036 else {
01037 long skip[1 << CHAR_BIT], pos;
01038 p = RSTRING_PTR(str);
01039 bm_init_skip(skip, p, n);
01040 if ((pos = bm_search(p, n, s, e - s, skip)) >= 0) {
01041 e = s + pos + n;
01042 }
01043 }
01044 }
01045 str = strio_substr(ptr, ptr->pos, e - s);
01046 }
01047 ptr->pos = e - RSTRING_PTR(ptr->string);
01048 ptr->lineno++;
01049 return str;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 static VALUE
01061 strio_gets(int argc, VALUE *argv, VALUE self)
01062 {
01063 VALUE str = strio_getline(argc, argv, readable(self));
01064
01065 rb_lastline_set(str);
01066 return str;
01067 }
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077 static VALUE
01078 strio_readline(int argc, VALUE *argv, VALUE self)
01079 {
01080 VALUE line = rb_funcall2(self, rb_intern("gets"), argc, argv);
01081 if (NIL_P(line)) rb_eof_error();
01082 return line;
01083 }
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099 static VALUE
01100 strio_each(int argc, VALUE *argv, VALUE self)
01101 {
01102 VALUE line;
01103
01104 StringIO(self);
01105 RETURN_ENUMERATOR(self, argc, argv);
01106
01107 if (argc > 0 && !NIL_P(argv[argc-1]) && NIL_P(rb_check_string_type(argv[argc-1])) &&
01108 NUM2LONG(argv[argc-1]) == 0) {
01109 rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
01110 }
01111
01112 while (!NIL_P(line = strio_getline(argc, argv, readable(self)))) {
01113 rb_yield(line);
01114 }
01115 return self;
01116 }
01117
01118
01119
01120
01121 static VALUE
01122 strio_lines(int argc, VALUE *argv, VALUE self)
01123 {
01124 rb_warn("StringIO#lines is deprecated; use #each_line instead");
01125 if (!rb_block_given_p())
01126 return rb_enumeratorize(self, ID2SYM(rb_intern("each_line")), argc, argv);
01127 return strio_each(argc, argv, self);
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138 static VALUE
01139 strio_readlines(int argc, VALUE *argv, VALUE self)
01140 {
01141 VALUE ary, line;
01142
01143 StringIO(self);
01144 ary = rb_ary_new();
01145 if (argc > 0 && !NIL_P(argv[argc-1]) && NIL_P(rb_check_string_type(argv[argc-1])) &&
01146 NUM2LONG(argv[argc-1]) == 0) {
01147 rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
01148 }
01149
01150 while (!NIL_P(line = strio_getline(argc, argv, readable(self)))) {
01151 rb_ary_push(ary, line);
01152 }
01153 return ary;
01154 }
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 static VALUE
01167 strio_write(VALUE self, VALUE str)
01168 {
01169 struct StringIO *ptr = writable(self);
01170 long len, olen;
01171 rb_encoding *enc, *enc2;
01172 rb_encoding *const ascii8bit = rb_ascii8bit_encoding();
01173
01174 if (!RB_TYPE_P(str, T_STRING))
01175 str = rb_obj_as_string(str);
01176 enc = rb_enc_get(ptr->string);
01177 enc2 = rb_enc_get(str);
01178 if (enc != enc2 && enc != ascii8bit) {
01179 str = rb_str_conv_enc(str, enc2, enc);
01180 }
01181 len = RSTRING_LEN(str);
01182 if (len == 0) return INT2FIX(0);
01183 check_modifiable(ptr);
01184 olen = RSTRING_LEN(ptr->string);
01185 if (ptr->flags & FMODE_APPEND) {
01186 ptr->pos = olen;
01187 }
01188 if (ptr->pos == olen) {
01189 if (enc == ascii8bit || enc2 == ascii8bit) {
01190 rb_enc_str_buf_cat(ptr->string, RSTRING_PTR(str), len, enc);
01191 OBJ_INFECT(ptr->string, str);
01192 }
01193 else {
01194 rb_str_buf_append(ptr->string, str);
01195 }
01196 }
01197 else {
01198 strio_extend(ptr, ptr->pos, len);
01199 memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
01200 OBJ_INFECT(ptr->string, str);
01201 }
01202 OBJ_INFECT(ptr->string, self);
01203 RB_GC_GUARD(str);
01204 ptr->pos += len;
01205 return LONG2NUM(len);
01206 }
01207
01208
01209
01210
01211
01212
01213
01214 #define strio_addstr rb_io_addstr
01215
01216
01217
01218
01219
01220
01221
01222
01223 #define strio_print rb_io_print
01224
01225
01226
01227
01228
01229
01230
01231 #define strio_printf rb_io_printf
01232
01233
01234
01235
01236
01237
01238
01239 static VALUE
01240 strio_putc(VALUE self, VALUE ch)
01241 {
01242 struct StringIO *ptr = writable(self);
01243 VALUE str;
01244
01245 check_modifiable(ptr);
01246 if (RB_TYPE_P(ch, T_STRING)) {
01247 str = rb_str_substr(ch, 0, 1);
01248 }
01249 else {
01250 char c = NUM2CHR(ch);
01251 str = rb_str_new(&c, 1);
01252 }
01253 strio_write(self, str);
01254 return ch;
01255 }
01256
01257
01258
01259
01260
01261
01262
01263 #define strio_puts rb_io_puts
01264
01265
01266
01267
01268
01269
01270
01271 static VALUE
01272 strio_read(int argc, VALUE *argv, VALUE self)
01273 {
01274 struct StringIO *ptr = readable(self);
01275 VALUE str = Qnil;
01276 long len;
01277 int binary = 0;
01278
01279 switch (argc) {
01280 case 2:
01281 str = argv[1];
01282 if (!NIL_P(str)) {
01283 StringValue(str);
01284 rb_str_modify(str);
01285 }
01286 case 1:
01287 if (!NIL_P(argv[0])) {
01288 len = NUM2LONG(argv[0]);
01289 if (len < 0) {
01290 rb_raise(rb_eArgError, "negative length %ld given", len);
01291 }
01292 if (len > 0 && ptr->pos >= RSTRING_LEN(ptr->string)) {
01293 if (!NIL_P(str)) rb_str_resize(str, 0);
01294 return Qnil;
01295 }
01296 binary = 1;
01297 break;
01298 }
01299
01300 case 0:
01301 len = RSTRING_LEN(ptr->string);
01302 if (len <= ptr->pos) {
01303 if (NIL_P(str)) {
01304 str = rb_str_new(0, 0);
01305 }
01306 else {
01307 rb_str_resize(str, 0);
01308 }
01309 return str;
01310 }
01311 else {
01312 len -= ptr->pos;
01313 }
01314 break;
01315 default:
01316 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
01317 }
01318 if (NIL_P(str)) {
01319 str = strio_substr(ptr, ptr->pos, len);
01320 if (binary) rb_enc_associate(str, rb_ascii8bit_encoding());
01321 }
01322 else {
01323 long rest = RSTRING_LEN(ptr->string) - ptr->pos;
01324 if (len > rest) len = rest;
01325 rb_str_resize(str, len);
01326 MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
01327 if (binary)
01328 rb_enc_associate(str, rb_ascii8bit_encoding());
01329 else
01330 rb_enc_copy(str, ptr->string);
01331 }
01332 ptr->pos += RSTRING_LEN(str);
01333 return str;
01334 }
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344 static VALUE
01345 strio_sysread(int argc, VALUE *argv, VALUE self)
01346 {
01347 VALUE val = rb_funcall2(self, rb_intern("read"), argc, argv);
01348 if (NIL_P(val)) {
01349 rb_eof_error();
01350 }
01351 return val;
01352 }
01353
01354
01355
01356
01357
01358
01359
01360
01361 static VALUE
01362 strio_read_nonblock(int argc, VALUE *argv, VALUE self)
01363 {
01364 VALUE opts = Qnil, val;
01365 int no_exception = 0;
01366
01367 rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
01368
01369 if (!NIL_P(opts)) {
01370 argc--;
01371
01372 if (Qfalse == rb_hash_aref(opts, sym_exception))
01373 no_exception = 1;
01374 }
01375
01376 val = strio_read(argc, argv, self);
01377 if (NIL_P(val)) {
01378 if (no_exception)
01379 return Qnil;
01380 else
01381 rb_eof_error();
01382 }
01383
01384 return val;
01385 }
01386
01387 #define strio_syswrite rb_io_write
01388
01389 static VALUE
01390 strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
01391 {
01392 VALUE str;
01393
01394 rb_scan_args(argc, argv, "10:", &str, NULL);
01395 return strio_syswrite(self, str);
01396 }
01397
01398 #define strio_isatty strio_false
01399
01400 #define strio_pid strio_nil
01401
01402 #define strio_fileno strio_nil
01403
01404
01405
01406
01407
01408
01409
01410
01411 static VALUE
01412 strio_size(VALUE self)
01413 {
01414 VALUE string = StringIO(self)->string;
01415 if (NIL_P(string)) {
01416 rb_raise(rb_eIOError, "not opened");
01417 }
01418 return ULONG2NUM(RSTRING_LEN(string));
01419 }
01420
01421
01422
01423
01424
01425
01426
01427
01428 static VALUE
01429 strio_truncate(VALUE self, VALUE len)
01430 {
01431 VALUE string = writable(self)->string;
01432 long l = NUM2LONG(len);
01433 long plen = RSTRING_LEN(string);
01434 if (l < 0) {
01435 error_inval("negative length");
01436 }
01437 rb_str_resize(string, l);
01438 if (plen < l) {
01439 MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
01440 }
01441 return len;
01442 }
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452 static VALUE
01453 strio_external_encoding(VALUE self)
01454 {
01455 return rb_enc_from_encoding(rb_enc_get(StringIO(self)->string));
01456 }
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466 static VALUE
01467 strio_internal_encoding(VALUE self)
01468 {
01469 return Qnil;
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482 static VALUE
01483 strio_set_encoding(int argc, VALUE *argv, VALUE self)
01484 {
01485 rb_encoding* enc;
01486 VALUE str = StringIO(self)->string;
01487 VALUE ext_enc, int_enc, opt;
01488
01489 argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt);
01490
01491 if (NIL_P(ext_enc)) {
01492 enc = rb_default_external_encoding();
01493 }
01494 else {
01495 enc = rb_to_encoding(ext_enc);
01496 }
01497 rb_enc_associate(str, enc);
01498 return self;
01499 }
01500
01501
01502
01503
01504 void
01505 Init_stringio()
01506 {
01507 VALUE StringIO = rb_define_class("StringIO", rb_cData);
01508
01509 rb_include_module(StringIO, rb_mEnumerable);
01510 rb_define_alloc_func(StringIO, strio_s_allocate);
01511 rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
01512 rb_define_method(StringIO, "initialize", strio_initialize, -1);
01513 rb_define_method(StringIO, "initialize_copy", strio_copy, 1);
01514 rb_define_method(StringIO, "reopen", strio_reopen, -1);
01515
01516 rb_define_method(StringIO, "string", strio_get_string, 0);
01517 rb_define_method(StringIO, "string=", strio_set_string, 1);
01518 rb_define_method(StringIO, "lineno", strio_get_lineno, 0);
01519 rb_define_method(StringIO, "lineno=", strio_set_lineno, 1);
01520
01521
01522
01523 rb_define_method(StringIO, "binmode", strio_binmode, 0);
01524 rb_define_method(StringIO, "close", strio_close, 0);
01525 rb_define_method(StringIO, "close_read", strio_close_read, 0);
01526 rb_define_method(StringIO, "close_write", strio_close_write, 0);
01527 rb_define_method(StringIO, "closed?", strio_closed, 0);
01528 rb_define_method(StringIO, "closed_read?", strio_closed_read, 0);
01529 rb_define_method(StringIO, "closed_write?", strio_closed_write, 0);
01530 rb_define_method(StringIO, "eof", strio_eof, 0);
01531 rb_define_method(StringIO, "eof?", strio_eof, 0);
01532
01533 rb_define_method(StringIO, "fcntl", strio_fcntl, -1);
01534
01535 rb_define_method(StringIO, "flush", strio_flush, 0);
01536
01537 rb_define_method(StringIO, "fsync", strio_fsync, 0);
01538 rb_define_method(StringIO, "pos", strio_get_pos, 0);
01539 rb_define_method(StringIO, "pos=", strio_set_pos, 1);
01540 rb_define_method(StringIO, "rewind", strio_rewind, 0);
01541 rb_define_method(StringIO, "seek", strio_seek, -1);
01542 rb_define_method(StringIO, "sync", strio_get_sync, 0);
01543
01544 rb_define_method(StringIO, "sync=", strio_set_sync, 1);
01545 rb_define_method(StringIO, "tell", strio_tell, 0);
01546
01547 rb_define_method(StringIO, "each", strio_each, -1);
01548 rb_define_method(StringIO, "each_line", strio_each, -1);
01549 rb_define_method(StringIO, "lines", strio_lines, -1);
01550 rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
01551 rb_define_method(StringIO, "bytes", strio_bytes, 0);
01552 rb_define_method(StringIO, "each_char", strio_each_char, 0);
01553 rb_define_method(StringIO, "chars", strio_chars, 0);
01554 rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0);
01555 rb_define_method(StringIO, "codepoints", strio_codepoints, 0);
01556 rb_define_method(StringIO, "getc", strio_getc, 0);
01557 rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
01558 rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
01559 rb_define_method(StringIO, "getbyte", strio_getbyte, 0);
01560 rb_define_method(StringIO, "gets", strio_gets, -1);
01561 rb_define_method(StringIO, "readlines", strio_readlines, -1);
01562 rb_define_method(StringIO, "read", strio_read, -1);
01563
01564 rb_define_method(StringIO, "write", strio_write, 1);
01565 rb_define_method(StringIO, "putc", strio_putc, 1);
01566
01567
01568
01569
01570
01571
01572
01573 rb_define_method(StringIO, "isatty", strio_isatty, 0);
01574 rb_define_method(StringIO, "tty?", strio_isatty, 0);
01575
01576
01577 rb_define_method(StringIO, "pid", strio_pid, 0);
01578
01579
01580 rb_define_method(StringIO, "fileno", strio_fileno, 0);
01581 rb_define_method(StringIO, "size", strio_size, 0);
01582 rb_define_method(StringIO, "length", strio_size, 0);
01583 rb_define_method(StringIO, "truncate", strio_truncate, 1);
01584
01585 rb_define_method(StringIO, "external_encoding", strio_external_encoding, 0);
01586 rb_define_method(StringIO, "internal_encoding", strio_internal_encoding, 0);
01587 rb_define_method(StringIO, "set_encoding", strio_set_encoding, -1);
01588
01589 {
01590 VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
01591 rb_define_method(mReadable, "readchar", strio_readchar, 0);
01592 rb_define_method(mReadable, "readbyte", strio_readbyte, 0);
01593 rb_define_method(mReadable, "readline", strio_readline, -1);
01594 rb_define_method(mReadable, "sysread", strio_sysread, -1);
01595 rb_define_method(mReadable, "readpartial", strio_sysread, -1);
01596 rb_define_method(mReadable, "read_nonblock", strio_read_nonblock, -1);
01597 rb_include_module(StringIO, mReadable);
01598 }
01599 {
01600 VALUE mWritable = rb_define_module_under(rb_cIO, "generic_writable");
01601 rb_define_method(mWritable, "<<", strio_addstr, 1);
01602 rb_define_method(mWritable, "print", strio_print, -1);
01603 rb_define_method(mWritable, "printf", strio_printf, -1);
01604 rb_define_method(mWritable, "puts", strio_puts, -1);
01605 rb_define_method(mWritable, "syswrite", strio_syswrite, 1);
01606 rb_define_method(mWritable, "write_nonblock", strio_syswrite_nonblock, -1);
01607 rb_include_module(StringIO, mWritable);
01608 }
01609
01610 sym_exception = ID2SYM(rb_intern("exception"));
01611 }
01612