|
Ruby 1.9.2p136(2010-12-25revision30365)
|
00001 /********************************************************************** 00002 00003 string.c - 00004 00005 $Author: yugui $ 00006 created at: Mon Aug 9 17:12:58 JST 1993 00007 00008 Copyright (C) 1993-2007 Yukihiro Matsumoto 00009 Copyright (C) 2000 Network Applied Communication Laboratory, Inc. 00010 Copyright (C) 2000 Information-technology Promotion Agency, Japan 00011 00012 **********************************************************************/ 00013 00014 #include "ruby/ruby.h" 00015 #include "ruby/re.h" 00016 #include "ruby/encoding.h" 00017 #include <assert.h> 00018 00019 #define BEG(no) regs->beg[no] 00020 #define END(no) regs->end[no] 00021 00022 #include <math.h> 00023 #include <ctype.h> 00024 00025 #ifdef HAVE_UNISTD_H 00026 #include <unistd.h> 00027 #endif 00028 00029 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) 00030 00031 #undef rb_str_new_cstr 00032 #undef rb_tainted_str_new_cstr 00033 #undef rb_usascii_str_new_cstr 00034 #undef rb_external_str_new_cstr 00035 #undef rb_locale_str_new_cstr 00036 #undef rb_str_new2 00037 #undef rb_str_new3 00038 #undef rb_str_new4 00039 #undef rb_str_new5 00040 #undef rb_tainted_str_new2 00041 #undef rb_usascii_str_new2 00042 #undef rb_str_dup_frozen 00043 #undef rb_str_buf_new_cstr 00044 #undef rb_str_buf_new2 00045 #undef rb_str_buf_cat2 00046 #undef rb_str_cat2 00047 00048 VALUE rb_cString; 00049 VALUE rb_cSymbol; 00050 00051 #define RUBY_MAX_CHAR_LEN 16 00052 #define STR_TMPLOCK FL_USER7 00053 #define STR_NOEMBED FL_USER1 00054 #define STR_SHARED FL_USER2 /* = ELTS_SHARED */ 00055 #define STR_ASSOC FL_USER3 00056 #define STR_SHARED_P(s) FL_ALL(s, STR_NOEMBED|ELTS_SHARED) 00057 #define STR_ASSOC_P(s) FL_ALL(s, STR_NOEMBED|STR_ASSOC) 00058 #define STR_NOCAPA (STR_NOEMBED|ELTS_SHARED|STR_ASSOC) 00059 #define STR_NOCAPA_P(s) (FL_TEST(s,STR_NOEMBED) && FL_ANY(s,ELTS_SHARED|STR_ASSOC)) 00060 #define STR_UNSET_NOCAPA(s) do {\ 00061 if (FL_TEST(s,STR_NOEMBED)) FL_UNSET(s,(ELTS_SHARED|STR_ASSOC));\ 00062 } while (0) 00063 00064 00065 #define STR_SET_NOEMBED(str) do {\ 00066 FL_SET(str, STR_NOEMBED);\ 00067 STR_SET_EMBED_LEN(str, 0);\ 00068 } while (0) 00069 #define STR_SET_EMBED(str) FL_UNSET(str, STR_NOEMBED) 00070 #define STR_EMBED_P(str) (!FL_TEST(str, STR_NOEMBED)) 00071 #define STR_SET_EMBED_LEN(str, n) do { \ 00072 long tmp_n = (n);\ 00073 RBASIC(str)->flags &= ~RSTRING_EMBED_LEN_MASK;\ 00074 RBASIC(str)->flags |= (tmp_n) << RSTRING_EMBED_LEN_SHIFT;\ 00075 } while (0) 00076 00077 #define STR_SET_LEN(str, n) do { \ 00078 if (STR_EMBED_P(str)) {\ 00079 STR_SET_EMBED_LEN(str, n);\ 00080 }\ 00081 else {\ 00082 RSTRING(str)->as.heap.len = (n);\ 00083 }\ 00084 } while (0) 00085 00086 #define STR_DEC_LEN(str) do {\ 00087 if (STR_EMBED_P(str)) {\ 00088 long n = RSTRING_LEN(str);\ 00089 n--;\ 00090 STR_SET_EMBED_LEN(str, n);\ 00091 }\ 00092 else {\ 00093 RSTRING(str)->as.heap.len--;\ 00094 }\ 00095 } while (0) 00096 00097 #define RESIZE_CAPA(str,capacity) do {\ 00098 if (STR_EMBED_P(str)) {\ 00099 if ((capacity) > RSTRING_EMBED_LEN_MAX) {\ 00100 char *tmp = ALLOC_N(char, capacity+1);\ 00101 memcpy(tmp, RSTRING_PTR(str), RSTRING_LEN(str));\ 00102 RSTRING(str)->as.heap.ptr = tmp;\ 00103 RSTRING(str)->as.heap.len = RSTRING_LEN(str);\ 00104 STR_SET_NOEMBED(str);\ 00105 RSTRING(str)->as.heap.aux.capa = (capacity);\ 00106 }\ 00107 }\ 00108 else {\ 00109 REALLOC_N(RSTRING(str)->as.heap.ptr, char, (capacity)+1);\ 00110 if (!STR_NOCAPA_P(str))\ 00111 RSTRING(str)->as.heap.aux.capa = (capacity);\ 00112 }\ 00113 } while (0) 00114 00115 #define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) 00116 #define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) 00117 00118 #define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str)) 00119 00120 static inline int 00121 single_byte_optimizable(VALUE str) 00122 { 00123 rb_encoding *enc; 00124 00125 /* Conservative. It may be ENC_CODERANGE_UNKNOWN. */ 00126 if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) 00127 return 1; 00128 00129 enc = STR_ENC_GET(str); 00130 if (rb_enc_mbmaxlen(enc) == 1) 00131 return 1; 00132 00133 /* Conservative. Possibly single byte. 00134 * "\xa1" in Shift_JIS for example. */ 00135 return 0; 00136 } 00137 00138 VALUE rb_fs; 00139 00140 static inline const char * 00141 search_nonascii(const char *p, const char *e) 00142 { 00143 #if SIZEOF_VALUE == 8 00144 # define NONASCII_MASK 0x8080808080808080ULL 00145 #elif SIZEOF_VALUE == 4 00146 # define NONASCII_MASK 0x80808080UL 00147 #endif 00148 #ifdef NONASCII_MASK 00149 if ((int)sizeof(VALUE) * 2 < e - p) { 00150 const VALUE *s, *t; 00151 const VALUE lowbits = sizeof(VALUE) - 1; 00152 s = (const VALUE*)(~lowbits & ((VALUE)p + lowbits)); 00153 while (p < (const char *)s) { 00154 if (!ISASCII(*p)) 00155 return p; 00156 p++; 00157 } 00158 t = (const VALUE*)(~lowbits & (VALUE)e); 00159 while (s < t) { 00160 if (*s & NONASCII_MASK) { 00161 t = s; 00162 break; 00163 } 00164 s++; 00165 } 00166 p = (const char *)t; 00167 } 00168 #endif 00169 while (p < e) { 00170 if (!ISASCII(*p)) 00171 return p; 00172 p++; 00173 } 00174 return NULL; 00175 } 00176 00177 static int 00178 coderange_scan(const char *p, long len, rb_encoding *enc) 00179 { 00180 const char *e = p + len; 00181 00182 if (rb_enc_to_index(enc) == 0) { 00183 /* enc is ASCII-8BIT. ASCII-8BIT string never be broken. */ 00184 p = search_nonascii(p, e); 00185 return p ? ENC_CODERANGE_VALID : ENC_CODERANGE_7BIT; 00186 } 00187 00188 if (rb_enc_asciicompat(enc)) { 00189 p = search_nonascii(p, e); 00190 if (!p) { 00191 return ENC_CODERANGE_7BIT; 00192 } 00193 while (p < e) { 00194 int ret = rb_enc_precise_mbclen(p, e, enc); 00195 if (!MBCLEN_CHARFOUND_P(ret)) { 00196 return ENC_CODERANGE_BROKEN; 00197 } 00198 p += MBCLEN_CHARFOUND_LEN(ret); 00199 if (p < e) { 00200 p = search_nonascii(p, e); 00201 if (!p) { 00202 return ENC_CODERANGE_VALID; 00203 } 00204 } 00205 } 00206 if (e < p) { 00207 return ENC_CODERANGE_BROKEN; 00208 } 00209 return ENC_CODERANGE_VALID; 00210 } 00211 00212 while (p < e) { 00213 int ret = rb_enc_precise_mbclen(p, e, enc); 00214 00215 if (!MBCLEN_CHARFOUND_P(ret)) { 00216 return ENC_CODERANGE_BROKEN; 00217 } 00218 p += MBCLEN_CHARFOUND_LEN(ret); 00219 } 00220 if (e < p) { 00221 return ENC_CODERANGE_BROKEN; 00222 } 00223 return ENC_CODERANGE_VALID; 00224 } 00225 00226 long 00227 rb_str_coderange_scan_restartable(const char *s, const char *e, rb_encoding *enc, int *cr) 00228 { 00229 const char *p = s; 00230 00231 if (*cr == ENC_CODERANGE_BROKEN) 00232 return e - s; 00233 00234 if (rb_enc_to_index(enc) == 0) { 00235 /* enc is ASCII-8BIT. ASCII-8BIT string never be broken. */ 00236 p = search_nonascii(p, e); 00237 *cr = (!p && *cr != ENC_CODERANGE_VALID) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID; 00238 return e - s; 00239 } 00240 else if (rb_enc_asciicompat(enc)) { 00241 p = search_nonascii(p, e); 00242 if (!p) { 00243 if (*cr != ENC_CODERANGE_VALID) *cr = ENC_CODERANGE_7BIT; 00244 return e - s; 00245 } 00246 while (p < e) { 00247 int ret = rb_enc_precise_mbclen(p, e, enc); 00248 if (!MBCLEN_CHARFOUND_P(ret)) { 00249 *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN; 00250 return p - s; 00251 } 00252 p += MBCLEN_CHARFOUND_LEN(ret); 00253 if (p < e) { 00254 p = search_nonascii(p, e); 00255 if (!p) { 00256 *cr = ENC_CODERANGE_VALID; 00257 return e - s; 00258 } 00259 } 00260 } 00261 *cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID; 00262 return p - s; 00263 } 00264 else { 00265 while (p < e) { 00266 int ret = rb_enc_precise_mbclen(p, e, enc); 00267 if (!MBCLEN_CHARFOUND_P(ret)) { 00268 *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN; 00269 return p - s; 00270 } 00271 p += MBCLEN_CHARFOUND_LEN(ret); 00272 } 00273 *cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID; 00274 return p - s; 00275 } 00276 } 00277 00278 static inline void 00279 str_enc_copy(VALUE str1, VALUE str2) 00280 { 00281 rb_enc_set_index(str1, ENCODING_GET(str2)); 00282 } 00283 00284 static void 00285 rb_enc_cr_str_copy_for_substr(VALUE dest, VALUE src) 00286 { 00287 /* this function is designed for copying encoding and coderange 00288 * from src to new string "dest" which is made from the part of src. 00289 */ 00290 str_enc_copy(dest, src); 00291 switch (ENC_CODERANGE(src)) { 00292 case ENC_CODERANGE_7BIT: 00293 ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); 00294 break; 00295 case ENC_CODERANGE_VALID: 00296 if (!rb_enc_asciicompat(STR_ENC_GET(src)) || 00297 search_nonascii(RSTRING_PTR(dest), RSTRING_END(dest))) 00298 ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID); 00299 else 00300 ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); 00301 break; 00302 default: 00303 if (RSTRING_LEN(dest) == 0) { 00304 if (!rb_enc_asciicompat(STR_ENC_GET(src))) 00305 ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID); 00306 else 00307 ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); 00308 } 00309 break; 00310 } 00311 } 00312 00313 static void 00314 rb_enc_cr_str_exact_copy(VALUE dest, VALUE src) 00315 { 00316 str_enc_copy(dest, src); 00317 ENC_CODERANGE_SET(dest, ENC_CODERANGE(src)); 00318 } 00319 00320 int 00321 rb_enc_str_coderange(VALUE str) 00322 { 00323 int cr = ENC_CODERANGE(str); 00324 00325 if (cr == ENC_CODERANGE_UNKNOWN) { 00326 rb_encoding *enc = STR_ENC_GET(str); 00327 cr = coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc); 00328 ENC_CODERANGE_SET(str, cr); 00329 } 00330 return cr; 00331 } 00332 00333 int 00334 rb_enc_str_asciionly_p(VALUE str) 00335 { 00336 rb_encoding *enc = STR_ENC_GET(str); 00337 00338 if (!rb_enc_asciicompat(enc)) 00339 return FALSE; 00340 else if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) 00341 return TRUE; 00342 return FALSE; 00343 } 00344 00345 static inline void 00346 str_mod_check(VALUE s, const char *p, long len) 00347 { 00348 if (RSTRING_PTR(s) != p || RSTRING_LEN(s) != len){ 00349 rb_raise(rb_eRuntimeError, "string modified"); 00350 } 00351 } 00352 00353 static inline void 00354 str_frozen_check(VALUE s) 00355 { 00356 if (OBJ_FROZEN(s)) { 00357 rb_raise(rb_eRuntimeError, "string frozen"); 00358 } 00359 } 00360 00361 size_t 00362 rb_str_capacity(VALUE str) 00363 { 00364 if (STR_EMBED_P(str)) { 00365 return RSTRING_EMBED_LEN_MAX; 00366 } 00367 else if (STR_NOCAPA_P(str)) { 00368 return RSTRING(str)->as.heap.len; 00369 } 00370 else { 00371 return RSTRING(str)->as.heap.aux.capa; 00372 } 00373 } 00374 00375 static inline VALUE 00376 str_alloc(VALUE klass) 00377 { 00378 NEWOBJ(str, struct RString); 00379 OBJSETUP(str, klass, T_STRING); 00380 00381 str->as.heap.ptr = 0; 00382 str->as.heap.len = 0; 00383 str->as.heap.aux.capa = 0; 00384 00385 return (VALUE)str; 00386 } 00387 00388 static VALUE 00389 str_new(VALUE klass, const char *ptr, long len) 00390 { 00391 VALUE str; 00392 00393 if (len < 0) { 00394 rb_raise(rb_eArgError, "negative string size (or size too big)"); 00395 } 00396 00397 str = str_alloc(klass); 00398 if (len > RSTRING_EMBED_LEN_MAX) { 00399 RSTRING(str)->as.heap.aux.capa = len; 00400 RSTRING(str)->as.heap.ptr = ALLOC_N(char,len+1); 00401 STR_SET_NOEMBED(str); 00402 } 00403 else if (len == 0) { 00404 ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT); 00405 } 00406 if (ptr) { 00407 memcpy(RSTRING_PTR(str), ptr, len); 00408 } 00409 STR_SET_LEN(str, len); 00410 RSTRING_PTR(str)[len] = '\0'; 00411 return str; 00412 } 00413 00414 VALUE 00415 rb_str_new(const char *ptr, long len) 00416 { 00417 return str_new(rb_cString, ptr, len); 00418 } 00419 00420 VALUE 00421 rb_usascii_str_new(const char *ptr, long len) 00422 { 00423 VALUE str = rb_str_new(ptr, len); 00424 ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT); 00425 return str; 00426 } 00427 00428 VALUE 00429 rb_enc_str_new(const char *ptr, long len, rb_encoding *enc) 00430 { 00431 VALUE str = rb_str_new(ptr, len); 00432 rb_enc_associate(str, enc); 00433 return str; 00434 } 00435 00436 VALUE 00437 rb_str_new_cstr(const char *ptr) 00438 { 00439 if (!ptr) { 00440 rb_raise(rb_eArgError, "NULL pointer given"); 00441 } 00442 return rb_str_new(ptr, strlen(ptr)); 00443 } 00444 00445 RUBY_ALIAS_FUNCTION(rb_str_new2(const char *ptr), rb_str_new_cstr, (ptr)) 00446 #define rb_str_new2 rb_str_new_cstr 00447 00448 VALUE 00449 rb_usascii_str_new_cstr(const char *ptr) 00450 { 00451 VALUE str = rb_str_new2(ptr); 00452 ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT); 00453 return str; 00454 } 00455 00456 RUBY_ALIAS_FUNCTION(rb_usascii_str_new2(const char *ptr), rb_usascii_str_new_cstr, (ptr)) 00457 #define rb_usascii_str_new2 rb_usascii_str_new_cstr 00458 00459 VALUE 00460 rb_tainted_str_new(const char *ptr, long len) 00461 { 00462 VALUE str = rb_str_new(ptr, len); 00463 00464 OBJ_TAINT(str); 00465 return str; 00466 } 00467 00468 VALUE 00469 rb_tainted_str_new_cstr(const char *ptr) 00470 { 00471 VALUE str = rb_str_new2(ptr); 00472 00473 OBJ_TAINT(str); 00474 return str; 00475 } 00476 00477 RUBY_ALIAS_FUNCTION(rb_tainted_str_new2(const char *ptr), rb_tainted_str_new_cstr, (ptr)) 00478 #define rb_tainted_str_new2 rb_tainted_str_new_cstr 00479 00480 VALUE 00481 rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts) 00482 { 00483 rb_econv_t *ec; 00484 rb_econv_result_t ret; 00485 long len; 00486 VALUE newstr; 00487 const unsigned char *sp; 00488 unsigned char *dp; 00489 00490 if (!to) return str; 00491 if (from == to) return str; 00492 if ((rb_enc_asciicompat(to) && ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) || 00493 to == rb_ascii8bit_encoding()) { 00494 if (STR_ENC_GET(str) != to) { 00495 str = rb_str_dup(str); 00496 rb_enc_associate(str, to); 00497 } 00498 return str; 00499 } 00500 00501 len = RSTRING_LEN(str); 00502 newstr = rb_str_new(0, len); 00503 00504 retry: 00505 ec = rb_econv_open_opts(from->name, to->name, ecflags, ecopts); 00506 if (!ec) return str; 00507 00508 sp = (unsigned char*)RSTRING_PTR(str); 00509 dp = (unsigned char*)RSTRING_PTR(newstr); 00510 ret = rb_econv_convert(ec, &sp, (unsigned char*)RSTRING_END(str), 00511 &dp, (unsigned char*)RSTRING_END(newstr), 0); 00512 rb_econv_close(ec); 00513 switch (ret) { 00514 case econv_destination_buffer_full: 00515 /* destination buffer short */ 00516 len = len < 2 ? 2 : len * 2; 00517 rb_str_resize(newstr, len); 00518 goto retry; 00519 00520 case econv_finished: 00521 len = dp - (unsigned char*)RSTRING_PTR(newstr); 00522 rb_str_set_len(newstr, len); 00523 rb_enc_associate(newstr, to); 00524 return newstr; 00525 00526 default: 00527 /* some error, return original */ 00528 return str; 00529 } 00530 } 00531 00532 VALUE 00533 rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to) 00534 { 00535 return rb_str_conv_enc_opts(str, from, to, 0, Qnil); 00536 } 00537 00538 VALUE 00539 rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *eenc) 00540 { 00541 VALUE str; 00542 00543 str = rb_tainted_str_new(ptr, len); 00544 if (eenc == rb_usascii_encoding() && 00545 rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) { 00546 rb_enc_associate(str, rb_ascii8bit_encoding()); 00547 return str; 00548 } 00549 rb_enc_associate(str, eenc); 00550 return rb_str_conv_enc(str, eenc, rb_default_internal_encoding()); 00551 } 00552 00553 VALUE 00554 rb_external_str_new(const char *ptr, long len) 00555 { 00556 return rb_external_str_new_with_enc(ptr, len, rb_default_external_encoding()); 00557 } 00558 00559 VALUE 00560 rb_external_str_new_cstr(const char *ptr) 00561 { 00562 return rb_external_str_new_with_enc(ptr, strlen(ptr), rb_default_external_encoding()); 00563 } 00564 00565 VALUE 00566 rb_locale_str_new(const char *ptr, long len) 00567 { 00568 return rb_external_str_new_with_enc(ptr, len, rb_locale_encoding()); 00569 } 00570 00571 VALUE 00572 rb_locale_str_new_cstr(const char *ptr) 00573 { 00574 return rb_external_str_new_with_enc(ptr, strlen(ptr), rb_locale_encoding()); 00575 } 00576 00577 VALUE 00578 rb_filesystem_str_new(const char *ptr, long len) 00579 { 00580 return rb_external_str_new_with_enc(ptr, len, rb_filesystem_encoding()); 00581 } 00582 00583 VALUE 00584 rb_filesystem_str_new_cstr(const char *ptr) 00585 { 00586 return rb_external_str_new_with_enc(ptr, strlen(ptr), rb_filesystem_encoding()); 00587 } 00588 00589 VALUE 00590 rb_str_export(VALUE str) 00591 { 00592 return rb_str_conv_enc(str, STR_ENC_GET(str), rb_default_external_encoding()); 00593 } 00594 00595 VALUE 00596 rb_str_export_locale(VALUE str) 00597 { 00598 return rb_str_conv_enc(str, STR_ENC_GET(str), rb_locale_encoding()); 00599 } 00600 00601 VALUE 00602 rb_str_export_to_enc(VALUE str, rb_encoding *enc) 00603 { 00604 return rb_str_conv_enc(str, STR_ENC_GET(str), enc); 00605 } 00606 00607 static VALUE 00608 str_replace_shared(VALUE str2, VALUE str) 00609 { 00610 if (RSTRING_LEN(str) <= RSTRING_EMBED_LEN_MAX) { 00611 STR_SET_EMBED(str2); 00612 memcpy(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str)+1); 00613 STR_SET_EMBED_LEN(str2, RSTRING_LEN(str)); 00614 } 00615 else { 00616 str = rb_str_new_frozen(str); 00617 FL_SET(str2, STR_NOEMBED); 00618 RSTRING(str2)->as.heap.len = RSTRING_LEN(str); 00619 RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str); 00620 RSTRING(str2)->as.heap.aux.shared = str; 00621 FL_SET(str2, ELTS_SHARED); 00622 } 00623 rb_enc_cr_str_exact_copy(str2, str); 00624 00625 return str2; 00626 } 00627 00628 static VALUE 00629 str_new_shared(VALUE klass, VALUE str) 00630 { 00631 return str_replace_shared(str_alloc(klass), str); 00632 } 00633 00634 static VALUE 00635 str_new3(VALUE klass, VALUE str) 00636 { 00637 return str_new_shared(klass, str); 00638 } 00639 00640 VALUE 00641 rb_str_new_shared(VALUE str) 00642 { 00643 VALUE str2 = str_new3(rb_obj_class(str), str); 00644 00645 OBJ_INFECT(str2, str); 00646 return str2; 00647 } 00648 00649 RUBY_ALIAS_FUNCTION(rb_str_new3(VALUE str), rb_str_new_shared, (str)) 00650 #define rb_str_new3 rb_str_new_shared 00651 00652 static VALUE 00653 str_new4(VALUE klass, VALUE str) 00654 { 00655 VALUE str2; 00656 00657 str2 = str_alloc(klass); 00658 STR_SET_NOEMBED(str2); 00659 RSTRING(str2)->as.heap.len = RSTRING_LEN(str); 00660 RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str); 00661 if (STR_SHARED_P(str)) { 00662 VALUE shared = RSTRING(str)->as.heap.aux.shared; 00663 assert(OBJ_FROZEN(shared)); 00664 FL_SET(str2, ELTS_SHARED); 00665 RSTRING(str2)->as.heap.aux.shared = shared; 00666 } 00667 else { 00668 FL_SET(str, ELTS_SHARED); 00669 RSTRING(str)->as.heap.aux.shared = str2; 00670 } 00671 rb_enc_cr_str_exact_copy(str2, str); 00672 OBJ_INFECT(str2, str); 00673 return str2; 00674 } 00675 00676 VALUE 00677 rb_str_new_frozen(VALUE orig) 00678 { 00679 VALUE klass, str; 00680 00681 if (OBJ_FROZEN(orig)) return orig; 00682 klass = rb_obj_class(orig); 00683 if (STR_SHARED_P(orig) && (str = RSTRING(orig)->as.heap.aux.shared)) { 00684 long ofs; 00685 assert(OBJ_FROZEN(str)); 00686 ofs = RSTRING_LEN(str) - RSTRING_LEN(orig); 00687 if ((ofs > 0) || (klass != RBASIC(str)->klass) || 00688 (!OBJ_TAINTED(str) && OBJ_TAINTED(orig)) || 00689 ENCODING_GET(str) != ENCODING_GET(orig)) { 00690 str = str_new3(klass, str); 00691 RSTRING(str)->as.heap.ptr += ofs; 00692 RSTRING(str)->as.heap.len -= ofs; 00693 rb_enc_cr_str_exact_copy(str, orig); 00694 OBJ_INFECT(str, orig); 00695 } 00696 } 00697 else if (STR_EMBED_P(orig)) { 00698 str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig)); 00699 rb_enc_cr_str_exact_copy(str, orig); 00700 OBJ_INFECT(str, orig); 00701 } 00702 else if (STR_ASSOC_P(orig)) { 00703 VALUE assoc = RSTRING(orig)->as.heap.aux.shared; 00704 FL_UNSET(orig, STR_ASSOC); 00705 str = str_new4(klass, orig); 00706 FL_SET(str, STR_ASSOC); 00707 RSTRING(str)->as.heap.aux.shared = assoc; 00708 } 00709 else { 00710 str = str_new4(klass, orig); 00711 } 00712 OBJ_FREEZE(str); 00713 return str; 00714 } 00715 00716 RUBY_ALIAS_FUNCTION(rb_str_new4(VALUE orig), rb_str_new_frozen, (orig)) 00717 #define rb_str_new4 rb_str_new_frozen 00718 00719 VALUE 00720 rb_str_new_with_class(VALUE obj, const char *ptr, long len) 00721 { 00722 return str_new(rb_obj_class(obj), ptr, len); 00723 } 00724 00725 RUBY_ALIAS_FUNCTION(rb_str_new5(VALUE obj, const char *ptr, long len), 00726 rb_str_new_with_class, (obj, ptr, len)) 00727 #define rb_str_new5 rb_str_new_with_class 00728 00729 static VALUE 00730 str_new_empty(VALUE str) 00731 { 00732 VALUE v = rb_str_new5(str, 0, 0); 00733 OBJ_INFECT(v, str); 00734 return v; 00735 } 00736 00737 #define STR_BUF_MIN_SIZE 128 00738 00739 VALUE 00740 rb_str_buf_new(long capa) 00741 { 00742 VALUE str = str_alloc(rb_cString); 00743 00744 if (capa < STR_BUF_MIN_SIZE) { 00745 capa = STR_BUF_MIN_SIZE; 00746 } 00747 FL_SET(str, STR_NOEMBED); 00748 RSTRING(str)->as.heap.aux.capa = capa; 00749 RSTRING(str)->as.heap.ptr = ALLOC_N(char, capa+1); 00750 RSTRING(str)->as.heap.ptr[0] = '\0'; 00751 00752 return str; 00753 } 00754 00755 VALUE 00756 rb_str_buf_new_cstr(const char *ptr) 00757 { 00758 VALUE str; 00759 long len = strlen(ptr); 00760 00761 str = rb_str_buf_new(len); 00762 rb_str_buf_cat(str, ptr, len); 00763 00764 return str; 00765 } 00766 00767 RUBY_ALIAS_FUNCTION(rb_str_buf_new2(const char *ptr), rb_str_buf_new_cstr, (ptr)) 00768 #define rb_str_buf_new2 rb_str_buf_new_cstr 00769 00770 VALUE 00771 rb_str_tmp_new(long len) 00772 { 00773 return str_new(0, 0, len); 00774 } 00775 00776 void 00777 rb_str_free(VALUE str) 00778 { 00779 if (!STR_EMBED_P(str) && !STR_SHARED_P(str)) { 00780 xfree(RSTRING(str)->as.heap.ptr); 00781 } 00782 } 00783 00784 size_t 00785 rb_str_memsize(VALUE str) 00786 { 00787 if (!STR_EMBED_P(str) && !STR_SHARED_P(str)) { 00788 return RSTRING(str)->as.heap.aux.capa; 00789 } 00790 else { 00791 return 0; 00792 } 00793 } 00794 00795 VALUE 00796 rb_str_to_str(VALUE str) 00797 { 00798 return rb_convert_type(str, T_STRING, "String", "to_str"); 00799 } 00800 00801 static inline void str_discard(VALUE str); 00802 00803 void 00804 rb_str_shared_replace(VALUE str, VALUE str2) 00805 { 00806 rb_encoding *enc; 00807 int cr; 00808 if (str == str2) return; 00809 enc = STR_ENC_GET(str2); 00810 cr = ENC_CODERANGE(str2); 00811 str_discard(str); 00812 OBJ_INFECT(str, str2); 00813 if (RSTRING_LEN(str2) <= RSTRING_EMBED_LEN_MAX) { 00814 STR_SET_EMBED(str); 00815 memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), RSTRING_LEN(str2)+1); 00816 STR_SET_EMBED_LEN(str, RSTRING_LEN(str2)); 00817 rb_enc_associate(str, enc); 00818 ENC_CODERANGE_SET(str, cr); 00819 return; 00820 } 00821 STR_SET_NOEMBED(str); 00822 STR_UNSET_NOCAPA(str); 00823 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2); 00824 RSTRING(str)->as.heap.len = RSTRING_LEN(str2); 00825 if (STR_NOCAPA_P(str2)) { 00826 FL_SET(str, RBASIC(str2)->flags & STR_NOCAPA); 00827 RSTRING(str)->as.heap.aux.shared = RSTRING(str2)->as.heap.aux.shared; 00828 } 00829 else { 00830 RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa; 00831 } 00832 STR_SET_EMBED(str2); /* abandon str2 */ 00833 RSTRING_PTR(str2)[0] = 0; 00834 STR_SET_EMBED_LEN(str2, 0); 00835 rb_enc_associate(str, enc); 00836 ENC_CODERANGE_SET(str, cr); 00837 } 00838 00839 static ID id_to_s; 00840 00841 VALUE 00842 rb_obj_as_string(VALUE obj) 00843 { 00844 VALUE str; 00845 00846 if (TYPE(obj) == T_STRING) { 00847 return obj; 00848 } 00849 str = rb_funcall(obj, id_to_s, 0); 00850 if (TYPE(str) != T_STRING) 00851 return rb_any_to_s(obj); 00852 if (OBJ_TAINTED(obj)) OBJ_TAINT(str); 00853 return str; 00854 } 00855 00856 static VALUE 00857 str_replace(VALUE str, VALUE str2) 00858 { 00859 long len; 00860 00861 len = RSTRING_LEN(str2); 00862 if (STR_ASSOC_P(str2)) { 00863 str2 = rb_str_new4(str2); 00864 } 00865 if (STR_SHARED_P(str2)) { 00866 VALUE shared = RSTRING(str2)->as.heap.aux.shared; 00867 assert(OBJ_FROZEN(shared)); 00868 STR_SET_NOEMBED(str); 00869 RSTRING(str)->as.heap.len = len; 00870 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2); 00871 FL_SET(str, ELTS_SHARED); 00872 FL_UNSET(str, STR_ASSOC); 00873 RSTRING(str)->as.heap.aux.shared = shared; 00874 } 00875 else { 00876 str_replace_shared(str, str2); 00877 } 00878 00879 OBJ_INFECT(str, str2); 00880 rb_enc_cr_str_exact_copy(str, str2); 00881 return str; 00882 } 00883 00884 static VALUE 00885 str_duplicate(VALUE klass, VALUE str) 00886 { 00887 VALUE dup = str_alloc(klass); 00888 str_replace(dup, str); 00889 return dup; 00890 } 00891 00892 VALUE 00893 rb_str_dup(VALUE str) 00894 { 00895 return str_duplicate(rb_obj_class(str), str); 00896 } 00897 00898 VALUE 00899 rb_str_resurrect(VALUE str) 00900 { 00901 return str_replace(str_alloc(rb_cString), str); 00902 } 00903 00904 /* 00905 * call-seq: 00906 * String.new(str="") -> new_str 00907 * 00908 * Returns a new string object containing a copy of <i>str</i>. 00909 */ 00910 00911 static VALUE 00912 rb_str_init(int argc, VALUE *argv, VALUE str) 00913 { 00914 VALUE orig; 00915 00916 if (argc > 0 && rb_scan_args(argc, argv, "01", &orig) == 1) 00917 rb_str_replace(str, orig); 00918 return str; 00919 } 00920 00921 static inline long 00922 enc_strlen(const char *p, const char *e, rb_encoding *enc, int cr) 00923 { 00924 long c; 00925 const char *q; 00926 00927 if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) { 00928 return (e - p + rb_enc_mbminlen(enc) - 1) / rb_enc_mbminlen(enc); 00929 } 00930 else if (rb_enc_asciicompat(enc)) { 00931 c = 0; 00932 if (cr == ENC_CODERANGE_7BIT || cr == ENC_CODERANGE_VALID) { 00933 while (p < e) { 00934 if (ISASCII(*p)) { 00935 q = search_nonascii(p, e); 00936 if (!q) 00937 return c + (e - p); 00938 c += q - p; 00939 p = q; 00940 } 00941 p += rb_enc_fast_mbclen(p, e, enc); 00942 c++; 00943 } 00944 } 00945 else { 00946 while (p < e) { 00947 if (ISASCII(*p)) { 00948 q = search_nonascii(p, e); 00949 if (!q) 00950 return c + (e - p); 00951 c += q - p; 00952 p = q; 00953 } 00954 p += rb_enc_mbclen(p, e, enc); 00955 c++; 00956 } 00957 } 00958 return c; 00959 } 00960 00961 for (c=0; p<e; c++) { 00962 p += rb_enc_mbclen(p, e, enc); 00963 } 00964 return c; 00965 } 00966 00967 long 00968 rb_enc_strlen(const char *p, const char *e, rb_encoding *enc) 00969 { 00970 return enc_strlen(p, e, enc, ENC_CODERANGE_UNKNOWN); 00971 } 00972 00973 long 00974 rb_enc_strlen_cr(const char *p, const char *e, rb_encoding *enc, int *cr) 00975 { 00976 long c; 00977 const char *q; 00978 int ret; 00979 00980 *cr = 0; 00981 if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) { 00982 return (e - p + rb_enc_mbminlen(enc) - 1) / rb_enc_mbminlen(enc); 00983 } 00984 else if (rb_enc_asciicompat(enc)) { 00985 c = 0; 00986 while (p < e) { 00987 if (ISASCII(*p)) { 00988 q = search_nonascii(p, e); 00989 if (!q) { 00990 if (!*cr) *cr = ENC_CODERANGE_7BIT; 00991 return c + (e - p); 00992 } 00993 c += q - p; 00994 p = q; 00995 } 00996 ret = rb_enc_precise_mbclen(p, e, enc); 00997 if (MBCLEN_CHARFOUND_P(ret)) { 00998 *cr |= ENC_CODERANGE_VALID; 00999 p += MBCLEN_CHARFOUND_LEN(ret); 01000 } 01001 else { 01002 *cr = ENC_CODERANGE_BROKEN; 01003 p++; 01004 } 01005 c++; 01006 } 01007 if (!*cr) *cr = ENC_CODERANGE_7BIT; 01008 return c; 01009 } 01010 01011 for (c=0; p<e; c++) { 01012 ret = rb_enc_precise_mbclen(p, e, enc); 01013 if (MBCLEN_CHARFOUND_P(ret)) { 01014 *cr |= ENC_CODERANGE_VALID; 01015 p += MBCLEN_CHARFOUND_LEN(ret); 01016 } 01017 else { 01018 *cr = ENC_CODERANGE_BROKEN; 01019 if (p + rb_enc_mbminlen(enc) <= e) 01020 p += rb_enc_mbminlen(enc); 01021 else 01022 p = e; 01023 } 01024 } 01025 if (!*cr) *cr = ENC_CODERANGE_7BIT; 01026 return c; 01027 } 01028 01029 #ifdef NONASCII_MASK 01030 #define is_utf8_lead_byte(c) (((c)&0xC0) != 0x80) 01031 static inline VALUE 01032 count_utf8_lead_bytes_with_word(const VALUE *s) 01033 { 01034 VALUE d = *s; 01035 d |= ~(d>>1); 01036 d >>= 6; 01037 d &= NONASCII_MASK >> 7; 01038 d += (d>>8); 01039 d += (d>>16); 01040 #if SIZEOF_VALUE == 8 01041 d += (d>>32); 01042 #endif 01043 return (d&0xF); 01044 } 01045 #endif 01046 01047 static long 01048 str_strlen(VALUE str, rb_encoding *enc) 01049 { 01050 const char *p, *e; 01051 long n; 01052 int cr; 01053 01054 if (single_byte_optimizable(str)) return RSTRING_LEN(str); 01055 if (!enc) enc = STR_ENC_GET(str); 01056 p = RSTRING_PTR(str); 01057 e = RSTRING_END(str); 01058 cr = ENC_CODERANGE(str); 01059 #ifdef NONASCII_MASK 01060 if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID && 01061 enc == rb_utf8_encoding()) { 01062 01063 VALUE len = 0; 01064 if ((int)sizeof(VALUE) * 2 < e - p) { 01065 const VALUE *s, *t; 01066 const VALUE lowbits = sizeof(VALUE) - 1; 01067 s = (const VALUE*)(~lowbits & ((VALUE)p + lowbits)); 01068 t = (const VALUE*)(~lowbits & (VALUE)e); 01069 while (p < (const char *)s) { 01070 if (is_utf8_lead_byte(*p)) len++; 01071 p++; 01072 } 01073 while (s < t) { 01074 len += count_utf8_lead_bytes_with_word(s); 01075 s++; 01076 } 01077 p = (const char *)s; 01078 } 01079 while (p < e) { 01080 if (is_utf8_lead_byte(*p)) len++; 01081 p++; 01082 } 01083 return (long)len; 01084 } 01085 #endif 01086 n = rb_enc_strlen_cr(p, e, enc, &cr); 01087 if (cr) { 01088 ENC_CODERANGE_SET(str, cr); 01089 } 01090 return n; 01091 } 01092 01093 long 01094 rb_str_strlen(VALUE str) 01095 { 01096 return str_strlen(str, STR_ENC_GET(str)); 01097 } 01098 01099 /* 01100 * call-seq: 01101 * str.length -> integer 01102 * str.size -> integer 01103 * 01104 * Returns the character length of <i>str</i>. 01105 */ 01106 01107 VALUE 01108 rb_str_length(VALUE str) 01109 { 01110 long len; 01111 01112 len = str_strlen(str, STR_ENC_GET(str)); 01113 return LONG2NUM(len); 01114 } 01115 01116 /* 01117 * call-seq: 01118 * str.bytesize -> integer 01119 * 01120 * Returns the length of <i>str</i> in bytes. 01121 */ 01122 01123 static VALUE 01124 rb_str_bytesize(VALUE str) 01125 { 01126 return INT2NUM(RSTRING_LEN(str)); 01127 } 01128 01129 /* 01130 * call-seq: 01131 * str.empty? -> true or false 01132 * 01133 * Returns <code>true</code> if <i>str</i> has a length of zero. 01134 * 01135 * "hello".empty? #=> false 01136 * "".empty? #=> true 01137 */ 01138 01139 static VALUE 01140 rb_str_empty(VALUE str) 01141 { 01142 if (RSTRING_LEN(str) == 0) 01143 return Qtrue; 01144 return Qfalse; 01145 } 01146 01147 /* 01148 * call-seq: 01149 * str + other_str -> new_str 01150 * 01151 * Concatenation---Returns a new <code>String</code> containing 01152 * <i>other_str</i> concatenated to <i>str</i>. 01153 * 01154 * "Hello from " + self.to_s #=> "Hello from main" 01155 */ 01156 01157 VALUE 01158 rb_str_plus(VALUE str1, VALUE str2) 01159 { 01160 VALUE str3; 01161 rb_encoding *enc; 01162 01163 StringValue(str2); 01164 enc = rb_enc_check(str1, str2); 01165 str3 = rb_str_new(0, RSTRING_LEN(str1)+RSTRING_LEN(str2)); 01166 memcpy(RSTRING_PTR(str3), RSTRING_PTR(str1), RSTRING_LEN(str1)); 01167 memcpy(RSTRING_PTR(str3) + RSTRING_LEN(str1), 01168 RSTRING_PTR(str2), RSTRING_LEN(str2)); 01169 RSTRING_PTR(str3)[RSTRING_LEN(str3)] = '\0'; 01170 01171 if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2)) 01172 OBJ_TAINT(str3); 01173 ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc), 01174 ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2))); 01175 return str3; 01176 } 01177 01178 /* 01179 * call-seq: 01180 * str * integer -> new_str 01181 * 01182 * Copy---Returns a new <code>String</code> containing <i>integer</i> copies of 01183 * the receiver. 01184 * 01185 * "Ho! " * 3 #=> "Ho! Ho! Ho! " 01186 */ 01187 01188 VALUE 01189 rb_str_times(VALUE str, VALUE times) 01190 { 01191 VALUE str2; 01192 long n, len; 01193 char *ptr2; 01194 01195 len = NUM2LONG(times); 01196 if (len < 0) { 01197 rb_raise(rb_eArgError, "negative argument"); 01198 } 01199 if (len && LONG_MAX/len < RSTRING_LEN(str)) { 01200 rb_raise(rb_eArgError, "argument too big"); 01201 } 01202 01203 str2 = rb_str_new5(str, 0, len *= RSTRING_LEN(str)); 01204 ptr2 = RSTRING_PTR(str2); 01205 if (len) { 01206 n = RSTRING_LEN(str); 01207 memcpy(ptr2, RSTRING_PTR(str), n); 01208 while (n <= len/2) { 01209 memcpy(ptr2 + n, ptr2, n); 01210 n *= 2; 01211 } 01212 memcpy(ptr2 + n, ptr2, len-n); 01213 } 01214 ptr2[RSTRING_LEN(str2)] = '\0'; 01215 OBJ_INFECT(str2, str); 01216 rb_enc_cr_str_copy_for_substr(str2, str); 01217 01218 return str2; 01219 } 01220 01221 /* 01222 * call-seq: 01223 * str % arg -> new_str 01224 * 01225 * Format---Uses <i>str</i> as a format specification, and returns the result 01226 * of applying it to <i>arg</i>. If the format specification contains more than 01227 * one substitution, then <i>arg</i> must be an <code>Array</code> or <code>Hash</code> 01228 * containing the values to be substituted. See <code>Kernel::sprintf</code> for 01229 * details of the format string. 01230 * 01231 * "%05d" % 123 #=> "00123" 01232 * "%-5s: %08x" % [ "ID", self.object_id ] #=> "ID : 200e14d6" 01233 * "foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar" 01234 */ 01235 01236 static VALUE 01237 rb_str_format_m(VALUE str, VALUE arg) 01238 { 01239 volatile VALUE tmp = rb_check_array_type(arg); 01240 01241 if (!NIL_P(tmp)) { 01242 return rb_str_format(RARRAY_LENINT(tmp), RARRAY_PTR(tmp), str); 01243 } 01244 return rb_str_format(1, &arg, str); 01245 } 01246 01247 static inline void 01248 str_modifiable(VALUE str) 01249 { 01250 if (FL_TEST(str, STR_TMPLOCK)) { 01251 rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked"); 01252 } 01253 if (OBJ_FROZEN(str)) rb_error_frozen("string"); 01254 if (!OBJ_UNTRUSTED(str) && rb_safe_level() >= 4) 01255 rb_raise(rb_eSecurityError, "Insecure: can't modify string"); 01256 } 01257 01258 static inline int 01259 str_independent(VALUE str) 01260 { 01261 str_modifiable(str); 01262 if (!STR_SHARED_P(str)) return 1; 01263 if (STR_EMBED_P(str)) return 1; 01264 return 0; 01265 } 01266 01267 static void 01268 str_make_independent(VALUE str) 01269 { 01270 char *ptr; 01271 long len = RSTRING_LEN(str); 01272 01273 ptr = ALLOC_N(char, len+1); 01274 if (RSTRING_PTR(str)) { 01275 memcpy(ptr, RSTRING_PTR(str), len); 01276 } 01277 STR_SET_NOEMBED(str); 01278 ptr[len] = 0; 01279 RSTRING(str)->as.heap.ptr = ptr; 01280 RSTRING(str)->as.heap.len = len; 01281 RSTRING(str)->as.heap.aux.capa = len; 01282 STR_UNSET_NOCAPA(str); 01283 } 01284 01285 void 01286 rb_str_modify(VALUE str) 01287 { 01288 if (!str_independent(str)) 01289 str_make_independent(str); 01290 ENC_CODERANGE_CLEAR(str); 01291 } 01292 01293 /* As rb_str_modify(), but don't clear coderange */ 01294 static void 01295 str_modify_keep_cr(VALUE str) 01296 { 01297 if (!str_independent(str)) 01298 str_make_independent(str); 01299 if (ENC_CODERANGE(str) == ENC_CODERANGE_BROKEN) 01300 /* Force re-scan later */ 01301 ENC_CODERANGE_CLEAR(str); 01302 } 01303 01304 static inline void 01305 str_discard(VALUE str) 01306 { 01307 str_modifiable(str); 01308 if (!STR_SHARED_P(str) && !STR_EMBED_P(str)) { 01309 xfree(RSTRING_PTR(str)); 01310 RSTRING(str)->as.heap.ptr = 0; 01311 RSTRING(str)->as.heap.len = 0; 01312 } 01313 } 01314 01315 void 01316 rb_str_associate(VALUE str, VALUE add) 01317 { 01318 /* sanity check */ 01319 if (OBJ_FROZEN(str)) rb_error_frozen("string"); 01320 if (STR_ASSOC_P(str)) { 01321 /* already associated */ 01322 rb_ary_concat(RSTRING(str)->as.heap.aux.shared, add); 01323 } 01324 else { 01325 if (STR_SHARED_P(str)) { 01326 VALUE assoc = RSTRING(str)->as.heap.aux.shared; 01327 str_make_independent(str); 01328 if (STR_ASSOC_P(assoc)) { 01329 assoc = RSTRING(assoc)->as.heap.aux.shared; 01330 rb_ary_concat(assoc, add); 01331 add = assoc; 01332 } 01333 } 01334 else if (STR_EMBED_P(str)) { 01335 str_make_independent(str); 01336 } 01337 else if (RSTRING(str)->as.heap.aux.capa != RSTRING_LEN(str)) { 01338 RESIZE_CAPA(str, RSTRING_LEN(str)); 01339 } 01340 FL_SET(str, STR_ASSOC); 01341 RBASIC(add)->klass = 0; 01342 RSTRING(str)->as.heap.aux.shared = add; 01343 } 01344 } 01345 01346 VALUE 01347 rb_str_associated(VALUE str) 01348 { 01349 if (STR_SHARED_P(str)) str = RSTRING(str)->as.heap.aux.shared; 01350 if (STR_ASSOC_P(str)) { 01351 return RSTRING(str)->as.heap.aux.shared; 01352 } 01353 return Qfalse; 01354 } 01355 01356 VALUE 01357 rb_string_value(volatile VALUE *ptr) 01358 { 01359 VALUE s = *ptr; 01360 if (TYPE(s) != T_STRING) { 01361 s = rb_str_to_str(s); 01362 *ptr = s; 01363 } 01364 return s; 01365 } 01366 01367 char * 01368 rb_string_value_ptr(volatile VALUE *ptr) 01369 { 01370 VALUE str = rb_string_value(ptr); 01371 return RSTRING_PTR(str); 01372 } 01373 01374 char * 01375 rb_string_value_cstr(volatile VALUE *ptr) 01376 { 01377 VALUE str = rb_string_value(ptr); 01378 char *s = RSTRING_PTR(str); 01379 long len = RSTRING_LEN(str); 01380 01381 if (!s || memchr(s, 0, len)) { 01382 rb_raise(rb_eArgError, "string contains null byte"); 01383 } 01384 if (s[len]) rb_str_modify(str); 01385 return s; 01386 } 01387 01388 VALUE 01389 rb_check_string_type(VALUE str) 01390 { 01391 str = rb_check_convert_type(str, T_STRING, "String", "to_str"); 01392 return str; 01393 } 01394 01395 /* 01396 * call-seq: 01397 * String.try_convert(obj) -> string or nil 01398 * 01399 * Try to convert <i>obj</i> into a String, using to_str method. 01400 * Returns converted string or nil if <i>obj</i> cannot be converted 01401 * for any reason. 01402 * 01403 * String.try_convert("str") #=> "str" 01404 * String.try_convert(/re/) #=> nil 01405 */ 01406 static VALUE 01407 rb_str_s_try_convert(VALUE dummy, VALUE str) 01408 { 01409 return rb_check_string_type(str); 01410 } 01411 01412 char* 01413 rb_enc_nth(const char *p, const char *e, long nth, rb_encoding *enc) 01414 { 01415 if (rb_enc_mbmaxlen(enc) == 1) { 01416 p += nth; 01417 } 01418 else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) { 01419 p += nth * rb_enc_mbmaxlen(enc); 01420 } 01421 else if (rb_enc_asciicompat(enc)) { 01422 const char *p2, *e2; 01423 int n; 01424 01425 while (p < e && 0 < nth) { 01426 e2 = p + nth; 01427 if (e < e2) 01428 return (char *)e; 01429 if (ISASCII(*p)) { 01430 p2 = search_nonascii(p, e2); 01431 if (!p2) 01432 return (char *)e2; 01433 nth -= p2 - p; 01434 p = p2; 01435 } 01436 n = rb_enc_mbclen(p, e, enc); 01437 p += n; 01438 nth--; 01439 } 01440 if (nth != 0) 01441 return (char *)e; 01442 return (char *)p; 01443 } 01444 else { 01445 while (p<e && nth--) { 01446 p += rb_enc_mbclen(p, e, enc); 01447 } 01448 } 01449 if (p > e) p = e; 01450 return (char*)p; 01451 } 01452 01453 static char* 01454 str_nth(const char *p, const char *e, long nth, rb_encoding *enc, int singlebyte) 01455 { 01456 if (singlebyte) 01457 p += nth; 01458 else { 01459 p = rb_enc_nth(p, e, nth, enc); 01460 } 01461 if (!p) return 0; 01462 if (p > e) p = e; 01463 return (char *)p; 01464 } 01465 01466 /* char offset to byte offset */ 01467 static long 01468 str_offset(const char *p, const char *e, long nth, rb_encoding *enc, int singlebyte) 01469 { 01470 const char *pp = str_nth(p, e, nth, enc, singlebyte); 01471 if (!pp) return e - p; 01472 return pp - p; 01473 } 01474 01475 long 01476 rb_str_offset(VALUE str, long pos) 01477 { 01478 return str_offset(RSTRING_PTR(str), RSTRING_END(str), pos, 01479 STR_ENC_GET(str), single_byte_optimizable(str)); 01480 } 01481 01482 #ifdef NONASCII_MASK 01483 static char * 01484 str_utf8_nth(const char *p, const char *e, long nth) 01485 { 01486 if ((int)SIZEOF_VALUE < e - p && (int)SIZEOF_VALUE * 2 < nth) { 01487 const VALUE *s, *t; 01488 const VALUE lowbits = sizeof(VALUE) - 1; 01489 s = (const VALUE*)(~lowbits & ((VALUE)p + lowbits)); 01490 t = (const VALUE*)(~lowbits & (VALUE)e); 01491 while (p < (const char *)s) { 01492 if (is_utf8_lead_byte(*p)) nth--; 01493 p++; 01494 } 01495 do { 01496 nth -= count_utf8_lead_bytes_with_word(s); 01497 s++; 01498 } while (s < t && (int)sizeof(VALUE) <= nth); 01499 p = (char *)s; 01500 } 01501 while (p < e) { 01502 if (is_utf8_lead_byte(*p)) { 01503 if (nth == 0) break; 01504 nth--; 01505 } 01506 p++; 01507 } 01508 return (char *)p; 01509 } 01510 01511 static long 01512 str_utf8_offset(const char *p, const char *e, long nth) 01513 { 01514 const char *pp = str_utf8_nth(p, e, nth); 01515 return pp - p; 01516 } 01517 #endif 01518 01519 /* byte offset to char offset */ 01520 long 01521 rb_str_sublen(VALUE str, long pos) 01522 { 01523 if (single_byte_optimizable(str) || pos < 0) 01524 return pos; 01525 else { 01526 char *p = RSTRING_PTR(str); 01527 return enc_strlen(p, p + pos, STR_ENC_GET(str), ENC_CODERANGE(str)); 01528 } 01529 } 01530 01531 VALUE 01532 rb_str_subseq(VALUE str, long beg, long len) 01533 { 01534 VALUE str2; 01535 01536 if (RSTRING_LEN(str) == beg + len && 01537 RSTRING_EMBED_LEN_MAX < len) { 01538 str2 = rb_str_new_shared(rb_str_new_frozen(str)); 01539 rb_str_drop_bytes(str2, beg); 01540 } 01541 else { 01542 str2 = rb_str_new5(str, RSTRING_PTR(str)+beg, len); 01543 } 01544 01545 rb_enc_cr_str_copy_for_substr(str2, str); 01546 OBJ_INFECT(str2, str); 01547 01548 return str2; 01549 } 01550 01551 VALUE 01552 rb_str_substr(VALUE str, long beg, long len) 01553 { 01554 rb_encoding *enc = STR_ENC_GET(str); 01555 VALUE str2; 01556 char *p, *s = RSTRING_PTR(str), *e = s + RSTRING_LEN(str); 01557 01558 if (len < 0) return Qnil; 01559 if (!RSTRING_LEN(str)) { 01560 len = 0; 01561 } 01562 if (single_byte_optimizable(str)) { 01563 if (beg > RSTRING_LEN(str)) return Qnil; 01564 if (beg < 0) { 01565 beg += RSTRING_LEN(str); 01566 if (beg < 0) return Qnil; 01567 } 01568 if (beg + len > RSTRING_LEN(str)) 01569 len = RSTRING_LEN(str) - beg; 01570 if (len <= 0) { 01571 len = 0; 01572 p = 0; 01573 } 01574 else 01575 p = s + beg; 01576 goto sub; 01577 } 01578 if (beg < 0) { 01579 if (len > -beg) len = -beg; 01580 if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) { 01581 beg = -beg; 01582 while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0); 01583 p = e; 01584 if (!p) return Qnil; 01585 while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0); 01586 if (!p) return Qnil; 01587 len = e - p; 01588 goto sub; 01589 } 01590 else { 01591 beg += str_strlen(str, enc); 01592 if (beg < 0) return Qnil; 01593 } 01594 } 01595 else if (beg > 0 && beg > str_strlen(str, enc)) { 01596 return Qnil; 01597 } 01598 if (len == 0) { 01599 p = 0; 01600 } 01601 #ifdef NONASCII_MASK 01602 else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID && 01603 enc == rb_utf8_encoding()) { 01604 p = str_utf8_nth(s, e, beg); 01605 len = str_utf8_offset(p, e, len); 01606 } 01607 #endif 01608 else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) { 01609 int char_sz = rb_enc_mbmaxlen(enc); 01610 01611 p = s + beg * char_sz; 01612 if (p > e) { 01613 p = e; 01614 len = 0; 01615 } 01616 else if (len * char_sz > e - p) 01617 len = e - p; 01618 else 01619 len *= char_sz; 01620 } 01621 else if ((p = str_nth(s, e, beg, enc, 0)) == e) { 01622 len = 0; 01623 } 01624 else { 01625 len = str_offset(p, e, len, enc, 0); 01626 } 01627 sub: 01628 if (len > RSTRING_EMBED_LEN_MAX && beg + len == RSTRING_LEN(str)) { 01629 str2 = rb_str_new4(str); 01630 str2 = str_new3(rb_obj_class(str2), str2); 01631 RSTRING(str2)->as.heap.ptr += RSTRING(str2)->as.heap.len - len; 01632 RSTRING(str2)->as.heap.len = len; 01633 } 01634 else { 01635 str2 = rb_str_new5(str, p, len); 01636 rb_enc_cr_str_copy_for_substr(str2, str); 01637 OBJ_INFECT(str2, str); 01638 } 01639 01640 return str2; 01641 } 01642 01643 VALUE 01644 rb_str_freeze(VALUE str) 01645 { 01646 if (STR_ASSOC_P(str)) { 01647 VALUE ary = RSTRING(str)->as.heap.aux.shared; 01648 OBJ_FREEZE(ary); 01649 } 01650 return rb_obj_freeze(str); 01651 } 01652 01653 RUBY_ALIAS_FUNCTION(rb_str_dup_frozen(VALUE str), rb_str_new_frozen, (str)) 01654 #define rb_str_dup_frozen rb_str_new_frozen 01655 01656 VALUE 01657 rb_str_locktmp(VALUE str) 01658 { 01659 if (FL_TEST(str, STR_TMPLOCK)) { 01660 rb_raise(rb_eRuntimeError, "temporal locking already locked string"); 01661 } 01662 FL_SET(str, STR_TMPLOCK); 01663 return str; 01664 } 01665 01666 VALUE 01667 rb_str_unlocktmp(VALUE str) 01668 { 01669 if (!FL_TEST(str, STR_TMPLOCK)) { 01670 rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string"); 01671 } 01672 FL_UNSET(str, STR_TMPLOCK); 01673 return str; 01674 } 01675 01676 void 01677 rb_str_set_len(VALUE str, long len) 01678 { 01679 rb_str_modify(str); 01680 STR_SET_LEN(str, len); 01681 RSTRING_PTR(str)[len] = '\0'; 01682 } 01683 01684 VALUE 01685 rb_str_resize(VALUE str, long len) 01686 { 01687 long slen; 01688 01689 if (len < 0) { 01690 rb_raise(rb_eArgError, "negative string size (or size too big)"); 01691 } 01692 01693 rb_str_modify(str); 01694 slen = RSTRING_LEN(str); 01695 if (len != slen) { 01696 if (STR_EMBED_P(str)) { 01697 char *ptr; 01698 if (len <= RSTRING_EMBED_LEN_MAX) { 01699 STR_SET_EMBED_LEN(str, len); 01700 RSTRING(str)->as.ary[len] = '\0'; 01701 return str; 01702 } 01703 ptr = ALLOC_N(char,len+1); 01704 MEMCPY(ptr, RSTRING(str)->as.ary, char, slen); 01705 RSTRING(str)->as.heap.ptr = ptr; 01706 STR_SET_NOEMBED(str); 01707 } 01708 else if (len <= RSTRING_EMBED_LEN_MAX) { 01709 char *ptr = RSTRING(str)->as.heap.ptr; 01710 STR_SET_EMBED(str); 01711 if (slen > 0) MEMCPY(RSTRING(str)->as.ary, ptr, char, len); 01712 RSTRING(str)->as.ary[len] = '\0'; 01713 STR_SET_EMBED_LEN(str, len); 01714 xfree(ptr); 01715 return str; 01716 } 01717 else if (slen < len || slen - len > 1024) { 01718 REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1); 01719 } 01720 if (!STR_NOCAPA_P(str)) { 01721 RSTRING(str)->as.heap.aux.capa = len; 01722 } 01723 RSTRING(str)->as.heap.len = len; 01724 RSTRING(str)->as.heap.ptr[len] = '\0'; /* sentinel */ 01725 } 01726 return str; 01727 } 01728 01729 static VALUE 01730 str_buf_cat(VALUE str, const char *ptr, long len) 01731 { 01732 long capa, total, off = -1; 01733 01734 if (ptr >= RSTRING_PTR(str) && ptr <= RSTRING_END(str)) { 01735 off = ptr - RSTRING_PTR(str); 01736 } 01737 rb_str_modify(str); 01738 if (len == 0) return 0; 01739 if (STR_ASSOC_P(str)) { 01740 FL_UNSET(str, STR_ASSOC); 01741 capa = RSTRING(str)->as.heap.aux.capa = RSTRING_LEN(str); 01742 } 01743 else if (STR_EMBED_P(str)) { 01744 capa = RSTRING_EMBED_LEN_MAX; 01745 } 01746 else { 01747 capa = RSTRING(str)->as.heap.aux.capa; 01748 } 01749 if (RSTRING_LEN(str) >= LONG_MAX - len) { 01750 rb_raise(rb_eArgError, "string sizes too big"); 01751 } 01752 total = RSTRING_LEN(str)+len; 01753 if (capa <= total) { 01754 while (total > capa) { 01755 if (capa + 1 >= LONG_MAX / 2) { 01756 capa = (total + 4095) / 4096; 01757 break; 01758 } 01759 capa = (capa + 1) * 2; 01760 } 01761 RESIZE_CAPA(str, capa); 01762 } 01763 if (off != -1) { 01764 ptr = RSTRING_PTR(str) + off; 01765 } 01766 memcpy(RSTRING_PTR(str) + RSTRING_LEN(str), ptr, len); 01767 STR_SET_LEN(str, total); 01768 RSTRING_PTR(str)[total] = '\0'; /* sentinel */ 01769 01770 return str; 01771 } 01772 01773 #define str_buf_cat2(str, ptr) str_buf_cat(str, (ptr), strlen(ptr)) 01774 01775 VALUE 01776 rb_str_buf_cat(VALUE str, const char *ptr, long len) 01777 { 01778 if (len == 0) return str; 01779 if (len < 0) { 01780 rb_raise(rb_eArgError, "negative string size (or size too big)"); 01781 } 01782 return str_buf_cat(str, ptr, len); 01783 } 01784 01785 VALUE 01786 rb_str_buf_cat2(VALUE str, const char *ptr) 01787 { 01788 return rb_str_buf_cat(str, ptr, strlen(ptr)); 01789 } 01790 01791 VALUE 01792 rb_str_cat(VALUE str, const char *ptr, long len) 01793 { 01794 if (len < 0) { 01795 rb_raise(rb_eArgError, "negative string size (or size too big)"); 01796 } 01797 if (STR_ASSOC_P(str)) { 01798 rb_str_modify(str); 01799 if (STR_EMBED_P(str)) str_make_independent(str); 01800 REALLOC_N(RSTRING(str)->as.heap.ptr, char, RSTRING(str)->as.heap.len+len+1); 01801 memcpy(RSTRING(str)->as.heap.ptr + RSTRING(str)->as.heap.len, ptr, len); 01802 RSTRING(str)->as.heap.len += len; 01803 RSTRING(str)->as.heap.ptr[RSTRING(str)->as.heap.len] = '\0'; /* sentinel */ 01804 return str; 01805 } 01806 01807 return rb_str_buf_cat(str, ptr, len); 01808 } 01809 01810 VALUE 01811 rb_str_cat2(VALUE str, const char *ptr) 01812 { 01813 return rb_str_cat(str, ptr, strlen(ptr)); 01814 } 01815 01816 static VALUE 01817 rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len, 01818 int ptr_encindex, int ptr_cr, int *ptr_cr_ret) 01819 { 01820 int str_encindex = ENCODING_GET(str); 01821 int res_encindex; 01822 int str_cr, res_cr; 01823 int str_a8 = ENCODING_IS_ASCII8BIT(str); 01824 int ptr_a8 = ptr_encindex == 0; 01825 01826 str_cr = ENC_CODERANGE(str); 01827 01828 if (str_encindex == ptr_encindex) { 01829 if (str_cr == ENC_CODERANGE_UNKNOWN || 01830 (ptr_a8 && str_cr != ENC_CODERANGE_7BIT)) { 01831 ptr_cr = ENC_CODERANGE_UNKNOWN; 01832 } 01833 else if (ptr_cr == ENC_CODERANGE_UNKNOWN) { 01834 ptr_cr = coderange_scan(ptr, len, rb_enc_from_index(ptr_encindex)); 01835 } 01836 } 01837 else { 01838 rb_encoding *str_enc = rb_enc_from_index(str_encindex); 01839 rb_encoding *ptr_enc = rb_enc_from_index(ptr_encindex); 01840 if (!rb_enc_asciicompat(str_enc) || !rb_enc_asciicompat(ptr_enc)) { 01841 if (len == 0) 01842 return str; 01843 if (RSTRING_LEN(str) == 0) { 01844 rb_str_buf_cat(str, ptr, len); 01845 ENCODING_CODERANGE_SET(str, ptr_encindex, ptr_cr); 01846 return str; 01847 } 01848 goto incompatible; 01849 } 01850 if (ptr_cr == ENC_CODERANGE_UNKNOWN) { 01851 ptr_cr = coderange_scan(ptr, len, ptr_enc); 01852 } 01853 if (str_cr == ENC_CODERANGE_UNKNOWN) { 01854 if (str_a8 || ptr_cr != ENC_CODERANGE_7BIT) { 01855 str_cr = rb_enc_str_coderange(str); 01856 } 01857 } 01858 } 01859 if (ptr_cr_ret) 01860 *ptr_cr_ret = ptr_cr; 01861 01862 if (str_encindex != ptr_encindex && 01863 str_cr != ENC_CODERANGE_7BIT && 01864 ptr_cr != ENC_CODERANGE_7BIT) { 01865 incompatible: 01866 rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s", 01867 rb_enc_name(rb_enc_from_index(str_encindex)), 01868 rb_enc_name(rb_enc_from_index(ptr_encindex))); 01869 } 01870 01871 if (str_cr == ENC_CODERANGE_UNKNOWN) { 01872 res_encindex = str_encindex; 01873 res_cr = ENC_CODERANGE_UNKNOWN; 01874 } 01875 else if (str_cr == ENC_CODERANGE_7BIT) { 01876 if (ptr_cr == ENC_CODERANGE_7BIT) { 01877 res_encindex = !str_a8 ? str_encindex : ptr_encindex; 01878 res_cr = ENC_CODERANGE_7BIT; 01879 } 01880 else { 01881 res_encindex = ptr_encindex; 01882 res_cr = ptr_cr; 01883 } 01884 } 01885 else if (str_cr == ENC_CODERANGE_VALID) { 01886 res_encindex = str_encindex; 01887 if (ptr_cr == ENC_CODERANGE_7BIT || ptr_cr == ENC_CODERANGE_VALID) 01888 res_cr = str_cr; 01889 else 01890 res_cr = ptr_cr; 01891 } 01892 else { /* str_cr == ENC_CODERANGE_BROKEN */ 01893 res_encindex = str_encindex; 01894 res_cr = str_cr; 01895 if (0 < len) res_cr = ENC_CODERANGE_UNKNOWN; 01896 } 01897 01898 if (len < 0) { 01899 rb_raise(rb_eArgError, "negative string size (or size too big)"); 01900 } 01901 str_buf_cat(str, ptr, len); 01902 ENCODING_CODERANGE_SET(str, res_encindex, res_cr); 01903 return str; 01904 } 01905 01906 VALUE 01907 rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *ptr_enc) 01908 { 01909 return rb_enc_cr_str_buf_cat(str, ptr, len, 01910 rb_enc_to_index(ptr_enc), ENC_CODERANGE_UNKNOWN, NULL); 01911 } 01912 01913 VALUE 01914 rb_str_buf_cat_ascii(VALUE str, const char *ptr) 01915 { 01916 /* ptr must reference NUL terminated ASCII string. */ 01917 int encindex = ENCODING_GET(str); 01918 rb_encoding *enc = rb_enc_from_index(encindex); 01919 if (rb_enc_asciicompat(enc)) { 01920 return rb_enc_cr_str_buf_cat(str, ptr, strlen(ptr), 01921 encindex, ENC_CODERANGE_7BIT, 0); 01922 } 01923 else { 01924 char *buf = ALLOCA_N(char, rb_enc_mbmaxlen(enc)); 01925 while (*ptr) { 01926 unsigned int c = (unsigned char)*ptr; 01927 int len = rb_enc_codelen(c, enc); 01928 rb_enc_mbcput(c, buf, enc); 01929 rb_enc_cr_str_buf_cat(str, buf, len, 01930 encindex, ENC_CODERANGE_VALID, 0); 01931 ptr++; 01932 } 01933 return str; 01934 } 01935 } 01936 01937 VALUE 01938 rb_str_buf_append(VALUE str, VALUE str2) 01939 { 01940 int str2_cr; 01941 01942 str2_cr = ENC_CODERANGE(str2); 01943 01944 rb_enc_cr_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2), 01945 ENCODING_GET(str2), str2_cr, &str2_cr); 01946 01947 OBJ_INFECT(str, str2); 01948 ENC_CODERANGE_SET(str2, str2_cr); 01949 01950 return str; 01951 } 01952 01953 VALUE 01954 rb_str_append(VALUE str, VALUE str2) 01955 { 01956 rb_encoding *enc; 01957 int cr, cr2; 01958 01959 StringValue(str2); 01960 if (RSTRING_LEN(str2) > 0 && STR_ASSOC_P(str)) { 01961 long len = RSTRING_LEN(str)+RSTRING_LEN(str2); 01962 enc = rb_enc_check(str, str2); 01963 cr = ENC_CODERANGE(str); 01964 if ((cr2 = ENC_CODERANGE(str2)) > cr) cr = cr2; 01965 rb_str_modify(str); 01966 REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1); 01967 memcpy(RSTRING(str)->as.heap.ptr + RSTRING(str)->as.heap.len, 01968 RSTRING_PTR(str2), RSTRING_LEN(str2)+1); 01969 RSTRING(str)->as.heap.len = len; 01970 rb_enc_associate(str, enc); 01971 ENC_CODERANGE_SET(str, cr); 01972 OBJ_INFECT(str, str2); 01973 return str; 01974 } 01975 return rb_str_buf_append(str, str2); 01976 } 01977 01978 01979 /* 01980 * call-seq: 01981 * str << integer -> str 01982 * str.concat(integer) -> str 01983 * str << obj -> str 01984 * str.concat(obj) -> str 01985 * 01986 * Append---Concatenates the given object to <i>str</i>. If the object is a 01987 * <code>Integer</code>, it is considered as a codepoint, and is converted 01988 * to a character before concatenation. 01989 * 01990 * a = "hello " 01991 * a << "world" #=> "hello world" 01992 * a.concat(33) #=> "hello world!" 01993 */ 01994 01995 VALUE 01996 rb_str_concat(VALUE str1, VALUE str2) 01997 { 01998 unsigned int lc; 01999 02000 if (FIXNUM_P(str2)) { 02001 if ((int)str2 < 0) 02002 rb_raise(rb_eRangeError, "negative argument"); 02003 lc = FIX2UINT(str2); 02004 } 02005 else if (TYPE(str2) == T_BIGNUM) { 02006 if (!RBIGNUM_SIGN(str2)) 02007 rb_raise(rb_eRangeError, "negative argument"); 02008 lc = NUM2UINT(str2); 02009 } 02010 else { 02011 return rb_str_append(str1, str2); 02012 } 02013 #if SIZEOF_INT < SIZEOF_VALUE 02014 if ((VALUE)lc > UINT_MAX) { 02015 rb_raise(rb_eRangeError, "%"PRIuVALUE" out of char range", lc); 02016 } 02017 #endif 02018 { 02019 rb_encoding *enc = STR_ENC_GET(str1); 02020 long pos = RSTRING_LEN(str1); 02021 int cr = ENC_CODERANGE(str1); 02022 int len; 02023 02024 if ((len = rb_enc_codelen(lc, enc)) <= 0) { 02025 rb_raise(rb_eRangeError, "%u invalid char", lc); 02026 } 02027 rb_str_resize(str1, pos+len); 02028 rb_enc_mbcput(lc, RSTRING_PTR(str1)+pos, enc); 02029 if (cr == ENC_CODERANGE_7BIT && lc > 127) 02030 cr = ENC_CODERANGE_VALID; 02031 ENC_CODERANGE_SET(str1, cr); 02032 return str1; 02033 } 02034 } 02035 02036 st_index_t 02037 rb_memhash(const void *ptr, long len) 02038 { 02039 return st_hash(ptr, len, rb_hash_start(0)); 02040 } 02041 02042 st_index_t 02043 rb_str_hash(VALUE str) 02044 { 02045 int e = ENCODING_GET(str); 02046 if (e && rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) { 02047 e = 0; 02048 } 02049 return rb_memhash((const void *)RSTRING_PTR(str), RSTRING_LEN(str)) ^ e; 02050 } 02051 02052 int 02053 rb_str_hash_cmp(VALUE str1, VALUE str2) 02054 { 02055 long len; 02056 02057 if (!rb_str_comparable(str1, str2)) return 1; 02058 if (RSTRING_LEN(str1) == (len = RSTRING_LEN(str2)) && 02059 memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len) == 0) { 02060 return 0; 02061 } 02062 return 1; 02063 } 02064 02065 /* 02066 * call-seq: 02067 * str.hash -> fixnum 02068 * 02069 * Return a hash based on the string's length and content. 02070 */ 02071 02072 static VALUE 02073 rb_str_hash_m(VALUE str) 02074 { 02075 st_index_t hval = rb_str_hash(str); 02076 return INT2FIX(hval); 02077 } 02078 02079 #define lesser(a,b) (((a)>(b))?(b):(a)) 02080 02081 int 02082 rb_str_comparable(VALUE str1, VALUE str2) 02083 { 02084 int idx1, idx2; 02085 int rc1, rc2; 02086 02087 if (RSTRING_LEN(str1) == 0) return TRUE; 02088 if (RSTRING_LEN(str2) == 0) return TRUE; 02089 idx1 = ENCODING_GET(str1); 02090 idx2 = ENCODING_GET(str2); 02091 if (idx1 == idx2) return TRUE; 02092 rc1 = rb_enc_str_coderange(str1); 02093 rc2 = rb_enc_str_coderange(str2); 02094 if (rc1 == ENC_CODERANGE_7BIT) { 02095 if (rc2 == ENC_CODERANGE_7BIT) return TRUE; 02096 if (rb_enc_asciicompat(rb_enc_from_index(idx2))) 02097 return TRUE; 02098 } 02099 if (rc2 == ENC_CODERANGE_7BIT) { 02100 if (rb_enc_asciicompat(rb_enc_from_index(idx1))) 02101 return TRUE; 02102 } 02103 return FALSE; 02104 } 02105 02106 int 02107 rb_str_cmp(VALUE str1, VALUE str2) 02108 { 02109 long len; 02110 int retval; 02111 02112 len = lesser(RSTRING_LEN(str1), RSTRING_LEN(str2)); 02113 retval = memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len); 02114 if (retval == 0) { 02115 if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) { 02116 if (!rb_str_comparable(str1, str2)) { 02117 if (ENCODING_GET(str1) > ENCODING_GET(str2)) 02118 return 1; 02119 return -1; 02120 } 02121 return 0; 02122 } 02123 if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return 1; 02124 return -1; 02125 } 02126 if (retval > 0) return 1; 02127 return -1; 02128 } 02129 02130 /* expect tail call optimization */ 02131 static VALUE 02132 str_eql(const VALUE str1, const VALUE str2) 02133 { 02134 const long len = RSTRING_LEN(str1); 02135 02136 if (len != RSTRING_LEN(str2)) return Qfalse; 02137 if (!rb_str_comparable(str1, str2)) return Qfalse; 02138 if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len) == 0) 02139 return Qtrue; 02140 return Qfalse; 02141 } 02142 /* 02143 * call-seq: 02144 * str == obj -> true or false 02145 * 02146 * Equality---If <i>obj</i> is not a <code>String</code>, returns 02147 * <code>false</code>. Otherwise, returns <code>true</code> if <i>str</i> 02148 * <code><=></code> <i>obj</i> returns zero. 02149 */ 02150 02151 VALUE 02152 rb_str_equal(VALUE str1, VALUE str2) 02153 { 02154 if (str1 == str2) return Qtrue; 02155 if (TYPE(str2) != T_STRING) { 02156 if (!rb_respond_to(str2, rb_intern("to_str"))) { 02157 return Qfalse; 02158 } 02159 return rb_equal(str2, str1); 02160 } 02161 return str_eql(str1, str2); 02162 } 02163 02164 /* 02165 * call-seq: 02166 * str.eql?(other) -> true or false 02167 * 02168 * Two strings are equal if they have the same length and content. 02169 */ 02170 02171 static VALUE 02172 rb_str_eql(VALUE str1, VALUE str2) 02173 { 02174 if (TYPE(str2) != T_STRING) return Qfalse; 02175 return str_eql(str1, str2); 02176 } 02177 02178 /* 02179 * call-seq: 02180 * str <=> other_str -> -1, 0, +1 or nil 02181 * 02182 * Comparison---Returns -1 if <i>other_str</i> is greater than, 0 if 02183 * <i>other_str</i> is equal to, and +1 if <i>other_str</i> is less than 02184 * <i>str</i>. If the strings are of different lengths, and the strings are 02185 * equal when compared up to the shortest length, then the longer string is 02186 * considered greater than the shorter one. In older versions of Ruby, setting 02187 * <code>$=</code> allowed case-insensitive comparisons; this is now deprecated 02188 * in favor of using <code>String#casecmp</code>. 02189 * 02190 * <code><=></code> is the basis for the methods <code><</code>, 02191 * <code><=</code>, <code>></code>, <code>>=</code>, and <code>between?</code>, 02192 * included from module <code>Comparable</code>. The method 02193 * <code>String#==</code> does not use <code>Comparable#==</code>. 02194 * 02195 * "abcdef" <=> "abcde" #=> 1 02196 * "abcdef" <=> "abcdef" #=> 0 02197 * "abcdef" <=> "abcdefg" #=> -1 02198 * "abcdef" <=> "ABCDEF" #=> 1 02199 */ 02200 02201 static VALUE 02202 rb_str_cmp_m(VALUE str1, VALUE str2) 02203 { 02204 long result; 02205 02206 if (TYPE(str2) != T_STRING) { 02207 if (!rb_respond_to(str2, rb_intern("to_str"))) { 02208 return Qnil; 02209 } 02210 else if (!rb_respond_to(str2, rb_intern("<=>"))) { 02211 return Qnil; 02212 } 02213 else { 02214 VALUE tmp = rb_funcall(str2, rb_intern("<=>"), 1, str1); 02215 02216 if (NIL_P(tmp)) return Qnil; 02217 if (!FIXNUM_P(tmp)) { 02218 return rb_funcall(LONG2FIX(0), '-', 1, tmp); 02219 } 02220 result = -FIX2LONG(tmp); 02221 } 02222 } 02223 else { 02224 result = rb_str_cmp(str1, str2); 02225 } 02226 return LONG2NUM(result); 02227 } 02228 02229 /* 02230 * call-seq: 02231 * str.casecmp(other_str) -> -1, 0, +1 or nil 02232 * 02233 * Case-insensitive version of <code>String#<=></code>. 02234 * 02235 * "abcdef".casecmp("abcde") #=> 1 02236 * "aBcDeF".casecmp("abcdef") #=> 0 02237 * "abcdef".casecmp("abcdefg") #=> -1 02238 * "abcdef".casecmp("ABCDEF") #=> 0 02239 */ 02240 02241 static VALUE 02242 rb_str_casecmp(VALUE str1, VALUE str2) 02243 { 02244 long len; 02245 rb_encoding *enc; 02246 char *p1, *p1end, *p2, *p2end; 02247 02248 StringValue(str2); 02249 enc = rb_enc_compatible(str1, str2); 02250 if (!enc) { 02251 return Qnil; 02252 } 02253 02254 p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1); 02255 p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2); 02256 if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) { 02257 while (p1 < p1end && p2 < p2end) { 02258 if (*p1 != *p2) { 02259 unsigned int c1 = TOUPPER(*p1 & 0xff); 02260 unsigned int c2 = TOUPPER(*p2 & 0xff); 02261 if (c1 != c2) 02262 return INT2FIX(c1 < c2 ? -1 : 1); 02263 } 02264 p1++; 02265 p2++; 02266 } 02267 } 02268 else { 02269 while (p1 < p1end && p2 < p2end) { 02270 int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc); 02271 int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc); 02272 02273 if (0 <= c1 && 0 <= c2) { 02274 c1 = TOUPPER(c1); 02275 c2 = TOUPPER(c2); 02276 if (c1 != c2) 02277 return INT2FIX(c1 < c2 ? -1 : 1); 02278 } 02279 else { 02280 int r; 02281 l1 = rb_enc_mbclen(p1, p1end, enc); 02282 l2 = rb_enc_mbclen(p2, p2end, enc); 02283 len = l1 < l2 ? l1 : l2; 02284 r = memcmp(p1, p2, len); 02285 if (r != 0) 02286 return INT2FIX(r < 0 ? -1 : 1); 02287 if (l1 != l2) 02288 return INT2FIX(l1 < l2 ? -1 : 1); 02289 } 02290 p1 += l1; 02291 p2 += l2; 02292 } 02293 } 02294 if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0); 02295 if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1); 02296 return INT2FIX(-1); 02297 } 02298 02299 static long 02300 rb_str_index(VALUE str, VALUE sub, long offset) 02301 { 02302 long pos; 02303 char *s, *sptr, *e; 02304 long len, slen; 02305 rb_encoding *enc; 02306 02307 enc = rb_enc_check(str, sub); 02308 if (is_broken_string(sub)) { 02309 return -1; 02310 } 02311 len = str_strlen(str, enc); 02312 slen = str_strlen(sub, enc); 02313 if (offset < 0) { 02314 offset += len; 02315 if (offset < 0) return -1; 02316 } 02317 if (len - offset < slen) return -1; 02318 s = RSTRING_PTR(str); 02319 e = s + RSTRING_LEN(str); 02320 if (offset) { 02321 offset = str_offset(s, RSTRING_END(str), offset, enc, single_byte_optimizable(str)); 02322 s += offset; 02323 } 02324 if (slen == 0) return offset; 02325 /* need proceed one character at a time */ 02326 sptr = RSTRING_PTR(sub); 02327 slen = RSTRING_LEN(sub); 02328 len = RSTRING_LEN(str) - offset; 02329 for (;;) { 02330 char *t; 02331 pos = rb_memsearch(sptr, slen, s, len, enc); 02332 if (pos < 0) return pos; 02333 t = rb_enc_right_char_head(s, s+pos, e, enc); 02334 if (t == s + pos) break; 02335 if ((len -= t - s) <= 0) return -1; 02336 offset += t - s; 02337 s = t; 02338 } 02339 return pos + offset; 02340 } 02341 02342 02343 /* 02344 * call-seq: 02345 * str.index(substring [, offset]) -> fixnum or nil 02346 * str.index(regexp [, offset]) -> fixnum or nil 02347 * 02348 * Returns the index of the first occurrence of the given <i>substring</i> or 02349 * pattern (<i>regexp</i>) in <i>str</i>. Returns <code>nil</code> if not 02350 * found. If the second parameter is present, it specifies the position in the 02351 * string to begin the search. 02352 * 02353 * "hello".index('e') #=> 1 02354 * "hello".index('lo') #=> 3 02355 * "hello".index('a') #=> nil 02356 * "hello".index(?e) #=> 1 02357 * "hello".index(/[aeiou]/, -3) #=> 4 02358 */ 02359 02360 static VALUE 02361 rb_str_index_m(int argc, VALUE *argv, VALUE str) 02362 { 02363 VALUE sub; 02364 VALUE initpos; 02365 long pos; 02366 02367 if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) { 02368 pos = NUM2LONG(initpos); 02369 } 02370 else { 02371 pos = 0; 02372 } 02373 if (pos < 0) { 02374 pos += str_strlen(str, STR_ENC_GET(str)); 02375 if (pos < 0) { 02376 if (TYPE(sub) == T_REGEXP) { 02377 rb_backref_set(Qnil); 02378 } 02379 return Qnil; 02380 } 02381 } 02382 02383 switch (TYPE(sub)) { 02384 case T_REGEXP: 02385 if (pos > str_strlen(str, STR_ENC_GET(str))) 02386 return Qnil; 02387 pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos, 02388 rb_enc_check(str, sub), single_byte_optimizable(str)); 02389 02390 pos = rb_reg_search(sub, str, pos, 0); 02391 pos = rb_str_sublen(str, pos); 02392 break; 02393 02394 default: { 02395 VALUE tmp; 02396 02397 tmp = rb_check_string_type(sub); 02398 if (NIL_P(tmp)) { 02399 rb_raise(rb_eTypeError, "type mismatch: %s given", 02400 rb_obj_classname(sub)); 02401 } 02402 sub = tmp; 02403 } 02404 /* fall through */ 02405 case T_STRING: 02406 pos = rb_str_index(str, sub, pos); 02407 pos = rb_str_sublen(str, pos); 02408 break; 02409 } 02410 02411 if (pos == -1) return Qnil; 02412 return LONG2NUM(pos); 02413 } 02414 02415 static long 02416 rb_str_rindex(VALUE str, VALUE sub, long pos) 02417 { 02418 long len, slen; 02419 char *s, *sbeg, *e, *t; 02420 rb_encoding *enc; 02421 int singlebyte = single_byte_optimizable(str); 02422 02423 enc = rb_enc_check(str, sub); 02424 if (is_broken_string(sub)) { 02425 return -1; 02426 } 02427 len = str_strlen(str, enc); 02428 slen = str_strlen(sub, enc); 02429 /* substring longer than string */ 02430 if (len < slen) return -1; 02431 if (len - pos < slen) { 02432 pos = len - slen; 02433 } 02434 if (len == 0) { 02435 return pos; 02436 } 02437 sbeg = RSTRING_PTR(str); 02438 e = RSTRING_END(str); 02439 t = RSTRING_PTR(sub); 02440 slen = RSTRING_LEN(sub); 02441 for (;;) { 02442 s = str_nth(sbeg, e, pos, enc, singlebyte); 02443 if (!s) return -1; 02444 if (memcmp(s, t, slen) == 0) { 02445 return pos; 02446 } 02447 if (pos == 0) break; 02448 pos--; 02449 } 02450 return -1; 02451 } 02452 02453 02454 /* 02455 * call-seq: 02456 * str.rindex(substring [, fixnum]) -> fixnum or nil 02457 * str.rindex(regexp [, fixnum]) -> fixnum or nil 02458 * 02459 * Returns the index of the last occurrence of the given <i>substring</i> or 02460 * pattern (<i>regexp</i>) in <i>str</i>. Returns <code>nil</code> if not 02461 * found. If the second parameter is present, it specifies the position in the 02462 * string to end the search---characters beyond this point will not be 02463 * considered. 02464 * 02465 * "hello".rindex('e') #=> 1 02466 * "hello".rindex('l') #=> 3 02467 * "hello".rindex('a') #=> nil 02468 * "hello".rindex(?e) #=> 1 02469 * "hello".rindex(/[aeiou]/, -2) #=> 1 02470 */ 02471 02472 static VALUE 02473 rb_str_rindex_m(int argc, VALUE *argv, VALUE str) 02474 { 02475 VALUE sub; 02476 VALUE vpos; 02477 rb_encoding *enc = STR_ENC_GET(str); 02478 long pos, len = str_strlen(str, enc); 02479 02480 if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) { 02481 pos = NUM2LONG(vpos); 02482 if (pos < 0) { 02483 pos += len; 02484 if (pos < 0) { 02485 if (TYPE(sub) == T_REGEXP) { 02486 rb_backref_set(Qnil); 02487 } 02488 return Qnil; 02489 } 02490 } 02491 if (pos > len) pos = len; 02492 } 02493 else { 02494 pos = len; 02495 } 02496 02497 switch (TYPE(sub)) { 02498 case T_REGEXP: 02499 /* enc = rb_get_check(str, sub); */ 02500 pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos, 02501 STR_ENC_GET(str), single_byte_optimizable(str)); 02502 02503 if (!RREGEXP(sub)->ptr || RREGEXP_SRC_LEN(sub)) { 02504 pos = rb_reg_search(sub, str, pos, 1); 02505 pos = rb_str_sublen(str, pos); 02506 } 02507 if (pos >= 0) return LONG2NUM(pos); 02508 break; 02509 02510 default: { 02511 VALUE tmp; 02512 02513 tmp = rb_check_string_type(sub); 02514 if (NIL_P(tmp)) { 02515 rb_raise(rb_eTypeError, "type mismatch: %s given", 02516 rb_obj_classname(sub)); 02517 } 02518 sub = tmp; 02519 } 02520 /* fall through */ 02521 case T_STRING: 02522 pos = rb_str_rindex(str, sub, pos); 02523 if (pos >= 0) return LONG2NUM(pos); 02524 break; 02525 } 02526 return Qnil; 02527 } 02528 02529 /* 02530 * call-seq: 02531 * str =~ obj -> fixnum or nil 02532 * 02533 * Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match 02534 * against <i>str</i>,and returns the position the match starts, or 02535 * <code>nil</code> if there is no match. Otherwise, invokes 02536 * <i>obj.=~</i>, passing <i>str</i> as an argument. The default 02537 * <code>=~</code> in <code>Object</code> returns <code>false</code>. 02538 * 02539 * "cat o' 9 tails" =~ /\d/ #=> 7 02540 * "cat o' 9 tails" =~ 9 #=> nil 02541 */ 02542 02543 static VALUE 02544 rb_str_match(VALUE x, VALUE y) 02545 { 02546 switch (TYPE(y)) { 02547 case T_STRING: 02548 rb_raise(rb_eTypeError, "type mismatch: String given"); 02549 02550 case T_REGEXP: 02551 return rb_reg_match(y, x); 02552 02553 default: 02554 return rb_funcall(y, rb_intern("=~"), 1, x); 02555 } 02556 } 02557 02558 02559 static VALUE get_pat(VALUE, int); 02560 02561 02562 /* 02563 * call-seq: 02564 * str.match(pattern) -> matchdata or nil 02565 * str.match(pattern, pos) -> matchdata or nil 02566 * 02567 * Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one), 02568 * then invokes its <code>match</code> method on <i>str</i>. If the second 02569 * parameter is present, it specifies the position in the string to begin the 02570 * search. 02571 * If the second parameter is present, it specifies the position in the string 02572 * to begin the search. 02573 * 02574 * 'hello'.match('(.)\1') #=> #<MatchData "ll" 1:"l"> 02575 * 'hello'.match('(.)\1')[0] #=> "ll" 02576 * 'hello'.match(/(.)\1/)[0] #=> "ll" 02577 * 'hello'.match('xx') #=> nil 02578 * 02579 * If a block is given, invoke the block with MatchData if match succeed, so 02580 * that you can write 02581 * 02582 * str.match(pat) {|m| ...} 02583 * 02584 * instead of 02585 * 02586 * if m = str.match(pat) 02587 * ... 02588 * end 02589 * 02590 * The return value is a value from block execution in this case. 02591 */ 02592 02593 static VALUE 02594 rb_str_match_m(int argc, VALUE *argv, VALUE str) 02595 { 02596 VALUE re, result; 02597 if (argc < 1) 02598 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc); 02599 re = argv[0]; 02600 argv[0] = str; 02601 result = rb_funcall2(get_pat(re, 0), rb_intern("match"), argc, argv); 02602 if (!NIL_P(result) && rb_block_given_p()) { 02603 return rb_yield(result); 02604 } 02605 return result; 02606 } 02607 02608 enum neighbor_char { 02609 NEIGHBOR_NOT_CHAR, 02610 NEIGHBOR_FOUND, 02611 NEIGHBOR_WRAPPED 02612 }; 02613 02614 static enum neighbor_char 02615 enc_succ_char(char *p, long len, rb_encoding *enc) 02616 { 02617 long i; 02618 int l; 02619 while (1) { 02620 for (i = len-1; 0 <= i && (unsigned char)p[i] == 0xff; i--) 02621 p[i] = '\0'; 02622 if (i < 0) 02623 return NEIGHBOR_WRAPPED; 02624 ++((unsigned char*)p)[i]; 02625 l = rb_enc_precise_mbclen(p, p+len, enc); 02626 if (MBCLEN_CHARFOUND_P(l)) { 02627 l = MBCLEN_CHARFOUND_LEN(l); 02628 if (l == len) { 02629 return NEIGHBOR_FOUND; 02630 } 02631 else { 02632 memset(p+l, 0xff, len-l); 02633 } 02634 } 02635 if (MBCLEN_INVALID_P(l) && i < len-1) { 02636 long len2; 02637 int l2; 02638 for (len2 = len-1; 0 < len2; len2--) { 02639 l2 = rb_enc_precise_mbclen(p, p+len2, enc); 02640 if (!MBCLEN_INVALID_P(l2)) 02641 break; 02642 } 02643 memset(p+len2+1, 0xff, len-(len2+1)); 02644 } 02645 } 02646 } 02647 02648 static enum neighbor_char 02649 enc_pred_char(char *p, long len, rb_encoding *enc) 02650 { 02651 long i; 02652 int l; 02653 while (1) { 02654 for (i = len-1; 0 <= i && (unsigned char)p[i] == 0; i--) 02655 p[i] = '\xff'; 02656 if (i < 0) 02657 return NEIGHBOR_WRAPPED; 02658 --((unsigned char*)p)[i]; 02659 l = rb_enc_precise_mbclen(p, p+len, enc); 02660 if (MBCLEN_CHARFOUND_P(l)) { 02661 l = MBCLEN_CHARFOUND_LEN(l); 02662 if (l == len) { 02663 return NEIGHBOR_FOUND; 02664 } 02665 else { 02666 memset(p+l, 0, len-l); 02667 } 02668 } 02669 if (MBCLEN_INVALID_P(l) && i < len-1) { 02670 long len2; 02671 int l2; 02672 for (len2 = len-1; 0 < len2; len2--) { 02673 l2 = rb_enc_precise_mbclen(p, p+len2, enc); 02674 if (!MBCLEN_INVALID_P(l2)) 02675 break; 02676 } 02677 memset(p+len2+1, 0, len-(len2+1)); 02678 } 02679 } 02680 } 02681 02682 /* 02683 overwrite +p+ by succeeding letter in +enc+ and returns 02684 NEIGHBOR_FOUND or NEIGHBOR_WRAPPED. 02685 When NEIGHBOR_WRAPPED, carried-out letter is stored into carry. 02686 assuming each ranges are successive, and mbclen 02687 never change in each ranges. 02688 NEIGHBOR_NOT_CHAR is returned if invalid character or the range has only one 02689 character. 02690 */ 02691 static enum neighbor_char 02692 enc_succ_alnum_char(char *p, long len, rb_encoding *enc, char *carry) 02693 { 02694 enum neighbor_char ret; 02695 unsigned int c; 02696 int ctype; 02697 int range; 02698 char save[ONIGENC_CODE_TO_MBC_MAXLEN]; 02699 02700 c = rb_enc_mbc_to_codepoint(p, p+len, enc); 02701 if (rb_enc_isctype(c, ONIGENC_CTYPE_DIGIT, enc)) 02702 ctype = ONIGENC_CTYPE_DIGIT; 02703 else if (rb_enc_isctype(c, ONIGENC_CTYPE_ALPHA, enc)) 02704 ctype = ONIGENC_CTYPE_ALPHA; 02705 else 02706 return NEIGHBOR_NOT_CHAR; 02707 02708 MEMCPY(save, p, char, len); 02709 ret = enc_succ_char(p, len, enc); 02710 if (ret == NEIGHBOR_FOUND) { 02711 c = rb_enc_mbc_to_codepoint(p, p+len, enc); 02712 if (rb_enc_isctype(c, ctype, enc)) 02713 return NEIGHBOR_FOUND; 02714 } 02715 MEMCPY(p, save, char, len); 02716 range = 1; 02717 while (1) { 02718 MEMCPY(save, p, char, len); 02719 ret = enc_pred_char(p, len, enc); 02720 if (ret == NEIGHBOR_FOUND) { 02721 c = rb_enc_mbc_to_codepoint(p, p+len, enc); 02722 if (!rb_enc_isctype(c, ctype, enc)) { 02723 MEMCPY(p, save, char, len); 02724 break; 02725 } 02726 } 02727 else { 02728 MEMCPY(p, save, char, len); 02729 break; 02730 } 02731 range++; 02732 } 02733 if (range == 1) { 02734 return NEIGHBOR_NOT_CHAR; 02735 } 02736 02737 if (ctype != ONIGENC_CTYPE_DIGIT) { 02738 MEMCPY(carry, p, char, len); 02739 return NEIGHBOR_WRAPPED; 02740 } 02741 02742 MEMCPY(carry, p, char, len); 02743 enc_succ_char(carry, len, enc); 02744 return NEIGHBOR_WRAPPED; 02745 } 02746 02747 02748 /* 02749 * call-seq: 02750 * str.succ -> new_str 02751 * str.next -> new_str 02752 * 02753 * Returns the successor to <i>str</i>. The successor is calculated by 02754 * incrementing characters starting from the rightmost alphanumeric (or 02755 * the rightmost character if there are no alphanumerics) in the 02756 * string. Incrementing a digit always results in another digit, and 02757 * incrementing a letter results in another letter of the same case. 02758 * Incrementing nonalphanumerics uses the underlying character set's 02759 * collating sequence. 02760 * 02761 * If the increment generates a ``carry,'' the character to the left of 02762 * it is incremented. This process repeats until there is no carry, 02763 * adding an additional character if necessary. 02764 * 02765 * "abcd".succ #=> "abce" 02766 * "THX1138".succ #=> "THX1139" 02767 * "<<koala>>".succ #=> "<<koalb>>" 02768 * "1999zzz".succ #=> "2000aaa" 02769 * "ZZZ9999".succ #=> "AAAA0000" 02770 * "***".succ #=> "**+" 02771 */ 02772 02773 VALUE 02774 rb_str_succ(VALUE orig) 02775 { 02776 rb_encoding *enc; 02777 VALUE str; 02778 char *sbeg, *s, *e, *last_alnum = 0; 02779 int c = -1; 02780 long l; 02781 char carry[ONIGENC_CODE_TO_MBC_MAXLEN] = "\1"; 02782 long carry_pos = 0, carry_len = 1; 02783 enum neighbor_char neighbor = NEIGHBOR_FOUND; 02784 02785 str = rb_str_new5(orig, RSTRING_PTR(orig), RSTRING_LEN(orig)); 02786 rb_enc_cr_str_copy_for_substr(str, orig); 02787 OBJ_INFECT(str, orig); 02788 if (RSTRING_LEN(str) == 0) return str; 02789 02790 enc = STR_ENC_GET(orig); 02791 sbeg = RSTRING_PTR(str); 02792 s = e = sbeg + RSTRING_LEN(str); 02793 02794 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) { 02795 if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) { 02796 if (ISALPHA(*last_alnum) ? ISDIGIT(*s) : 02797 ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) { 02798 s = last_alnum; 02799 break; 02800 } 02801 } 02802 if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue; 02803 neighbor = enc_succ_alnum_char(s, l, enc, carry); 02804 switch (neighbor) { 02805 case NEIGHBOR_NOT_CHAR: 02806 continue; 02807 case NEIGHBOR_FOUND: 02808 return str; 02809 case NEIGHBOR_WRAPPED: 02810 last_alnum = s; 02811 break; 02812 } 02813 c = 1; 02814 carry_pos = s - sbeg; 02815 carry_len = l; 02816 } 02817 if (c == -1) { /* str contains no alnum */ 02818 s = e; 02819 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) { 02820 enum neighbor_char neighbor; 02821 if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue; 02822 neighbor = enc_succ_char(s, l, enc); 02823 if (neighbor == NEIGHBOR_FOUND) 02824 return str; 02825 if (rb_enc_precise_mbclen(s, s+l, enc) != l) { 02826 /* wrapped to \0...\0. search next valid char. */ 02827 enc_succ_char(s, l, enc); 02828 } 02829 if (!rb_enc_asciicompat(enc)) { 02830 MEMCPY(carry, s, char, l); 02831 carry_len = l; 02832 } 02833 carry_pos = s - sbeg; 02834 } 02835 } 02836 RESIZE_CAPA(str, RSTRING_LEN(str) + carry_len); 02837 s = RSTRING_PTR(str) + carry_pos; 02838 memmove(s + carry_len, s, RSTRING_LEN(str) - carry_pos); 02839 memmove(s, carry, carry_len); 02840 STR_SET_LEN(str, RSTRING_LEN(str) + carry_len); 02841 RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0'; 02842 rb_enc_str_coderange(str); 02843 return str; 02844 } 02845 02846 02847 /* 02848 * call-seq: 02849 * str.succ! -> str 02850 * str.next! -> str 02851 * 02852 * Equivalent to <code>String#succ</code>, but modifies the receiver in 02853 * place. 02854 */ 02855 02856 static VALUE 02857 rb_str_succ_bang(VALUE str) 02858 { 02859 rb_str_shared_replace(str, rb_str_succ(str)); 02860 02861 return str; 02862 } 02863 02864 02865 /* 02866 * call-seq: 02867 * str.upto(other_str, exclusive=false) {|s| block } -> str 02868 * str.upto(other_str, exclusive=false) -> an_enumerator 02869 * 02870 * Iterates through successive values, starting at <i>str</i> and 02871 * ending at <i>other_str</i> inclusive, passing each value in turn to 02872 * the block. The <code>String#succ</code> method is used to generate 02873 * each value. If optional second argument exclusive is omitted or is false, 02874 * the last value will be included; otherwise it will be excluded. 02875 * 02876 * If no block is given, an enumerator is returned instead. 02877 * 02878 * "a8".upto("b6") {|s| print s, ' ' } 02879 * for s in "a8".."b6" 02880 * print s, ' ' 02881 * end 02882 * 02883 * <em>produces:</em> 02884 * 02885 * a8 a9 b0 b1 b2 b3 b4 b5 b6 02886 * a8 a9 b0 b1 b2 b3 b4 b5 b6 02887 * 02888 * If <i>str</i> and <i>other_str</i> contains only ascii numeric characters, 02889 * both are recognized as decimal numbers. In addition, the width of 02890 * string (e.g. leading zeros) is handled appropriately. 02891 * 02892 * "9".upto("11").to_a #=> ["9", "10", "11"] 02893 * "25".upto("5").to_a #=> [] 02894 * "07".upto("11").to_a #=> ["07", "08", "09", "10", "11"] 02895 */ 02896 02897 static VALUE 02898 rb_str_upto(int argc, VALUE *argv, VALUE beg) 02899 { 02900 VALUE end, exclusive; 02901 VALUE current, after_end; 02902 ID succ; 02903 int n, excl, ascii; 02904 rb_encoding *enc; 02905 02906 rb_scan_args(argc, argv, "11", &end, &exclusive); 02907 RETURN_ENUMERATOR(beg, argc, argv); 02908 excl = RTEST(exclusive); 02909 CONST_ID(succ, "succ"); 02910 StringValue(end); 02911 enc = rb_enc_check(beg, end); 02912 ascii = (is_ascii_string(beg) && is_ascii_string(end)); 02913 /* single character */ 02914 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) { 02915 char c = RSTRING_PTR(beg)[0]; 02916 char e = RSTRING_PTR(end)[0]; 02917 02918 if (c > e || (excl && c == e)) return beg; 02919 for (;;) { 02920 rb_yield(rb_enc_str_new(&c, 1, enc)); 02921 if (!excl && c == e) break; 02922 c++; 02923 if (excl && c == e) break; 02924 } 02925 return beg; 02926 } 02927 /* both edges are all digits */ 02928 if (ascii && ISDIGIT(RSTRING_PTR(beg)[0]) && ISDIGIT(RSTRING_PTR(end)[0])) { 02929 char *s, *send; 02930 VALUE b, e; 02931 int width; 02932 02933 s = RSTRING_PTR(beg); send = RSTRING_END(beg); 02934 width = rb_long2int(send - s); 02935 while (s < send) { 02936 if (!ISDIGIT(*s)) goto no_digits; 02937 s++; 02938 } 02939 s = RSTRING_PTR(end); send = RSTRING_END(end); 02940 while (s < send) { 02941 if (!ISDIGIT(*s)) goto no_digits; 02942 s++; 02943 } 02944 b = rb_str_to_inum(beg, 10, FALSE); 02945 e = rb_str_to_inum(end, 10, FALSE); 02946 if (FIXNUM_P(b) && FIXNUM_P(e)) { 02947 long bi = FIX2LONG(b); 02948 long ei = FIX2LONG(e); 02949 rb_encoding *usascii = rb_usascii_encoding(); 02950 02951 while (bi <= ei) { 02952 if (excl && bi == ei) break; 02953 rb_yield(rb_enc_sprintf(usascii, "%.*ld", width, bi)); 02954 bi++; 02955 } 02956 } 02957 else { 02958 ID op = excl ? '<' : rb_intern("<="); 02959 VALUE args[2], fmt = rb_obj_freeze(rb_usascii_str_new_cstr("%.*d")); 02960 02961 args[0] = INT2FIX(width); 02962 while (rb_funcall(b, op, 1, e)) { 02963 args[1] = b; 02964 rb_yield(rb_str_format(numberof(args), args, fmt)); 02965 b = rb_funcall(b, succ, 0, 0); 02966 } 02967 } 02968 return beg; 02969 } 02970 /* normal case */ 02971 no_digits: 02972 n = rb_str_cmp(beg, end); 02973 if (n > 0 || (excl && n == 0)) return beg; 02974 02975 after_end = rb_funcall(end, succ, 0, 0); 02976 current = rb_str_dup(beg); 02977 while (!rb_str_equal(current, after_end)) { 02978 VALUE next = Qnil; 02979 if (excl || !rb_str_equal(current, end)) 02980 next = rb_funcall(current, succ, 0, 0); 02981 rb_yield(current); 02982 if (NIL_P(next)) break; 02983 current = next; 02984 StringValue(current); 02985 if (excl && rb_str_equal(current, end)) break; 02986 if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0) 02987 break; 02988 } 02989 02990 return beg; 02991 } 02992 02993 static VALUE 02994 rb_str_subpat(VALUE str, VALUE re, VALUE backref) 02995 { 02996 if (rb_reg_search(re, str, 0, 0) >= 0) { 02997 VALUE match = rb_backref_get(); 02998 int nth = rb_reg_backref_number(match, backref); 02999 return rb_reg_nth_match(nth, match); 03000 } 03001 return Qnil; 03002 } 03003 03004 static VALUE 03005 rb_str_aref(VALUE str, VALUE indx) 03006 { 03007 long idx; 03008 03009 switch (TYPE(indx)) { 03010 case T_FIXNUM: 03011 idx = FIX2LONG(indx); 03012 03013 num_index: 03014 str = rb_str_substr(str, idx, 1); 03015 if (!NIL_P(str) && RSTRING_LEN(str) == 0) return Qnil; 03016 return str; 03017 03018 case T_REGEXP: 03019 return rb_str_subpat(str, indx, INT2FIX(0)); 03020 03021 case T_STRING: 03022 if (rb_str_index(str, indx, 0) != -1) 03023 return rb_str_dup(indx); 03024 return Qnil; 03025 03026 default: 03027 /* check if indx is Range */ 03028 { 03029 long beg, len; 03030 VALUE tmp; 03031 03032 len = str_strlen(str, STR_ENC_GET(str)); 03033 switch (rb_range_beg_len(indx, &beg, &len, len, 0)) { 03034 case Qfalse: 03035 break; 03036 case Qnil: 03037 return Qnil; 03038 default: 03039 tmp = rb_str_substr(str, beg, len); 03040 return tmp; 03041 } 03042 } 03043 idx = NUM2LONG(indx); 03044 goto num_index; 03045 } 03046 return Qnil; /* not reached */ 03047 } 03048 03049 03050 /* 03051 * call-seq: 03052 * str[fixnum] -> new_str or nil 03053 * str[fixnum, fixnum] -> new_str or nil 03054 * str[range] -> new_str or nil 03055 * str[regexp] -> new_str or nil 03056 * str[regexp, fixnum] -> new_str or nil 03057 * str[other_str] -> new_str or nil 03058 * str.slice(fixnum) -> new_str or nil 03059 * str.slice(fixnum, fixnum) -> new_str or nil 03060 * str.slice(range) -> new_str or nil 03061 * str.slice(regexp) -> new_str or nil 03062 * str.slice(regexp, fixnum) -> new_str or nil 03063 * str.slice(regexp, capname) -> new_str or nil 03064 * str.slice(other_str) -> new_str or nil 03065 * 03066 * Element Reference---If passed a single <code>Fixnum</code>, returns a 03067 * substring of one character at that position. If passed two <code>Fixnum</code> 03068 * objects, returns a substring starting at the offset given by the first, and 03069 * a length given by the second. If given a range, a substring containing 03070 * characters at offsets given by the range is returned. In all three cases, if 03071 * an offset is negative, it is counted from the end of <i>str</i>. Returns 03072 * <code>nil</code> if the initial offset falls outside the string, the length 03073 * is negative, or the beginning of the range is greater than the end. 03074 * 03075 * If a <code>Regexp</code> is supplied, the matching portion of <i>str</i> is 03076 * returned. If a numeric or name parameter follows the regular expression, that 03077 * component of the <code>MatchData</code> is returned instead. If a 03078 * <code>String</code> is given, that string is returned if it occurs in 03079 * <i>str</i>. In both cases, <code>nil</code> is returned if there is no 03080 * match. 03081 * 03082 * a = "hello there" 03083 * a[1] #=> "e" 03084 * a[1,3] #=> "ell" 03085 * a[1..3] #=> "ell" 03086 * a[-3,2] #=> "er" 03087 * a[-4..-2] #=> "her" 03088 * a[12..-1] #=> nil 03089 * a[-2..-4] #=> "" 03090 * a[/[aeiou](.)\1/] #=> "ell" 03091 * a[/[aeiou](.)\1/, 0] #=> "ell" 03092 * a[/[aeiou](.)\1/, 1] #=> "l" 03093 * a[/[aeiou](.)\1/, 2] #=> nil 03094 * a["lo"] #=> "lo" 03095 * a["bye"] #=> nil 03096 */ 03097 03098 static VALUE 03099 rb_str_aref_m(int argc, VALUE *argv, VALUE str) 03100 { 03101 if (argc == 2) { 03102 if (TYPE(argv[0]) == T_REGEXP) { 03103 return rb_str_subpat(str, argv[0], argv[1]); 03104 } 03105 return rb_str_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1])); 03106 } 03107 if (argc != 1) { 03108 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc); 03109 } 03110 return rb_str_aref(str, argv[0]); 03111 } 03112 03113 VALUE 03114 rb_str_drop_bytes(VALUE str, long len) 03115 { 03116 char *ptr = RSTRING_PTR(str); 03117 long olen = RSTRING_LEN(str), nlen; 03118 03119 str_modifiable(str); 03120 if (len > olen) len = olen; 03121 nlen = olen - len; 03122 if (nlen <= RSTRING_EMBED_LEN_MAX) { 03123 char *oldptr = ptr; 03124 int fl = (int)(RBASIC(str)->flags & (STR_NOEMBED|ELTS_SHARED)); 03125 STR_SET_EMBED(str); 03126 STR_SET_EMBED_LEN(str, nlen); 03127 ptr = RSTRING(str)->as.ary; 03128 memmove(ptr, oldptr + len, nlen); 03129 if (fl == STR_NOEMBED) xfree(oldptr); 03130 } 03131 else { 03132 if (!STR_SHARED_P(str)) rb_str_new4(str); 03133 ptr = RSTRING(str)->as.heap.ptr += len; 03134 RSTRING(str)->as.heap.len = nlen; 03135 } 03136 ptr[nlen] = 0; 03137 ENC_CODERANGE_CLEAR(str); 03138 return str; 03139 } 03140 03141 static void 03142 rb_str_splice_0(VALUE str, long beg, long len, VALUE val) 03143 { 03144 if (beg == 0 && RSTRING_LEN(val) == 0) { 03145 rb_str_drop_bytes(str, len); 03146 OBJ_INFECT(str, val); 03147 return; 03148 } 03149 03150 rb_str_modify(str); 03151 if (len < RSTRING_LEN(val)) { 03152 /* expand string */ 03153 RESIZE_CAPA(str, RSTRING_LEN(str) + RSTRING_LEN(val) - len + 1); 03154 } 03155 03156 if (RSTRING_LEN(val) != len) { 03157 memmove(RSTRING_PTR(str) + beg + RSTRING_LEN(val), 03158 RSTRING_PTR(str) + beg + len, 03159 RSTRING_LEN(str) - (beg + len)); 03160 } 03161 if (RSTRING_LEN(val) < beg && len < 0) { 03162 MEMZERO(RSTRING_PTR(str) + RSTRING_LEN(str), char, -len); 03163 } 03164 if (RSTRING_LEN(val) > 0) { 03165 memmove(RSTRING_PTR(str)+beg, RSTRING_PTR(val), RSTRING_LEN(val)); 03166 } 03167 STR_SET_LEN(str, RSTRING_LEN(str) + RSTRING_LEN(val) - len); 03168 if (RSTRING_PTR(str)) { 03169 RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0'; 03170 } 03171 OBJ_INFECT(str, val); 03172 } 03173 03174 static void 03175 rb_str_splice(VALUE str, long beg, long len, VALUE val) 03176 { 03177 long slen; 03178 char *p, *e; 03179 rb_encoding *enc; 03180 int singlebyte = single_byte_optimizable(str); 03181 int cr; 03182 03183 if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len); 03184 03185 StringValue(val); 03186 enc = rb_enc_check(str, val); 03187 slen = str_strlen(str, enc); 03188 03189 if (slen < beg) { 03190 out_of_range: 03191 rb_raise(rb_eIndexError, "index %ld out of string", beg); 03192 } 03193 if (beg < 0) { 03194 if (-beg > slen) { 03195 goto out_of_range; 03196 } 03197 beg += slen; 03198 } 03199 if (slen < len || slen < beg + len) { 03200 len = slen - beg; 03201 } 03202 str_modify_keep_cr(str); 03203 p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc, singlebyte); 03204 if (!p) p = RSTRING_END(str); 03205 e = str_nth(p, RSTRING_END(str), len, enc, singlebyte); 03206 if (!e) e = RSTRING_END(str); 03207 /* error check */ 03208 beg = p - RSTRING_PTR(str); /* physical position */ 03209 len = e - p; /* physical length */ 03210 rb_str_splice_0(str, beg, len, val); 03211 rb_enc_associate(str, enc); 03212 cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val)); 03213 if (cr != ENC_CODERANGE_BROKEN) 03214 ENC_CODERANGE_SET(str, cr); 03215 } 03216 03217 void 03218 rb_str_update(VALUE str, long beg, long len, VALUE val) 03219 { 03220 rb_str_splice(str, beg, len, val); 03221 } 03222 03223 static void 03224 rb_str_subpat_set(VALUE str, VALUE re, VALUE backref, VALUE val) 03225 { 03226 int nth; 03227 VALUE match; 03228 long start, end, len; 03229 rb_encoding *enc; 03230 struct re_registers *regs; 03231 03232 if (rb_reg_search(re, str, 0, 0) < 0) { 03233 rb_raise(rb_eIndexError, "regexp not matched"); 03234 } 03235 match = rb_backref_get(); 03236 nth = rb_reg_backref_number(match, backref); 03237 regs = RMATCH_REGS(match); 03238 if (nth >= regs->num_regs) { 03239 out_of_range: 03240 rb_raise(rb_eIndexError, "index %d out of regexp", nth); 03241 } 03242 if (nth < 0) { 03243 if (-nth >= regs->num_regs) { 03244 goto out_of_range; 03245 } 03246 nth += regs->num_regs; 03247 } 03248 03249 start = BEG(nth); 03250 if (start == -1) { 03251 rb_raise(rb_eIndexError, "regexp group %d not matched", nth); 03252 } 03253 end = END(nth); 03254 len = end - start; 03255 StringValue(val); 03256 enc = rb_enc_check(str, val); 03257 rb_str_splice_0(str, start, len, val); 03258 rb_enc_associate(str, enc); 03259 } 03260 03261 static VALUE 03262 rb_str_aset(VALUE str, VALUE indx, VALUE val) 03263 { 03264 long idx, beg; 03265 03266 switch (TYPE(indx)) { 03267 case T_FIXNUM: 03268 idx = FIX2LONG(indx); 03269 num_index: 03270 rb_str_splice(str, idx, 1, val); 03271 return val; 03272 03273 case T_REGEXP: 03274 rb_str_subpat_set(str, indx, INT2FIX(0), val); 03275 return val; 03276 03277 case T_STRING: 03278 beg = rb_str_index(str, indx, 0); 03279 if (beg < 0) { 03280 rb_raise(rb_eIndexError, "string not matched"); 03281 } 03282 beg = rb_str_sublen(str, beg); 03283 rb_str_splice(str, beg, str_strlen(indx, 0), val); 03284 return val; 03285 03286 default: 03287 /* check if indx is Range */ 03288 { 03289 long beg, len; 03290 if (rb_range_beg_len(indx, &beg, &len, str_strlen(str, 0), 2)) { 03291 rb_str_splice(str, beg, len, val); 03292 return val; 03293 } 03294 } 03295 idx = NUM2LONG(indx); 03296 goto num_index; 03297 } 03298 } 03299 03300 /* 03301 * call-seq: 03302 * str[fixnum] = new_str 03303 * str[fixnum, fixnum] = new_str 03304 * str[range] = aString 03305 * str[regexp] = new_str 03306 * str[regexp, fixnum] = new_str 03307 * str[regexp, name] = new_str 03308 * str[other_str] = new_str 03309 * 03310 * Element Assignment---Replaces some or all of the content of <i>str</i>. The 03311 * portion of the string affected is determined using the same criteria as 03312 * <code>String#[]</code>. If the replacement string is not the same length as 03313 * the text it is replacing, the string will be adjusted accordingly. If the 03314 * regular expression or string is used as the index doesn't match a position 03315 * in the string, <code>IndexError</code> is raised. If the regular expression 03316 * form is used, the optional second <code>Fixnum</code> allows you to specify 03317 * which portion of the match to replace (effectively using the 03318 * <code>MatchData</code> indexing rules. The forms that take a 03319 * <code>Fixnum</code> will raise an <code>IndexError</code> if the value is 03320 * out of range; the <code>Range</code> form will raise a 03321 * <code>RangeError</code>, and the <code>Regexp</code> and <code>String</code> 03322 * forms will silently ignore the assignment. 03323 */ 03324 03325 static VALUE 03326 rb_str_aset_m(int argc, VALUE *argv, VALUE str) 03327 { 03328 if (argc == 3) { 03329 if (TYPE(argv[0]) == T_REGEXP) { 03330 rb_str_subpat_set(str, argv[0], argv[1], argv[2]); 03331 } 03332 else { 03333 rb_str_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]); 03334 } 03335 return argv[2]; 03336 } 03337 if (argc != 2) { 03338 rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc); 03339 } 03340 return rb_str_aset(str, argv[0], argv[1]); 03341 } 03342 03343 /* 03344 * call-seq: 03345 * str.insert(index, other_str) -> str 03346 * 03347 * Inserts <i>other_str</i> before the character at the given 03348 * <i>index</i>, modifying <i>str</i>. Negative indices count from the 03349 * end of the string, and insert <em>after</em> the given character. 03350 * The intent is insert <i>aString</i> so that it starts at the given 03351 * <i>index</i>. 03352 * 03353 * "abcd".insert(0, 'X') #=> "Xabcd" 03354 * "abcd".insert(3, 'X') #=> "abcXd" 03355 * "abcd".insert(4, 'X') #=> "abcdX" 03356 * "abcd".insert(-3, 'X') #=> "abXcd" 03357 * "abcd".insert(-1, 'X') #=> "abcdX" 03358 */ 03359 03360 static VALUE 03361 rb_str_insert(VALUE str, VALUE idx, VALUE str2) 03362 { 03363 long pos = NUM2LONG(idx); 03364 03365 if (pos == -1) { 03366 return rb_str_append(str, str2); 03367 } 03368 else if (pos < 0) { 03369 pos++; 03370 } 03371 rb_str_splice(str, pos, 0, str2); 03372 return str; 03373 } 03374 03375 03376 /* 03377 * call-seq: 03378 * str.slice!(fixnum) -> fixnum or nil 03379 * str.slice!(fixnum, fixnum) -> new_str or nil 03380 * str.slice!(range) -> new_str or nil 03381 * str.slice!(regexp) -> new_str or nil 03382 * str.slice!(other_str) -> new_str or nil 03383 * 03384 * Deletes the specified portion from <i>str</i>, and returns the portion 03385 * deleted. 03386 * 03387 * string = "this is a string" 03388 * string.slice!(2) #=> "i" 03389 * string.slice!(3..6) #=> " is " 03390 * string.slice!(/s.*t/) #=> "sa st" 03391 * string.slice!("r") #=> "r" 03392 * string #=> "thing" 03393 */ 03394 03395 static VALUE 03396 rb_str_slice_bang(int argc, VALUE *argv, VALUE str) 03397 { 03398 VALUE result; 03399 VALUE buf[3]; 03400 int i; 03401 03402 if (argc < 1 || 2 < argc) { 03403 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc); 03404 } 03405 for (i=0; i<argc; i++) { 03406 buf[i] = argv[i]; 03407 } 03408 str_modify_keep_cr(str); 03409 buf[i] = rb_str_new(0,0); 03410 result = rb_str_aref_m(argc, buf, str); 03411 if (!NIL_P(result)) { 03412 rb_str_aset_m(argc+1, buf, str); 03413 } 03414 return result; 03415 } 03416 03417 static VALUE 03418 get_pat(VALUE pat, int quote) 03419 { 03420 VALUE val; 03421 03422 switch (TYPE(pat)) { 03423 case T_REGEXP: 03424 return pat; 03425 03426 case T_STRING: 03427 break; 03428 03429 default: 03430 val = rb_check_string_type(pat); 03431 if (NIL_P(val)) { 03432 Check_Type(pat, T_REGEXP); 03433 } 03434 pat = val; 03435 } 03436 03437 if (quote) { 03438 pat = rb_reg_quote(pat); 03439 } 03440 03441 return rb_reg_regcomp(pat); 03442 } 03443 03444 03445 /* 03446 * call-seq: 03447 * str.sub!(pattern, replacement) -> str or nil 03448 * str.sub!(pattern) {|match| block } -> str or nil 03449 * 03450 * Performs the substitutions of <code>String#sub</code> in place, 03451 * returning <i>str</i>, or <code>nil</code> if no substitutions were 03452 * performed. 03453 */ 03454 03455 static VALUE 03456 rb_str_sub_bang(int argc, VALUE *argv, VALUE str) 03457 { 03458 VALUE pat, repl, hash = Qnil; 03459 int iter = 0; 03460 int tainted = 0; 03461 int untrusted = 0; 03462 long plen; 03463 03464 if (argc == 1 && rb_block_given_p()) { 03465 iter = 1; 03466 } 03467 else if (argc == 2) { 03468 repl = argv[1]; 03469 hash = rb_check_convert_type(argv[1], T_HASH, "Hash", "to_hash"); 03470 if (NIL_P(hash)) { 03471 StringValue(repl); 03472 } 03473 if (OBJ_TAINTED(repl)) tainted = 1; 03474 if (OBJ_UNTRUSTED(repl)) untrusted = 1; 03475 } 03476 else { 03477 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc); 03478 } 03479 03480 pat = get_pat(argv[0], 1); 03481 str_modifiable(str); 03482 if (rb_reg_search(pat, str, 0, 0) >= 0) { 03483 rb_encoding *enc; 03484 int cr = ENC_CODERANGE(str); 03485 VALUE match = rb_backref_get(); 03486 struct re_registers *regs = RMATCH_REGS(match); 03487 long beg0 = BEG(0); 03488 long end0 = END(0); 03489 char *p, *rp; 03490 long len, rlen; 03491 03492 if (iter || !NIL_P(hash)) { 03493 p = RSTRING_PTR(str); len = RSTRING_LEN(str); 03494 03495 if (iter) { 03496 repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match))); 03497 } 03498 else { 03499 repl = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0)); 03500 repl = rb_obj_as_string(repl); 03501 } 03502 str_mod_check(str, p, len); 03503 str_frozen_check(str); 03504 } 03505 else { 03506 repl = rb_reg_regsub(repl, str, regs, pat); 03507 } 03508 enc = rb_enc_compatible(str, repl); 03509 if (!enc) { 03510 rb_encoding *str_enc = STR_ENC_GET(str); 03511 p = RSTRING_PTR(str); len = RSTRING_LEN(str); 03512 if (coderange_scan(p, beg0, str_enc) != ENC_CODERANGE_7BIT || 03513 coderange_scan(p+end0, len-end0, str_enc) != ENC_CODERANGE_7BIT) { 03514 rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s", 03515 rb_enc_name(str_enc), 03516 rb_enc_name(STR_ENC_GET(repl))); 03517 } 03518 enc = STR_ENC_GET(repl); 03519 } 03520 rb_str_modify(str); 03521 rb_enc_associate(str, enc); 03522 if (OBJ_TAINTED(repl)) tainted = 1; 03523 if (OBJ_UNTRUSTED(repl)) untrusted = 1; 03524 if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) { 03525 int cr2 = ENC_CODERANGE(repl); 03526 if (cr2 == ENC_CODERANGE_BROKEN || 03527 (cr == ENC_CODERANGE_VALID && cr2 == ENC_CODERANGE_7BIT)) 03528 cr = ENC_CODERANGE_UNKNOWN; 03529 else 03530 cr = cr2; 03531 } 03532 plen = end0 - beg0; 03533 rp = RSTRING_PTR(repl); rlen = RSTRING_LEN(repl); 03534 len = RSTRING_LEN(str); 03535 if (rlen > plen) { 03536 RESIZE_CAPA(str, len + rlen - plen); 03537 } 03538 p = RSTRING_PTR(str); 03539 if (rlen != plen) { 03540 memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen); 03541 } 03542 memcpy(p + beg0, rp, rlen); 03543 len += rlen - plen; 03544 STR_SET_LEN(str, len); 03545 RSTRING_PTR(str)[len] = '\0'; 03546 ENC_CODERANGE_SET(str, cr); 03547 if (tainted) OBJ_TAINT(str); 03548 if (untrusted) OBJ_UNTRUST(str); 03549 03550 return str; 03551 } 03552 return Qnil; 03553 } 03554 03555 03556 /* 03557 * call-seq: 03558 * str.sub(pattern, replacement) -> new_str 03559 * str.sub(pattern, hash) -> new_str 03560 * str.sub(pattern) {|match| block } -> new_str 03561 * 03562 * Returns a copy of <i>str</i> with the <em>first</em> occurrence of 03563 * <i>pattern</i> substituted for the second argument. The <i>pattern</i> is 03564 * typically a <code>Regexp</code>; if given as a <code>String</code>, any 03565 * regular expression metacharacters it contains will be interpreted 03566 * literally, e.g. <code>'\\\d'</code> will match a backlash followed by 'd', 03567 * instead of a digit. 03568 * 03569 * If <i>replacement</i> is a <code>String</code> it will be substituted for 03570 * the matched text. It may contain back-references to the pattern's capture 03571 * groups of the form <code>\\\d</code>, where <i>d</i> is a group number, or 03572 * <code>\\\k<n></code>, where <i>n</i> is a group name. If it is a 03573 * double-quoted string, both back-references must be preceded by an 03574 * additional backslash. However, within <i>replacement</i> the special match 03575 * variables, such as <code>&$</code>, will not refer to the current match. 03576 * 03577 * If the second argument is a <code>Hash</code>, and the matched text is one 03578 * of its keys, the corresponding value is the replacement string. 03579 * 03580 * In the block form, the current match string is passed in as a parameter, 03581 * and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>, 03582 * <code>$&</code>, and <code>$'</code> will be set appropriately. The value 03583 * returned by the block will be substituted for the match on each call. 03584 * 03585 * The result inherits any tainting in the original string or any supplied 03586 * replacement string. 03587 * 03588 * "hello".sub(/[aeiou]/, '*') #=> "h*llo" 03589 * "hello".sub(/([aeiou])/, '<\1>') #=> "h<e>llo" 03590 * "hello".sub(/./) {|s| s.ord.to_s + ' ' } #=> "104 ello" 03591 * "hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*') #=> "h*e*llo" 03592 * 'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV) 03593 * #=> "Is /bin/bash your preferred shell?" 03594 */ 03595 03596 static VALUE 03597 rb_str_sub(int argc, VALUE *argv, VALUE str) 03598 { 03599 str = rb_str_dup(str); 03600 rb_str_sub_bang(argc, argv, str); 03601 return str; 03602 } 03603 03604 static VALUE 03605 str_gsub(int argc, VALUE *argv, VALUE str, int bang) 03606 { 03607 VALUE pat, val, repl, match, dest, hash = Qnil; 03608 struct re_registers *regs; 03609 long beg, n; 03610 long beg0, end0; 03611 long offset, blen, slen, len, last; 03612 int iter = 0; 03613 char *sp, *cp; 03614 int tainted = 0; 03615 rb_encoding *str_enc; 03616 03617 switch (argc) { 03618 case 1: 03619 RETURN_ENUMERATOR(str, argc, argv); 03620 iter = 1; 03621 break; 03622 case 2: 03623 repl = argv[1]; 03624 hash = rb_check_convert_type(argv[1], T_HASH, "Hash", "to_hash"); 03625 if (NIL_P(hash)) { 03626 StringValue(repl); 03627 } 03628 if (OBJ_TAINTED(repl)) tainted = 1; 03629 break; 03630 default: 03631 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc); 03632 } 03633 03634 pat = get_pat(argv[0], 1); 03635 beg = rb_reg_search(pat, str, 0, 0); 03636 if (beg < 0) { 03637 if (bang) return Qnil; /* no match, no substitution */ 03638 return rb_str_dup(str); 03639 } 03640 03641 offset = 0; 03642 n = 0; 03643 blen = RSTRING_LEN(str) + 30; /* len + margin */ 03644 dest = rb_str_buf_new(blen); 03645 sp = RSTRING_PTR(str); 03646 slen = RSTRING_LEN(str); 03647 cp = sp; 03648 str_enc = STR_ENC_GET(str); 03649 03650 do { 03651 n++; 03652 match = rb_backref_get(); 03653 regs = RMATCH_REGS(match); 03654 beg0 = BEG(0); 03655 end0 = END(0); 03656 if (iter || !NIL_P(hash)) { 03657 if (iter) { 03658 val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match))); 03659 } 03660 else { 03661 val = rb_hash_aref(hash, rb_str_subseq(str, BEG(0), END(0) - BEG(0))); 03662 val = rb_obj_as_string(val); 03663 } 03664 str_mod_check(str, sp, slen); 03665 if (val == dest) { /* paranoid check [ruby-dev:24827] */ 03666 rb_raise(rb_eRuntimeError, "block should not cheat"); 03667 } 03668 } 03669 else { 03670 val = rb_reg_regsub(repl, str, regs, pat); 03671 } 03672 03673 if (OBJ_TAINTED(val)) tainted = 1; 03674 03675 len = beg - offset; /* copy pre-match substr */ 03676 if (len) { 03677 rb_enc_str_buf_cat(dest, cp, len, str_enc); 03678 } 03679 03680 rb_str_buf_append(dest, val); 03681 03682 last = offset; 03683 offset = end0; 03684 if (beg0 == end0) { 03685 /* 03686 * Always consume at least one character of the input string 03687 * in order to prevent infinite loops. 03688 */ 03689 if (RSTRING_LEN(str) <= end0) break; 03690 len = rb_enc_fast_mbclen(RSTRING_PTR(str)+end0, RSTRING_END(str), str_enc); 03691 rb_enc_str_buf_cat(dest, RSTRING_PTR(str)+end0, len, str_enc); 03692 offset = end0 + len; 03693 } 03694 cp = RSTRING_PTR(str) + offset; 03695 if (offset > RSTRING_LEN(str)) break; 03696 beg = rb_reg_search(pat, str, offset, 0); 03697 } while (beg >= 0); 03698 if (RSTRING_LEN(str) > offset) { 03699 rb_enc_str_buf_cat(dest, cp, RSTRING_LEN(str) - offset, str_enc); 03700 } 03701 rb_reg_search(pat, str, last, 0); 03702 if (bang) { 03703 rb_str_shared_replace(str, dest); 03704 } 03705 else { 03706 RBASIC(dest)->klass = rb_obj_class(str); 03707 OBJ_INFECT(dest, str); 03708 str = dest; 03709 } 03710 03711 if (tainted) OBJ_TAINT(str); 03712 return str; 03713 } 03714 03715 03716 /* 03717 * call-seq: 03718 * str.gsub!(pattern, replacement) -> str or nil 03719 * str.gsub!(pattern) {|match| block } -> str or nil 03720 * str.gsub!(pattern) -> an_enumerator 03721 * 03722 * Performs the substitutions of <code>String#gsub</code> in place, returning 03723 * <i>str</i>, or <code>nil</code> if no substitutions were performed. 03724 * If no block and no <i>replacement</i> is given, an enumerator is returned instead. 03725 */ 03726 03727 static VALUE 03728 rb_str_gsub_bang(int argc, VALUE *argv, VALUE str) 03729 { 03730 str_modify_keep_cr(str); 03731 return str_gsub(argc, argv, str, 1); 03732 } 03733 03734 03735 /* 03736 * call-seq: 03737 * str.gsub(pattern, replacement) -> new_str 03738 * str.gsub(pattern, hash) -> new_str 03739 * str.gsub(pattern) {|match| block } -> new_str 03740 * str.gsub(pattern) -> enumerator 03741 * 03742 * Returns a copy of <i>str</i> with the <em>all</em> occurrences of 03743 * <i>pattern</i> substituted for the second argument. The <i>pattern</i> is 03744 * typically a <code>Regexp</code>; if given as a <code>String</code>, any 03745 * regular expression metacharacters it contains will be interpreted 03746 * literally, e.g. <code>'\\\d'</code> will match a backlash followed by 'd', 03747 * instead of a digit. 03748 * 03749 * If <i>replacement</i> is a <code>String</code> it will be substituted for 03750 * the matched text. It may contain back-references to the pattern's capture 03751 * groups of the form <code>\\\d</code>, where <i>d</i> is a group number, or 03752 * <code>\\\k<n></code>, where <i>n</i> is a group name. If it is a 03753 * double-quoted string, both back-references must be preceded by an 03754 * additional backslash. However, within <i>replacement</i> the special match 03755 * variables, such as <code>&$</code>, will not refer to the current match. 03756 * 03757 * If the second argument is a <code>Hash</code>, and the matched text is one 03758 * of its keys, the corresponding value is the replacement string. 03759 * 03760 * In the block form, the current match string is passed in as a parameter, 03761 * and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>, 03762 * <code>$&</code>, and <code>$'</code> will be set appropriately. The value 03763 * returned by the block will be substituted for the match on each call. 03764 * 03765 * The result inherits any tainting in the original string or any supplied 03766 * replacement string. 03767 * 03768 * When neither a block nor a second argument is supplied, an 03769 * <code>Enumerator</code> is returned. 03770 * 03771 * "hello".gsub(/[aeiou]/, '*') #=> "h*ll*" 03772 * "hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>" 03773 * "hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 " 03774 * "hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}" 03775 * 'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*" 03776 */ 03777 03778 static VALUE 03779 rb_str_gsub(int argc, VALUE *argv, VALUE str) 03780 { 03781 return str_gsub(argc, argv, str, 0); 03782 } 03783 03784 03785 /* 03786 * call-seq: 03787 * str.replace(other_str) -> str 03788 * 03789 * Replaces the contents and taintedness of <i>str</i> with the corresponding 03790 * values in <i>other_str</i>. 03791 * 03792 * s = "hello" #=> "hello" 03793 * s.replace "world" #=> "world" 03794 */ 03795 03796 VALUE 03797 rb_str_replace(VALUE str, VALUE str2) 03798 { 03799 str_modifiable(str); 03800 if (str == str2) return str; 03801 03802 StringValue(str2); 03803 str_discard(str); 03804 return str_replace(str, str2); 03805 } 03806 03807 /* 03808 * call-seq: 03809 * string.clear -> string 03810 * 03811 * Makes string empty. 03812 * 03813 * a = "abcde" 03814 * a.clear #=> "" 03815 */ 03816 03817 static VALUE 03818 rb_str_clear(VALUE str) 03819 { 03820 str_discard(str); 03821 STR_SET_EMBED(str); 03822 STR_SET_EMBED_LEN(str, 0); 03823 RSTRING_PTR(str)[0] = 0; 03824 if (rb_enc_asciicompat(STR_ENC_GET(str))) 03825 ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT); 03826 else 03827 ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID); 03828 return str; 03829 } 03830 03831 /* 03832 * call-seq: 03833 * string.chr -> string 03834 * 03835 * Returns a one-character string at the beginning of the string. 03836 * 03837 * a = "abcde" 03838 * a.chr #=> "a" 03839 */ 03840 03841 static VALUE 03842 rb_str_chr(VALUE str) 03843 { 03844 return rb_str_substr(str, 0, 1); 03845 } 03846 03847 /* 03848 * call-seq: 03849 * str.getbyte(index) -> 0 .. 255 03850 * 03851 * returns the <i>index</i>th byte as an integer. 03852 */ 03853 static VALUE 03854 rb_str_getbyte(VALUE str, VALUE index) 03855 { 03856 long pos = NUM2LONG(index); 03857 03858 if (pos < 0) 03859 pos += RSTRING_LEN(str); 03860 if (pos < 0 || RSTRING_LEN(str) <= pos) 03861 return Qnil; 03862 03863 return INT2FIX((unsigned char)RSTRING_PTR(str)[pos]); 03864 } 03865 03866 /* 03867 * call-seq: 03868 * str.setbyte(index, int) -> int 03869 * 03870 * modifies the <i>index</i>th byte as <i>int</i>. 03871 */ 03872 static VALUE 03873 rb_str_setbyte(VALUE str, VALUE index, VALUE value) 03874 { 03875 long pos = NUM2LONG(index); 03876 int byte = NUM2INT(value); 03877 03878 rb_str_modify(str); 03879 03880 if (pos < -RSTRING_LEN(str) || RSTRING_LEN(str) <= pos) 03881 rb_raise(rb_eIndexError, "index %ld out of string", pos); 03882 if (pos < 0) 03883 pos += RSTRING_LEN(str); 03884 03885 RSTRING_PTR(str)[pos] = byte; 03886 03887 return value; 03888 } 03889 03890 /* 03891 * call-seq: 03892 * str.reverse -> new_str 03893 * 03894 * Returns a new string with the characters from <i>str</i> in reverse order. 03895 * 03896 * "stressed".reverse #=> "desserts" 03897 */ 03898 03899 static VALUE 03900 rb_str_reverse(VALUE str) 03901 { 03902 rb_encoding *enc; 03903 VALUE rev; 03904 char *s, *e, *p; 03905 int single = 1; 03906 03907 if (RSTRING_LEN(str) <= 1) return rb_str_dup(str); 03908 enc = STR_ENC_GET(str); 03909 rev = rb_str_new5(str, 0, RSTRING_LEN(str)); 03910 s = RSTRING_PTR(str); e = RSTRING_END(str); 03911 p = RSTRING_END(rev); 03912 03913 if (RSTRING_LEN(str) > 1) { 03914 if (single_byte_optimizable(str)) { 03915 while (s < e) { 03916 *--p = *s++; 03917 } 03918 } 03919 else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID) { 03920 while (s < e) { 03921 int clen = rb_enc_fast_mbclen(s, e, enc); 03922 03923 if (clen > 1 || (*s & 0x80)) single = 0; 03924 p -= clen; 03925 memcpy(p, s, clen); 03926 s += clen; 03927 } 03928 } 03929 else { 03930 while (s < e) { 03931 int clen = rb_enc_mbclen(s, e, enc); 03932 03933 if (clen > 1 || (*s & 0x80)) single = 0; 03934 p -= clen; 03935 memcpy(p, s, clen); 03936 s += clen; 03937 } 03938 } 03939 } 03940 STR_SET_LEN(rev, RSTRING_LEN(str)); 03941 OBJ_INFECT(rev, str); 03942 if (ENC_CODERANGE(str) == ENC_CODERANGE_UNKNOWN) { 03943 if (single) { 03944 ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT); 03945 } 03946 else { 03947 ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID); 03948 } 03949 } 03950 rb_enc_cr_str_copy_for_substr(rev, str); 03951 03952 return rev; 03953 } 03954 03955 03956 /* 03957 * call-seq: 03958 * str.reverse! -> str 03959 * 03960 * Reverses <i>str</i> in place. 03961 */ 03962 03963 static VALUE 03964 rb_str_reverse_bang(VALUE str) 03965 { 03966 if (RSTRING_LEN(str) > 1) { 03967 if (single_byte_optimizable(str)) { 03968 char *s, *e, c; 03969 03970 str_modify_keep_cr(str); 03971 s = RSTRING_PTR(str); 03972 e = RSTRING_END(str) - 1; 03973 while (s < e) { 03974 c = *s; 03975 *s++ = *e; 03976 *e-- = c; 03977 } 03978 } 03979 else { 03980 rb_str_shared_replace(str, rb_str_reverse(str)); 03981 } 03982 } 03983 else { 03984 str_modify_keep_cr(str); 03985 } 03986 return str; 03987 } 03988 03989 03990 /* 03991 * call-seq: 03992 * str.include? other_str -> true or false 03993 * 03994 * Returns <code>true</code> if <i>str</i> contains the given string or 03995 * character. 03996 * 03997 * "hello".include? "lo" #=> true 03998 * "hello".include? "ol" #=> false 03999 * "hello".include? ?h #=> true 04000 */ 04001 04002 static VALUE 04003 rb_str_include(VALUE str, VALUE arg) 04004 { 04005 long i; 04006 04007 StringValue(arg); 04008 i = rb_str_index(str, arg, 0); 04009 04010 if (i == -1) return Qfalse; 04011 return Qtrue; 04012 } 04013 04014 04015 /* 04016 * call-seq: 04017 * str.to_i(base=10) -> integer 04018 * 04019 * Returns the result of interpreting leading characters in <i>str</i> as an 04020 * integer base <i>base</i> (between 2 and 36). Extraneous characters past the 04021 * end of a valid number are ignored. If there is not a valid number at the 04022 * start of <i>str</i>, <code>0</code> is returned. This method never raises an 04023 * exception when <i>base</i> is valid. 04024 * 04025 * "12345".to_i #=> 12345 04026 * "99 red balloons".to_i #=> 99 04027 * "0a".to_i #=> 0 04028 * "0a".to_i(16) #=> 10 04029 * "hello".to_i #=> 0 04030 * "1100101".to_i(2) #=> 101 04031 * "1100101".to_i(8) #=> 294977 04032 * "1100101".to_i(10) #=> 1100101 04033 * "1100101".to_i(16) #=> 17826049 04034 */ 04035 04036 static VALUE 04037 rb_str_to_i(int argc, VALUE *argv, VALUE str) 04038 { 04039 int base; 04040 04041 if (argc == 0) base = 10; 04042 else { 04043 VALUE b; 04044 04045 rb_scan_args(argc, argv, "01", &b); 04046 base = NUM2INT(b); 04047 } 04048 if (base < 0) { 04049 rb_raise(rb_eArgError, "invalid radix %d", base); 04050 } 04051 return rb_str_to_inum(str, base, FALSE); 04052 } 04053 04054 04055 /* 04056 * call-seq: 04057 * str.to_f -> float 04058 * 04059 * Returns the result of interpreting leading characters in <i>str</i> as a 04060 * floating point number. Extraneous characters past the end of a valid number 04061 * are ignored. If there is not a valid number at the start of <i>str</i>, 04062 * <code>0.0</code> is returned. This method never raises an exception. 04063 * 04064 * "123.45e1".to_f #=> 1234.5 04065 * "45.67 degrees".to_f #=> 45.67 04066 * "thx1138".to_f #=> 0.0 04067 */ 04068 04069 static VALUE 04070 rb_str_to_f(VALUE str) 04071 { 04072 return DBL2NUM(rb_str_to_dbl(str, FALSE)); 04073 } 04074 04075 04076 /* 04077 * call-seq: 04078 * str.to_s -> str 04079 * str.to_str -> str 04080 * 04081 * Returns the receiver. 04082 */ 04083 04084 static VALUE 04085 rb_str_to_s(VALUE str) 04086 { 04087 if (rb_obj_class(str) != rb_cString) { 04088 return str_duplicate(rb_cString, str); 04089 } 04090 return str; 04091 } 04092 04093 #if 0 04094 static void 04095 str_cat_char(VALUE str, unsigned int c, rb_encoding *enc) 04096 { 04097 char s[RUBY_MAX_CHAR_LEN]; 04098 int n = rb_enc_codelen(c, enc); 04099 04100 rb_enc_mbcput(c, s, enc); 04101 rb_enc_str_buf_cat(str, s, n, enc); 04102 } 04103 #endif 04104 04105 #define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */ 04106 04107 int 04108 rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p) 04109 { 04110 char buf[CHAR_ESC_LEN + 1]; 04111 int l; 04112 04113 #if SIZEOF_INT > 4 04114 c &= 0xffffffff; 04115 #endif 04116 if (unicode_p) { 04117 if (c < 0x7F && ISPRINT(c)) { 04118 snprintf(buf, CHAR_ESC_LEN, "%c", c); 04119 } 04120 else if (c < 0x10000) { 04121 snprintf(buf, CHAR_ESC_LEN, "\\u%04X", c); 04122 } 04123 else { 04124 snprintf(buf, CHAR_ESC_LEN, "\\u{%X}", c); 04125 } 04126 } 04127 else { 04128 if (c < 0x100) { 04129 snprintf(buf, CHAR_ESC_LEN, "\\x%02X", c); 04130 } 04131 else { 04132 snprintf(buf, CHAR_ESC_LEN, "\\x{%X}", c); 04133 } 04134 } 04135 l = (int)strlen(buf); /* CHAR_ESC_LEN cannot exceed INT_MAX */ 04136 rb_str_buf_cat(result, buf, l); 04137 return l; 04138 } 04139 04140 /* 04141 * call-seq: 04142 * str.inspect -> string 04143 * 04144 * Returns a printable version of _str_, surrounded by quote marks, 04145 * with special characters escaped. 04146 * 04147 * str = "hello" 04148 * str[3] = "\b" 04149 * str.inspect #=> "\"hel\\bo\"" 04150 */ 04151 04152 VALUE 04153 rb_str_inspect(VALUE str) 04154 { 04155 rb_encoding *enc = STR_ENC_GET(str); 04156 const char *p, *pend, *prev; 04157 char buf[CHAR_ESC_LEN + 1]; 04158 VALUE result = rb_str_buf_new(0); 04159 rb_encoding *resenc = rb_default_internal_encoding(); 04160 int unicode_p = rb_enc_unicode_p(enc); 04161 int asciicompat = rb_enc_asciicompat(enc); 04162 04163 if (resenc == NULL) resenc = rb_default_external_encoding(); 04164 if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding(); 04165 rb_enc_associate(result, resenc); 04166 str_buf_cat2(result, "\""); 04167 04168 p = RSTRING_PTR(str); pend = RSTRING_END(str); 04169 prev = p; 04170 while (p < pend) { 04171 unsigned int c, cc; 04172 int n; 04173 04174 n = rb_enc_precise_mbclen(p, pend, enc); 04175 if (!MBCLEN_CHARFOUND_P(n)) { 04176 if (p > prev) str_buf_cat(result, prev, p - prev); 04177 n = rb_enc_mbminlen(enc); 04178 if (pend < p + n) 04179 n = (int)(pend - p); 04180 while (n--) { 04181 snprintf(buf, CHAR_ESC_LEN, "\\x%02X", *p & 0377); 04182 str_buf_cat(result, buf, strlen(buf)); 04183 prev = ++p; 04184 } 04185 continue; 04186 } 04187 n = MBCLEN_CHARFOUND_LEN(n); 04188 c = rb_enc_mbc_to_codepoint(p, pend, enc); 04189 p += n; 04190 if (c == '"'|| c == '\\' || 04191 (c == '#' && 04192 p < pend && 04193 MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) && 04194 (cc = rb_enc_codepoint(p,pend,enc), 04195 (cc == '$' || cc == '@' || cc == '{')))) { 04196 if (p - n > prev) str_buf_cat(result, prev, p - n - prev); 04197 str_buf_cat2(result, "\\"); 04198 if (asciicompat || enc == resenc) { 04199 prev = p - n; 04200 continue; 04201 } 04202 } 04203 switch (c) { 04204 case '\n': cc = 'n'; break; 04205 case '\r': cc = 'r'; break; 04206 case '\t': cc = 't'; break; 04207 case '\f': cc = 'f'; break; 04208 case '\013': cc = 'v'; break; 04209 case '\010': cc = 'b'; break; 04210 case '\007': cc = 'a'; break; 04211 case 033: cc = 'e'; break; 04212 default: cc = 0; break; 04213 } 04214 if (cc) { 04215 if (p - n > prev) str_buf_cat(result, prev, p - n - prev); 04216 buf[0] = '\\'; 04217 buf[1] = (char)cc; 04218 str_buf_cat(result, buf, 2); 04219 prev = p; 04220 continue; 04221 } 04222 if ((enc == resenc && rb_enc_isprint(c, enc)) || 04223 (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c))) { 04224 continue; 04225 } 04226 else { 04227 if (p - n > prev) str_buf_cat(result, prev, p - n - prev); 04228 rb_str_buf_cat_escaped_char(result, c, unicode_p); 04229 prev = p; 04230 continue; 04231 } 04232 } 04233 if (p > prev) str_buf_cat(result, prev, p - prev); 04234 str_buf_cat2(result, "\""); 04235 04236 OBJ_INFECT(result, str); 04237 return result; 04238 } 04239 04240 #define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{')) 04241 04242 /* 04243 * call-seq: 04244 * str.dump -> new_str 04245 * 04246 * Produces a version of <i>str</i> with all nonprinting characters replaced by 04247 * <code>\nnn</code> notation and all special characters escaped. 04248 */ 04249 04250 VALUE 04251 rb_str_dump(VALUE str) 04252 { 04253 rb_encoding *enc = rb_enc_get(str); 04254 long len; 04255 const char *p, *pend; 04256 char *q, *qend; 04257 VALUE result; 04258 int u8 = (enc == rb_utf8_encoding()); 04259 04260 len = 2; /* "" */ 04261 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str); 04262 while (p < pend) { 04263 unsigned char c = *p++; 04264 switch (c) { 04265 case '"': case '\\': 04266 case '\n': case '\r': 04267 case '\t': case '\f': 04268 case '\013': case '\010': case '\007': case '\033': 04269 len += 2; 04270 break; 04271 04272 case '#': 04273 len += IS_EVSTR(p, pend) ? 2 : 1; 04274 break; 04275 04276 default: 04277 if (ISPRINT(c)) { 04278 len++; 04279 } 04280 else { 04281 if (u8) { /* \u{NN} */ 04282 int n = rb_enc_precise_mbclen(p-1, pend, enc); 04283 if (MBCLEN_CHARFOUND_P(n-1)) { 04284 unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc); 04285 while (cc >>= 4) len++; 04286 len += 5; 04287 p += MBCLEN_CHARFOUND_LEN(n)-1; 04288 break; 04289 } 04290 } 04291 len += 4; /* \xNN */ 04292 } 04293 break; 04294 } 04295 } 04296 if (!rb_enc_asciicompat(enc)) { 04297 len += 19; /* ".force_encoding('')" */ 04298 len += strlen(enc->name); 04299 } 04300 04301 result = rb_str_new5(str, 0, len); 04302 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str); 04303 q = RSTRING_PTR(result); qend = q + len + 1; 04304 04305 *q++ = '"'; 04306 while (p < pend) { 04307 unsigned char c = *p++; 04308 04309 if (c == '"' || c == '\\') { 04310 *q++ = '\\'; 04311 *q++ = c; 04312 } 04313 else if (c == '#') { 04314 if (IS_EVSTR(p, pend)) *q++ = '\\'; 04315 *q++ = '#'; 04316 } 04317 else if (c == '\n') { 04318 *q++ = '\\'; 04319 *q++ = 'n'; 04320 } 04321 else if (c == '\r') { 04322 *q++ = '\\'; 04323 *q++ = 'r'; 04324 } 04325 else if (c == '\t') { 04326 *q++ = '\\'; 04327 *q++ = 't'; 04328 } 04329 else if (c == '\f') { 04330 *q++ = '\\'; 04331 *q++ = 'f'; 04332 } 04333 else if (c == '\013') { 04334 *q++ = '\\'; 04335 *q++ = 'v'; 04336 } 04337 else if (c == '\010') { 04338 *q++ = '\\'; 04339 *q++ = 'b'; 04340 } 04341 else if (c == '\007') { 04342 *q++ = '\\'; 04343 *q++ = 'a'; 04344 } 04345 else if (c == '\033') { 04346 *q++ = '\\'; 04347 *q++ = 'e'; 04348 } 04349 else if (ISPRINT(c)) { 04350 *q++ = c; 04351 } 04352 else { 04353 *q++ = '\\'; 04354 if (u8) { 04355 int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1; 04356 if (MBCLEN_CHARFOUND_P(n)) { 04357 int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc); 04358 p += n; 04359 snprintf(q, qend-q, "u{%x}", cc); 04360 q += strlen(q); 04361 continue; 04362 } 04363 } 04364 snprintf(q, qend-q, "x%02X", c); 04365 q += 3; 04366 } 04367 } 04368 *q++ = '"'; 04369 *q = '\0'; 04370 if (!rb_enc_asciicompat(enc)) { 04371 snprintf(q, qend-q, ".force_encoding(\"%s\")", enc->name); 04372 enc = rb_ascii8bit_encoding(); 04373 } 04374 OBJ_INFECT(result, str); 04375 /* result from dump is ASCII */ 04376 rb_enc_associate(result, enc); 04377 ENC_CODERANGE_SET(result, ENC_CODERANGE_7BIT); 04378 return result; 04379 } 04380 04381 04382 static void 04383 rb_str_check_dummy_enc(rb_encoding *enc) 04384 { 04385 if (rb_enc_dummy_p(enc)) { 04386 rb_raise(rb_eEncCompatError, "incompatible encoding with this operation: %s", 04387 rb_enc_name(enc)); 04388 } 04389 } 04390 04391 /* 04392 * call-seq: 04393 * str.upcase! -> str or nil 04394 * 04395 * Upcases the contents of <i>str</i>, returning <code>nil</code> if no changes 04396 * were made. 04397 * Note: case replacement is effective only in ASCII region. 04398 */ 04399 04400 static VALUE 04401 rb_str_upcase_bang(VALUE str) 04402 { 04403 rb_encoding *enc; 04404 char *s, *send; 04405 int modify = 0; 04406 int n; 04407 04408 str_modify_keep_cr(str); 04409 enc = STR_ENC_GET(str); 04410 rb_str_check_dummy_enc(enc); 04411 s = RSTRING_PTR(str); send = RSTRING_END(str); 04412 if (single_byte_optimizable(str)) { 04413 while (s < send) { 04414 unsigned int c = *(unsigned char*)s; 04415 04416 if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') { 04417 *s = 'A' + (c - 'a'); 04418 modify = 1; 04419 } 04420 s++; 04421 } 04422 } 04423 else { 04424 int ascompat = rb_enc_asciicompat(enc); 04425 04426 while (s < send) { 04427 unsigned int c; 04428 04429 if (ascompat && (c = *(unsigned char*)s) < 0x80) { 04430 if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') { 04431 *s = 'A' + (c - 'a'); 04432 modify = 1; 04433 } 04434 s++; 04435 } 04436 else { 04437 c = rb_enc_codepoint_len(s, send, &n, enc); 04438 if (rb_enc_islower(c, enc)) { 04439 /* assuming toupper returns codepoint with same size */ 04440 rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc); 04441 modify = 1; 04442 } 04443 s += n; 04444 } 04445 } 04446 } 04447 04448 if (modify) return str; 04449 return Qnil; 04450 } 04451 04452 04453 /* 04454 * call-seq: 04455 * str.upcase -> new_str 04456 * 04457 * Returns a copy of <i>str</i> with all lowercase letters replaced with their 04458 * uppercase counterparts. The operation is locale insensitive---only 04459 * characters ``a'' to ``z'' are affected. 04460 * Note: case replacement is effective only in ASCII region. 04461 * 04462 * "hEllO".upcase #=> "HELLO" 04463 */ 04464 04465 static VALUE 04466 rb_str_upcase(VALUE str) 04467 { 04468 str = rb_str_dup(str); 04469 rb_str_upcase_bang(str); 04470 return str; 04471 } 04472 04473 04474 /* 04475 * call-seq: 04476 * str.downcase! -> str or nil 04477 * 04478 * Downcases the contents of <i>str</i>, returning <code>nil</code> if no 04479 * changes were made. 04480 * Note: case replacement is effective only in ASCII region. 04481 */ 04482 04483 static VALUE 04484 rb_str_downcase_bang(VALUE str) 04485 { 04486 rb_encoding *enc; 04487 char *s, *send; 04488 int modify = 0; 04489 04490 str_modify_keep_cr(str); 04491 enc = STR_ENC_GET(str); 04492 rb_str_check_dummy_enc(enc); 04493 s = RSTRING_PTR(str); send = RSTRING_END(str); 04494 if (single_byte_optimizable(str)) { 04495 while (s < send) { 04496 unsigned int c = *(unsigned char*)s; 04497 04498 if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') { 04499 *s = 'a' + (c - 'A'); 04500 modify = 1; 04501 } 04502 s++; 04503 } 04504 } 04505 else { 04506 int ascompat = rb_enc_asciicompat(enc); 04507 04508 while (s < send) { 04509 unsigned int c; 04510 int n; 04511 04512 if (ascompat && (c = *(unsigned char*)s) < 0x80) { 04513 if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') { 04514 *s = 'a' + (c - 'A'); 04515 modify = 1; 04516 } 04517 s++; 04518 } 04519 else { 04520 c = rb_enc_codepoint_len(s, send, &n, enc); 04521 if (rb_enc_isupper(c, enc)) { 04522 /* assuming toupper returns codepoint with same size */ 04523 rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc); 04524 modify = 1; 04525 } 04526 s += n; 04527 } 04528 } 04529 } 04530 04531 if (modify) return str; 04532 return Qnil; 04533 } 04534 04535 04536 /* 04537 * call-seq: 04538 * str.downcase -> new_str 04539 * 04540 * Returns a copy of <i>str</i> with all uppercase letters replaced with their 04541 * lowercase counterparts. The operation is locale insensitive---only 04542 * characters ``A'' to ``Z'' are affected. 04543 * Note: case replacement is effective only in ASCII region. 04544 * 04545 * "hEllO".downcase #=> "hello" 04546 */ 04547 04548 static VALUE 04549 rb_str_downcase(VALUE str) 04550 { 04551 str = rb_str_dup(str); 04552 rb_str_downcase_bang(str); 04553 return str; 04554 } 04555 04556 04557 /* 04558 * call-seq: 04559 * str.capitalize! -> str or nil 04560 * 04561 * Modifies <i>str</i> by converting the first character to uppercase and the 04562 * remainder to lowercase. Returns <code>nil</code> if no changes are made. 04563 * Note: case conversion is effective only in ASCII region. 04564 * 04565 * a = "hello" 04566 * a.capitalize! #=> "Hello" 04567 * a #=> "Hello" 04568 * a.capitalize! #=> nil 04569 */ 04570 04571 static VALUE 04572 rb_str_capitalize_bang(VALUE str) 04573 { 04574 rb_encoding *enc; 04575 char *s, *send; 04576 int modify = 0; 04577 unsigned int c; 04578 int n; 04579 04580 str_modify_keep_cr(str); 04581 enc = STR_ENC_GET(str); 04582 rb_str_check_dummy_enc(enc); 04583 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil; 04584 s = RSTRING_PTR(str); send = RSTRING_END(str); 04585 04586 c = rb_enc_codepoint_len(s, send, &n, enc); 04587 if (rb_enc_islower(c, enc)) { 04588 rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc); 04589 modify = 1; 04590 } 04591 s += n; 04592 while (s < send) { 04593 c = rb_enc_codepoint_len(s, send, &n, enc); 04594 if (rb_enc_isupper(c, enc)) { 04595 rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc); 04596 modify = 1; 04597 } 04598 s += n; 04599 } 04600 04601 if (modify) return str; 04602 return Qnil; 04603 } 04604 04605 04606 /* 04607 * call-seq: 04608 * str.capitalize -> new_str 04609 * 04610 * Returns a copy of <i>str</i> with the first character converted to uppercase 04611 * and the remainder to lowercase. 04612 * Note: case conversion is effective only in ASCII region. 04613 * 04614 * "hello".capitalize #=> "Hello" 04615 * "HELLO".capitalize #=> "Hello" 04616 * "123ABC".capitalize #=> "123abc" 04617 */ 04618 04619 static VALUE 04620 rb_str_capitalize(VALUE str) 04621 { 04622 str = rb_str_dup(str); 04623 rb_str_capitalize_bang(str); 04624 return str; 04625 } 04626 04627 04628 /* 04629 * call-seq: 04630 * str.swapcase! -> str or nil 04631 * 04632 * Equivalent to <code>String#swapcase</code>, but modifies the receiver in 04633 * place, returning <i>str</i>, or <code>nil</code> if no changes were made. 04634 * Note: case conversion is effective only in ASCII region. 04635 */ 04636 04637 static VALUE 04638 rb_str_swapcase_bang(VALUE str) 04639 { 04640 rb_encoding *enc; 04641 char *s, *send; 04642 int modify = 0; 04643 int n; 04644 04645 str_modify_keep_cr(str); 04646 enc = STR_ENC_GET(str); 04647 rb_str_check_dummy_enc(enc); 04648 s = RSTRING_PTR(str); send = RSTRING_END(str); 04649 while (s < send) { 04650 unsigned int c = rb_enc_codepoint_len(s, send, &n, enc); 04651 04652 if (rb_enc_isupper(c, enc)) { 04653 /* assuming toupper returns codepoint with same size */ 04654 rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc); 04655 modify = 1; 04656 } 04657 else if (rb_enc_islower(c, enc)) { 04658 /* assuming tolower returns codepoint with same size */ 04659 rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc); 04660 modify = 1; 04661 } 04662 s += n; 04663 } 04664 04665 if (modify) return str; 04666 return Qnil; 04667 } 04668 04669 04670 /* 04671 * call-seq: 04672 * str.swapcase -> new_str 04673 * 04674 * Returns a copy of <i>str</i> with uppercase alphabetic characters converted 04675 * to lowercase and lowercase characters converted to uppercase. 04676 * Note: case conversion is effective only in ASCII region. 04677 * 04678 * "Hello".swapcase #=> "hELLO" 04679 * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11" 04680 */ 04681 04682 static VALUE 04683 rb_str_swapcase(VALUE str) 04684 { 04685 str = rb_str_dup(str); 04686 rb_str_swapcase_bang(str); 04687 return str; 04688 } 04689 04690 typedef unsigned char *USTR; 04691 04692 struct tr { 04693 int gen; 04694 unsigned int now, max; 04695 char *p, *pend; 04696 }; 04697 04698 static unsigned int 04699 trnext(struct tr *t, rb_encoding *enc) 04700 { 04701 int n; 04702 04703 for (;;) { 04704 if (!t->gen) { 04705 if (t->p == t->pend) return -1; 04706 if (t->p < t->pend - 1 && *t->p == '\\') { 04707 t->p++; 04708 } 04709 t->now = rb_enc_codepoint_len(t->p, t->pend, &n, enc); 04710 t->p += n; 04711 if (t->p < t->pend - 1 && *t->p == '-') { 04712 t->p++; 04713 if (t->p < t->pend) { 04714 unsigned int c = rb_enc_codepoint_len(t->p, t->pend, &n, enc); 04715 t->p += n; 04716 if (t->now > c) { 04717 if (t->now < 0x80 && c < 0x80) { 04718 rb_raise(rb_eArgError, 04719 "invalid range \"%c-%c\" in string transliteration", 04720 t->now, c); 04721 } 04722 else { 04723 rb_raise(rb_eArgError, "invalid range in string transliteration"); 04724 } 04725 continue; /* not reached */ 04726 } 04727 t->gen = 1; 04728 t->max = c; 04729 } 04730 } 04731 return t->now; 04732 } 04733 else if (++t->now < t->max) { 04734 return t->now; 04735 } 04736 else { 04737 t->gen = 0; 04738 return t->max; 04739 } 04740 } 04741 } 04742 04743 static VALUE rb_str_delete_bang(int,VALUE*,VALUE); 04744 04745 static VALUE 04746 tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) 04747 { 04748 const unsigned int errc = -1; 04749 unsigned int trans[256]; 04750 rb_encoding *enc, *e1, *e2; 04751 struct tr trsrc, trrepl; 04752 int cflag = 0; 04753 unsigned int c, c0; 04754 int last = 0, modify = 0, i, l; 04755 char *s, *send; 04756 VALUE hash = 0; 04757 int singlebyte = single_byte_optimizable(str); 04758 int cr; 04759 04760 #define CHECK_IF_ASCII(c) \ 04761 (void)((cr == ENC_CODERANGE_7BIT && !rb_isascii(c)) ? \ 04762 (cr = ENC_CODERANGE_VALID) : 0) 04763 04764 StringValue(src); 04765 StringValue(repl); 04766 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil; 04767 if (RSTRING_LEN(repl) == 0) { 04768 return rb_str_delete_bang(1, &src, str); 04769 } 04770 04771 cr = ENC_CODERANGE(str); 04772 e1 = rb_enc_check(str, src); 04773 e2 = rb_enc_check(str, repl); 04774 if (e1 == e2) { 04775 enc = e1; 04776 } 04777 else { 04778 enc = rb_enc_check(src, repl); 04779 } 04780 trsrc.p = RSTRING_PTR(src); trsrc.pend = trsrc.p + RSTRING_LEN(src); 04781 if (RSTRING_LEN(src) > 1 && 04782 rb_enc_ascget(trsrc.p, trsrc.pend, &l, enc) == '^' && 04783 trsrc.p + l < trsrc.pend) { 04784 cflag = 1; 04785 trsrc.p += l; 04786 } 04787 trrepl.p = RSTRING_PTR(repl); 04788 trrepl.pend = trrepl.p + RSTRING_LEN(repl); 04789 trsrc.gen = trrepl.gen = 0; 04790 trsrc.now = trrepl.now = 0; 04791 trsrc.max = trrepl.max = 0; 04792 04793 if (cflag) { 04794 for (i=0; i<256; i++) { 04795 trans[i] = 1; 04796 } 04797 while ((c = trnext(&trsrc, enc)) != errc) { 04798 if (c < 256) { 04799 trans[c] = errc; 04800 } 04801 else { 04802 if (!hash) hash = rb_hash_new(); 04803 rb_hash_aset(hash, UINT2NUM(c), Qtrue); 04804 } 04805 } 04806 while ((c = trnext(&trrepl, enc)) != errc) 04807 /* retrieve last replacer */; 04808 last = trrepl.now; 04809 for (i=0; i<256; i++) { 04810 if (trans[i] != errc) { 04811 trans[i] = last; 04812 } 04813 } 04814 } 04815 else { 04816 unsigned int r; 04817 04818 for (i=0; i<256; i++) { 04819 trans[i] = errc; 04820 } 04821 while ((c = trnext(&trsrc, enc)) != errc) { 04822 r = trnext(&trrepl, enc); 04823 if (r == errc) r = trrepl.now; 04824 if (c < 256) { 04825 trans[c] = r; 04826 if (rb_enc_codelen(r, enc) != 1) singlebyte = 0; 04827 } 04828 else { 04829 if (!hash) hash = rb_hash_new(); 04830 rb_hash_aset(hash, UINT2NUM(c), UINT2NUM(r)); 04831 } 04832 } 04833 } 04834 04835 if (cr == ENC_CODERANGE_VALID) 04836 cr = ENC_CODERANGE_7BIT; 04837 str_modify_keep_cr(str); 04838 s = RSTRING_PTR(str); send = RSTRING_END(str); 04839 if (sflag) { 04840 int clen, tlen; 04841 long offset, max = RSTRING_LEN(str); 04842 unsigned int save = -1; 04843 char *buf = ALLOC_N(char, max), *t = buf; 04844 04845 while (s < send) { 04846 int may_modify = 0; 04847 04848 c0 = c = rb_enc_codepoint_len(s, send, &clen, e1); 04849 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc); 04850 04851 s += clen; 04852 if (c < 256) { 04853 c = trans[c]; 04854 } 04855 else if (hash) { 04856 VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c)); 04857 if (NIL_P(tmp)) { 04858 if (cflag) c = last; 04859 else c = errc; 04860 } 04861 else if (cflag) c = errc; 04862 else c = NUM2INT(tmp); 04863 } 04864 else { 04865 c = errc; 04866 } 04867 if (c != (unsigned int)-1) { 04868 if (save == c) { 04869 CHECK_IF_ASCII(c); 04870 continue; 04871 } 04872 save = c; 04873 tlen = rb_enc_codelen(c, enc); 04874 modify = 1; 04875 } 04876 else { 04877 save = -1; 04878 c = c0; 04879 if (enc != e1) may_modify = 1; 04880 } 04881 while (t - buf + tlen >= max) { 04882 offset = t - buf; 04883 max *= 2; 04884 REALLOC_N(buf, char, max); 04885 t = buf + offset; 04886 } 04887 rb_enc_mbcput(c, t, enc); 04888 if (may_modify && memcmp(s, t, tlen) != 0) { 04889 modify = 1; 04890 } 04891 CHECK_IF_ASCII(c); 04892 t += tlen; 04893 } 04894 *t = '\0'; 04895 RSTRING(str)->as.heap.ptr = buf; 04896 RSTRING(str)->as.heap.len = t - buf; 04897 STR_SET_NOEMBED(str); 04898 RSTRING(str)->as.heap.aux.capa = max; 04899 } 04900 else if (rb_enc_mbmaxlen(enc) == 1 || (singlebyte && !hash)) { 04901 while (s < send) { 04902 c = (unsigned char)*s; 04903 if (trans[c] != errc) { 04904 if (!cflag) { 04905 c = trans[c]; 04906 *s = c; 04907 modify = 1; 04908 } 04909 else { 04910 *s = last; 04911 modify = 1; 04912 } 04913 } 04914 CHECK_IF_ASCII(c); 04915 s++; 04916 } 04917 } 04918 else { 04919 int clen, tlen, max = (int)(RSTRING_LEN(str) * 1.2); 04920 long offset; 04921 char *buf = ALLOC_N(char, max), *t = buf; 04922 04923 while (s < send) { 04924 int may_modify = 0; 04925 c0 = c = rb_enc_codepoint_len(s, send, &clen, e1); 04926 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc); 04927 04928 if (c < 256) { 04929 c = trans[c]; 04930 } 04931 else if (hash) { 04932 VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c)); 04933 if (NIL_P(tmp)) { 04934 if (cflag) c = last; 04935 else c = errc; 04936 } 04937 else if (cflag) c = errc; 04938 else c = NUM2INT(tmp); 04939 } 04940 else { 04941 c = errc; 04942 } 04943 if (c != errc) { 04944 tlen = rb_enc_codelen(c, enc); 04945 modify = 1; 04946 } 04947 else { 04948 c = c0; 04949 if (enc != e1) may_modify = 1; 04950 } 04951 while (t - buf + tlen >= max) { 04952 offset = t - buf; 04953 max *= 2; 04954 REALLOC_N(buf, char, max); 04955 t = buf + offset; 04956 } 04957 if (s != t) { 04958 rb_enc_mbcput(c, t, enc); 04959 if (may_modify && memcmp(s, t, tlen) != 0) { 04960 modify = 1; 04961 } 04962 } 04963 CHECK_IF_ASCII(c); 04964 s += clen; 04965 t += tlen; 04966 } 04967 if (!STR_EMBED_P(str)) { 04968 xfree(RSTRING(str)->as.heap.ptr); 04969 } 04970 *t = '\0'; 04971 RSTRING(str)->as.heap.ptr = buf; 04972 RSTRING(str)->as.heap.len = t - buf; 04973 STR_SET_NOEMBED(str); 04974 RSTRING(str)->as.heap.aux.capa = max; 04975 } 04976 04977 if (modify) { 04978 if (cr != ENC_CODERANGE_BROKEN) 04979 ENC_CODERANGE_SET(str, cr); 04980 rb_enc_associate(str, enc); 04981 return str; 04982 } 04983 return Qnil; 04984 } 04985 04986 04987 /* 04988 * call-seq: 04989 * str.tr!(from_str, to_str) -> str or nil 04990 * 04991 * Translates <i>str</i> in place, using the same rules as 04992 * <code>String#tr</code>. Returns <i>str</i>, or <code>nil</code> if no 04993 * changes were made. 04994 */ 04995 04996 static VALUE 04997 rb_str_tr_bang(VALUE str, VALUE src, VALUE repl) 04998 { 04999 return tr_trans(str, src, repl, 0); 05000 } 05001 05002 05003 /* 05004 * call-seq: 05005 * str.tr(from_str, to_str) -> new_str 05006 * 05007 * Returns a copy of <i>str</i> with the characters in <i>from_str</i> replaced 05008 * by the corresponding characters in <i>to_str</i>. If <i>to_str</i> is 05009 * shorter than <i>from_str</i>, it is padded with its last character. Both 05010 * strings may use the c1--c2 notation to denote ranges of characters, and 05011 * <i>from_str</i> may start with a <code>^</code>, which denotes all 05012 * characters except those listed. 05013 * 05014 * "hello".tr('aeiou', '*') #=> "h*ll*" 05015 * "hello".tr('^aeiou', '*') #=> "*e**o" 05016 * "hello".tr('el', 'ip') #=> "hippo" 05017 * "hello".tr('a-y', 'b-z') #=> "ifmmp" 05018 */ 05019 05020 static VALUE 05021 rb_str_tr(VALUE str, VALUE src, VALUE repl) 05022 { 05023 str = rb_str_dup(str); 05024 tr_trans(str, src, repl, 0); 05025 return str; 05026 } 05027 05028 static void 05029 tr_setup_table(VALUE str, char stable[256], int first, 05030 VALUE *tablep, VALUE *ctablep, rb_encoding *enc) 05031 { 05032 const unsigned int errc = -1; 05033 char buf[256]; 05034 struct tr tr; 05035 unsigned int c; 05036 VALUE table = 0, ptable = 0; 05037 int i, l, cflag = 0; 05038 05039 tr.p = RSTRING_PTR(str); tr.pend = tr.p + RSTRING_LEN(str); 05040 tr.gen = tr.now = tr.max = 0; 05041 05042 if (RSTRING_LEN(str) > 1 && rb_enc_ascget(tr.p, tr.pend, &l, enc) == '^') { 05043 cflag = 1; 05044 tr.p += l; 05045 05046 table = rb_hash_new(); 05047 ptable = *ctablep; 05048 *ctablep = table; 05049 } 05050 else { 05051 table = rb_hash_new(); 05052 ptable = *tablep; 05053 *tablep = table; 05054 } 05055 if (first) { 05056 for (i=0; i<256; i++) { 05057 stable[i] = 1; 05058 } 05059 } 05060 for (i=0; i<256; i++) { 05061 buf[i] = cflag; 05062 } 05063 05064 while ((c = trnext(&tr, enc)) != errc) { 05065 if (c < 256) { 05066 buf[c & 0xff] = !cflag; 05067 } 05068 else { 05069 VALUE key = UINT2NUM(c); 05070 05071 if (!table) { 05072 table = rb_hash_new(); 05073 ptable = *tablep; 05074 *tablep = table; 05075 } 05076 if (!ptable || !NIL_P(rb_hash_aref(ptable, key))) { 05077 rb_hash_aset(table, key, Qtrue); 05078 } 05079 } 05080 } 05081 for (i=0; i<256; i++) { 05082 stable[i] = stable[i] && buf[i]; 05083 } 05084 } 05085 05086 05087 static int 05088 tr_find(unsigned int c, char table[256], VALUE del, VALUE nodel) 05089 { 05090 if (c < 256) { 05091 return table[c] != 0; 05092 } 05093 else { 05094 VALUE v = UINT2NUM(c); 05095 05096 if (del) { 05097 if (!NIL_P(rb_hash_lookup(del, v)) && 05098 (!nodel || NIL_P(rb_hash_lookup(nodel, v)))) { 05099 return TRUE; 05100 } 05101 } 05102 else if (nodel && NIL_P(rb_hash_lookup(nodel, v))) { 05103 return TRUE; 05104 } 05105 return FALSE; 05106 } 05107 } 05108 05109 /* 05110 * call-seq: 05111 * str.delete!([other_str]+) -> str or nil 05112 * 05113 * Performs a <code>delete</code> operation in place, returning <i>str</i>, or 05114 * <code>nil</code> if <i>str</i> was not modified. 05115 */ 05116 05117 static VALUE 05118 rb_str_delete_bang(int argc, VALUE *argv, VALUE str) 05119 { 05120 char squeez[256]; 05121 rb_encoding *enc = 0; 05122 char *s, *send, *t; 05123 VALUE del = 0, nodel = 0; 05124 int modify = 0; 05125 int i, ascompat, cr; 05126 05127 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil; 05128 if (argc < 1) { 05129 rb_raise(rb_eArgError, "wrong number of arguments (at least 1)"); 05130 } 05131 for (i=0; i<argc; i++) { 05132 VALUE s = argv[i]; 05133 05134 StringValue(s); 05135 enc = rb_enc_check(str, s); 05136 tr_setup_table(s, squeez, i==0, &del, &nodel, enc); 05137 } 05138 05139 str_modify_keep_cr(str); 05140 ascompat = rb_enc_asciicompat(enc); 05141 s = t = RSTRING_PTR(str); 05142 send = RSTRING_END(str); 05143 cr = ascompat ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID; 05144 while (s < send) { 05145 unsigned int c; 05146 int clen; 05147 05148 if (ascompat && (c = *(unsigned char*)s) < 0x80) { 05149 if (squeez[c]) { 05150 modify = 1; 05151 } 05152 else { 05153 if (t != s) *t = c; 05154 t++; 05155 } 05156 s++; 05157 } 05158 else { 05159 c = rb_enc_codepoint_len(s, send, &clen, enc); 05160 05161 if (tr_find(c, squeez, del, nodel)) { 05162 modify = 1; 05163 } 05164 else { 05165 if (t != s) rb_enc_mbcput(c, t, enc); 05166 t += clen; 05167 if (cr == ENC_CODERANGE_7BIT) cr = ENC_CODERANGE_VALID; 05168 } 05169 s += clen; 05170 } 05171 } 05172 *t = '\0'; 05173 STR_SET_LEN(str, t - RSTRING_PTR(str)); 05174 ENC_CODERANGE_SET(str, cr); 05175 05176 if (modify) return str; 05177 return Qnil; 05178 } 05179 05180 05181 /* 05182 * call-seq: 05183 * str.delete([other_str]+) -> new_str 05184 * 05185 * Returns a copy of <i>str</i> with all characters in the intersection of its 05186 * arguments deleted. Uses the same rules for building the set of characters as 05187 * <code>String#count</code>. 05188 * 05189 * "hello".delete "l","lo" #=> "heo" 05190 * "hello".delete "lo" #=> "he" 05191 * "hello".delete "aeiou", "^e" #=> "hell" 05192 * "hello".delete "ej-m" #=> "ho" 05193 */ 05194 05195 static VALUE 05196 rb_str_delete(int argc, VALUE *argv, VALUE str) 05197 { 05198 str = rb_str_dup(str); 05199 rb_str_delete_bang(argc, argv, str); 05200 return str; 05201 } 05202 05203 05204 /* 05205 * call-seq: 05206 * str.squeeze!([other_str]*) -> str or nil 05207 * 05208 * Squeezes <i>str</i> in place, returning either <i>str</i>, or 05209 * <code>nil</code> if no changes were made. 05210 */ 05211 05212 static VALUE 05213 rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str) 05214 { 05215 char squeez[256]; 05216 rb_encoding *enc = 0; 05217 VALUE del = 0, nodel = 0; 05218 char *s, *send, *t; 05219 int i, modify = 0; 05220 int ascompat, singlebyte = single_byte_optimizable(str); 05221 unsigned int save; 05222 05223 if (argc == 0) { 05224 enc = STR_ENC_GET(str); 05225 } 05226 else { 05227 for (i=0; i<argc; i++) { 05228 VALUE s = argv[i]; 05229 05230 StringValue(s); 05231 enc = rb_enc_check(str, s); 05232 if (singlebyte && !single_byte_optimizable(s)) 05233 singlebyte = 0; 05234 tr_setup_table(s, squeez, i==0, &del, &nodel, enc); 05235 } 05236 } 05237 05238 str_modify_keep_cr(str); 05239 s = t = RSTRING_PTR(str); 05240 if (!s || RSTRING_LEN(str) == 0) return Qnil; 05241 send = RSTRING_END(str); 05242 save = -1; 05243 ascompat = rb_enc_asciicompat(enc); 05244 05245 if (singlebyte) { 05246 while (s < send) { 05247 unsigned int c = *(unsigned char*)s++; 05248 if (c != save || (argc > 0 && !squeez[c])) { 05249 *t++ = save = c; 05250 } 05251 } 05252 } else { 05253 while (s < send) { 05254 unsigned int c; 05255 int clen; 05256 05257 if (ascompat && (c = *(unsigned char*)s) < 0x80) { 05258 if (c != save || (argc > 0 && !squeez[c])) { 05259 *t++ = save = c; 05260 } 05261 s++; 05262 } 05263 else { 05264 c = rb_enc_codepoint_len(s, send, &clen, enc); 05265 05266 if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) { 05267 if (t != s) rb_enc_mbcput(c, t, enc); 05268 save = c; 05269 t += clen; 05270 } 05271 s += clen; 05272 } 05273 } 05274 } 05275 05276 *t = '\0'; 05277 if (t - RSTRING_PTR(str) != RSTRING_LEN(str)) { 05278 STR_SET_LEN(str, t - RSTRING_PTR(str)); 05279 modify = 1; 05280 } 05281 05282 if (modify) return str; 05283 return Qnil; 05284 } 05285 05286 05287 /* 05288 * call-seq: 05289 * str.squeeze([other_str]*) -> new_str 05290 * 05291 * Builds a set of characters from the <i>other_str</i> parameter(s) using the 05292 * procedure described for <code>String#count</code>. Returns a new string 05293 * where runs of the same character that occur in this set are replaced by a 05294 * single character. If no arguments are given, all runs of identical 05295 * characters are replaced by a single character. 05296 * 05297 * "yellow moon".squeeze #=> "yelow mon" 05298 * " now is the".squeeze(" ") #=> " now is the" 05299 * "putters shoot balls".squeeze("m-z") #=> "puters shot balls" 05300 */ 05301 05302 static VALUE 05303 rb_str_squeeze(int argc, VALUE *argv, VALUE str) 05304 { 05305 str = rb_str_dup(str); 05306 rb_str_squeeze_bang(argc, argv, str); 05307 return str; 05308 } 05309 05310 05311 /* 05312 * call-seq: 05313 * str.tr_s!(from_str, to_str) -> str or nil 05314 * 05315 * Performs <code>String#tr_s</code> processing on <i>str</i> in place, 05316 * returning <i>str</i>, or <code>nil</code> if no changes were made. 05317 */ 05318 05319 static VALUE 05320 rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl) 05321 { 05322 return tr_trans(str, src, repl, 1); 05323 } 05324 05325 05326 /* 05327 * call-seq: 05328 * str.tr_s(from_str, to_str) -> new_str 05329 * 05330 * Processes a copy of <i>str</i> as described under <code>String#tr</code>, 05331 * then removes duplicate characters in regions that were affected by the 05332 * translation. 05333 * 05334 * "hello".tr_s('l', 'r') #=> "hero" 05335 * "hello".tr_s('el', '*') #=> "h*o" 05336 * "hello".tr_s('el', 'hx') #=> "hhxo" 05337 */ 05338 05339 static VALUE 05340 rb_str_tr_s(VALUE str, VALUE src, VALUE repl) 05341 { 05342 str = rb_str_dup(str); 05343 tr_trans(str, src, repl, 1); 05344 return str; 05345 } 05346 05347 05348 /* 05349 * call-seq: 05350 * str.count([other_str]+) -> fixnum 05351 * 05352 * Each <i>other_str</i> parameter defines a set of characters to count. The 05353 * intersection of these sets defines the characters to count in 05354 * <i>str</i>. Any <i>other_str</i> that starts with a caret (^) is 05355 * negated. The sequence c1--c2 means all characters between c1 and c2. 05356 * 05357 * a = "hello world" 05358 * a.count "lo" #=> 5 05359 * a.count "lo", "o" #=> 2 05360 * a.count "hello", "^l" #=> 4 05361 * a.count "ej-m" #=> 4 05362 */ 05363 05364 static VALUE 05365 rb_str_count(int argc, VALUE *argv, VALUE str) 05366 { 05367 char table[256]; 05368 rb_encoding *enc = 0; 05369 VALUE del = 0, nodel = 0; 05370 char *s, *send; 05371 int i; 05372 int ascompat; 05373 05374 if (argc < 1) { 05375 rb_raise(rb_eArgError, "wrong number of arguments (at least 1)"); 05376 } 05377 for (i=0; i<argc; i++) { 05378 VALUE tstr = argv[i]; 05379 unsigned char c; 05380 05381 StringValue(tstr); 05382 enc = rb_enc_check(str, tstr); 05383 if (argc == 1 && RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) && 05384 (c = RSTRING_PTR(tstr)[0]) < 0x80 && !is_broken_string(str)) { 05385 int n = 0; 05386 05387 s = RSTRING_PTR(str); 05388 if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0); 05389 send = RSTRING_END(str); 05390 while (s < send) { 05391 if (*(unsigned char*)s++ == c) n++; 05392 } 05393 return INT2NUM(n); 05394 } 05395 tr_setup_table(tstr, table, i==0, &del, &nodel, enc); 05396 } 05397 05398 s = RSTRING_PTR(str); 05399 if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0); 05400 send = RSTRING_END(str); 05401 ascompat = rb_enc_asciicompat(enc); 05402 i = 0; 05403 while (s < send) { 05404 unsigned int c; 05405 05406 if (ascompat && (c = *(unsigned char*)s) < 0x80) { 05407 if (table[c]) { 05408 i++; 05409 } 05410 s++; 05411 } 05412 else { 05413 int clen; 05414 c = rb_enc_codepoint_len(s, send, &clen, enc); 05415 if (tr_find(c, table, del, nodel)) { 05416 i++; 05417 } 05418 s += clen; 05419 } 05420 } 05421 05422 return INT2NUM(i); 05423 } 05424 05425 static const char isspacetable[256] = { 05426 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 05427 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05428 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05429 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05430 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05431 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05432 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05433 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05434 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05435 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05436 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05437 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05438 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05439 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05440 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 05441 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 05442 }; 05443 05444 #define ascii_isspace(c) isspacetable[(unsigned char)(c)] 05445 05446 /* 05447 * call-seq: 05448 * str.split(pattern=$;, [limit]) -> anArray 05449 * 05450 * Divides <i>str</i> into substrings based on a delimiter, returning an array 05451 * of these substrings. 05452 * 05453 * If <i>pattern</i> is a <code>String</code>, then its contents are used as 05454 * the delimiter when splitting <i>str</i>. If <i>pattern</i> is a single 05455 * space, <i>str</i> is split on whitespace, with leading whitespace and runs 05456 * of contiguous whitespace characters ignored. 05457 * 05458 * If <i>pattern</i> is a <code>Regexp</code>, <i>str</i> is divided where the 05459 * pattern matches. Whenever the pattern matches a zero-length string, 05460 * <i>str</i> is split into individual characters. If <i>pattern</i> contains 05461 * groups, the respective matches will be returned in the array as well. 05462 * 05463 * If <i>pattern</i> is omitted, the value of <code>$;</code> is used. If 05464 * <code>$;</code> is <code>nil</code> (which is the default), <i>str</i> is 05465 * split on whitespace as if ` ' were specified. 05466 * 05467 * If the <i>limit</i> parameter is omitted, trailing null fields are 05468 * suppressed. If <i>limit</i> is a positive number, at most that number of 05469 * fields will be returned (if <i>limit</i> is <code>1</code>, the entire 05470 * string is returned as the only entry in an array). If negative, there is no 05471 * limit to the number of fields returned, and trailing null fields are not 05472 * suppressed. 05473 * 05474 * " now's the time".split #=> ["now's", "the", "time"] 05475 * " now's the time".split(' ') #=> ["now's", "the", "time"] 05476 * " now's the time".split(/ /) #=> ["", "now's", "", "the", "time"] 05477 * "1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"] 05478 * "hello".split(//) #=> ["h", "e", "l", "l", "o"] 05479 * "hello".split(//, 3) #=> ["h", "e", "llo"] 05480 * "hi mom".split(%r{\s*}) #=> ["h", "i", "m", "o", "m"] 05481 * 05482 * "mellow yellow".split("ello") #=> ["m", "w y", "w"] 05483 * "1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"] 05484 * "1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"] 05485 * "1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""] 05486 */ 05487 05488 static VALUE 05489 rb_str_split_m(int argc, VALUE *argv, VALUE str) 05490 { 05491 rb_encoding *enc; 05492 VALUE spat; 05493 VALUE limit; 05494 enum {awk, string, regexp} split_type; 05495 long beg, end, i = 0; 05496 int lim = 0; 05497 VALUE result, tmp; 05498 05499 if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) { 05500 lim = NUM2INT(limit); 05501 if (lim <= 0) limit = Qnil; 05502 else if (lim == 1) { 05503 if (RSTRING_LEN(str) == 0) 05504 return rb_ary_new2(0); 05505 return rb_ary_new3(1, str); 05506 } 05507 i = 1; 05508 } 05509 05510 enc = STR_ENC_GET(str); 05511 if (NIL_P(spat)) { 05512 if (!NIL_P(rb_fs)) { 05513 spat = rb_fs; 05514 goto fs_set; 05515 } 05516 split_type = awk; 05517 } 05518 else { 05519 fs_set: 05520 if (TYPE(spat) == T_STRING) { 05521 rb_encoding *enc2 = STR_ENC_GET(spat); 05522 05523 split_type = string; 05524 if (RSTRING_LEN(spat) == 0) { 05525 /* Special case - split into chars */ 05526 spat = rb_reg_regcomp(spat); 05527 split_type = regexp; 05528 } 05529 else if (rb_enc_asciicompat(enc2) == 1) { 05530 if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){ 05531 split_type = awk; 05532 } 05533 } 05534 else { 05535 int l; 05536 if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l, enc2) == ' ' && 05537 RSTRING_LEN(spat) == l) { 05538 split_type = awk; 05539 } 05540 } 05541 } 05542 else { 05543 spat = get_pat(spat, 1); 05544 split_type = regexp; 05545 } 05546 } 05547 05548 result = rb_ary_new(); 05549 beg = 0; 05550 if (split_type == awk) { 05551 char *ptr = RSTRING_PTR(str); 05552 char *eptr = RSTRING_END(str); 05553 char *bptr = ptr; 05554 int skip = 1; 05555 unsigned int c; 05556 05557 end = beg; 05558 if (is_ascii_string(str)) { 05559 while (ptr < eptr) { 05560 c = (unsigned char)*ptr++; 05561 if (skip) { 05562 if (ascii_isspace(c)) { 05563 beg = ptr - bptr; 05564 } 05565 else { 05566 end = ptr - bptr; 05567 skip = 0; 05568 if (!NIL_P(limit) && lim <= i) break; 05569 } 05570 } 05571 else if (ascii_isspace(c)) { 05572 rb_ary_push(result, rb_str_subseq(str, beg, end-beg)); 05573 skip = 1; 05574 beg = ptr - bptr; 05575 if (!NIL_P(limit)) ++i; 05576 } 05577 else { 05578 end = ptr - bptr; 05579 } 05580 } 05581 } 05582 else { 05583 while (ptr < eptr) { 05584 int n; 05585 05586 c = rb_enc_codepoint_len(ptr, eptr, &n, enc); 05587 ptr += n; 05588 if (skip) { 05589 if (rb_isspace(c)) { 05590 beg = ptr - bptr; 05591 } 05592 else { 05593 end = ptr - bptr; 05594 skip = 0; 05595 if (!NIL_P(limit) && lim <= i) break; 05596 } 05597 } 05598 else if (rb_isspace(c)) { 05599 rb_ary_push(result, rb_str_subseq(str, beg, end-beg)); 05600 skip = 1; 05601 beg = ptr - bptr; 05602 if (!NIL_P(limit)) ++i; 05603 } 05604 else { 05605 end = ptr - bptr; 05606 } 05607 } 05608 } 05609 } 05610 else if (split_type == string) { 05611 char *ptr = RSTRING_PTR(str); 05612 char *temp = ptr; 05613 char *eptr = RSTRING_END(str); 05614 char *sptr = RSTRING_PTR(spat); 05615 long slen = RSTRING_LEN(spat); 05616 05617 if (is_broken_string(str)) { 05618 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str))); 05619 } 05620 if (is_broken_string(spat)) { 05621 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(spat))); 05622 } 05623 enc = rb_enc_check(str, spat); 05624 while (ptr < eptr && 05625 (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) { 05626 /* Check we are at the start of a char */ 05627 char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc); 05628 if (t != ptr + end) { 05629 ptr = t; 05630 continue; 05631 } 05632 rb_ary_push(result, rb_str_subseq(str, ptr - temp, end)); 05633 ptr += end + slen; 05634 if (!NIL_P(limit) && lim <= ++i) break; 05635 } 05636 beg = ptr - temp; 05637 } 05638 else { 05639 char *ptr = RSTRING_PTR(str); 05640 long len = RSTRING_LEN(str); 05641 long start = beg; 05642 long idx; 05643 int last_null = 0; 05644 struct re_registers *regs; 05645 05646 while ((end = rb_reg_search(spat, str, start, 0)) >= 0) { 05647 regs = RMATCH_REGS(rb_backref_get()); 05648 if (start == end && BEG(0) == END(0)) { 05649 if (!ptr) { 05650 rb_ary_push(result, str_new_empty(str)); 05651 break; 05652 } 05653 else if (last_null == 1) { 05654 rb_ary_push(result, rb_str_subseq(str, beg, 05655 rb_enc_fast_mbclen(ptr+beg, 05656 ptr+len, 05657 enc))); 05658 beg = start; 05659 } 05660 else { 05661 if (ptr+start == ptr+len) 05662 start++; 05663 else 05664 start += rb_enc_fast_mbclen(ptr+start,ptr+len,enc); 05665 last_null = 1; 05666 continue; 05667 } 05668 } 05669 else { 05670 rb_ary_push(result, rb_str_subseq(str, beg, end-beg)); 05671 beg = start = END(0); 05672 } 05673 last_null = 0; 05674 05675 for (idx=1; idx < regs->num_regs; idx++) { 05676 if (BEG(idx) == -1) continue; 05677 if (BEG(idx) == END(idx)) 05678 tmp = str_new_empty(str); 05679 else 05680 tmp = rb_str_subseq(str, BEG(idx), END(idx)-BEG(idx)); 05681 rb_ary_push(result, tmp); 05682 } 05683 if (!NIL_P(limit) && lim <= ++i) break; 05684 } 05685 } 05686 if (RSTRING_LEN(str) > 0 && (!NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) { 05687 if (RSTRING_LEN(str) == beg) 05688 tmp = str_new_empty(str); 05689 else 05690 tmp = rb_str_subseq(str, beg, RSTRING_LEN(str)-beg); 05691 rb_ary_push(result, tmp); 05692 } 05693 if (NIL_P(limit) && lim == 0) { 05694 long len; 05695 while ((len = RARRAY_LEN(result)) > 0 && 05696 (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0)) 05697 rb_ary_pop(result); 05698 } 05699 05700 return result; 05701 } 05702 05703 VALUE 05704 rb_str_split(VALUE str, const char *sep0) 05705 { 05706 VALUE sep; 05707 05708 StringValue(str); 05709 sep = rb_str_new2(sep0); 05710 return rb_str_split_m(1, &sep, str); 05711 } 05712 05713 05714 /* 05715 * call-seq: 05716 * str.each_line(separator=$/) {|substr| block } -> str 05717 * str.each_line(separator=$/) -> an_enumerator 05718 * 05719 * str.lines(separator=$/) {|substr| block } -> str 05720 * str.lines(separator=$/) -> an_enumerator 05721 * 05722 * Splits <i>str</i> using the supplied parameter as the record separator 05723 * (<code>$/</code> by default), passing each substring in turn to the supplied 05724 * block. If a zero-length record separator is supplied, the string is split 05725 * into paragraphs delimited by multiple successive newlines. 05726 * 05727 * If no block is given, an enumerator is returned instead. 05728 * 05729 * print "Example one\n" 05730 * "hello\nworld".each_line {|s| p s} 05731 * print "Example two\n" 05732 * "hello\nworld".each_line('l') {|s| p s} 05733 * print "Example three\n" 05734 * "hello\n\n\nworld".each_line('') {|s| p s} 05735 * 05736 * <em>produces:</em> 05737 * 05738 * Example one 05739 * "hello\n" 05740 * "world" 05741 * Example two 05742 * "hel" 05743 * "l" 05744 * "o\nworl" 05745 * "d" 05746 * Example three 05747 * "hello\n\n\n" 05748 * "world" 05749 */ 05750 05751 static VALUE 05752 rb_str_each_line(int argc, VALUE *argv, VALUE str) 05753 { 05754 rb_encoding *enc; 05755 VALUE rs; 05756 unsigned int newline; 05757 const char *p, *pend, *s, *ptr; 05758 long len, rslen; 05759 VALUE line; 05760 int n; 05761 VALUE orig = str; 05762 05763 if (argc == 0) { 05764 rs = rb_rs; 05765 } 05766 else { 05767 rb_scan_args(argc, argv, "01", &rs); 05768 } 05769 RETURN_ENUMERATOR(str, argc, argv); 05770 if (NIL_P(rs)) { 05771 rb_yield(str); 05772 return orig; 05773 } 05774 str = rb_str_new4(str); 05775 ptr = p = s = RSTRING_PTR(str); 05776 pend = p + RSTRING_LEN(str); 05777 len = RSTRING_LEN(str); 05778 StringValue(rs); 05779 if (rs == rb_default_rs) { 05780 enc = rb_enc_get(str); 05781 while (p < pend) { 05782 char *p0; 05783 05784 p = memchr(p, '\n', pend - p); 05785 if (!p) break; 05786 p0 = rb_enc_left_char_head(s, p, pend, enc); 05787 if (!rb_enc_is_newline(p0, pend, enc)) { 05788 p++; 05789 continue; 05790 } 05791 p = p0 + rb_enc_mbclen(p0, pend, enc); 05792 line = rb_str_new5(str, s, p - s); 05793 OBJ_INFECT(line, str); 05794 rb_enc_cr_str_copy_for_substr(line, str); 05795 rb_yield(line); 05796 str_mod_check(str, ptr, len); 05797 s = p; 05798 } 05799 goto finish; 05800 } 05801 05802 enc = rb_enc_check(str, rs); 05803 rslen = RSTRING_LEN(rs); 05804 if (rslen == 0) { 05805 newline = '\n'; 05806 } 05807 else { 05808 newline = rb_enc_codepoint(RSTRING_PTR(rs), RSTRING_END(rs), enc); 05809 } 05810 05811 while (p < pend) { 05812 unsigned int c = rb_enc_codepoint_len(p, pend, &n, enc); 05813 05814 again: 05815 if (rslen == 0 && c == newline) { 05816 p += n; 05817 if (p < pend && (c = rb_enc_codepoint_len(p, pend, &n, enc)) != newline) { 05818 goto again; 05819 } 05820 while (p < pend && rb_enc_codepoint(p, pend, enc) == newline) { 05821 p += n; 05822 } 05823 p -= n; 05824 } 05825 if (c == newline && 05826 (rslen <= 1 || memcmp(RSTRING_PTR(rs), p, rslen) == 0)) { 05827 line = rb_str_new5(str, s, p - s + (rslen ? rslen : n)); 05828 OBJ_INFECT(line, str); 05829 rb_enc_cr_str_copy_for_substr(line, str); 05830 rb_yield(line); 05831 str_mod_check(str, ptr, len); 05832 s = p + (rslen ? rslen : n); 05833 } 05834 p += n; 05835 } 05836 05837 finish: 05838 if (s != pend) { 05839 line = rb_str_new5(str, s, pend - s); 05840 OBJ_INFECT(line, str); 05841 rb_enc_cr_str_copy_for_substr(line, str); 05842 rb_yield(line); 05843 } 05844 05845 return orig; 05846 } 05847 05848 05849 /* 05850 * call-seq: 05851 * str.bytes {|fixnum| block } -> str 05852 * str.bytes -> an_enumerator 05853 * 05854 * str.each_byte {|fixnum| block } -> str 05855 * str.each_byte -> an_enumerator 05856 * 05857 * Passes each byte in <i>str</i> to the given block, or returns 05858 * an enumerator if no block is given. 05859 * 05860 * "hello".each_byte {|c| print c, ' ' } 05861 * 05862 * <em>produces:</em> 05863 * 05864 * 104 101 108 108 111 05865 */ 05866 05867 static VALUE 05868 rb_str_each_byte(VALUE str) 05869 { 05870 long i; 05871 05872 RETURN_ENUMERATOR(str, 0, 0); 05873 for (i=0; i<RSTRING_LEN(str); i++) { 05874 rb_yield(INT2FIX(RSTRING_PTR(str)[i] & 0xff)); 05875 } 05876 return str; 05877 } 05878 05879 05880 /* 05881 * call-seq: 05882 * str.chars {|cstr| block } -> str 05883 * str.chars -> an_enumerator 05884 * 05885 * str.each_char {|cstr| block } -> str 05886 * str.each_char -> an_enumerator 05887 * 05888 * Passes each character in <i>str</i> to the given block, or returns 05889 * an enumerator if no block is given. 05890 * 05891 * "hello".each_char {|c| print c, ' ' } 05892 * 05893 * <em>produces:</em> 05894 * 05895 * h e l l o 05896 */ 05897 05898 static VALUE 05899 rb_str_each_char(VALUE str) 05900 { 05901 VALUE orig = str; 05902 long i, len, n; 05903 const char *ptr; 05904 rb_encoding *enc; 05905 05906 RETURN_ENUMERATOR(str, 0, 0); 05907 str = rb_str_new4(str); 05908 ptr = RSTRING_PTR(str); 05909 len = RSTRING_LEN(str); 05910 enc = rb_enc_get(str); 05911 switch (ENC_CODERANGE(str)) { 05912 case ENC_CODERANGE_VALID: 05913 case ENC_CODERANGE_7BIT: 05914 for (i = 0; i < len; i += n) { 05915 n = rb_enc_fast_mbclen(ptr + i, ptr + len, enc); 05916 rb_yield(rb_str_subseq(str, i, n)); 05917 } 05918 break; 05919 default: 05920 for (i = 0; i < len; i += n) { 05921 n = rb_enc_mbclen(ptr + i, ptr + len, enc); 05922 rb_yield(rb_str_subseq(str, i, n)); 05923 } 05924 } 05925 return orig; 05926 } 05927 05928 /* 05929 * call-seq: 05930 * str.codepoints {|integer| block } -> str 05931 * str.codepoints -> an_enumerator 05932 * 05933 * str.each_codepoint {|integer| block } -> str 05934 * str.each_codepoint -> an_enumerator 05935 * 05936 * Passes the <code>Integer</code> ordinal of each character in <i>str</i>, 05937 * also known as a <i>codepoint</i> when applied to Unicode strings to the 05938 * given block. 05939 * 05940 * If no block is given, an enumerator is returned instead. 05941 * 05942 * "hello\u0639".each_codepoint {|c| print c, ' ' } 05943 * 05944 * <em>produces:</em> 05945 * 05946 * 104 101 108 108 111 1593 05947 */ 05948 05949 static VALUE 05950 rb_str_each_codepoint(VALUE str) 05951 { 05952 VALUE orig = str; 05953 long len; 05954 int n; 05955 unsigned int c; 05956 const char *ptr, *end; 05957 rb_encoding *enc; 05958 05959 if (single_byte_optimizable(str)) return rb_str_each_byte(str); 05960 RETURN_ENUMERATOR(str, 0, 0); 05961 str = rb_str_new4(str); 05962 ptr = RSTRING_PTR(str); 05963 len = RSTRING_LEN(str); 05964 end = RSTRING_END(str); 05965 enc = STR_ENC_GET(str); 05966 while (ptr < end) { 05967 c = rb_enc_codepoint_len(ptr, end, &n, enc); 05968 rb_yield(UINT2NUM(c)); 05969 ptr += n; 05970 } 05971 return orig; 05972 } 05973 05974 static long 05975 chopped_length(VALUE str) 05976 { 05977 rb_encoding *enc = STR_ENC_GET(str); 05978 const char *p, *p2, *beg, *end; 05979 05980 beg = RSTRING_PTR(str); 05981 end = beg + RSTRING_LEN(str); 05982 if (beg > end) return 0; 05983 p = rb_enc_prev_char(beg, end, end, enc); 05984 if (!p) return 0; 05985 if (p > beg && rb_enc_ascget(p, end, 0, enc) == '\n') { 05986 p2 = rb_enc_prev_char(beg, p, end, enc); 05987 if (p2 && rb_enc_ascget(p2, end, 0, enc) == '\r') p = p2; 05988 } 05989 return p - beg; 05990 } 05991 05992 /* 05993 * call-seq: 05994 * str.chop! -> str or nil 05995 * 05996 * Processes <i>str</i> as for <code>String#chop</code>, returning <i>str</i>, 05997 * or <code>nil</code> if <i>str</i> is the empty string. See also 05998 * <code>String#chomp!</code>. 05999 */ 06000 06001 static VALUE 06002 rb_str_chop_bang(VALUE str) 06003 { 06004 str_modify_keep_cr(str); 06005 if (RSTRING_LEN(str) > 0) { 06006 long len; 06007 len = chopped_length(str); 06008 STR_SET_LEN(str, len); 06009 RSTRING_PTR(str)[len] = '\0'; 06010 if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) { 06011 ENC_CODERANGE_CLEAR(str); 06012 } 06013 return str; 06014 } 06015 return Qnil; 06016 } 06017 06018 06019 /* 06020 * call-seq: 06021 * str.chop -> new_str 06022 * 06023 * Returns a new <code>String</code> with the last character removed. If the 06024 * string ends with <code>\r\n</code>, both characters are removed. Applying 06025 * <code>chop</code> to an empty string returns an empty 06026 * string. <code>String#chomp</code> is often a safer alternative, as it leaves 06027 * the string unchanged if it doesn't end in a record separator. 06028 * 06029 * "string\r\n".chop #=> "string" 06030 * "string\n\r".chop #=> "string\n" 06031 * "string\n".chop #=> "string" 06032 * "string".chop #=> "strin" 06033 * "x".chop.chop #=> "" 06034 */ 06035 06036 static VALUE 06037 rb_str_chop(VALUE str) 06038 { 06039 VALUE str2 = rb_str_new5(str, RSTRING_PTR(str), chopped_length(str)); 06040 rb_enc_cr_str_copy_for_substr(str2, str); 06041 OBJ_INFECT(str2, str); 06042 return str2; 06043 } 06044 06045 06046 /* 06047 * call-seq: 06048 * str.chomp!(separator=$/) -> str or nil 06049 * 06050 * Modifies <i>str</i> in place as described for <code>String#chomp</code>, 06051 * returning <i>str</i>, or <code>nil</code> if no modifications were made. 06052 */ 06053 06054 static VALUE 06055 rb_str_chomp_bang(int argc, VALUE *argv, VALUE str) 06056 { 06057 rb_encoding *enc; 06058 VALUE rs; 06059 int newline; 06060 char *p, *pp, *e; 06061 long len, rslen; 06062 06063 str_modify_keep_cr(str); 06064 len = RSTRING_LEN(str); 06065 if (len == 0) return Qnil; 06066 p = RSTRING_PTR(str); 06067 e = p + len; 06068 if (argc == 0) { 06069 rs = rb_rs; 06070 if (rs == rb_default_rs) { 06071 smart_chomp: 06072 enc = rb_enc_get(str); 06073 if (rb_enc_mbminlen(enc) > 1) { 06074 pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc); 06075 if (rb_enc_is_newline(pp, e, enc)) { 06076 e = pp; 06077 } 06078 pp = e - rb_enc_mbminlen(enc); 06079 if (pp >= p) { 06080 pp = rb_enc_left_char_head(p, pp, e, enc); 06081 if (rb_enc_ascget(pp, e, 0, enc) == '\r') { 06082 e = pp; 06083 } 06084 } 06085 if (e == RSTRING_END(str)) { 06086 return Qnil; 06087 } 06088 len = e - RSTRING_PTR(str); 06089 STR_SET_LEN(str, len); 06090 } 06091 else { 06092 if (RSTRING_PTR(str)[len-1] == '\n') { 06093 STR_DEC_LEN(str); 06094 if (RSTRING_LEN(str) > 0 && 06095 RSTRING_PTR(str)[RSTRING_LEN(str)-1] == '\r') { 06096 STR_DEC_LEN(str); 06097 } 06098 } 06099 else if (RSTRING_PTR(str)[len-1] == '\r') { 06100 STR_DEC_LEN(str); 06101 } 06102 else { 06103 return Qnil; 06104 } 06105 } 06106 RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0'; 06107 return str; 06108 } 06109 } 06110 else { 06111 rb_scan_args(argc, argv, "01", &rs); 06112 } 06113 if (NIL_P(rs)) return Qnil; 06114 StringValue(rs); 06115 rslen = RSTRING_LEN(rs); 06116 if (rslen == 0) { 06117 while (len>0 && p[len-1] == '\n') { 06118 len--; 06119 if (len>0 && p[len-1] == '\r') 06120 len--; 06121 } 06122 if (len < RSTRING_LEN(str)) { 06123 STR_SET_LEN(str, len); 06124 RSTRING_PTR(str)[len] = '\0'; 06125 return str; 06126 } 06127 return Qnil; 06128 } 06129 if (rslen > len) return Qnil; 06130 newline = RSTRING_PTR(rs)[rslen-1]; 06131 if (rslen == 1 && newline == '\n') 06132 goto smart_chomp; 06133 06134 enc = rb_enc_check(str, rs); 06135 if (is_broken_string(rs)) { 06136 return Qnil; 06137 } 06138 pp = e - rslen; 06139 if (p[len-1] == newline && 06140 (rslen <= 1 || 06141 memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) { 06142 if (rb_enc_left_char_head(p, pp, e, enc) != pp) 06143 return Qnil; 06144 if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) { 06145 ENC_CODERANGE_CLEAR(str); 06146 } 06147 STR_SET_LEN(str, RSTRING_LEN(str) - rslen); 06148 RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0'; 06149 return str; 06150 } 06151 return Qnil; 06152 } 06153 06154 06155 /* 06156 * call-seq: 06157 * str.chomp(separator=$/) -> new_str 06158 * 06159 * Returns a new <code>String</code> with the given record separator removed 06160 * from the end of <i>str</i> (if present). If <code>$/</code> has not been 06161 * changed from the default Ruby record separator, then <code>chomp</code> also 06162 * removes carriage return characters (that is it will remove <code>\n</code>, 06163 * <code>\r</code>, and <code>\r\n</code>). 06164 * 06165 * "hello".chomp #=> "hello" 06166 * "hello\n".chomp #=> "hello" 06167 * "hello\r\n".chomp #=> "hello" 06168 * "hello\n\r".chomp #=> "hello\n" 06169 * "hello\r".chomp #=> "hello" 06170 * "hello \n there".chomp #=> "hello \n there" 06171 * "hello".chomp("llo") #=> "he" 06172 */ 06173 06174 static VALUE 06175 rb_str_chomp(int argc, VALUE *argv, VALUE str) 06176 { 06177 str = rb_str_dup(str); 06178 rb_str_chomp_bang(argc, argv, str); 06179 return str; 06180 } 06181 06182 /* 06183 * call-seq: 06184 * str.lstrip! -> self or nil 06185 * 06186 * Removes leading whitespace from <i>str</i>, returning <code>nil</code> if no 06187 * change was made. See also <code>String#rstrip!</code> and 06188 * <code>String#strip!</code>. 06189 * 06190 * " hello ".lstrip #=> "hello " 06191 * "hello".lstrip! #=> nil 06192 */ 06193 06194 static VALUE 06195 rb_str_lstrip_bang(VALUE str) 06196 { 06197 rb_encoding *enc; 06198 char *s, *t, *e; 06199 06200 str_modify_keep_cr(str); 06201 enc = STR_ENC_GET(str); 06202 s = RSTRING_PTR(str); 06203 if (!s || RSTRING_LEN(str) == 0) return Qnil; 06204 e = t = RSTRING_END(str); 06205 /* remove spaces at head */ 06206 while (s < e) { 06207 int n; 06208 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc); 06209 06210 if (!rb_isspace(cc)) break; 06211 s += n; 06212 } 06213 06214 if (s > RSTRING_PTR(str)) { 06215 STR_SET_LEN(str, t-s); 06216 memmove(RSTRING_PTR(str), s, RSTRING_LEN(str)); 06217 RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0'; 06218 return str; 06219 } 06220 return Qnil; 06221 } 06222 06223 06224 /* 06225 * call-seq: 06226 * str.lstrip -> new_str 06227 * 06228 * Returns a copy of <i>str</i> with leading whitespace removed. See also 06229 * <code>String#rstrip</code> and <code>String#strip</code>. 06230 * 06231 * " hello ".lstrip #=> "hello " 06232 * "hello".lstrip #=> "hello" 06233 */ 06234 06235 static VALUE 06236 rb_str_lstrip(VALUE str) 06237 { 06238 str = rb_str_dup(str); 06239 rb_str_lstrip_bang(str); 06240 return str; 06241 } 06242 06243 06244 /* 06245 * call-seq: 06246 * str.rstrip! -> self or nil 06247 * 06248 * Removes trailing whitespace from <i>str</i>, returning <code>nil</code> if 06249 * no change was made. See also <code>String#lstrip!</code> and 06250 * <code>String#strip!</code>. 06251 * 06252 * " hello ".rstrip #=> " hello" 06253 * "hello".rstrip! #=> nil 06254 */ 06255 06256 static VALUE 06257 rb_str_rstrip_bang(VALUE str) 06258 { 06259 rb_encoding *enc; 06260 char *s, *t, *e; 06261 06262 str_modify_keep_cr(str); 06263 enc = STR_ENC_GET(str); 06264 rb_str_check_dummy_enc(enc); 06265 s = RSTRING_PTR(str); 06266 if (!s || RSTRING_LEN(str) == 0) return Qnil; 06267 t = e = RSTRING_END(str); 06268 06269 /* remove trailing spaces or '\0's */ 06270 if (single_byte_optimizable(str)) { 06271 unsigned char c; 06272 while (s < t && ((c = *(t-1)) == '\0' || ascii_isspace(c))) t--; 06273 } 06274 else { 06275 char *tp; 06276 06277 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) { 06278 unsigned int c = rb_enc_codepoint(tp, e, enc); 06279 if (c && !rb_isspace(c)) break; 06280 t = tp; 06281 } 06282 } 06283 if (t < e) { 06284 long len = t-RSTRING_PTR(str); 06285 06286 STR_SET_LEN(str, len); 06287 RSTRING_PTR(str)[len] = '\0'; 06288 return str; 06289 } 06290 return Qnil; 06291 } 06292 06293 06294 /* 06295 * call-seq: 06296 * str.rstrip -> new_str 06297 * 06298 * Returns a copy of <i>str</i> with trailing whitespace removed. See also 06299 * <code>String#lstrip</code> and <code>String#strip</code>. 06300 * 06301 * " hello ".rstrip #=> " hello" 06302 * "hello".rstrip #=> "hello" 06303 */ 06304 06305 static VALUE 06306 rb_str_rstrip(VALUE str) 06307 { 06308 str = rb_str_dup(str); 06309 rb_str_rstrip_bang(str); 06310 return str; 06311 } 06312 06313 06314 /* 06315 * call-seq: 06316 * str.strip! -> str or nil 06317 * 06318 * Removes leading and trailing whitespace from <i>str</i>. Returns 06319 * <code>nil</code> if <i>str</i> was not altered. 06320 */ 06321 06322 static VALUE 06323 rb_str_strip_bang(VALUE str) 06324 { 06325 VALUE l = rb_str_lstrip_bang(str); 06326 VALUE r = rb_str_rstrip_bang(str); 06327 06328 if (NIL_P(l) && NIL_P(r)) return Qnil; 06329 return str; 06330 } 06331 06332 06333 /* 06334 * call-seq: 06335 * str.strip -> new_str 06336 * 06337 * Returns a copy of <i>str</i> with leading and trailing whitespace removed. 06338 * 06339 * " hello ".strip #=> "hello" 06340 * "\tgoodbye\r\n".strip #=> "goodbye" 06341 */ 06342 06343 static VALUE 06344 rb_str_strip(VALUE str) 06345 { 06346 str = rb_str_dup(str); 06347 rb_str_strip_bang(str); 06348 return str; 06349 } 06350 06351 static VALUE 06352 scan_once(VALUE str, VALUE pat, long *start) 06353 { 06354 VALUE result, match; 06355 struct re_registers *regs; 06356 int i; 06357 06358 if (rb_reg_search(pat, str, *start, 0) >= 0) { 06359 match = rb_backref_get(); 06360 regs = RMATCH_REGS(match); 06361 if (BEG(0) == END(0)) { 06362 rb_encoding *enc = STR_ENC_GET(str); 06363 /* 06364 * Always consume at least one character of the input string 06365 */ 06366 if (RSTRING_LEN(str) > END(0)) 06367 *start = END(0)+rb_enc_fast_mbclen(RSTRING_PTR(str)+END(0), 06368 RSTRING_END(str), enc); 06369 else 06370 *start = END(0)+1; 06371 } 06372 else { 06373 *start = END(0); 06374 } 06375 if (regs->num_regs == 1) { 06376 return rb_reg_nth_match(0, match); 06377 } 06378 result = rb_ary_new2(regs->num_regs); 06379 for (i=1; i < regs->num_regs; i++) { 06380 rb_ary_push(result, rb_reg_nth_match(i, match)); 06381 } 06382 06383 return result; 06384 } 06385 return Qnil; 06386 } 06387 06388 06389 /* 06390 * call-seq: 06391 * str.scan(pattern) -> array 06392 * str.scan(pattern) {|match, ...| block } -> str 06393 * 06394 * Both forms iterate through <i>str</i>, matching the pattern (which may be a 06395 * <code>Regexp</code> or a <code>String</code>). For each match, a result is 06396 * generated and either added to the result array or passed to the block. If 06397 * the pattern contains no groups, each individual result consists of the 06398 * matched string, <code>$&</code>. If the pattern contains groups, each 06399 * individual result is itself an array containing one entry per group. 06400 * 06401 * a = "cruel world" 06402 * a.scan(/\w+/) #=> ["cruel", "world"] 06403 * a.scan(/.../) #=> ["cru", "el ", "wor"] 06404 * a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]] 06405 * a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]] 06406 * 06407 * And the block form: 06408 * 06409 * a.scan(/\w+/) {|w| print "<<#{w}>> " } 06410 * print "\n" 06411 * a.scan(/(.)(.)/) {|x,y| print y, x } 06412 * print "\n" 06413 * 06414 * <em>produces:</em> 06415 * 06416 * <<cruel>> <<world>> 06417 * rceu lowlr 06418 */ 06419 06420 static VALUE 06421 rb_str_scan(VALUE str, VALUE pat) 06422 { 06423 VALUE result; 06424 long start = 0; 06425 long last = -1, prev = 0; 06426 char *p = RSTRING_PTR(str); long len = RSTRING_LEN(str); 06427 06428 pat = get_pat(pat, 1); 06429 if (!rb_block_given_p()) { 06430 VALUE ary = rb_ary_new(); 06431 06432 while (!NIL_P(result = scan_once(str, pat, &start))) { 06433 last = prev; 06434 prev = start; 06435 rb_ary_push(ary, result); 06436 } 06437 if (last >= 0) rb_reg_search(pat, str, last, 0); 06438 return ary; 06439 } 06440 06441 while (!NIL_P(result = scan_once(str, pat, &start))) { 06442 last = prev; 06443 prev = start; 06444 rb_yield(result); 06445 str_mod_check(str, p, len); 06446 } 06447 if (last >= 0) rb_reg_search(pat, str, last, 0); 06448 return str; 06449 } 06450 06451 06452 /* 06453 * call-seq: 06454 * str.hex -> integer 06455 * 06456 * Treats leading characters from <i>str</i> as a string of hexadecimal digits 06457 * (with an optional sign and an optional <code>0x</code>) and returns the 06458 * corresponding number. Zero is returned on error. 06459 * 06460 * "0x0a".hex #=> 10 06461 * "-1234".hex #=> -4660 06462 * "0".hex #=> 0 06463 * "wombat".hex #=> 0 06464 */ 06465 06466 static VALUE 06467 rb_str_hex(VALUE str) 06468 { 06469 rb_encoding *enc = rb_enc_get(str); 06470 06471 if (!rb_enc_asciicompat(enc)) { 06472 rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s", rb_enc_name(enc)); 06473 } 06474 return rb_str_to_inum(str, 16, FALSE); 06475 } 06476 06477 06478 /* 06479 * call-seq: 06480 * str.oct -> integer 06481 * 06482 * Treats leading characters of <i>str</i> as a string of octal digits (with an 06483 * optional sign) and returns the corresponding number. Returns 0 if the 06484 * conversion fails. 06485 * 06486 * "123".oct #=> 83 06487 * "-377".oct #=> -255 06488 * "bad".oct #=> 0 06489 * "0377bad".oct #=> 255 06490 */ 06491 06492 static VALUE 06493 rb_str_oct(VALUE str) 06494 { 06495 rb_encoding *enc = rb_enc_get(str); 06496 06497 if (!rb_enc_asciicompat(enc)) { 06498 rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s", rb_enc_name(enc)); 06499 } 06500 return rb_str_to_inum(str, -8, FALSE); 06501 } 06502 06503 06504 /* 06505 * call-seq: 06506 * str.crypt(other_str) -> new_str 06507 * 06508 * Applies a one-way cryptographic hash to <i>str</i> by invoking the standard 06509 * library function <code>crypt</code>. The argument is the salt string, which 06510 * should be two characters long, each character drawn from 06511 * <code>[a-zA-Z0-9./]</code>. 06512 */ 06513 06514 static VALUE 06515 rb_str_crypt(VALUE str, VALUE salt) 06516 { 06517 extern char *crypt(const char *, const char *); 06518 VALUE result; 06519 const char *s, *saltp; 06520 #ifdef BROKEN_CRYPT 06521 char salt_8bit_clean[3]; 06522 #endif 06523 06524 StringValue(salt); 06525 if (RSTRING_LEN(salt) < 2) 06526 rb_raise(rb_eArgError, "salt too short (need >=2 bytes)"); 06527 06528 s = RSTRING_PTR(str); 06529 if (!s) s = ""; 06530 saltp = RSTRING_PTR(salt); 06531 #ifdef BROKEN_CRYPT 06532 if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) { 06533 salt_8bit_clean[0] = saltp[0] & 0x7f; 06534 salt_8bit_clean[1] = saltp[1] & 0x7f; 06535 salt_8bit_clean[2] = '\0'; 06536 saltp = salt_8bit_clean; 06537 } 06538 #endif 06539 result = rb_str_new2(crypt(s, saltp)); 06540 OBJ_INFECT(result, str); 06541 OBJ_INFECT(result, salt); 06542 return result; 06543 } 06544 06545 06546 /* 06547 * call-seq: 06548 * str.intern -> symbol 06549 * str.to_sym -> symbol 06550 * 06551 * Returns the <code>Symbol</code> corresponding to <i>str</i>, creating the 06552 * symbol if it did not previously exist. See <code>Symbol#id2name</code>. 06553 * 06554 * "Koala".intern #=> :Koala 06555 * s = 'cat'.to_sym #=> :cat 06556 * s == :cat #=> true 06557 * s = '@cat'.to_sym #=> :@cat 06558 * s == :@cat #=> true 06559 * 06560 * This can also be used to create symbols that cannot be represented using the 06561 * <code>:xxx</code> notation. 06562 * 06563 * 'cat and dog'.to_sym #=> :"cat and dog" 06564 */ 06565 06566 VALUE 06567 rb_str_intern(VALUE s) 06568 { 06569 VALUE str = RB_GC_GUARD(s); 06570 ID id; 06571 06572 id = rb_intern_str(str); 06573 return ID2SYM(id); 06574 } 06575 06576 06577 /* 06578 * call-seq: 06579 * str.ord -> integer 06580 * 06581 * Return the <code>Integer</code> ordinal of a one-character string. 06582 * 06583 * "a".ord #=> 97 06584 */ 06585 06586 VALUE 06587 rb_str_ord(VALUE s) 06588 { 06589 unsigned int c; 06590 06591 c = rb_enc_codepoint(RSTRING_PTR(s), RSTRING_END(s), STR_ENC_GET(s)); 06592 return UINT2NUM(c); 06593 } 06594 /* 06595 * call-seq: 06596 * str.sum(n=16) -> integer 06597 * 06598 * Returns a basic <em>n</em>-bit checksum of the characters in <i>str</i>, 06599 * where <em>n</em> is the optional <code>Fixnum</code> parameter, defaulting 06600 * to 16. The result is simply the sum of the binary value of each character in 06601 * <i>str</i> modulo <code>2**n - 1</code>. This is not a particularly good 06602 * checksum. 06603 */ 06604 06605 static VALUE 06606 rb_str_sum(int argc, VALUE *argv, VALUE str) 06607 { 06608 VALUE vbits; 06609 int bits; 06610 char *ptr, *p, *pend; 06611 long len; 06612 VALUE sum = INT2FIX(0); 06613 unsigned long sum0 = 0; 06614 06615 if (argc == 0) { 06616 bits = 16; 06617 } 06618 else { 06619 rb_scan_args(argc, argv, "01", &vbits); 06620 bits = NUM2INT(vbits); 06621 } 06622 ptr = p = RSTRING_PTR(str); 06623 len = RSTRING_LEN(str); 06624 pend = p + len; 06625 06626 while (p < pend) { 06627 if (FIXNUM_MAX - UCHAR_MAX < sum0) { 06628 sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0)); 06629 str_mod_check(str, ptr, len); 06630 sum0 = 0; 06631 } 06632 sum0 += (unsigned char)*p; 06633 p++; 06634 } 06635 06636 if (bits == 0) { 06637 if (sum0) { 06638 sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0)); 06639 } 06640 } 06641 else { 06642 if (sum == INT2FIX(0)) { 06643 if (bits < (int)sizeof(long)*CHAR_BIT) { 06644 sum0 &= (((unsigned long)1)<<bits)-1; 06645 } 06646 sum = LONG2FIX(sum0); 06647 } 06648 else { 06649 VALUE mod; 06650 06651 if (sum0) { 06652 sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0)); 06653 } 06654 06655 mod = rb_funcall(INT2FIX(1), rb_intern("<<"), 1, INT2FIX(bits)); 06656 mod = rb_funcall(mod, '-', 1, INT2FIX(1)); 06657 sum = rb_funcall(sum, '&', 1, mod); 06658 } 06659 } 06660 return sum; 06661 } 06662 06663 static VALUE 06664 rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag) 06665 { 06666 rb_encoding *enc; 06667 VALUE w; 06668 long width, len, flen = 1, fclen = 1; 06669 VALUE res; 06670 char *p; 06671 const char *f = " "; 06672 long n, size, llen, rlen, llen2 = 0, rlen2 = 0; 06673 volatile VALUE pad; 06674 int singlebyte = 1, cr; 06675 06676 rb_scan_args(argc, argv, "11", &w, &pad); 06677 enc = STR_ENC_GET(str); 06678 width = NUM2LONG(w); 06679 if (argc == 2) { 06680 StringValue(pad); 06681 enc = rb_enc_check(str, pad); 06682 f = RSTRING_PTR(pad); 06683 flen = RSTRING_LEN(pad); 06684 fclen = str_strlen(pad, enc); 06685 singlebyte = single_byte_optimizable(pad); 06686 if (flen == 0 || fclen == 0) { 06687 rb_raise(rb_eArgError, "zero width padding"); 06688 } 06689 } 06690 len = str_strlen(str, enc); 06691 if (width < 0 || len >= width) return rb_str_dup(str); 06692 n = width - len; 06693 llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2); 06694 rlen = n - llen; 06695 cr = ENC_CODERANGE(str); 06696 if (flen > 1) { 06697 llen2 = str_offset(f, f + flen, llen % fclen, enc, singlebyte); 06698 rlen2 = str_offset(f, f + flen, rlen % fclen, enc, singlebyte); 06699 } 06700 size = RSTRING_LEN(str); 06701 if ((len = llen / fclen + rlen / fclen) >= LONG_MAX / flen || 06702 (len *= flen) >= LONG_MAX - llen2 - rlen2 || 06703 (len += llen2 + rlen2) >= LONG_MAX - size) { 06704 rb_raise(rb_eArgError, "argument too big"); 06705 } 06706 len += size; 06707 res = rb_str_new5(str, 0, len); 06708 p = RSTRING_PTR(res); 06709 if (flen <= 1) { 06710 memset(p, *f, llen); 06711 p += llen; 06712 } 06713 else { 06714 while (llen >= fclen) { 06715 memcpy(p,f,flen); 06716 p += flen; 06717 llen -= fclen; 06718 } 06719 if (llen > 0) { 06720 memcpy(p, f, llen2); 06721 p += llen2; 06722 } 06723 } 06724 memcpy(p, RSTRING_PTR(str), size); 06725 p += size; 06726 if (flen <= 1) { 06727 memset(p, *f, rlen); 06728 p += rlen; 06729 } 06730 else { 06731 while (rlen >= fclen) { 06732 memcpy(p,f,flen); 06733 p += flen; 06734 rlen -= fclen; 06735 } 06736 if (rlen > 0) { 06737 memcpy(p, f, rlen2); 06738 p += rlen2; 06739 } 06740 } 06741 *p = '\0'; 06742 STR_SET_LEN(res, p-RSTRING_PTR(res)); 06743 OBJ_INFECT(res, str); 06744 if (!NIL_P(pad)) OBJ_INFECT(res, pad); 06745 rb_enc_associate(res, enc); 06746 if (argc == 2) 06747 cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(pad)); 06748 if (cr != ENC_CODERANGE_BROKEN) 06749 ENC_CODERANGE_SET(res, cr); 06750 return res; 06751 } 06752 06753 06754 /* 06755 * call-seq: 06756 * str.ljust(integer, padstr=' ') -> new_str 06757 * 06758 * If <i>integer</i> is greater than the length of <i>str</i>, returns a new 06759 * <code>String</code> of length <i>integer</i> with <i>str</i> left justified 06760 * and padded with <i>padstr</i>; otherwise, returns <i>str</i>. 06761 * 06762 * "hello".ljust(4) #=> "hello" 06763 * "hello".ljust(20) #=> "hello " 06764 * "hello".ljust(20, '1234') #=> "hello123412341234123" 06765 */ 06766 06767 static VALUE 06768 rb_str_ljust(int argc, VALUE *argv, VALUE str) 06769 { 06770 return rb_str_justify(argc, argv, str, 'l'); 06771 } 06772 06773 06774 /* 06775 * call-seq: 06776 * str.rjust(integer, padstr=' ') -> new_str 06777 * 06778 * If <i>integer</i> is greater than the length of <i>str</i>, returns a new 06779 * <code>String</code> of length <i>integer</i> with <i>str</i> right justified 06780 * and padded with <i>padstr</i>; otherwise, returns <i>str</i>. 06781 * 06782 * "hello".rjust(4) #=> "hello" 06783 * "hello".rjust(20) #=> " hello" 06784 * "hello".rjust(20, '1234') #=> "123412341234123hello" 06785 */ 06786 06787 static VALUE 06788 rb_str_rjust(int argc, VALUE *argv, VALUE str) 06789 { 06790 return rb_str_justify(argc, argv, str, 'r'); 06791 } 06792 06793 06794 /* 06795 * call-seq: 06796 * str.center(integer, padstr) -> new_str 06797 * 06798 * If <i>integer</i> is greater than the length of <i>str</i>, returns a new 06799 * <code>String</code> of length <i>integer</i> with <i>str</i> centered and 06800 * padded with <i>padstr</i>; otherwise, returns <i>str</i>. 06801 * 06802 * "hello".center(4) #=> "hello" 06803 * "hello".center(20) #=> " hello " 06804 * "hello".center(20, '123') #=> "1231231hello12312312" 06805 */ 06806 06807 static VALUE 06808 rb_str_center(int argc, VALUE *argv, VALUE str) 06809 { 06810 return rb_str_justify(argc, argv, str, 'c'); 06811 } 06812 06813 /* 06814 * call-seq: 06815 * str.partition(sep) -> [head, sep, tail] 06816 * str.partition(regexp) -> [head, match, tail] 06817 * 06818 * Searches <i>sep</i> or pattern (<i>regexp</i>) in the string 06819 * and returns the part before it, the match, and the part 06820 * after it. 06821 * If it is not found, returns two empty strings and <i>str</i>. 06822 * 06823 * "hello".partition("l") #=> ["he", "l", "lo"] 06824 * "hello".partition("x") #=> ["hello", "", ""] 06825 * "hello".partition(/.l/) #=> ["h", "el", "lo"] 06826 */ 06827 06828 static VALUE 06829 rb_str_partition(VALUE str, VALUE sep) 06830 { 06831 long pos; 06832 int regex = FALSE; 06833 06834 if (TYPE(sep) == T_REGEXP) { 06835 pos = rb_reg_search(sep, str, 0, 0); 06836 regex = TRUE; 06837 } 06838 else { 06839 VALUE tmp; 06840 06841 tmp = rb_check_string_type(sep); 06842 if (NIL_P(tmp)) { 06843 rb_raise(rb_eTypeError, "type mismatch: %s given", 06844 rb_obj_classname(sep)); 06845 } 06846 sep = tmp; 06847 pos = rb_str_index(str, sep, 0); 06848 } 06849 if (pos < 0) { 06850 failed: 06851 return rb_ary_new3(3, str, str_new_empty(str), str_new_empty(str)); 06852 } 06853 if (regex) { 06854 sep = rb_str_subpat(str, sep, INT2FIX(0)); 06855 if (pos == 0 && RSTRING_LEN(sep) == 0) goto failed; 06856 } 06857 return rb_ary_new3(3, rb_str_subseq(str, 0, pos), 06858 sep, 06859 rb_str_subseq(str, pos+RSTRING_LEN(sep), 06860 RSTRING_LEN(str)-pos-RSTRING_LEN(sep))); 06861 } 06862 06863 /* 06864 * call-seq: 06865 * str.rpartition(sep) -> [head, sep, tail] 06866 * str.rpartition(regexp) -> [head, match, tail] 06867 * 06868 * Searches <i>sep</i> or pattern (<i>regexp</i>) in the string from the end 06869 * of the string, and returns the part before it, the match, and the part 06870 * after it. 06871 * If it is not found, returns two empty strings and <i>str</i>. 06872 * 06873 * "hello".rpartition("l") #=> ["hel", "l", "o"] 06874 * "hello".rpartition("x") #=> ["", "", "hello"] 06875 * "hello".rpartition(/.l/) #=> ["he", "ll", "o"] 06876 */ 06877 06878 static VALUE 06879 rb_str_rpartition(VALUE str, VALUE sep) 06880 { 06881 long pos = RSTRING_LEN(str); 06882 int regex = FALSE; 06883 06884 if (TYPE(sep) == T_REGEXP) { 06885 pos = rb_reg_search(sep, str, pos, 1); 06886 regex = TRUE; 06887 } 06888 else { 06889 VALUE tmp; 06890 06891 tmp = rb_check_string_type(sep); 06892 if (NIL_P(tmp)) { 06893 rb_raise(rb_eTypeError, "type mismatch: %s given", 06894 rb_obj_classname(sep)); 06895 } 06896 sep = tmp; 06897 pos = rb_str_sublen(str, pos); 06898 pos = rb_str_rindex(str, sep, pos); 06899 } 06900 if (pos < 0) { 06901 return rb_ary_new3(3, str_new_empty(str), str_new_empty(str), str); 06902 } 06903 if (regex) { 06904 sep = rb_reg_nth_match(0, rb_backref_get()); 06905 } 06906 return rb_ary_new3(3, rb_str_substr(str, 0, pos), 06907 sep, 06908 rb_str_substr(str,pos+str_strlen(sep,STR_ENC_GET(sep)),RSTRING_LEN(str))); 06909 } 06910 06911 /* 06912 * call-seq: 06913 * str.start_with?([prefix]+) -> true or false 06914 * 06915 * Returns true if <i>str</i> starts with a prefix given. 06916 * 06917 * p "hello".start_with?("hell") #=> true 06918 * 06919 * # returns true if one of prefix matches. 06920 * p "hello".start_with?("heaven", "hell") #=> true 06921 * p "hello".start_with?("heaven", "paradice") #=> false 06922 * 06923 * 06924 * 06925 */ 06926 06927 static VALUE 06928 rb_str_start_with(int argc, VALUE *argv, VALUE str) 06929 { 06930 int i; 06931 06932 for (i=0; i<argc; i++) { 06933 VALUE tmp = rb_check_string_type(argv[i]); 06934 if (NIL_P(tmp)) continue; 06935 rb_enc_check(str, tmp); 06936 if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue; 06937 if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0) 06938 return Qtrue; 06939 } 06940 return Qfalse; 06941 } 06942 06943 /* 06944 * call-seq: 06945 * str.end_with?([suffix]+) -> true or false 06946 * 06947 * Returns true if <i>str</i> ends with a suffix given. 06948 */ 06949 06950 static VALUE 06951 rb_str_end_with(int argc, VALUE *argv, VALUE str) 06952 { 06953 int i; 06954 char *p, *s, *e; 06955 rb_encoding *enc; 06956 06957 for (i=0; i<argc; i++) { 06958 VALUE tmp = rb_check_string_type(argv[i]); 06959 if (NIL_P(tmp)) continue; 06960 enc = rb_enc_check(str, tmp); 06961 if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue; 06962 p = RSTRING_PTR(str); 06963 e = p + RSTRING_LEN(str); 06964 s = e - RSTRING_LEN(tmp); 06965 if (rb_enc_left_char_head(p, s, e, enc) != s) 06966 continue; 06967 if (memcmp(s, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0) 06968 return Qtrue; 06969 } 06970 return Qfalse; 06971 } 06972 06973 void 06974 rb_str_setter(VALUE val, ID id, VALUE *var) 06975 { 06976 if (!NIL_P(val) && TYPE(val) != T_STRING) { 06977 rb_raise(rb_eTypeError, "value of %s must be String", rb_id2name(id)); 06978 } 06979 *var = val; 06980 } 06981 06982 06983 /* 06984 * call-seq: 06985 * str.force_encoding(encoding) -> str 06986 * 06987 * Changes the encoding to +encoding+ and returns self. 06988 */ 06989 06990 static VALUE 06991 rb_str_force_encoding(VALUE str, VALUE enc) 06992 { 06993 str_modifiable(str); 06994 rb_enc_associate(str, rb_to_encoding(enc)); 06995 ENC_CODERANGE_CLEAR(str); 06996 return str; 06997 } 06998 06999 /* 07000 * call-seq: 07001 * str.valid_encoding? -> true or false 07002 * 07003 * Returns true for a string which encoded correctly. 07004 * 07005 * "\xc2\xa1".force_encoding("UTF-8").valid_encoding? #=> true 07006 * "\xc2".force_encoding("UTF-8").valid_encoding? #=> false 07007 * "\x80".force_encoding("UTF-8").valid_encoding? #=> false 07008 */ 07009 07010 static VALUE 07011 rb_str_valid_encoding_p(VALUE str) 07012 { 07013 int cr = rb_enc_str_coderange(str); 07014 07015 return cr == ENC_CODERANGE_BROKEN ? Qfalse : Qtrue; 07016 } 07017 07018 /* 07019 * call-seq: 07020 * str.ascii_only? -> true or false 07021 * 07022 * Returns true for a string which has only ASCII characters. 07023 * 07024 * "abc".force_encoding("UTF-8").ascii_only? #=> true 07025 * "abc\u{6666}".force_encoding("UTF-8").ascii_only? #=> false 07026 */ 07027 07028 static VALUE 07029 rb_str_is_ascii_only_p(VALUE str) 07030 { 07031 int cr = rb_enc_str_coderange(str); 07032 07033 return cr == ENC_CODERANGE_7BIT ? Qtrue : Qfalse; 07034 } 07035 07036 /********************************************************************** 07037 * Document-class: Symbol 07038 * 07039 * <code>Symbol</code> objects represent names and some strings 07040 * inside the Ruby 07041 * interpreter. They are generated using the <code>:name</code> and 07042 * <code>:"string"</code> literals 07043 * syntax, and by the various <code>to_sym</code> methods. The same 07044 * <code>Symbol</code> object will be created for a given name or string 07045 * for the duration of a program's execution, regardless of the context 07046 * or meaning of that name. Thus if <code>Fred</code> is a constant in 07047 * one context, a method in another, and a class in a third, the 07048 * <code>Symbol</code> <code>:Fred</code> will be the same object in 07049 * all three contexts. 07050 * 07051 * module One 07052 * class Fred 07053 * end 07054 * $f1 = :Fred 07055 * end 07056 * module Two 07057 * Fred = 1 07058 * $f2 = :Fred 07059 * end 07060 * def Fred() 07061 * end 07062 * $f3 = :Fred 07063 * $f1.object_id #=> 2514190 07064 * $f2.object_id #=> 2514190 07065 * $f3.object_id #=> 2514190 07066 * 07067 */ 07068 07069 07070 /* 07071 * call-seq: 07072 * sym == obj -> true or false 07073 * 07074 * Equality---If <i>sym</i> and <i>obj</i> are exactly the same 07075 * symbol, returns <code>true</code>. 07076 */ 07077 07078 static VALUE 07079 sym_equal(VALUE sym1, VALUE sym2) 07080 { 07081 if (sym1 == sym2) return Qtrue; 07082 return Qfalse; 07083 } 07084 07085 07086 static int 07087 sym_printable(const char *s, const char *send, rb_encoding *enc) 07088 { 07089 while (s < send) { 07090 int n; 07091 int c = rb_enc_codepoint_len(s, send, &n, enc); 07092 07093 if (!rb_enc_isprint(c, enc)) return FALSE; 07094 s += n; 07095 } 07096 return TRUE; 07097 } 07098 07099 /* 07100 * call-seq: 07101 * sym.inspect -> string 07102 * 07103 * Returns the representation of <i>sym</i> as a symbol literal. 07104 * 07105 * :fred.inspect #=> ":fred" 07106 */ 07107 07108 static VALUE 07109 sym_inspect(VALUE sym) 07110 { 07111 VALUE str; 07112 ID id = SYM2ID(sym); 07113 rb_encoding *enc; 07114 const char *ptr; 07115 long len; 07116 char *dest; 07117 rb_encoding *resenc = rb_default_internal_encoding(); 07118 07119 if (resenc == NULL) resenc = rb_default_external_encoding(); 07120 sym = rb_id2str(id); 07121 enc = STR_ENC_GET(sym); 07122 ptr = RSTRING_PTR(sym); 07123 len = RSTRING_LEN(sym); 07124 if ((resenc != enc && !rb_str_is_ascii_only_p(sym)) || len != (long)strlen(ptr) || 07125 !rb_enc_symname_p(ptr, enc) || !sym_printable(ptr, ptr + len, enc)) { 07126 str = rb_str_inspect(sym); 07127 len = RSTRING_LEN(str); 07128 rb_str_resize(str, len + 1); 07129 dest = RSTRING_PTR(str); 07130 memmove(dest + 1, dest, len); 07131 dest[0] = ':'; 07132 } 07133 else { 07134 char *dest; 07135 str = rb_enc_str_new(0, len + 1, enc); 07136 dest = RSTRING_PTR(str); 07137 dest[0] = ':'; 07138 memcpy(dest + 1, ptr, len); 07139 } 07140 return str; 07141 } 07142 07143 07144 /* 07145 * call-seq: 07146 * sym.id2name -> string 07147 * sym.to_s -> string 07148 * 07149 * Returns the name or string corresponding to <i>sym</i>. 07150 * 07151 * :fred.id2name #=> "fred" 07152 */ 07153 07154 07155 VALUE 07156 rb_sym_to_s(VALUE sym) 07157 { 07158 ID id = SYM2ID(sym); 07159 07160 return str_new3(rb_cString, rb_id2str(id)); 07161 } 07162 07163 07164 /* 07165 * call-seq: 07166 * sym.to_sym -> sym 07167 * sym.intern -> sym 07168 * 07169 * In general, <code>to_sym</code> returns the <code>Symbol</code> corresponding 07170 * to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned 07171 * in this case. 07172 */ 07173 07174 static VALUE 07175 sym_to_sym(VALUE sym) 07176 { 07177 return sym; 07178 } 07179 07180 VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv); 07181 07182 static VALUE 07183 sym_call(VALUE args, VALUE sym, int argc, VALUE *argv) 07184 { 07185 VALUE obj; 07186 07187 if (argc < 1) { 07188 rb_raise(rb_eArgError, "no receiver given"); 07189 } 07190 obj = argv[0]; 07191 return rb_funcall_passing_block(obj, (ID)sym, argc - 1, argv + 1); 07192 } 07193 07194 /* 07195 * call-seq: 07196 * sym.to_proc 07197 * 07198 * Returns a _Proc_ object which respond to the given method by _sym_. 07199 * 07200 * (1..3).collect(&:to_s) #=> ["1", "2", "3"] 07201 */ 07202 07203 static VALUE 07204 sym_to_proc(VALUE sym) 07205 { 07206 static VALUE sym_proc_cache = Qfalse; 07207 enum {SYM_PROC_CACHE_SIZE = 67}; 07208 VALUE proc; 07209 long id, index; 07210 VALUE *aryp; 07211 07212 if (!sym_proc_cache) { 07213 sym_proc_cache = rb_ary_tmp_new(SYM_PROC_CACHE_SIZE * 2); 07214 rb_gc_register_mark_object(sym_proc_cache); 07215 rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil); 07216 } 07217 07218 id = SYM2ID(sym); 07219 index = (id % SYM_PROC_CACHE_SIZE) << 1; 07220 07221 aryp = RARRAY_PTR(sym_proc_cache); 07222 if (aryp[index] == sym) { 07223 return aryp[index + 1]; 07224 } 07225 else { 07226 proc = rb_proc_new(sym_call, (VALUE)id); 07227 aryp[index] = sym; 07228 aryp[index + 1] = proc; 07229 return proc; 07230 } 07231 } 07232 07233 /* 07234 * call-seq: 07235 * 07236 * sym.succ 07237 * 07238 * Same as <code>sym.to_s.succ.intern</code>. 07239 */ 07240 07241 static VALUE 07242 sym_succ(VALUE sym) 07243 { 07244 return rb_str_intern(rb_str_succ(rb_sym_to_s(sym))); 07245 } 07246 07247 /* 07248 * call-seq: 07249 * 07250 * str <=> other -> -1, 0, +1 or nil 07251 * 07252 * Compares _sym_ with _other_ in string form. 07253 */ 07254 07255 static VALUE 07256 sym_cmp(VALUE sym, VALUE other) 07257 { 07258 if (!SYMBOL_P(other)) { 07259 return Qnil; 07260 } 07261 return rb_str_cmp_m(rb_sym_to_s(sym), rb_sym_to_s(other)); 07262 } 07263 07264 /* 07265 * call-seq: 07266 * 07267 * sym.casecmp(other) -> -1, 0, +1 or nil 07268 * 07269 * Case-insensitive version of <code>Symbol#<=></code>. 07270 */ 07271 07272 static VALUE 07273 sym_casecmp(VALUE sym, VALUE other) 07274 { 07275 if (!SYMBOL_P(other)) { 07276 return Qnil; 07277 } 07278 return rb_str_casecmp(rb_sym_to_s(sym), rb_sym_to_s(other)); 07279 } 07280 07281 /* 07282 * call-seq: 07283 * sym =~ obj -> fixnum or nil 07284 * 07285 * Returns <code>sym.to_s =~ obj</code>. 07286 */ 07287 07288 static VALUE 07289 sym_match(VALUE sym, VALUE other) 07290 { 07291 return rb_str_match(rb_sym_to_s(sym), other); 07292 } 07293 07294 /* 07295 * call-seq: 07296 * sym[idx] -> char 07297 * sym[b, n] -> char 07298 * 07299 * Returns <code>sym.to_s[]</code>. 07300 */ 07301 07302 static VALUE 07303 sym_aref(int argc, VALUE *argv, VALUE sym) 07304 { 07305 return rb_str_aref_m(argc, argv, rb_sym_to_s(sym)); 07306 } 07307 07308 /* 07309 * call-seq: 07310 * sym.length -> integer 07311 * 07312 * Same as <code>sym.to_s.length</code>. 07313 */ 07314 07315 static VALUE 07316 sym_length(VALUE sym) 07317 { 07318 return rb_str_length(rb_id2str(SYM2ID(sym))); 07319 } 07320 07321 /* 07322 * call-seq: 07323 * sym.empty? -> true or false 07324 * 07325 * Returns that _sym_ is :"" or not. 07326 */ 07327 07328 static VALUE 07329 sym_empty(VALUE sym) 07330 { 07331 return rb_str_empty(rb_id2str(SYM2ID(sym))); 07332 } 07333 07334 /* 07335 * call-seq: 07336 * sym.upcase -> symbol 07337 * 07338 * Same as <code>sym.to_s.upcase.intern</code>. 07339 */ 07340 07341 static VALUE 07342 sym_upcase(VALUE sym) 07343 { 07344 return rb_str_intern(rb_str_upcase(rb_id2str(SYM2ID(sym)))); 07345 } 07346 07347 /* 07348 * call-seq: 07349 * sym.downcase -> symbol 07350 * 07351 * Same as <code>sym.to_s.downcase.intern</code>. 07352 */ 07353 07354 static VALUE 07355 sym_downcase(VALUE sym) 07356 { 07357 return rb_str_intern(rb_str_downcase(rb_id2str(SYM2ID(sym)))); 07358 } 07359 07360 /* 07361 * call-seq: 07362 * sym.capitalize -> symbol 07363 * 07364 * Same as <code>sym.to_s.capitalize.intern</code>. 07365 */ 07366 07367 static VALUE 07368 sym_capitalize(VALUE sym) 07369 { 07370 return rb_str_intern(rb_str_capitalize(rb_id2str(SYM2ID(sym)))); 07371 } 07372 07373 /* 07374 * call-seq: 07375 * sym.swapcase -> symbol 07376 * 07377 * Same as <code>sym.to_s.swapcase.intern</code>. 07378 */ 07379 07380 static VALUE 07381 sym_swapcase(VALUE sym) 07382 { 07383 return rb_str_intern(rb_str_swapcase(rb_id2str(SYM2ID(sym)))); 07384 } 07385 07386 /* 07387 * call-seq: 07388 * sym.encoding -> encoding 07389 * 07390 * Returns the Encoding object that represents the encoding of _sym_. 07391 */ 07392 07393 static VALUE 07394 sym_encoding(VALUE sym) 07395 { 07396 return rb_obj_encoding(rb_id2str(SYM2ID(sym))); 07397 } 07398 07399 ID 07400 rb_to_id(VALUE name) 07401 { 07402 VALUE tmp; 07403 ID id; 07404 07405 switch (TYPE(name)) { 07406 default: 07407 tmp = rb_check_string_type(name); 07408 if (NIL_P(tmp)) { 07409 tmp = rb_inspect(name); 07410 rb_raise(rb_eTypeError, "%s is not a symbol", 07411 RSTRING_PTR(tmp)); 07412 } 07413 name = tmp; 07414 /* fall through */ 07415 case T_STRING: 07416 name = rb_str_intern(name); 07417 /* fall through */ 07418 case T_SYMBOL: 07419 return SYM2ID(name); 07420 } 07421 return id; 07422 } 07423 07424 /* 07425 * A <code>String</code> object holds and manipulates an arbitrary sequence of 07426 * bytes, typically representing characters. String objects may be created 07427 * using <code>String::new</code> or as literals. 07428 * 07429 * Because of aliasing issues, users of strings should be aware of the methods 07430 * that modify the contents of a <code>String</code> object. Typically, 07431 * methods with names ending in ``!'' modify their receiver, while those 07432 * without a ``!'' return a new <code>String</code>. However, there are 07433 * exceptions, such as <code>String#[]=</code>. 07434 * 07435 */ 07436 07437 void 07438 Init_String(void) 07439 { 07440 #undef rb_intern 07441 #define rb_intern(str) rb_intern_const(str) 07442 07443 rb_cString = rb_define_class("String", rb_cObject); 07444 rb_include_module(rb_cString, rb_mComparable); 07445 rb_define_alloc_func(rb_cString, str_alloc); 07446 rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1); 07447 rb_define_method(rb_cString, "initialize", rb_str_init, -1); 07448 rb_define_method(rb_cString, "initialize_copy", rb_str_replace, 1); 07449 rb_define_method(rb_cString, "<=>", rb_str_cmp_m, 1); 07450 rb_define_method(rb_cString, "==", rb_str_equal, 1); 07451 rb_define_method(rb_cString, "===", rb_str_equal, 1); 07452 rb_define_method(rb_cString, "eql?", rb_str_eql, 1); 07453 rb_define_method(rb_cString, "hash", rb_str_hash_m, 0); 07454 rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1); 07455 rb_define_method(rb_cString, "+", rb_str_plus, 1); 07456 rb_define_method(rb_cString, "*", rb_str_times, 1); 07457 rb_define_method(rb_cString, "%", rb_str_format_m, 1); 07458 rb_define_method(rb_cString, "[]", rb_str_aref_m, -1); 07459 rb_define_method(rb_cString, "[]=", rb_str_aset_m, -1); 07460 rb_define_method(rb_cString, "insert", rb_str_insert, 2); 07461 rb_define_method(rb_cString, "length", rb_str_length, 0); 07462 rb_define_method(rb_cString, "size", rb_str_length, 0); 07463 rb_define_method(rb_cString, "bytesize", rb_str_bytesize, 0); 07464 rb_define_method(rb_cString, "empty?", rb_str_empty, 0); 07465 rb_define_method(rb_cString, "=~", rb_str_match, 1); 07466 rb_define_method(rb_cString, "match", rb_str_match_m, -1); 07467 rb_define_method(rb_cString, "succ", rb_str_succ, 0); 07468 rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0); 07469 rb_define_method(rb_cString, "next", rb_str_succ, 0); 07470 rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0); 07471 rb_define_method(rb_cString, "upto", rb_str_upto, -1); 07472 rb_define_method(rb_cString, "index", rb_str_index_m, -1); 07473 rb_define_method(rb_cString, "rindex", rb_str_rindex_m, -1); 07474 rb_define_method(rb_cString, "replace", rb_str_replace, 1); 07475 rb_define_method(rb_cString, "clear", rb_str_clear, 0); 07476 rb_define_method(rb_cString, "chr", rb_str_chr, 0); 07477 rb_define_method(rb_cString, "getbyte", rb_str_getbyte, 1); 07478 rb_define_method(rb_cString, "setbyte", rb_str_setbyte, 2); 07479 07480 rb_define_method(rb_cString, "to_i", rb_str_to_i, -1); 07481 rb_define_method(rb_cString, "to_f", rb_str_to_f, 0); 07482 rb_define_method(rb_cString, "to_s", rb_str_to_s, 0); 07483 rb_define_method(rb_cString, "to_str", rb_str_to_s, 0); 07484 rb_define_method(rb_cString, "inspect", rb_str_inspect, 0); 07485 rb_define_method(rb_cString, "dump", rb_str_dump, 0); 07486 07487 rb_define_method(rb_cString, "upcase", rb_str_upcase, 0); 07488 rb_define_method(rb_cString, "downcase", rb_str_downcase, 0); 07489 rb_define_method(rb_cString, "capitalize", rb_str_capitalize, 0); 07490 rb_define_method(rb_cString, "swapcase", rb_str_swapcase, 0); 07491 07492 rb_define_method(rb_cString, "upcase!", rb_str_upcase_bang, 0); 07493 rb_define_method(rb_cString, "downcase!", rb_str_downcase_bang, 0); 07494 rb_define_method(rb_cString, "capitalize!", rb_str_capitalize_bang, 0); 07495 rb_define_method(rb_cString, "swapcase!", rb_str_swapcase_bang, 0); 07496 07497 rb_define_method(rb_cString, "hex", rb_str_hex, 0); 07498 rb_define_method(rb_cString, "oct", rb_str_oct, 0); 07499 rb_define_method(rb_cString, "split", rb_str_split_m, -1); 07500 rb_define_method(rb_cString, "lines", rb_str_each_line, -1); 07501 rb_define_method(rb_cString, "bytes", rb_str_each_byte, 0); 07502 rb_define_method(rb_cString, "chars", rb_str_each_char, 0); 07503 rb_define_method(rb_cString, "codepoints", rb_str_each_codepoint, 0); 07504 rb_define_method(rb_cString, "reverse", rb_str_reverse, 0); 07505 rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0); 07506 rb_define_method(rb_cString, "concat", rb_str_concat, 1); 07507 rb_define_method(rb_cString, "<<", rb_str_concat, 1); 07508 rb_define_method(rb_cString, "crypt", rb_str_crypt, 1); 07509 rb_define_method(rb_cString, "intern", rb_str_intern, 0); 07510 rb_define_method(rb_cString, "to_sym", rb_str_intern, 0); 07511 rb_define_method(rb_cString, "ord", rb_str_ord, 0); 07512 07513 rb_define_method(rb_cString, "include?", rb_str_include, 1); 07514 rb_define_method(rb_cString, "start_with?", rb_str_start_with, -1); 07515 rb_define_method(rb_cString, "end_with?", rb_str_end_with, -1); 07516 07517 rb_define_method(rb_cString, "scan", rb_str_scan, 1); 07518 07519 rb_define_method(rb_cString, "ljust", rb_str_ljust, -1); 07520 rb_define_method(rb_cString, "rjust", rb_str_rjust, -1); 07521 rb_define_method(rb_cString, "center", rb_str_center, -1); 07522 07523 rb_define_method(rb_cString, "sub", rb_str_sub, -1); 07524 rb_define_method(rb_cString, "gsub", rb_str_gsub, -1); 07525 rb_define_method(rb_cString, "chop", rb_str_chop, 0); 07526 rb_define_method(rb_cString, "chomp", rb_str_chomp, -1); 07527 rb_define_method(rb_cString, "strip", rb_str_strip, 0); 07528 rb_define_method(rb_cString, "lstrip", rb_str_lstrip, 0); 07529 rb_define_method(rb_cString, "rstrip", rb_str_rstrip, 0); 07530 07531 rb_define_method(rb_cString, "sub!", rb_str_sub_bang, -1); 07532 rb_define_method(rb_cString, "gsub!", rb_str_gsub_bang, -1); 07533 rb_define_method(rb_cString, "chop!", rb_str_chop_bang, 0); 07534 rb_define_method(rb_cString, "chomp!", rb_str_chomp_bang, -1); 07535 rb_define_method(rb_cString, "strip!", rb_str_strip_bang, 0); 07536 rb_define_method(rb_cString, "lstrip!", rb_str_lstrip_bang, 0); 07537 rb_define_method(rb_cString, "rstrip!", rb_str_rstrip_bang, 0); 07538 07539 rb_define_method(rb_cString, "tr", rb_str_tr, 2); 07540 rb_define_method(rb_cString, "tr_s", rb_str_tr_s, 2); 07541 rb_define_method(rb_cString, "delete", rb_str_delete, -1); 07542 rb_define_method(rb_cString, "squeeze", rb_str_squeeze, -1); 07543 rb_define_method(rb_cString, "count", rb_str_count, -1); 07544 07545 rb_define_method(rb_cString, "tr!", rb_str_tr_bang, 2); 07546 rb_define_method(rb_cString, "tr_s!", rb_str_tr_s_bang, 2); 07547 rb_define_method(rb_cString, "delete!", rb_str_delete_bang, -1); 07548 rb_define_method(rb_cString, "squeeze!", rb_str_squeeze_bang, -1); 07549 07550 rb_define_method(rb_cString, "each_line", rb_str_each_line, -1); 07551 rb_define_method(rb_cString, "each_byte", rb_str_each_byte, 0); 07552 rb_define_method(rb_cString, "each_char", rb_str_each_char, 0); 07553 rb_define_method(rb_cString, "each_codepoint", rb_str_each_codepoint, 0); 07554 07555 rb_define_method(rb_cString, "sum", rb_str_sum, -1); 07556 07557 rb_define_method(rb_cString, "slice", rb_str_aref_m, -1); 07558 rb_define_method(rb_cString, "slice!", rb_str_slice_bang, -1); 07559 07560 rb_define_method(rb_cString, "partition", rb_str_partition, 1); 07561 rb_define_method(rb_cString, "rpartition", rb_str_rpartition, 1); 07562 07563 rb_define_method(rb_cString, "encoding", rb_obj_encoding, 0); /* in encoding.c */ 07564 rb_define_method(rb_cString, "force_encoding", rb_str_force_encoding, 1); 07565 rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0); 07566 rb_define_method(rb_cString, "ascii_only?", rb_str_is_ascii_only_p, 0); 07567 07568 id_to_s = rb_intern("to_s"); 07569 07570 rb_fs = Qnil; 07571 rb_define_variable("$;", &rb_fs); 07572 rb_define_variable("$-F", &rb_fs); 07573 07574 rb_cSymbol = rb_define_class("Symbol", rb_cObject); 07575 rb_include_module(rb_cSymbol, rb_mComparable); 07576 rb_undef_alloc_func(rb_cSymbol); 07577 rb_undef_method(CLASS_OF(rb_cSymbol), "new"); 07578 rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */ 07579 07580 rb_define_method(rb_cSymbol, "==", sym_equal, 1); 07581 rb_define_method(rb_cSymbol, "===", sym_equal, 1); 07582 rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0); 07583 rb_define_method(rb_cSymbol, "to_s", rb_sym_to_s, 0); 07584 rb_define_method(rb_cSymbol, "id2name", rb_sym_to_s, 0); 07585 rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0); 07586 rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0); 07587 rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0); 07588 rb_define_method(rb_cSymbol, "succ", sym_succ, 0); 07589 rb_define_method(rb_cSymbol, "next", sym_succ, 0); 07590 07591 rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1); 07592 rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1); 07593 rb_define_method(rb_cSymbol, "=~", sym_match, 1); 07594 07595 rb_define_method(rb_cSymbol, "[]", sym_aref, -1); 07596 rb_define_method(rb_cSymbol, "slice", sym_aref, -1); 07597 rb_define_method(rb_cSymbol, "length", sym_length, 0); 07598 rb_define_method(rb_cSymbol, "size", sym_length, 0); 07599 rb_define_method(rb_cSymbol, "empty?", sym_empty, 0); 07600 rb_define_method(rb_cSymbol, "match", sym_match, 1); 07601 07602 rb_define_method(rb_cSymbol, "upcase", sym_upcase, 0); 07603 rb_define_method(rb_cSymbol, "downcase", sym_downcase, 0); 07604 rb_define_method(rb_cSymbol, "capitalize", sym_capitalize, 0); 07605 rb_define_method(rb_cSymbol, "swapcase", sym_swapcase, 0); 07606 07607 rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0); 07608 } 07609
1.7.3