• 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(rb_io_taint_check(self));
00087 
00088     if (!ptr) {
00089         rb_raise(rb_eIOError, "uninitialized stream");
00090     }
00091     return ptr;
00092 }
00093 
00094 static VALUE
00095 strio_substr(struct StringIO *ptr, long pos, long len)
00096 {
00097     VALUE str = ptr->string;
00098     rb_encoding *enc = rb_enc_get(str);
00099     long rlen = RSTRING_LEN(str) - pos;
00100 
00101     if (len > rlen) len = rlen;
00102     if (len < 0) len = 0;
00103     return rb_enc_str_new(RSTRING_PTR(str)+pos, len, enc);
00104 }
00105 
00106 #define StringIO(obj) get_strio(obj)
00107 
00108 #define CLOSED(ptr) (!((ptr)->flags & FMODE_READWRITE))
00109 #define READABLE(ptr) ((ptr)->flags & FMODE_READABLE)
00110 #define WRITABLE(ptr) ((ptr)->flags & FMODE_WRITABLE)
00111 
00112 static struct StringIO*
00113 readable(struct StringIO *ptr)
00114 {
00115     if (!READABLE(ptr)) {
00116         rb_raise(rb_eIOError, "not opened for reading");
00117     }
00118     return ptr;
00119 }
00120 
00121 static struct StringIO*
00122 writable(struct StringIO *ptr)
00123 {
00124     if (!WRITABLE(ptr)) {
00125         rb_raise(rb_eIOError, "not opened for writing");
00126     }
00127     if (!OBJ_TAINTED(ptr->string)) {
00128         rb_secure(4);
00129     }
00130     return ptr;
00131 }
00132 
00133 static void
00134 check_modifiable(struct StringIO *ptr)
00135 {
00136     if (OBJ_FROZEN(ptr->string)) {
00137         rb_raise(rb_eIOError, "not modifiable string");
00138     }
00139 }
00140 
00141 static VALUE
00142 strio_s_allocate(VALUE klass)
00143 {
00144     return TypedData_Wrap_Struct(klass, &strio_data_type, 0);
00145 }
00146 
00147 /*
00148  * 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     rb_io_taint_check(self);
00314     ptr->flags &= ~FMODE_READWRITE;
00315     StringValue(string);
00316     ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
00317     ptr->pos = 0;
00318     ptr->lineno = 0;
00319     return ptr->string = string;
00320 }
00321 
00322 /*
00323  * 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     rb_io_taint_check(self);
00506     if (argc == 1 && TYPE(*argv) != T_STRING) {
00507         return strio_copy(self, *argv);
00508     }
00509     strio_init(argc, argv, StringIO(self));
00510     return self;
00511 }
00512 
00513 /*
00514  * 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, lim;
00923 
00924     rb_scan_args(argc, argv, "02", &str, &lim);
00925     switch (argc) {
00926       case 0:
00927         str = rb_rs;
00928         break;
00929 
00930       case 1:
00931         if (!NIL_P(str) && TYPE(str) != T_STRING) {
00932             VALUE tmp = rb_check_string_type(str);
00933             if (NIL_P(tmp)) {
00934                 limit = NUM2LONG(str);
00935                 if (limit == 0) return rb_str_new(0,0);
00936                 str = rb_rs;
00937             }
00938             else {
00939                 str = tmp;
00940             }
00941         }
00942         break;
00943 
00944       case 2:
00945         if (!NIL_P(str)) StringValue(str);
00946         limit = NUM2LONG(lim);
00947         break;
00948     }
00949 
00950     if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
00951         return Qnil;
00952     }
00953     s = RSTRING_PTR(ptr->string);
00954     e = s + RSTRING_LEN(ptr->string);
00955     s += ptr->pos;
00956     if (limit > 0 && s + limit < e) {
00957         e = rb_enc_right_char_head(s, s + limit, e, rb_enc_get(ptr->string));
00958     }
00959     if (NIL_P(str)) {
00960         str = strio_substr(ptr, ptr->pos, e - s);
00961     }
00962     else if ((n = RSTRING_LEN(str)) == 0) {
00963         p = s;
00964         while (*p == '\n') {
00965             if (++p == e) {
00966                 return Qnil;
00967             }
00968         }
00969         s = p;
00970         while ((p = memchr(p, '\n', e - p)) && (p != e)) {
00971             if (*++p == '\n') {
00972                 e = p + 1;
00973                 break;
00974             }
00975         }
00976         str = strio_substr(ptr, s - RSTRING_PTR(ptr->string), e - s);
00977     }
00978     else if (n == 1) {
00979         if ((p = memchr(s, RSTRING_PTR(str)[0], e - s)) != 0) {
00980             e = p + 1;
00981         }
00982         str = strio_substr(ptr, ptr->pos, e - s);
00983     }
00984     else {
00985         if (n < e - s) {
00986             if (e - s < 1024) {
00987                 for (p = s; p + n <= e; ++p) {
00988                     if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
00989                         e = p + n;
00990                         break;
00991                     }
00992                 }
00993             }
00994             else {
00995                 long skip[1 << CHAR_BIT], pos;
00996                 p = RSTRING_PTR(str);
00997                 bm_init_skip(skip, p, n);
00998                 if ((pos = bm_search(p, n, s, e - s, skip)) >= 0) {
00999                     e = s + pos + n;
01000                 }
01001             }
01002         }
01003         str = strio_substr(ptr, ptr->pos, e - s);
01004     }
01005     ptr->pos = e - RSTRING_PTR(ptr->string);
01006     ptr->lineno++;
01007     return str;
01008 }
01009 
01010 /*
01011  * call-seq:
01012  *   strio.gets(sep=$/)     -> string or nil
01013  *   strio.gets(limit)      -> string or nil
01014  *   strio.gets(sep, limit) -> string or nil
01015  *
01016  * See IO#gets.
01017  */
01018 static VALUE
01019 strio_gets(int argc, VALUE *argv, VALUE self)
01020 {
01021     VALUE str = strio_getline(argc, argv, readable(StringIO(self)));
01022 
01023     rb_lastline_set(str);
01024     return str;
01025 }
01026 
01027 /*
01028  * call-seq:
01029  *   strio.readline(sep=$/)     -> string
01030  *   strio.readline(limit)      -> string or nil
01031  *   strio.readline(sep, limit) -> string or nil
01032  *
01033  * See IO#readline.
01034  */
01035 static VALUE
01036 strio_readline(int argc, VALUE *argv, VALUE self)
01037 {
01038     VALUE line = strio_gets(argc, argv, self);
01039     if (NIL_P(line)) rb_eof_error();
01040     return line;
01041 }
01042 
01043 /*
01044  * call-seq:
01045  *   strio.each(sep=$/) {|line| block }         -> strio
01046  *   strio.each(limit) {|line| block }          -> strio
01047  *   strio.each(sep, limit) {|line| block }     -> strio
01048  *   strio.each(...)                            -> anEnumerator
01049  *
01050  *   strio.each_line(sep=$/) {|line| block }    -> strio
01051  *   strio.each_line(limit) {|line| block }     -> strio
01052  *   strio.each_line(sep,limit) {|line| block } -> strio
01053  *   strio.each_line(...)                       -> anEnumerator
01054  *
01055  *   strio.lines(sep=$/) {|line| block }        -> strio
01056  *   strio.lines(limit) {|line| block }         -> strio
01057  *   strio.lines(sep,limit) {|line| block }     -> strio
01058  *   strio.lines(...)                           -> anEnumerator
01059  *
01060  * See IO#each.
01061  */
01062 static VALUE
01063 strio_each(int argc, VALUE *argv, VALUE self)
01064 {
01065     struct StringIO *ptr = StringIO(self);
01066     VALUE line;
01067 
01068     RETURN_ENUMERATOR(self, argc, argv);
01069 
01070     while (!NIL_P(line = strio_getline(argc, argv, readable(ptr)))) {
01071         rb_yield(line);
01072     }
01073     return self;
01074 }
01075 
01076 /*
01077  * call-seq:
01078  *   strio.readlines(sep=$/)    ->   array
01079  *   strio.readlines(limit)     ->   array
01080  *   strio.readlines(sep,limit) ->   array
01081  *
01082  * See IO#readlines.
01083  */
01084 static VALUE
01085 strio_readlines(int argc, VALUE *argv, VALUE self)
01086 {
01087     struct StringIO *ptr = StringIO(self);
01088     VALUE ary = rb_ary_new(), line;
01089     while (!NIL_P(line = strio_getline(argc, argv, readable(ptr)))) {
01090         rb_ary_push(ary, line);
01091     }
01092     return ary;
01093 }
01094 
01095 /*
01096  * call-seq:
01097  *   strio.write(string)    -> integer
01098  *   strio.syswrite(string) -> integer
01099  *
01100  * Appends the given string to the underlying buffer string of *strio*.
01101  * The stream must be opened for writing.  If the argument is not a
01102  * string, it will be converted to a string using <code>to_s</code>.
01103  * Returns the number of bytes written.  See IO#write.
01104  */
01105 static VALUE
01106 strio_write(VALUE self, VALUE str)
01107 {
01108     struct StringIO *ptr = writable(StringIO(self));
01109     long len, olen;
01110     rb_encoding *enc, *enc2;
01111 
01112     RB_GC_GUARD(str);
01113     if (TYPE(str) != T_STRING)
01114         str = rb_obj_as_string(str);
01115     enc = rb_enc_get(ptr->string);
01116     enc2 = rb_enc_get(str);
01117     if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
01118         str = rb_str_conv_enc(str, enc2, enc);
01119     }
01120     len = RSTRING_LEN(str);
01121     if (len == 0) return INT2FIX(0);
01122     check_modifiable(ptr);
01123     olen = RSTRING_LEN(ptr->string);
01124     if (ptr->flags & FMODE_APPEND) {
01125         ptr->pos = olen;
01126     }
01127     if (ptr->pos == olen) {
01128         rb_str_cat(ptr->string, RSTRING_PTR(str), len);
01129     }
01130     else {
01131         strio_extend(ptr, ptr->pos, len);
01132         memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
01133         OBJ_INFECT(ptr->string, str);
01134     }
01135     OBJ_INFECT(ptr->string, self);
01136     ptr->pos += len;
01137     return LONG2NUM(len);
01138 }
01139 
01140 /*
01141  * call-seq:
01142  *   strio << obj     -> strio
01143  *
01144  * See IO#<<.
01145  */
01146 #define strio_addstr rb_io_addstr
01147 
01148 /*
01149  * call-seq:
01150  *   strio.print()             -> nil
01151  *   strio.print(obj, ...)     -> nil
01152  *
01153  * See IO#print.
01154  */
01155 #define strio_print rb_io_print
01156 
01157 /*
01158  * call-seq:
01159  *   strio.printf(format_string [, obj, ...] )   -> nil
01160  *
01161  * See IO#printf.
01162  */
01163 #define strio_printf rb_io_printf
01164 
01165 /*
01166  * call-seq:
01167  *   strio.putc(obj)    -> obj
01168  *
01169  * See IO#putc.
01170  */
01171 static VALUE
01172 strio_putc(VALUE self, VALUE ch)
01173 {
01174     struct StringIO *ptr = writable(StringIO(self));
01175     int c = NUM2CHR(ch);
01176     long olen;
01177 
01178     check_modifiable(ptr);
01179     olen = RSTRING_LEN(ptr->string);
01180     if (ptr->flags & FMODE_APPEND) {
01181         ptr->pos = olen;
01182     }
01183     strio_extend(ptr, ptr->pos, 1);
01184     RSTRING_PTR(ptr->string)[ptr->pos++] = c;
01185     OBJ_INFECT(ptr->string, self);
01186     return ch;
01187 }
01188 
01189 /*
01190  * call-seq:
01191  *   strio.puts(obj, ...)    -> nil
01192  *
01193  * See IO#puts.
01194  */
01195 #define strio_puts rb_io_puts
01196 
01197 /*
01198  * call-seq:
01199  *   strio.read([length [, buffer]])    -> string, buffer, or nil
01200  *
01201  * See IO#read.
01202  */
01203 static VALUE
01204 strio_read(int argc, VALUE *argv, VALUE self)
01205 {
01206     struct StringIO *ptr = readable(StringIO(self));
01207     VALUE str = Qnil;
01208     long len;
01209 
01210     switch (argc) {
01211       case 2:
01212         str = argv[1];
01213         StringValue(str);
01214         rb_str_modify(str);
01215       case 1:
01216         if (!NIL_P(argv[0])) {
01217             len = NUM2LONG(argv[0]);
01218             if (len < 0) {
01219                 rb_raise(rb_eArgError, "negative length %ld given", len);
01220             }
01221             if (len > 0 && ptr->pos >= RSTRING_LEN(ptr->string)) {
01222                 if (!NIL_P(str)) rb_str_resize(str, 0);
01223                 return Qnil;
01224             }
01225             break;
01226         }
01227         /* fall through */
01228       case 0:
01229         len = RSTRING_LEN(ptr->string);
01230         if (len <= ptr->pos) {
01231             if (NIL_P(str)) {
01232                 str = rb_str_new(0, 0);
01233             }
01234             else {
01235                 rb_str_resize(str, 0);
01236             }
01237             return str;
01238         }
01239         else {
01240             len -= ptr->pos;
01241         }
01242         break;
01243       default:
01244         rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
01245     }
01246     if (NIL_P(str)) {
01247         str = strio_substr(ptr, ptr->pos, len);
01248         if (argc > 0) rb_enc_associate(str, rb_ascii8bit_encoding());
01249     }
01250     else {
01251         long rest = RSTRING_LEN(ptr->string) - ptr->pos;
01252         if (len > rest) len = rest;
01253         rb_str_resize(str, len);
01254         MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
01255     }
01256     if (NIL_P(str)) {
01257         str = rb_str_new(0, 0);
01258         len = 0;
01259     }
01260     else {
01261         ptr->pos += len = RSTRING_LEN(str);
01262     }
01263     return str;
01264 }
01265 
01266 /*
01267  * call-seq:
01268  *   strio.sysread(integer[, outbuf])    -> string
01269  *
01270  * Similar to #read, but raises +EOFError+ at end of string instead of
01271  * returning +nil+, as well as IO#sysread does.
01272  */
01273 static VALUE
01274 strio_sysread(int argc, VALUE *argv, VALUE self)
01275 {
01276     VALUE val = strio_read(argc, argv, self);
01277     if (NIL_P(val)) {
01278         rb_eof_error();
01279     }
01280     return val;
01281 }
01282 
01283 #define strio_syswrite strio_write
01284 
01285 /*
01286  * call-seq:
01287  *   strio.isatty -> nil
01288  *   strio.tty? -> nil
01289  *
01290  */
01291 #define strio_isatty strio_false
01292 
01293 /* call-seq: strio.pid -> nil */
01294 #define strio_pid strio_nil
01295 
01296 /* call-seq: strio.fileno -> nil */
01297 #define strio_fileno strio_nil
01298 
01299 /*
01300  * call-seq:
01301  *   strio.size   -> integer
01302  *
01303  * Returns the size of the buffer string.
01304  */
01305 static VALUE
01306 strio_size(VALUE self)
01307 {
01308     VALUE string = StringIO(self)->string;
01309     if (NIL_P(string)) {
01310         rb_raise(rb_eIOError, "not opened");
01311     }
01312     return ULONG2NUM(RSTRING_LEN(string));
01313 }
01314 
01315 /*
01316  * call-seq:
01317  *   strio.truncate(integer)    -> 0
01318  *
01319  * Truncates the buffer string to at most _integer_ bytes. The *strio*
01320  * must be opened for writing.
01321  */
01322 static VALUE
01323 strio_truncate(VALUE self, VALUE len)
01324 {
01325     VALUE string = writable(StringIO(self))->string;
01326     long l = NUM2LONG(len);
01327     long plen = RSTRING_LEN(string);
01328     if (l < 0) {
01329         error_inval("negative legnth");
01330     }
01331     rb_str_resize(string, l);
01332     if (plen < l) {
01333         MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
01334     }
01335     return len;
01336 }
01337 
01338 /*
01339  *  call-seq:
01340  *     strio.external_encoding   => encoding
01341  *
01342  *  Returns the Encoding object that represents the encoding of the file.
01343  *  If strio is write mode and no encoding is specified, returns <code>nil</code>.
01344  */
01345 
01346 static VALUE
01347 strio_external_encoding(VALUE self)
01348 {
01349     return rb_enc_from_encoding(rb_enc_get(StringIO(self)->string));
01350 }
01351 
01352 /*
01353  *  call-seq:
01354  *     strio.internal_encoding   => encoding
01355  *
01356  *  Returns the Encoding of the internal string if conversion is
01357  *  specified.  Otherwise returns nil.
01358  */
01359 
01360 static VALUE
01361 strio_internal_encoding(VALUE self)
01362 {
01363      return Qnil;
01364 }
01365 
01366 /*
01367  *  call-seq:
01368  *     strio.set_encoding(ext_enc)                => strio
01369  *
01370  *  Tagged with the encoding specified.
01371  */
01372 
01373 static VALUE
01374 strio_set_encoding(VALUE self, VALUE ext_enc)
01375 {
01376     rb_encoding* enc;
01377     VALUE str = StringIO(self)->string;
01378     enc = rb_to_encoding(ext_enc);
01379     rb_enc_associate(str, enc);
01380     return self;
01381 }
01382 
01383 /*
01384  * Pseudo I/O on String object.
01385  */
01386 void
01387 Init_stringio()
01388 {
01389     VALUE StringIO = rb_define_class("StringIO", rb_cData);
01390 
01391     rb_include_module(StringIO, rb_mEnumerable);
01392     rb_define_alloc_func(StringIO, strio_s_allocate);
01393     rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
01394     rb_define_method(StringIO, "initialize", strio_initialize, -1);
01395     rb_define_method(StringIO, "initialize_copy", strio_copy, 1);
01396     rb_define_method(StringIO, "reopen", strio_reopen, -1);
01397 
01398     rb_define_method(StringIO, "string", strio_get_string, 0);
01399     rb_define_method(StringIO, "string=", strio_set_string, 1);
01400     rb_define_method(StringIO, "lineno", strio_get_lineno, 0);
01401     rb_define_method(StringIO, "lineno=", strio_set_lineno, 1);
01402 
01403     rb_define_method(StringIO, "binmode", strio_binmode, 0);
01404     rb_define_method(StringIO, "close", strio_close, 0);
01405     rb_define_method(StringIO, "close_read", strio_close_read, 0);
01406     rb_define_method(StringIO, "close_write", strio_close_write, 0);
01407     rb_define_method(StringIO, "closed?", strio_closed, 0);
01408     rb_define_method(StringIO, "closed_read?", strio_closed_read, 0);
01409     rb_define_method(StringIO, "closed_write?", strio_closed_write, 0);
01410     rb_define_method(StringIO, "eof", strio_eof, 0);
01411     rb_define_method(StringIO, "eof?", strio_eof, 0);
01412     rb_define_method(StringIO, "fcntl", strio_fcntl, -1);
01413     rb_define_method(StringIO, "flush", strio_flush, 0);
01414     rb_define_method(StringIO, "fsync", strio_fsync, 0);
01415     rb_define_method(StringIO, "pos", strio_get_pos, 0);
01416     rb_define_method(StringIO, "pos=", strio_set_pos, 1);
01417     rb_define_method(StringIO, "rewind", strio_rewind, 0);
01418     rb_define_method(StringIO, "seek", strio_seek, -1);
01419     rb_define_method(StringIO, "sync", strio_get_sync, 0);
01420     rb_define_method(StringIO, "sync=", strio_set_sync, 1);
01421     rb_define_method(StringIO, "tell", strio_tell, 0);
01422 
01423     rb_define_method(StringIO, "each", strio_each, -1);
01424     rb_define_method(StringIO, "each_line", strio_each, -1);
01425     rb_define_method(StringIO, "lines", strio_each, -1);
01426     rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
01427     rb_define_method(StringIO, "bytes", strio_each_byte, 0);
01428     rb_define_method(StringIO, "each_char", strio_each_char, 0);
01429     rb_define_method(StringIO, "chars", strio_each_char, 0);
01430     rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0);
01431     rb_define_method(StringIO, "codepoints", strio_each_codepoint, 0);
01432     rb_define_method(StringIO, "getc", strio_getc, 0);
01433     rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
01434     rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
01435     rb_define_method(StringIO, "readchar", strio_readchar, 0);
01436     rb_define_method(StringIO, "getbyte", strio_getbyte, 0);
01437     rb_define_method(StringIO, "readbyte", strio_readbyte, 0);
01438     rb_define_method(StringIO, "gets", strio_gets, -1);
01439     rb_define_method(StringIO, "readline", strio_readline, -1);
01440     rb_define_method(StringIO, "readlines", strio_readlines, -1);
01441     rb_define_method(StringIO, "read", strio_read, -1);
01442     rb_define_method(StringIO, "sysread", strio_sysread, -1);
01443     rb_define_method(StringIO, "readpartial", strio_sysread, -1);
01444     rb_define_method(StringIO, "read_nonblock", strio_sysread, -1);
01445 
01446     rb_define_method(StringIO, "write", strio_write, 1);
01447     rb_define_method(StringIO, "<<", strio_addstr, 1);
01448     rb_define_method(StringIO, "print", strio_print, -1);
01449     rb_define_method(StringIO, "printf", strio_printf, -1);
01450     rb_define_method(StringIO, "putc", strio_putc, 1);
01451     rb_define_method(StringIO, "puts", strio_puts, -1);
01452     rb_define_method(StringIO, "syswrite", strio_syswrite, 1);
01453     rb_define_method(StringIO, "write_nonblock", strio_syswrite, 1);
01454 
01455     rb_define_method(StringIO, "isatty", strio_isatty, 0);
01456     rb_define_method(StringIO, "tty?", strio_isatty, 0);
01457     rb_define_method(StringIO, "pid", strio_pid, 0);
01458     rb_define_method(StringIO, "fileno", strio_fileno, 0);
01459     rb_define_method(StringIO, "size", strio_size, 0);
01460     rb_define_method(StringIO, "length", strio_size, 0);
01461     rb_define_method(StringIO, "truncate", strio_truncate, 1);
01462 
01463     rb_define_method(StringIO, "external_encoding", strio_external_encoding, 0);
01464     rb_define_method(StringIO, "internal_encoding", strio_internal_encoding, 0);
01465     rb_define_method(StringIO, "set_encoding", strio_set_encoding, 1);
01466 }
01467 

Generated on Sat Jul 7 2012 15:29:15 for Ruby by  doxygen 1.7.1