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