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