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