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