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