ext/stringio/stringio.c


DEFINITIONS

This source file includes following functions.
  1. strio_alloc
  2. strio_mark
  3. strio_free
  4. check_strio
  5. get_strio
  6. readable
  7. writable
  8. check_modifiable
  9. strio_s_allocate
  10. strio_s_open
  11. strio_initialize
  12. strio_finalize
  13. strio_false
  14. strio_nil
  15. strio_self
  16. strio_0
  17. strio_first
  18. strio_unimpl
  19. strio_get_string
  20. strio_set_string
  21. strio_close
  22. strio_close_read
  23. strio_close_write
  24. strio_closed
  25. strio_closed_read
  26. strio_closed_write
  27. strio_eof
  28. strio_become
  29. strio_get_lineno
  30. strio_set_lineno
  31. strio_reopen
  32. strio_get_pos
  33. strio_set_pos
  34. strio_rewind
  35. strio_seek
  36. strio_get_sync
  37. strio_each_byte
  38. strio_getc
  39. strio_ungetc
  40. strio_readchar
  41. bm_init_skip
  42. bm_search
  43. strio_gets_internal
  44. strio_gets
  45. strio_readline
  46. strio_each
  47. strio_readlines
  48. strio_write
  49. strio_putc
  50. strio_read
  51. strio_sysread
  52. strio_size
  53. strio_truncate
  54. Init_stringio


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