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