|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3