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