Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/stringio/stringio.c

Go to the documentation of this file.

    00001 /**********************************************************************
    00002
    00003   stringio.c -
    00004
    00005   $Author: yugui $
    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 *);
    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(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  * call-seq: StringIO.new(string=""[, mode])
    00149  *
    00150  * Creates new StringIO instance from with _string_ and _mode_.
    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  * call-seq: StringIO.open(string=""[, mode]) {|strio| ...}
    00217  *
    00218  * Equivalent to StringIO.new except that when it is called with a block, it
    00219  * yields with the new instance and closes it, and returns the result which
    00220  * returned from the block.
    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  * Returns +false+.  Just for compatibility to IO.
    00232  */
    00233 static VALUE
    00234 strio_false(VALUE self)
    00235 {
    00236     StringIO(self);
    00237     return Qfalse;
    00238 }
    00239
    00240 /*
    00241  * Returns +nil+.  Just for compatibility to IO.
    00242  */
    00243 static VALUE
    00244 strio_nil(VALUE self)
    00245 {
    00246     StringIO(self);
    00247     return Qnil;
    00248 }
    00249
    00250 /*
    00251  * Returns *strio* itself.  Just for compatibility to IO.
    00252  */
    00253 static VALUE
    00254 strio_self(VALUE self)
    00255 {
    00256     StringIO(self);
    00257     return self;
    00258 }
    00259
    00260 /*
    00261  * Returns 0.  Just for compatibility to IO.
    00262  */
    00263 static VALUE
    00264 strio_0(VALUE self)
    00265 {
    00266     StringIO(self);
    00267     return INT2FIX(0);
    00268 }
    00269
    00270 /*
    00271  * Returns the argument unchanged.  Just for compatibility to IO.
    00272  */
    00273 static VALUE
    00274 strio_first(VALUE self, VALUE arg)
    00275 {
    00276     StringIO(self);
    00277     return arg;
    00278 }
    00279
    00280 /*
    00281  * Raises NotImplementedError.
    00282  */
    00283 static VALUE
    00284 strio_unimpl(int argc, VALUE *argv, VALUE self)
    00285 {
    00286     StringIO(self);
    00287     rb_notimplement();
    00288     return Qnil;                /* not reached */
    00289 }
    00290
    00291 /*
    00292  * call-seq: strio.string     -> string
    00293  *
    00294  * Returns underlying String object, the subject of IO.
    00295  */
    00296 static VALUE
    00297 strio_get_string(VALUE self)
    00298 {
    00299     return StringIO(self)->string;
    00300 }
    00301
    00302 /*
    00303  * call-seq:
    00304  *   strio.string = string  -> string
    00305  *
    00306  * Changes underlying String object, the subject of IO.
    00307  */
    00308 static VALUE
    00309 strio_set_string(VALUE self, VALUE string)
    00310 {
    00311     struct StringIO *ptr = StringIO(self);
    00312
    00313     if (!OBJ_TAINTED(self)) rb_secure(4);
    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  * call-seq:
    00324  *   strio.close  -> nil
    00325  *
    00326  * Closes strio.  The *strio* is unavailable for any further data
    00327  * operations; an +IOError+ is raised if such an attempt is made.
    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  * call-seq:
    00342  *   strio.close_read    -> nil
    00343  *
    00344  * Closes the read end of a StringIO.  Will raise an +IOError+ if the
    00345  * *strio* is not readable.
    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  * call-seq:
    00360  *   strio.close_write    -> nil
    00361  *
    00362  * Closes the write end of a StringIO.  Will raise an  +IOError+ if the
    00363  * *strio* is not writeable.
    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  * call-seq:
    00378  *   strio.closed?    -> true or false
    00379  *
    00380  * Returns +true+ if *strio* is completely closed, +false+ otherwise.
    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  * call-seq:
    00392  *   strio.closed_read?    -> true or false
    00393  *
    00394  * Returns +true+ if *strio* is not readable, +false+ otherwise.
    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  * call-seq:
    00406  *   strio.closed_write?    -> true or false
    00407  *
    00408  * Returns +true+ if *strio* is not writable, +false+ otherwise.
    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  * call-seq:
    00420  *   strio.eof     -> true or false
    00421  *   strio.eof?    -> true or false
    00422  *
    00423  * Returns true if *strio* is at end of file. The stringio must be
    00424  * opened for reading or an +IOError+ will be raised.
    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 /* :nodoc: */
    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  * call-seq:
    00454  *   strio.lineno    -> integer
    00455  *
    00456  * Returns the current line number in *strio*. The stringio must be
    00457  * opened for reading. +lineno+ counts the number of times  +gets+ is
    00458  * called, rather than the number of newlines  encountered. The two
    00459  * values will differ if +gets+ is  called with a separator other than
    00460  * newline.  See also the  <code>$.</code> variable.
    00461  */
    00462 static VALUE
    00463 strio_get_lineno(VALUE self)
    00464 {
    00465     return LONG2NUM(StringIO(self)->lineno);
    00466 }
    00467
    00468 /*
    00469  * call-seq:
    00470  *   strio.lineno = integer    -> integer
    00471  *
    00472  * Manually sets the current line number to the given value.
    00473  * <code>$.</code> is updated only on the next read.
    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 /* call-seq: strio.binmode -> true */
    00483 #define strio_binmode strio_self
    00484
    00485 /* call-seq: strio.fcntl */
    00486 #define strio_fcntl strio_unimpl
    00487
    00488 /* call-seq: strio.flush -> strio */
    00489 #define strio_flush strio_self
    00490
    00491 /* call-seq: strio.fsync -> 0 */
    00492 #define strio_fsync strio_0
    00493
    00494 /*
    00495  * call-seq:
    00496  *   strio.reopen(other_StrIO)     -> strio
    00497  *   strio.reopen(string, mode)    -> strio
    00498  *
    00499  * Reinitializes *strio* with the given <i>other_StrIO</i> or _string_
    00500  * and _mode_ (see StringIO#new).
    00501  */
    00502 static VALUE
    00503 strio_reopen(int argc, VALUE *argv, VALUE self)
    00504 {
    00505     if (!OBJ_TAINTED(self)) rb_secure(4);
    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  * call-seq:
    00515  *   strio.pos     -> integer
    00516  *   strio.tell    -> integer
    00517  *
    00518  * Returns the current offset (in bytes) of *strio*.
    00519  */
    00520 static VALUE
    00521 strio_get_pos(VALUE self)
    00522 {
    00523     return LONG2NUM(StringIO(self)->pos);
    00524 }
    00525
    00526 /*
    00527  * call-seq:
    00528  *   strio.pos = integer    -> integer
    00529  *
    00530  * Seeks to the given position (in bytes) in *strio*.
    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  * call-seq:
    00546  *   strio.rewind    -> 0
    00547  *
    00548  * Positions *strio* to the beginning of input, resetting
    00549  * +lineno+ to zero.
    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  * call-seq:
    00562  *   strio.seek(amount, whence=SEEK_SET) -> 0
    00563  *
    00564  * Seeks to a given offset _amount_ in the stream according to
    00565  * the value of _whence_ (see IO#seek).
    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  * call-seq:
    00600  *   strio.sync    -> true
    00601  *
    00602  * Returns +true+ always.
    00603  */
    00604 static VALUE
    00605 strio_get_sync(VALUE self)
    00606 {
    00607     StringIO(self);
    00608     return Qtrue;
    00609 }
    00610
    00611 /* call-seq: strio.sync = boolean -> boolean */
    00612 #define strio_set_sync strio_first
    00613
    00614 #define strio_tell strio_get_pos
    00615
    00616 /*
    00617  * call-seq:
    00618  *   strio.bytes {|byte| block }      -> strio
    00619  *   strio.bytes                      -> anEnumerator
    00620  *
    00621  *   strio.each_byte {|byte| block }  -> strio
    00622  *   strio.each_byte                  -> anEnumerator
    00623  *
    00624  * See IO#each_byte.
    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  * call-seq:
    00642  *   strio.getc   -> string or nil
    00643  *
    00644  * See IO#getc.
    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  * call-seq:
    00665  *   strio.getbyte   -> fixnum or nil
    00666  *
    00667  * See IO#getbyte.
    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  * call-seq:
    00700  *   strio.ungetc(string)   -> nil
    00701  *
    00702  * Pushes back one character (passed as a parameter) onto *strio*
    00703  * such that a subsequent buffered read will return it.  There is no
    00704  * limitation for multiple pushbacks including pushing back behind the
    00705  * beginning of the buffer string.
    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         /* get logical position */
    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  * call-seq:
    00758  *   strio.ungetbyte(fixnum)   -> nil
    00759  *
    00760  * See IO#ungetbyte
    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  * call-seq:
    00800  *   strio.readchar   -> string
    00801  *
    00802  * See IO#readchar.
    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  * call-seq:
    00814  *   strio.readbyte   -> fixnum
    00815  *
    00816  * See IO#readbyte.
    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  * call-seq:
    00828  *   strio.chars {|char| block }      -> strio
    00829  *   strio.chars                      -> anEnumerator
    00830  *
    00831  *   strio.each_char {|char| block }  -> strio
    00832  *   strio.each_char                  -> anEnumerator
    00833  *
    00834  * See IO#each_char.
    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  * call-seq:
    00851  *   strio.codepoints {|c| block }      -> strio
    00852  *   strio.codepoints                   -> anEnumerator
    00853  *
    00854  *   strio.each_codepoint {|c| block }  -> strio
    00855  *   strio.each_codepoint               -> anEnumerator
    00856  *
    00857  * See IO#each_codepoint.
    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 /* Boyer-Moore search: copied from regex.c */
    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  * call-seq:
    01010  *   strio.gets(sep=$/)     -> string or nil
    01011  *   strio.gets(limit)      -> string or nil
    01012  *   strio.gets(sep, limit) -> string or nil
    01013  *
    01014  * See IO#gets.
    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  * call-seq:
    01027  *   strio.readline(sep=$/)     -> string
    01028  *   strio.readline(limit)      -> string or nil
    01029  *   strio.readline(sep, limit) -> string or nil
    01030  *
    01031  * See IO#readline.
    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  * call-seq:
    01043  *   strio.each(sep=$/) {|line| block }         -> strio
    01044  *   strio.each(limit) {|line| block }          -> strio
    01045  *   strio.each(sep, limit) {|line| block }     -> strio
    01046  *   strio.each(...)                            -> anEnumerator
    01047  *
    01048  *   strio.each_line(sep=$/) {|line| block }    -> strio
    01049  *   strio.each_line(limit) {|line| block }     -> strio
    01050  *   strio.each_line(sep,limit) {|line| block } -> strio
    01051  *   strio.each_line(...)                       -> anEnumerator
    01052  *
    01053  *   strio.lines(sep=$/) {|line| block }        -> strio
    01054  *   strio.lines(limit) {|line| block }         -> strio
    01055  *   strio.lines(sep,limit) {|line| block }     -> strio
    01056  *   strio.lines(...)                           -> anEnumerator
    01057  *
    01058  * See IO#each.
    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  * call-seq:
    01076  *   strio.readlines(sep=$/)    ->   array
    01077  *   strio.readlines(limit)     ->   array
    01078  *   strio.readlines(sep,limit) ->   array
    01079  *
    01080  * See IO#readlines.
    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  * call-seq:
    01095  *   strio.write(string)    -> integer
    01096  *   strio.syswrite(string) -> integer
    01097  *
    01098  * Appends the given string to the underlying buffer string of *strio*.
    01099  * The stream must be opened for writing.  If the argument is not a
    01100  * string, it will be converted to a string using <code>to_s</code>.
    01101  * Returns the number of bytes written.  See IO#write.
    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  * call-seq:
    01140  *   strio << obj     -> strio
    01141  *
    01142  * See IO#<<.
    01143  */
    01144 #define strio_addstr rb_io_addstr
    01145
    01146 /*
    01147  * call-seq:
    01148  *   strio.print()             -> nil
    01149  *   strio.print(obj, ...)     -> nil
    01150  *
    01151  * See IO#print.
    01152  */
    01153 #define strio_print rb_io_print
    01154
    01155 /*
    01156  * call-seq:
    01157  *   strio.printf(format_string [, obj, ...] )   -> nil
    01158  *
    01159  * See IO#printf.
    01160  */
    01161 #define strio_printf rb_io_printf
    01162
    01163 /*
    01164  * call-seq:
    01165  *   strio.putc(obj)    -> obj
    01166  *
    01167  * See IO#putc.
    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  * call-seq:
    01189  *   strio.puts(obj, ...)    -> nil
    01190  *
    01191  * See IO#puts.
    01192  */
    01193 #define strio_puts rb_io_puts
    01194
    01195 /*
    01196  * call-seq:
    01197  *   strio.read([length [, buffer]])    -> string, buffer, or nil
    01198  *
    01199  * See IO#read.
    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         /* fall through */
    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  * call-seq:
    01266  *   strio.sysread(integer[, outbuf])    -> string
    01267  *
    01268  * Similar to #read, but raises +EOFError+ at end of string instead of
    01269  * returning +nil+, as well as IO#sysread does.
    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  * call-seq:
    01285  *   strio.isatty -> nil
    01286  *   strio.tty? -> nil
    01287  *
    01288  */
    01289 #define strio_isatty strio_false
    01290
    01291 /* call-seq: strio.pid -> nil */
    01292 #define strio_pid strio_nil
    01293
    01294 /* call-seq: strio.fileno -> nil */
    01295 #define strio_fileno strio_nil
    01296
    01297 /*
    01298  * call-seq:
    01299  *   strio.size   -> integer
    01300  *
    01301  * Returns the size of the buffer string.
    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  * call-seq:
    01315  *   strio.truncate(integer)    -> 0
    01316  *
    01317  * Truncates the buffer string to at most _integer_ bytes. The *strio*
    01318  * must be opened for writing.
    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  *  call-seq:
    01338  *     strio.external_encoding   => encoding
    01339  *
    01340  *  Returns the Encoding object that represents the encoding of the file.
    01341  *  If strio is write mode and no encoding is specified, returns <code>nil</code>.
    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  *  call-seq:
    01352  *     strio.internal_encoding   => encoding
    01353  *
    01354  *  Returns the Encoding of the internal string if conversion is
    01355  *  specified.  Otherwise returns nil.
    01356  */
    01357
    01358 static VALUE
    01359 strio_internal_encoding(VALUE self)
    01360 {
    01361      return Qnil;
    01362 }
    01363
    01364 /*
    01365  *  call-seq:
    01366  *     strio.set_encoding(ext_enc)                => strio
    01367  *
    01368  *  Tagged with the encoding specified.
    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  * Pseudo I/O on String object.
    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