string.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   string.c -
00004 
00005   $Author: nagachika $
00006   created at: Mon Aug  9 17:12:58 JST 1993
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
00009   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
00010   Copyright (C) 2000  Information-technology Promotion Agency, Japan
00011 
00012 **********************************************************************/
00013 
00014 #include "ruby/ruby.h"
00015 #include "ruby/re.h"
00016 #include "ruby/encoding.h"
00017 #include "vm_core.h"
00018 #include "internal.h"
00019 #include "probes.h"
00020 #include <assert.h>
00021 
00022 #define BEG(no) (regs->beg[(no)])
00023 #define END(no) (regs->end[(no)])
00024 
00025 #include <math.h>
00026 #include <ctype.h>
00027 
00028 #ifdef HAVE_UNISTD_H
00029 #include <unistd.h>
00030 #endif
00031 
00032 #define STRING_ENUMERATORS_WANTARRAY 0 /* next major */
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         /* because of lazy sweep, str may be unmarked already and swept
00181          * at next time */
00182         rb_gc_resurrect(*fstr = *key);
00183         return ST_STOP;
00184     }
00185 
00186     if (STR_SHARED_P(str)) {
00187         /* str should not be shared */
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     /* Conservative.  It may be ENC_CODERANGE_UNKNOWN. */
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     /* Conservative.  Possibly single byte.
00247      * "\xa1" in Shift_JIS for example. */
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         /* enc is ASCII-8BIT.  ASCII-8BIT string never be broken. */
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         /* enc is ASCII-8BIT.  ASCII-8BIT string never be broken. */
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     /* this function is designed for copying encoding and coderange
00401      * from src to new string "dest" which is made from the part of src.
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         /* destination buffer short */
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         /* some error, return original */
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); /* TODO: WB is not needed because str2 is *new* object */
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         /* TODO: WB is not needed because str is new object */
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);        /* abandon 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  *  call-seq:
01079  *     String.new(str="")   -> new_str
01080  *
01081  *  Returns a new string object containing a copy of <i>str</i>.
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  * UTF-8 leading bytes have either 0xxxxxxx or 11xxxxxx
01207  * bit representation. (see http://en.wikipedia.org/wiki/UTF-8)
01208  * Therefore, following pseudo code can detect UTF-8 leading byte.
01209  *
01210  * if (!(byte & 0x80))
01211  *   byte |= 0x40;          // turn on bit6
01212  * return ((byte>>6) & 1);  // bit6 represent it's leading byte or not.
01213  *
01214  * This function calculate every bytes in the argument word `s'
01215  * using the above logic concurrently. and gather every bytes result.
01216  */
01217 static inline VALUE
01218 count_utf8_lead_bytes_with_word(const VALUE *s)
01219 {
01220     VALUE d = *s;
01221 
01222     /* Transform into bit0 represent UTF-8 leading or not. */
01223     d |= ~(d>>1);
01224     d >>= 6;
01225     d &= NONASCII_MASK >> 7;
01226 
01227     /* Gather every bytes. */
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  *  call-seq:
01291  *     str.length   -> integer
01292  *     str.size     -> integer
01293  *
01294  *  Returns the character length of <i>str</i>.
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  *  call-seq:
01308  *     str.bytesize  -> integer
01309  *
01310  *  Returns the length of +str+ in bytes.
01311  *
01312  *    "\x80\u3042".bytesize  #=> 4
01313  *    "hello".bytesize       #=> 5
01314  */
01315 
01316 static VALUE
01317 rb_str_bytesize(VALUE str)
01318 {
01319     return LONG2NUM(RSTRING_LEN(str));
01320 }
01321 
01322 /*
01323  *  call-seq:
01324  *     str.empty?   -> true or false
01325  *
01326  *  Returns <code>true</code> if <i>str</i> has a length of zero.
01327  *
01328  *     "hello".empty?   #=> false
01329  *     " ".empty?       #=> false
01330  *     "".empty?        #=> true
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  *  call-seq:
01343  *     str + other_str   -> new_str
01344  *
01345  *  Concatenation---Returns a new <code>String</code> containing
01346  *  <i>other_str</i> concatenated to <i>str</i>.
01347  *
01348  *     "Hello from " + self.to_s   #=> "Hello from main"
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  *  call-seq:
01374  *     str * integer   -> new_str
01375  *
01376  *  Copy --- Returns a new String containing +integer+ copies of the receiver.
01377  *  +integer+ must be greater than or equal to 0.
01378  *
01379  *     "Ho! " * 3   #=> "Ho! Ho! Ho! "
01380  *     "Ho! " * 0   #=> ""
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  *  call-seq:
01418  *     str % arg   -> new_str
01419  *
01420  *  Format---Uses <i>str</i> as a format specification, and returns the result
01421  *  of applying it to <i>arg</i>. If the format specification contains more than
01422  *  one substitution, then <i>arg</i> must be an <code>Array</code> or <code>Hash</code>
01423  *  containing the values to be substituted. See <code>Kernel::sprintf</code> for
01424  *  details of the format string.
01425  *
01426  *     "%05d" % 123                              #=> "00123"
01427  *     "%-5s: %08x" % [ "ID", self.object_id ]   #=> "ID   : 200e14d6"
01428  *     "foo = %{foo}" % { :foo => 'bar' }        #=> "foo = bar"
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 /* As rb_str_modify(), but don't clear coderange */
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         /* Force re-scan later */
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     /* sanity check */
01542     rb_check_frozen(str);
01543     if (STR_ASSOC_P(str)) {
01544         /* already associated */
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  *  call-seq:
01687  *     String.try_convert(obj) -> string or nil
01688  *
01689  *  Try to convert <i>obj</i> into a String, using to_str method.
01690  *  Returns converted string or nil if <i>obj</i> cannot be converted
01691  *  for any reason.
01692  *
01693  *     String.try_convert("str")     #=> "str"
01694  *     String.try_convert(/re/)      #=> nil
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 /* char offset to byte offset */
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 /* byte offset to char offset */
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); /* sentinel */
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'; /* sentinel */
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)); /* sentinel */
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 { /* str_cr == ENC_CODERANGE_BROKEN */
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     /* ptr must reference NUL terminated ASCII string. */
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  *  call-seq:
02325  *     str << integer       -> str
02326  *     str.concat(integer)  -> str
02327  *     str << obj           -> str
02328  *     str.concat(obj)      -> str
02329  *
02330  *  Append---Concatenates the given object to <i>str</i>. If the object is a
02331  *  <code>Integer</code>, it is considered as a codepoint, and is converted
02332  *  to a character before concatenation.
02333  *
02334  *     a = "hello "
02335  *     a << "world"   #=> "hello world"
02336  *     a.concat(33)   #=> "hello world!"
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         /* US-ASCII automatically extended to ASCII-8BIT */
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  *  call-seq:
02403  *     str.prepend(other_str)  -> str
02404  *
02405  *  Prepend---Prepend the given string to <i>str</i>.
02406  *
02407  *     a = "world"
02408  *     a.prepend("hello ") #=> "hello world"
02409  *     a                   #=> "hello world"
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  * call-seq:
02446  *    str.hash   -> fixnum
02447  *
02448  * Return a hash based on the string's length and content.
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 /* expect tail call optimization */
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  *  call-seq:
02529  *     str == obj    -> true or false
02530  *     str === obj   -> true or false
02531  *
02532  *  === Equality
02533  *
02534  *  Returns whether +str+ == +obj+, similar to Object#==.
02535  *
02536  *  If +obj+ is not an instance of String but responds to +to_str+, then the
02537  *  two strings are compared using case equality Object#===.
02538  *
02539  *  Otherwise, returns similarly to String#eql?, comparing length and content.
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  * call-seq:
02557  *   str.eql?(other)   -> true or false
02558  *
02559  * Two strings are equal if they have the same length and content.
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  *  call-seq:
02572  *     string <=> other_string   -> -1, 0, +1 or nil
02573  *
02574  *
02575  *  Comparison---Returns -1, 0, +1 or nil depending on whether +string+ is less
02576  *  than, equal to, or greater than +other_string+.
02577  *
02578  *  +nil+ is returned if the two values are incomparable.
02579  *
02580  *  If the strings are of different lengths, and the strings are equal when
02581  *  compared up to the shortest length, then the longer string is considered
02582  *  greater than the shorter one.
02583  *
02584  *  <code><=></code> is the basis for the methods <code><</code>,
02585  *  <code><=</code>, <code>></code>, <code>>=</code>, and
02586  *  <code>between?</code>, included from module Comparable. The method
02587  *  String#== does not use Comparable#==.
02588  *
02589  *     "abcdef" <=> "abcde"     #=> 1
02590  *     "abcdef" <=> "abcdef"    #=> 0
02591  *     "abcdef" <=> "abcdefg"   #=> -1
02592  *     "abcdef" <=> "ABCDEF"    #=> 1
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  *  call-seq:
02617  *     str.casecmp(other_str)   -> -1, 0, +1 or nil
02618  *
02619  *  Case-insensitive version of <code>String#<=></code>.
02620  *
02621  *     "abcdef".casecmp("abcde")     #=> 1
02622  *     "aBcDeF".casecmp("abcdef")    #=> 0
02623  *     "abcdef".casecmp("abcdefg")   #=> -1
02624  *     "abcdef".casecmp("ABCDEF")    #=> 0
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     /* need proceed one character at a time */
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  *  call-seq:
02732  *     str.index(substring [, offset])   -> fixnum or nil
02733  *     str.index(regexp [, offset])      -> fixnum or nil
02734  *
02735  *  Returns the index of the first occurrence of the given <i>substring</i> or
02736  *  pattern (<i>regexp</i>) in <i>str</i>. Returns <code>nil</code> if not
02737  *  found. If the second parameter is present, it specifies the position in the
02738  *  string to begin the search.
02739  *
02740  *     "hello".index('e')             #=> 1
02741  *     "hello".index('lo')            #=> 3
02742  *     "hello".index('a')             #=> nil
02743  *     "hello".index(?e)              #=> 1
02744  *     "hello".index(/[aeiou]/, -3)   #=> 4
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         /* fall through */
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     /* substring longer than string */
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  *  call-seq:
02896  *     str.rindex(substring [, fixnum])   -> fixnum or nil
02897  *     str.rindex(regexp [, fixnum])   -> fixnum or nil
02898  *
02899  *  Returns the index of the last occurrence of the given <i>substring</i> or
02900  *  pattern (<i>regexp</i>) in <i>str</i>. Returns <code>nil</code> if not
02901  *  found. If the second parameter is present, it specifies the position in the
02902  *  string to end the search---characters beyond this point will not be
02903  *  considered.
02904  *
02905  *     "hello".rindex('e')             #=> 1
02906  *     "hello".rindex('l')             #=> 3
02907  *     "hello".rindex('a')             #=> nil
02908  *     "hello".rindex(?e)              #=> 1
02909  *     "hello".rindex(/[aeiou]/, -2)   #=> 1
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         /* enc = rb_get_check(str, sub); */
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         /* fall through */
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  *  call-seq:
02973  *     str =~ obj   -> fixnum or nil
02974  *
02975  *  Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match
02976  *  against <i>str</i>,and returns the position the match starts, or
02977  *  <code>nil</code> if there is no match. Otherwise, invokes
02978  *  <i>obj.=~</i>, passing <i>str</i> as an argument. The default
02979  *  <code>=~</code> in <code>Object</code> returns <code>nil</code>.
02980  *
02981  *  Note: <code>str =~ regexp</code> is not the same as
02982  *  <code>regexp =~ str</code>. Strings captured from named capture groups
02983  *  are assigned to local variables only in the second case.
02984  *
02985  *     "cat o' 9 tails" =~ /\d/   #=> 7
02986  *     "cat o' 9 tails" =~ 9      #=> nil
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  *  call-seq:
03012  *     str.match(pattern)        -> matchdata or nil
03013  *     str.match(pattern, pos)   -> matchdata or nil
03014  *
03015  *  Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one),
03016  *  then invokes its <code>match</code> method on <i>str</i>.  If the second
03017  *  parameter is present, it specifies the position in the string to begin the
03018  *  search.
03019  *
03020  *     'hello'.match('(.)\1')      #=> #<MatchData "ll" 1:"l">
03021  *     'hello'.match('(.)\1')[0]   #=> "ll"
03022  *     'hello'.match(/(.)\1/)[0]   #=> "ll"
03023  *     'hello'.match('xx')         #=> nil
03024  *
03025  *  If a block is given, invoke the block with MatchData if match succeed, so
03026  *  that you can write
03027  *
03028  *     str.match(pat) {|m| ...}
03029  *
03030  *  instead of
03031  *
03032  *     if m = str.match(pat)
03033  *       ...
03034  *     end
03035  *
03036  *  The return value is a value from block execution in this case.
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         /* wchar, trivial case */
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         /* wchar, trivial case */
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   overwrite +p+ by succeeding letter in +enc+ and returns
03167   NEIGHBOR_FOUND or NEIGHBOR_WRAPPED.
03168   When NEIGHBOR_WRAPPED, carried-out letter is stored into carry.
03169   assuming each ranges are successive, and mbclen
03170   never change in each ranges.
03171   NEIGHBOR_NOT_CHAR is returned if invalid character or the range has only one
03172   character.
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  *  call-seq:
03233  *     str.succ   -> new_str
03234  *     str.next   -> new_str
03235  *
03236  *  Returns the successor to <i>str</i>. The successor is calculated by
03237  *  incrementing characters starting from the rightmost alphanumeric (or
03238  *  the rightmost character if there are no alphanumerics) in the
03239  *  string. Incrementing a digit always results in another digit, and
03240  *  incrementing a letter results in another letter of the same case.
03241  *  Incrementing nonalphanumerics uses the underlying character set's
03242  *  collating sequence.
03243  *
03244  *  If the increment generates a ``carry,'' the character to the left of
03245  *  it is incremented. This process repeats until there is no carry,
03246  *  adding an additional character if necessary.
03247  *
03248  *     "abcd".succ        #=> "abce"
03249  *     "THX1138".succ     #=> "THX1139"
03250  *     "<<koala>>".succ   #=> "<<koalb>>"
03251  *     "1999zzz".succ     #=> "2000aaa"
03252  *     "ZZZ9999".succ     #=> "AAAA0000"
03253  *     "***".succ         #=> "**+"
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) {              /* str contains no alnum */
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                 /* wrapped to \0...\0.  search next valid char. */
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  *  call-seq:
03347  *     str.succ!   -> str
03348  *     str.next!   -> str
03349  *
03350  *  Equivalent to <code>String#succ</code>, but modifies the receiver in
03351  *  place.
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  *  call-seq:
03365  *     str.upto(other_str, exclusive=false) {|s| block }   -> str
03366  *     str.upto(other_str, exclusive=false)                -> an_enumerator
03367  *
03368  *  Iterates through successive values, starting at <i>str</i> and
03369  *  ending at <i>other_str</i> inclusive, passing each value in turn to
03370  *  the block. The <code>String#succ</code> method is used to generate
03371  *  each value.  If optional second argument exclusive is omitted or is false,
03372  *  the last value will be included; otherwise it will be excluded.
03373  *
03374  *  If no block is given, an enumerator is returned instead.
03375  *
03376  *     "a8".upto("b6") {|s| print s, ' ' }
03377  *     for s in "a8".."b6"
03378  *       print s, ' '
03379  *     end
03380  *
03381  *  <em>produces:</em>
03382  *
03383  *     a8 a9 b0 b1 b2 b3 b4 b5 b6
03384  *     a8 a9 b0 b1 b2 b3 b4 b5 b6
03385  *
03386  *  If <i>str</i> and <i>other_str</i> contains only ascii numeric characters,
03387  *  both are recognized as decimal numbers. In addition, the width of
03388  *  string (e.g. leading zeros) is handled appropriately.
03389  *
03390  *     "9".upto("11").to_a   #=> ["9", "10", "11"]
03391  *     "25".upto("5").to_a   #=> []
03392  *     "07".upto("11").to_a  #=> ["07", "08", "09", "10", "11"]
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     /* single character */
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     /* both edges are all digits */
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     /* normal case */
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         /* check if indx is Range */
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  *  call-seq:
03554  *     str[index]                 -> new_str or nil
03555  *     str[start, length]         -> new_str or nil
03556  *     str[range]                 -> new_str or nil
03557  *     str[regexp]                -> new_str or nil
03558  *     str[regexp, capture]       -> new_str or nil
03559  *     str[match_str]             -> new_str or nil
03560  *     str.slice(index)           -> new_str or nil
03561  *     str.slice(start, length)   -> new_str or nil
03562  *     str.slice(range)           -> new_str or nil
03563  *     str.slice(regexp)          -> new_str or nil
03564  *     str.slice(regexp, capture) -> new_str or nil
03565  *     str.slice(match_str)       -> new_str or nil
03566  *
03567  *  Element Reference --- If passed a single +index+, returns a substring of
03568  *  one character at that index. If passed a +start+ index and a +length+,
03569  *  returns a substring containing +length+ characters starting at the
03570  *  +index+. If passed a +range+, its beginning and end are interpreted as
03571  *  offsets delimiting the substring to be returned.
03572  *
03573  *  In these three cases, if an index is negative, it is counted from the end
03574  *  of the string.  For the +start+ and +range+ cases the starting index
03575  *  is just before a character and an index matching the string's size.
03576  *  Additionally, an empty string is returned when the starting index for a
03577  *  character range is at the end of the string.
03578  *
03579  *  Returns +nil+ if the initial index falls outside the string or the length
03580  *  is negative.
03581  *
03582  *  If a +Regexp+ is supplied, the matching portion of the string is
03583  *  returned.  If a +capture+ follows the regular expression, which may be a
03584  *  capture group index or name, follows the regular expression that component
03585  *  of the MatchData is returned instead.
03586  *
03587  *  If a +match_str+ is given, that string is returned if it occurs in
03588  *  the string.
03589  *
03590  *  Returns +nil+ if the regular expression does not match or the match string
03591  *  cannot be found.
03592  *
03593  *     a = "hello there"
03594  *
03595  *     a[1]                   #=> "e"
03596  *     a[2, 3]                #=> "llo"
03597  *     a[2..3]                #=> "ll"
03598  *
03599  *     a[-3, 2]               #=> "er"
03600  *     a[7..-2]               #=> "her"
03601  *     a[-4..-2]              #=> "her"
03602  *     a[-2..-4]              #=> ""
03603  *
03604  *     a[11, 0]               #=> ""
03605  *     a[11]                  #=> nil
03606  *     a[12, 0]               #=> nil
03607  *     a[12..-1]              #=> nil
03608  *
03609  *     a[/[aeiou](.)\1/]      #=> "ell"
03610  *     a[/[aeiou](.)\1/, 0]   #=> "ell"
03611  *     a[/[aeiou](.)\1/, 1]   #=> "l"
03612  *     a[/[aeiou](.)\1/, 2]   #=> nil
03613  *
03614  *     a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l"
03615  *     a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"]     #=> "e"
03616  *
03617  *     a["lo"]                #=> "lo"
03618  *     a["bye"]               #=> nil
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         /* expand string */
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     /* error check */
03729     beg = p - RSTRING_PTR(str); /* physical position */
03730     len = e - p;                /* physical length */
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         /* check if indx is Range */
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  *  call-seq:
03826  *     str[fixnum] = new_str
03827  *     str[fixnum, fixnum] = new_str
03828  *     str[range] = aString
03829  *     str[regexp] = new_str
03830  *     str[regexp, fixnum] = new_str
03831  *     str[regexp, name] = new_str
03832  *     str[other_str] = new_str
03833  *
03834  *  Element Assignment---Replaces some or all of the content of <i>str</i>. The
03835  *  portion of the string affected is determined using the same criteria as
03836  *  <code>String#[]</code>. If the replacement string is not the same length as
03837  *  the text it is replacing, the string will be adjusted accordingly. If the
03838  *  regular expression or string is used as the index doesn't match a position
03839  *  in the string, <code>IndexError</code> is raised. If the regular expression
03840  *  form is used, the optional second <code>Fixnum</code> allows you to specify
03841  *  which portion of the match to replace (effectively using the
03842  *  <code>MatchData</code> indexing rules. The forms that take a
03843  *  <code>Fixnum</code> will raise an <code>IndexError</code> if the value is
03844  *  out of range; the <code>Range</code> form will raise a
03845  *  <code>RangeError</code>, and the <code>Regexp</code> and <code>String</code>
03846  *  will raise an <code>IndexError</code> on negative match.
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  *  call-seq:
03867  *     str.insert(index, other_str)   -> str
03868  *
03869  *  Inserts <i>other_str</i> before the character at the given
03870  *  <i>index</i>, modifying <i>str</i>. Negative indices count from the
03871  *  end of the string, and insert <em>after</em> the given character.
03872  *  The intent is insert <i>aString</i> so that it starts at the given
03873  *  <i>index</i>.
03874  *
03875  *     "abcd".insert(0, 'X')    #=> "Xabcd"
03876  *     "abcd".insert(3, 'X')    #=> "abcXd"
03877  *     "abcd".insert(4, 'X')    #=> "abcdX"
03878  *     "abcd".insert(-3, 'X')   #=> "abXcd"
03879  *     "abcd".insert(-1, 'X')   #=> "abcdX"
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  *  call-seq:
03900  *     str.slice!(fixnum)           -> fixnum or nil
03901  *     str.slice!(fixnum, fixnum)   -> new_str or nil
03902  *     str.slice!(range)            -> new_str or nil
03903  *     str.slice!(regexp)           -> new_str or nil
03904  *     str.slice!(other_str)        -> new_str or nil
03905  *
03906  *  Deletes the specified portion from <i>str</i>, and returns the portion
03907  *  deleted.
03908  *
03909  *     string = "this is a string"
03910  *     string.slice!(2)        #=> "i"
03911  *     string.slice!(3..6)     #=> " is "
03912  *     string.slice!(/s.*t/)   #=> "sa st"
03913  *     string.slice!("r")      #=> "r"
03914  *     string                  #=> "thing"
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  *  call-seq:
03967  *     str.sub!(pattern, replacement)          -> str or nil
03968  *     str.sub!(pattern) {|match| block }      -> str or nil
03969  *
03970  *  Performs the same substitution as String#sub in-place.
03971  *
03972  *  Returns +str+ if a substitution was performed or +nil+ if no substitution
03973  *  was performed.
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  *  call-seq:
04074  *     str.sub(pattern, replacement)         -> new_str
04075  *     str.sub(pattern, hash)                -> new_str
04076  *     str.sub(pattern) {|match| block }     -> new_str
04077  *
04078  *  Returns a copy of +str+ with the _first_ occurrence of +pattern+
04079  *  replaced by the second argument. The +pattern+ is typically a Regexp; if
04080  *  given as a String, any regular expression metacharacters it contains will
04081  *  be interpreted literally, e.g. <code>'\\\d'</code> will match a backlash
04082  *  followed by 'd', instead of a digit.
04083  *
04084  *  If +replacement+ is a String it will be substituted for the matched text.
04085  *  It may contain back-references to the pattern's capture groups of the form
04086  *  <code>"\\d"</code>, where <i>d</i> is a group number, or
04087  *  <code>"\\k<n>"</code>, where <i>n</i> is a group name. If it is a
04088  *  double-quoted string, both back-references must be preceded by an
04089  *  additional backslash. However, within +replacement+ the special match
04090  *  variables, such as <code>&$</code>, will not refer to the current match.
04091  *
04092  *  If the second argument is a Hash, and the matched text is one of its keys,
04093  *  the corresponding value is the replacement string.
04094  *
04095  *  In the block form, the current match string is passed in as a parameter,
04096  *  and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
04097  *  <code>$&</code>, and <code>$'</code> will be set appropriately. The value
04098  *  returned by the block will be substituted for the match on each call.
04099  *
04100  *  The result inherits any tainting in the original string or any supplied
04101  *  replacement string.
04102  *
04103  *     "hello".sub(/[aeiou]/, '*')                  #=> "h*llo"
04104  *     "hello".sub(/([aeiou])/, '<\1>')             #=> "h<e>llo"
04105  *     "hello".sub(/./) {|s| s.ord.to_s + ' ' }     #=> "104 ello"
04106  *     "hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*')  #=> "h*e*llo"
04107  *     'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV)
04108  *      #=> "Is /bin/bash your preferred shell?"
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;  /* no match, no substitution */
04153         return rb_str_dup(str);
04154     }
04155 
04156     offset = 0;
04157     n = 0;
04158     blen = RSTRING_LEN(str) + 30; /* len + margin */
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) {  /* paranoid check [ruby-dev:24827] */
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;    /* copy pre-match substr */
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              * Always consume at least one character of the input string
04204              * in order to prevent infinite loops.
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  *  call-seq:
04235  *     str.gsub!(pattern, replacement)        -> str or nil
04236  *     str.gsub!(pattern) {|match| block }    -> str or nil
04237  *     str.gsub!(pattern)                     -> an_enumerator
04238  *
04239  *  Performs the substitutions of <code>String#gsub</code> in place, returning
04240  *  <i>str</i>, or <code>nil</code> if no substitutions were performed.
04241  *  If no block and no <i>replacement</i> is given, an enumerator is returned instead.
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  *  call-seq:
04254  *     str.gsub(pattern, replacement)       -> new_str
04255  *     str.gsub(pattern, hash)              -> new_str
04256  *     str.gsub(pattern) {|match| block }   -> new_str
04257  *     str.gsub(pattern)                    -> enumerator
04258  *
04259  *  Returns a copy of <i>str</i> with the <em>all</em> occurrences of
04260  *  <i>pattern</i> substituted for the second argument. The <i>pattern</i> is
04261  *  typically a <code>Regexp</code>; if given as a <code>String</code>, any
04262  *  regular expression metacharacters it contains will be interpreted
04263  *  literally, e.g. <code>'\\\d'</code> will match a backlash followed by 'd',
04264  *  instead of a digit.
04265  *
04266  *  If <i>replacement</i> is a <code>String</code> it will be substituted for
04267  *  the matched text. It may contain back-references to the pattern's capture
04268  *  groups of the form <code>\\\d</code>, where <i>d</i> is a group number, or
04269  *  <code>\\\k<n></code>, where <i>n</i> is a group name. If it is a
04270  *  double-quoted string, both back-references must be preceded by an
04271  *  additional backslash. However, within <i>replacement</i> the special match
04272  *  variables, such as <code>$&</code>, will not refer to the current match.
04273  *
04274  *  If the second argument is a <code>Hash</code>, and the matched text is one
04275  *  of its keys, the corresponding value is the replacement string.
04276  *
04277  *  In the block form, the current match string is passed in as a parameter,
04278  *  and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
04279  *  <code>$&</code>, and <code>$'</code> will be set appropriately. The value
04280  *  returned by the block will be substituted for the match on each call.
04281  *
04282  *  The result inherits any tainting in the original string or any supplied
04283  *  replacement string.
04284  *
04285  *  When neither a block nor a second argument is supplied, an
04286  *  <code>Enumerator</code> is returned.
04287  *
04288  *     "hello".gsub(/[aeiou]/, '*')                  #=> "h*ll*"
04289  *     "hello".gsub(/([aeiou])/, '<\1>')             #=> "h<e>ll<o>"
04290  *     "hello".gsub(/./) {|s| s.ord.to_s + ' '}      #=> "104 101 108 108 111 "
04291  *     "hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}')  #=> "h{e}ll{o}"
04292  *     'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*')    #=> "h3ll*"
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  *  call-seq:
04304  *     str.replace(other_str)   -> str
04305  *
04306  *  Replaces the contents and taintedness of <i>str</i> with the corresponding
04307  *  values in <i>other_str</i>.
04308  *
04309  *     s = "hello"         #=> "hello"
04310  *     s.replace "world"   #=> "world"
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  *  call-seq:
04326  *     string.clear    ->  string
04327  *
04328  *  Makes string empty.
04329  *
04330  *     a = "abcde"
04331  *     a.clear    #=> ""
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  *  call-seq:
04350  *     string.chr    ->  string
04351  *
04352  *  Returns a one-character string at the beginning of the string.
04353  *
04354  *     a = "abcde"
04355  *     a.chr    #=> "a"
04356  */
04357 
04358 static VALUE
04359 rb_str_chr(VALUE str)
04360 {
04361     return rb_str_substr(str, 0, 1);
04362 }
04363 
04364 /*
04365  *  call-seq:
04366  *     str.getbyte(index)          -> 0 .. 255
04367  *
04368  *  returns the <i>index</i>th byte as an integer.
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  *  call-seq:
04385  *     str.setbyte(index, integer) -> integer
04386  *
04387  *  modifies the <i>index</i>th byte as <i>integer</i>.
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         /* check if indx is Range */
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  *  call-seq:
04498  *     str.byteslice(fixnum)           -> new_str or nil
04499  *     str.byteslice(fixnum, fixnum)   -> new_str or nil
04500  *     str.byteslice(range)            -> new_str or nil
04501  *
04502  *  Byte Reference---If passed a single <code>Fixnum</code>, returns a
04503  *  substring of one byte at that position. If passed two <code>Fixnum</code>
04504  *  objects, returns a substring starting at the offset given by the first, and
04505  *  a length given by the second. If given a <code>Range</code>, a substring containing
04506  *  bytes at offsets given by the range is returned. In all three cases, if
04507  *  an offset is negative, it is counted from the end of <i>str</i>. Returns
04508  *  <code>nil</code> if the initial offset falls outside the string, the length
04509  *  is negative, or the beginning of the range is greater than the end.
04510  *  The encoding of the resulted string keeps original encoding.
04511  *
04512  *     "hello".byteslice(1)     #=> "e"
04513  *     "hello".byteslice(-1)    #=> "o"
04514  *     "hello".byteslice(1, 2)  #=> "el"
04515  *     "\x80\u3042".byteslice(1, 3) #=> "\u3042"
04516  *     "\x03\u3042\xff".byteslice(1..3) #=> "\u3042"
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  *  call-seq:
04531  *     str.reverse   -> new_str
04532  *
04533  *  Returns a new string with the characters from <i>str</i> in reverse order.
04534  *
04535  *     "stressed".reverse   #=> "desserts"
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  *  call-seq:
04597  *     str.reverse!   -> str
04598  *
04599  *  Reverses <i>str</i> in place.
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  *  call-seq:
04631  *     str.include? other_str   -> true or false
04632  *
04633  *  Returns <code>true</code> if <i>str</i> contains the given string or
04634  *  character.
04635  *
04636  *     "hello".include? "lo"   #=> true
04637  *     "hello".include? "ol"   #=> false
04638  *     "hello".include? ?h     #=> true
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  *  call-seq:
04656  *     str.to_i(base=10)   -> integer
04657  *
04658  *  Returns the result of interpreting leading characters in <i>str</i> as an
04659  *  integer base <i>base</i> (between 2 and 36). Extraneous characters past the
04660  *  end of a valid number are ignored. If there is not a valid number at the
04661  *  start of <i>str</i>, <code>0</code> is returned. This method never raises an
04662  *  exception when <i>base</i> is valid.
04663  *
04664  *     "12345".to_i             #=> 12345
04665  *     "99 red balloons".to_i   #=> 99
04666  *     "0a".to_i                #=> 0
04667  *     "0a".to_i(16)            #=> 10
04668  *     "hello".to_i             #=> 0
04669  *     "1100101".to_i(2)        #=> 101
04670  *     "1100101".to_i(8)        #=> 294977
04671  *     "1100101".to_i(10)       #=> 1100101
04672  *     "1100101".to_i(16)       #=> 17826049
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  *  call-seq:
04696  *     str.to_f   -> float
04697  *
04698  *  Returns the result of interpreting leading characters in <i>str</i> as a
04699  *  floating point number. Extraneous characters past the end of a valid number
04700  *  are ignored. If there is not a valid number at the start of <i>str</i>,
04701  *  <code>0.0</code> is returned. This method never raises an exception.
04702  *
04703  *     "123.45e1".to_f        #=> 1234.5
04704  *     "45.67 degrees".to_f   #=> 45.67
04705  *     "thx1138".to_f         #=> 0.0
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  *  call-seq:
04717  *     str.to_s     -> str
04718  *     str.to_str   -> str
04719  *
04720  *  Returns the receiver.
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 /* sizeof(\x{ hex of 32bit unsigned int } \0) */
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);       /* CHAR_ESC_LEN cannot exceed INT_MAX */
04775     rb_str_buf_cat(result, buf, l);
04776     return l;
04777 }
04778 
04779 /*
04780  * call-seq:
04781  *   str.inspect   -> string
04782  *
04783  * Returns a printable version of _str_, surrounded by quote marks,
04784  * with special characters escaped.
04785  *
04786  *    str = "hello"
04787  *    str[3] = "\b"
04788  *    str.inspect       #=> "\"hel\\bo\""
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  *  call-seq:
04890  *     str.dump   -> new_str
04891  *
04892  *  Produces a version of +str+ with all non-printing characters replaced by
04893  *  <code>\nnn</code> notation and all special characters escaped.
04894  *
04895  *    "hello \n ''".dump  #=> "\"hello \\n ''\"
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) {   /* \u{NN} */
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;       /* \xNN */
04940             }
04941             break;
04942         }
04943     }
04944     if (!rb_enc_asciicompat(enc)) {
04945         len += 19;              /* ".force_encoding('')" */
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     /* result from dump is ASCII */
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  *  call-seq:
05041  *     str.upcase!   -> str or nil
05042  *
05043  *  Upcases the contents of <i>str</i>, returning <code>nil</code> if no changes
05044  *  were made.
05045  *  Note: case replacement is effective only in ASCII region.
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                     /* assuming toupper returns codepoint with same size */
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  *  call-seq:
05103  *     str.upcase   -> new_str
05104  *
05105  *  Returns a copy of <i>str</i> with all lowercase letters replaced with their
05106  *  uppercase counterparts. The operation is locale insensitive---only
05107  *  characters ``a'' to ``z'' are affected.
05108  *  Note: case replacement is effective only in ASCII region.
05109  *
05110  *     "hEllO".upcase   #=> "HELLO"
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  *  call-seq:
05124  *     str.downcase!   -> str or nil
05125  *
05126  *  Downcases the contents of <i>str</i>, returning <code>nil</code> if no
05127  *  changes were made.
05128  *  Note: case replacement is effective only in ASCII region.
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                     /* assuming toupper returns codepoint with same size */
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  *  call-seq:
05186  *     str.downcase   -> new_str
05187  *
05188  *  Returns a copy of <i>str</i> with all uppercase letters replaced with their
05189  *  lowercase counterparts. The operation is locale insensitive---only
05190  *  characters ``A'' to ``Z'' are affected.
05191  *  Note: case replacement is effective only in ASCII region.
05192  *
05193  *     "hEllO".downcase   #=> "hello"
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  *  call-seq:
05207  *     str.capitalize!   -> str or nil
05208  *
05209  *  Modifies <i>str</i> by converting the first character to uppercase and the
05210  *  remainder to lowercase. Returns <code>nil</code> if no changes are made.
05211  *  Note: case conversion is effective only in ASCII region.
05212  *
05213  *     a = "hello"
05214  *     a.capitalize!   #=> "Hello"
05215  *     a               #=> "Hello"
05216  *     a.capitalize!   #=> nil
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  *  call-seq:
05256  *     str.capitalize   -> new_str
05257  *
05258  *  Returns a copy of <i>str</i> with the first character converted to uppercase
05259  *  and the remainder to lowercase.
05260  *  Note: case conversion is effective only in ASCII region.
05261  *
05262  *     "hello".capitalize    #=> "Hello"
05263  *     "HELLO".capitalize    #=> "Hello"
05264  *     "123ABC".capitalize   #=> "123abc"
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  *  call-seq:
05278  *     str.swapcase!   -> str or nil
05279  *
05280  *  Equivalent to <code>String#swapcase</code>, but modifies the receiver in
05281  *  place, returning <i>str</i>, or <code>nil</code> if no changes were made.
05282  *  Note: case conversion is effective only in ASCII region.
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             /* assuming toupper returns codepoint with same size */
05302             rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
05303             modify = 1;
05304         }
05305         else if (rb_enc_islower(c, enc)) {
05306             /* assuming tolower returns codepoint with same size */
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  *  call-seq:
05320  *     str.swapcase   -> new_str
05321  *
05322  *  Returns a copy of <i>str</i> with uppercase alphabetic characters converted
05323  *  to lowercase and lowercase characters converted to uppercase.
05324  *  Note: case conversion is effective only in ASCII region.
05325  *
05326  *     "Hello".swapcase          #=> "hELLO"
05327  *     "cYbEr_PuNk11".swapcase   #=> "CyBeR_pUnK11"
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; /* not reached */
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             /* retrieve last replacer */;
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  *  call-seq:
05649  *     str.tr!(from_str, to_str)   -> str or nil
05650  *
05651  *  Translates <i>str</i> in place, using the same rules as
05652  *  <code>String#tr</code>. Returns <i>str</i>, or <code>nil</code> if no
05653  *  changes were made.
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  *  call-seq:
05665  *     str.tr(from_str, to_str)   => new_str
05666  *
05667  *  Returns a copy of +str+ with the characters in +from_str+ replaced by the
05668  *  corresponding characters in +to_str+.  If +to_str+ is shorter than
05669  *  +from_str+, it is padded with its last character in order to maintain the
05670  *  correspondence.
05671  *
05672  *     "hello".tr('el', 'ip')      #=> "hippo"
05673  *     "hello".tr('aeiou', '*')    #=> "h*ll*"
05674  *     "hello".tr('aeiou', 'AA*')  #=> "hAll*"
05675  *
05676  *  Both strings may use the <code>c1-c2</code> notation to denote ranges of
05677  *  characters, and +from_str+ may start with a <code>^</code>, which denotes
05678  *  all characters except those listed.
05679  *
05680  *     "hello".tr('a-y', 'b-z')    #=> "ifmmp"
05681  *     "hello".tr('^aeiou', '*')   #=> "*e**o"
05682  *
05683  *  The backslash character <code></code> can be used to escape
05684  *  <code>^</code> or <code>-</code> and is otherwise ignored unless it
05685  *  appears at the end of a range or the end of the +from_str+ or +to_str+:
05686  *
05687  *     "hello^world".tr("\\^aeiou", "*") #=> "h*ll**w*rld"
05688  *     "hello-world".tr("a\\-eo", "*")   #=> "h*ll**w*rld"
05689  *
05690  *     "hello\r\nworld".tr("\r", "")   #=> "hello\nworld"
05691  *     "hello\r\nworld".tr("\\r", "")  #=> "hello\r\nwold"
05692  *     "hello\r\nworld".tr("\\\r", "") #=> "hello\nworld"
05693  *
05694  *     "X['\\b']".tr("X\\", "")   #=> "['b']"
05695  *     "X['\\b']".tr("X-\\]", "") #=> "'b'"
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  *  call-seq:
05795  *     str.delete!([other_str]+)   -> str or nil
05796  *
05797  *  Performs a <code>delete</code> operation in place, returning <i>str</i>, or
05798  *  <code>nil</code> if <i>str</i> was not modified.
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  *  call-seq:
05865  *     str.delete([other_str]+)   -> new_str
05866  *
05867  *  Returns a copy of <i>str</i> with all characters in the intersection of its
05868  *  arguments deleted. Uses the same rules for building the set of characters as
05869  *  <code>String#count</code>.
05870  *
05871  *     "hello".delete "l","lo"        #=> "heo"
05872  *     "hello".delete "lo"            #=> "he"
05873  *     "hello".delete "aeiou", "^e"   #=> "hell"
05874  *     "hello".delete "ej-m"          #=> "ho"
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  *  call-seq:
05888  *     str.squeeze!([other_str]*)   -> str or nil
05889  *
05890  *  Squeezes <i>str</i> in place, returning either <i>str</i>, or
05891  *  <code>nil</code> if no changes were made.
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  *  call-seq:
05971  *     str.squeeze([other_str]*)    -> new_str
05972  *
05973  *  Builds a set of characters from the <i>other_str</i> parameter(s) using the
05974  *  procedure described for <code>String#count</code>. Returns a new string
05975  *  where runs of the same character that occur in this set are replaced by a
05976  *  single character. If no arguments are given, all runs of identical
05977  *  characters are replaced by a single character.
05978  *
05979  *     "yellow moon".squeeze                  #=> "yelow mon"
05980  *     "  now   is  the".squeeze(" ")         #=> " now is the"
05981  *     "putters shoot balls".squeeze("m-z")   #=> "puters shot balls"
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  *  call-seq:
05995  *     str.tr_s!(from_str, to_str)   -> str or nil
05996  *
05997  *  Performs <code>String#tr_s</code> processing on <i>str</i> in place,
05998  *  returning <i>str</i>, or <code>nil</code> if no changes were made.
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  *  call-seq:
06010  *     str.tr_s(from_str, to_str)   -> new_str
06011  *
06012  *  Processes a copy of <i>str</i> as described under <code>String#tr</code>,
06013  *  then removes duplicate characters in regions that were affected by the
06014  *  translation.
06015  *
06016  *     "hello".tr_s('l', 'r')     #=> "hero"
06017  *     "hello".tr_s('el', '*')    #=> "h*o"
06018  *     "hello".tr_s('el', 'hx')   #=> "hhxo"
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  *  call-seq:
06032  *     str.count([other_str]+)   -> fixnum
06033  *
06034  *  Each +other_str+ parameter defines a set of characters to count.  The
06035  *  intersection of these sets defines the characters to count in +str+.  Any
06036  *  +other_str+ that starts with a caret <code>^</code> is negated.  The
06037  *  sequence <code>c1-c2</code> means all characters between c1 and c2.  The
06038  *  backslash character <code></code> can be used to escape <code>^</code> or
06039  *  <code>-</code> and is otherwise ignored unless it appears at the end of a
06040  *  sequence or the end of a +other_str+.
06041  *
06042  *     a = "hello world"
06043  *     a.count "lo"                   #=> 5
06044  *     a.count "lo", "o"              #=> 2
06045  *     a.count "hello", "^l"          #=> 4
06046  *     a.count "ej-m"                 #=> 4
06047  *
06048  *     "hello^world".count "\\^aeiou" #=> 4
06049  *     "hello-world".count "a\\-eo"   #=> 4
06050  *
06051  *     c = "hello world\\r\\n"
06052  *     c.count "\\"                   #=> 2
06053  *     c.count "\\A"                  #=> 0
06054  *     c.count "X-\\w"                #=> 3
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  *  call-seq:
06150  *     str.split(pattern=$;, [limit])   -> anArray
06151  *
06152  *  Divides <i>str</i> into substrings based on a delimiter, returning an array
06153  *  of these substrings.
06154  *
06155  *  If <i>pattern</i> is a <code>String</code>, then its contents are used as
06156  *  the delimiter when splitting <i>str</i>. If <i>pattern</i> is a single
06157  *  space, <i>str</i> is split on whitespace, with leading whitespace and runs
06158  *  of contiguous whitespace characters ignored.
06159  *
06160  *  If <i>pattern</i> is a <code>Regexp</code>, <i>str</i> is divided where the
06161  *  pattern matches. Whenever the pattern matches a zero-length string,
06162  *  <i>str</i> is split into individual characters. If <i>pattern</i> contains
06163  *  groups, the respective matches will be returned in the array as well.
06164  *
06165  *  If <i>pattern</i> is omitted, the value of <code>$;</code> is used.  If
06166  *  <code>$;</code> is <code>nil</code> (which is the default), <i>str</i> is
06167  *  split on whitespace as if ` ' were specified.
06168  *
06169  *  If the <i>limit</i> parameter is omitted, trailing null fields are
06170  *  suppressed. If <i>limit</i> is a positive number, at most that number of
06171  *  fields will be returned (if <i>limit</i> is <code>1</code>, the entire
06172  *  string is returned as the only entry in an array). If negative, there is no
06173  *  limit to the number of fields returned, and trailing null fields are not
06174  *  suppressed.
06175  *
06176  *  When the input +str+ is empty an empty Array is returned as the string is
06177  *  considered to have no fields to split.
06178  *
06179  *     " now's  the time".split        #=> ["now's", "the", "time"]
06180  *     " now's  the time".split(' ')   #=> ["now's", "the", "time"]
06181  *     " now's  the time".split(/ /)   #=> ["", "now's", "", "the", "time"]
06182  *     "1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
06183  *     "hello".split(//)               #=> ["h", "e", "l", "l", "o"]
06184  *     "hello".split(//, 3)            #=> ["h", "e", "llo"]
06185  *     "hi mom".split(%r{\s*})         #=> ["h", "i", "m", "o", "m"]
06186  *
06187  *     "mellow yellow".split("ello")   #=> ["m", "w y", "w"]
06188  *     "1,2,,3,4,,".split(',')         #=> ["1", "2", "", "3", "4"]
06189  *     "1,2,,3,4,,".split(',', 4)      #=> ["1", "2", "", "3,4,,"]
06190  *     "1,2,,3,4,,".split(',', -4)     #=> ["1", "2", "", "3", "4", "", ""]
06191  *
06192  *     "".split(',', -1)               #=> []
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                 /* Special case - split into chars */
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             /* Check we are at the start of a char */
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  *  call-seq:
06537  *     str.each_line(separator=$/) {|substr| block }   -> str
06538  *     str.each_line(separator=$/)                     -> an_enumerator
06539  *
06540  *  Splits <i>str</i> using the supplied parameter as the record
06541  *  separator (<code>$/</code> by default), passing each substring in
06542  *  turn to the supplied block.  If a zero-length record separator is
06543  *  supplied, the string is split into paragraphs delimited by
06544  *  multiple successive newlines.
06545  *
06546  *  If no block is given, an enumerator is returned instead.
06547  *
06548  *     print "Example one\n"
06549  *     "hello\nworld".each_line {|s| p s}
06550  *     print "Example two\n"
06551  *     "hello\nworld".each_line('l') {|s| p s}
06552  *     print "Example three\n"
06553  *     "hello\n\n\nworld".each_line('') {|s| p s}
06554  *
06555  *  <em>produces:</em>
06556  *
06557  *     Example one
06558  *     "hello\n"
06559  *     "world"
06560  *     Example two
06561  *     "hel"
06562  *     "l"
06563  *     "o\nworl"
06564  *     "d"
06565  *     Example three
06566  *     "hello\n\n\n"
06567  *     "world"
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  *  call-seq:
06578  *     str.lines(separator=$/)  -> an_array
06579  *
06580  *  Returns an array of lines in <i>str</i> split using the supplied
06581  *  record separator (<code>$/</code> by default).  This is a
06582  *  shorthand for <code>str.each_line(separator).to_a</code>.
06583  *
06584  *  If a block is given, which is a deprecated form, works the same as
06585  *  <code>each_line</code>.
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  *  call-seq:
06638  *     str.each_byte {|fixnum| block }    -> str
06639  *     str.each_byte                      -> an_enumerator
06640  *
06641  *  Passes each byte in <i>str</i> to the given block, or returns an
06642  *  enumerator if no block is given.
06643  *
06644  *     "hello".each_byte {|c| print c, ' ' }
06645  *
06646  *  <em>produces:</em>
06647  *
06648  *     104 101 108 108 111
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  *  call-seq:
06659  *     str.bytes    -> an_array
06660  *
06661  *  Returns an array of bytes in <i>str</i>.  This is a shorthand for
06662  *  <code>str.each_byte.to_a</code>.
06663  *
06664  *  If a block is given, which is a deprecated form, works the same as
06665  *  <code>each_byte</code>.
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  *  call-seq:
06744  *     str.each_char {|cstr| block }    -> str
06745  *     str.each_char                    -> an_enumerator
06746  *
06747  *  Passes each character in <i>str</i> to the given block, or returns
06748  *  an enumerator if no block is given.
06749  *
06750  *     "hello".each_char {|c| print c, ' ' }
06751  *
06752  *  <em>produces:</em>
06753  *
06754  *     h e l l o
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  *  call-seq:
06765  *     str.chars    -> an_array
06766  *
06767  *  Returns an array of characters in <i>str</i>.  This is a shorthand
06768  *  for <code>str.each_char.to_a</code>.
06769  *
06770  *  If a block is given, which is a deprecated form, works the same as
06771  *  <code>each_char</code>.
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  *  call-seq:
06834  *     str.each_codepoint {|integer| block }    -> str
06835  *     str.each_codepoint                       -> an_enumerator
06836  *
06837  *  Passes the <code>Integer</code> ordinal of each character in <i>str</i>,
06838  *  also known as a <i>codepoint</i> when applied to Unicode strings to the
06839  *  given block.
06840  *
06841  *  If no block is given, an enumerator is returned instead.
06842  *
06843  *     "hello\u0639".each_codepoint {|c| print c, ' ' }
06844  *
06845  *  <em>produces:</em>
06846  *
06847  *     104 101 108 108 111 1593
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  *  call-seq:
06858  *     str.codepoints   -> an_array
06859  *
06860  *  Returns an array of the <code>Integer</code> ordinals of the
06861  *  characters in <i>str</i>.  This is a shorthand for
06862  *  <code>str.each_codepoint.to_a</code>.
06863  *
06864  *  If a block is given, which is a deprecated form, works the same as
06865  *  <code>each_codepoint</code>.
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  *  call-seq:
06895  *     str.chop!   -> str or nil
06896  *
06897  *  Processes <i>str</i> as for <code>String#chop</code>, returning <i>str</i>,
06898  *  or <code>nil</code> if <i>str</i> is the empty string.  See also
06899  *  <code>String#chomp!</code>.
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  *  call-seq:
06922  *     str.chop   -> new_str
06923  *
06924  *  Returns a new <code>String</code> with the last character removed.  If the
06925  *  string ends with <code>\r\n</code>, both characters are removed. Applying
06926  *  <code>chop</code> to an empty string returns an empty
06927  *  string. <code>String#chomp</code> is often a safer alternative, as it leaves
06928  *  the string unchanged if it doesn't end in a record separator.
06929  *
06930  *     "string\r\n".chop   #=> "string"
06931  *     "string\n\r".chop   #=> "string\n"
06932  *     "string\n".chop     #=> "string"
06933  *     "string".chop       #=> "strin"
06934  *     "x".chop.chop       #=> ""
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  *  call-seq:
06946  *     str.chomp!(separator=$/)   -> str or nil
06947  *
06948  *  Modifies <i>str</i> in place as described for <code>String#chomp</code>,
06949  *  returning <i>str</i>, or <code>nil</code> if no modifications were made.
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  *  call-seq:
07055  *     str.chomp(separator=$/)   -> new_str
07056  *
07057  *  Returns a new <code>String</code> with the given record separator removed
07058  *  from the end of <i>str</i> (if present). If <code>$/</code> has not been
07059  *  changed from the default Ruby record separator, then <code>chomp</code> also
07060  *  removes carriage return characters (that is it will remove <code>\n</code>,
07061  *  <code>\r</code>, and <code>\r\n</code>).
07062  *
07063  *     "hello".chomp            #=> "hello"
07064  *     "hello\n".chomp          #=> "hello"
07065  *     "hello\r\n".chomp        #=> "hello"
07066  *     "hello\n\r".chomp        #=> "hello\n"
07067  *     "hello\r".chomp          #=> "hello"
07068  *     "hello \n there".chomp   #=> "hello \n there"
07069  *     "hello".chomp("llo")     #=> "he"
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  *  call-seq:
07082  *     str.lstrip!   -> self or nil
07083  *
07084  *  Removes leading whitespace from <i>str</i>, returning <code>nil</code> if no
07085  *  change was made. See also <code>String#rstrip!</code> and
07086  *  <code>String#strip!</code>.
07087  *
07088  *     "  hello  ".lstrip   #=> "hello  "
07089  *     "hello".lstrip!      #=> nil
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     /* remove spaces at head */
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  *  call-seq:
07124  *     str.lstrip   -> new_str
07125  *
07126  *  Returns a copy of <i>str</i> with leading whitespace removed. See also
07127  *  <code>String#rstrip</code> and <code>String#strip</code>.
07128  *
07129  *     "  hello  ".lstrip   #=> "hello  "
07130  *     "hello".lstrip       #=> "hello"
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  *  call-seq:
07144  *     str.rstrip!   -> self or nil
07145  *
07146  *  Removes trailing whitespace from <i>str</i>, returning <code>nil</code> if
07147  *  no change was made. See also <code>String#lstrip!</code> and
07148  *  <code>String#strip!</code>.
07149  *
07150  *     "  hello  ".rstrip   #=> "  hello"
07151  *     "hello".rstrip!      #=> nil
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     /* remove trailing spaces or '\0's */
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  *  call-seq:
07194  *     str.rstrip   -> new_str
07195  *
07196  *  Returns a copy of <i>str</i> with trailing whitespace removed. See also
07197  *  <code>String#lstrip</code> and <code>String#strip</code>.
07198  *
07199  *     "  hello  ".rstrip   #=> "  hello"
07200  *     "hello".rstrip       #=> "hello"
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  *  call-seq:
07214  *     str.strip!   -> str or nil
07215  *
07216  *  Removes leading and trailing whitespace from <i>str</i>. Returns
07217  *  <code>nil</code> if <i>str</i> was not altered.
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  *  call-seq:
07233  *     str.strip   -> new_str
07234  *
07235  *  Returns a copy of <i>str</i> with leading and trailing whitespace removed.
07236  *
07237  *     "    hello    ".strip   #=> "hello"
07238  *     "\tgoodbye\r\n".strip   #=> "goodbye"
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              * Always consume at least one character of the input string
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  *  call-seq:
07289  *     str.scan(pattern)                         -> array
07290  *     str.scan(pattern) {|match, ...| block }   -> str
07291  *
07292  *  Both forms iterate through <i>str</i>, matching the pattern (which may be a
07293  *  <code>Regexp</code> or a <code>String</code>). For each match, a result is
07294  *  generated and either added to the result array or passed to the block. If
07295  *  the pattern contains no groups, each individual result consists of the
07296  *  matched string, <code>$&</code>.  If the pattern contains groups, each
07297  *  individual result is itself an array containing one entry per group.
07298  *
07299  *     a = "cruel world"
07300  *     a.scan(/\w+/)        #=> ["cruel", "world"]
07301  *     a.scan(/.../)        #=> ["cru", "el ", "wor"]
07302  *     a.scan(/(...)/)      #=> [["cru"], ["el "], ["wor"]]
07303  *     a.scan(/(..)(..)/)   #=> [["cr", "ue"], ["l ", "wo"]]
07304  *
07305  *  And the block form:
07306  *
07307  *     a.scan(/\w+/) {|w| print "<<#{w}>> " }
07308  *     print "\n"
07309  *     a.scan(/(.)(.)/) {|x,y| print y, x }
07310  *     print "\n"
07311  *
07312  *  <em>produces:</em>
07313  *
07314  *     <<cruel>> <<world>>
07315  *     rceu lowlr
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  *  call-seq:
07352  *     str.hex   -> integer
07353  *
07354  *  Treats leading characters from <i>str</i> as a string of hexadecimal digits
07355  *  (with an optional sign and an optional <code>0x</code>) and returns the
07356  *  corresponding number. Zero is returned on error.
07357  *
07358  *     "0x0a".hex     #=> 10
07359  *     "-1234".hex    #=> -4660
07360  *     "0".hex        #=> 0
07361  *     "wombat".hex   #=> 0
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  *  call-seq:
07373  *     str.oct   -> integer
07374  *
07375  *  Treats leading characters of <i>str</i> as a string of octal digits (with an
07376  *  optional sign) and returns the corresponding number.  Returns 0 if the
07377  *  conversion fails.
07378  *
07379  *     "123".oct       #=> 83
07380  *     "-377".oct      #=> -255
07381  *     "bad".oct       #=> 0
07382  *     "0377bad".oct   #=> 255
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  *  call-seq:
07394  *     str.crypt(salt_str)   -> new_str
07395  *
07396  *  Applies a one-way cryptographic hash to <i>str</i> by invoking the
07397  *  standard library function <code>crypt(3)</code> with the given
07398  *  salt string.  While the format and the result are system and
07399  *  implementation dependent, using a salt matching the regular
07400  *  expression <code>\A[a-zA-Z0-9./]{2}</code> should be valid and
07401  *  safe on any platform, in which only the first two characters are
07402  *  significant.
07403  *
07404  *  This method is for use in system specific scripts, so if you want
07405  *  a cross-platform hash function consider using Digest or OpenSSL
07406  *  instead.
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  *  call-seq:
07448  *     str.intern   -> symbol
07449  *     str.to_sym   -> symbol
07450  *
07451  *  Returns the <code>Symbol</code> corresponding to <i>str</i>, creating the
07452  *  symbol if it did not previously exist. See <code>Symbol#id2name</code>.
07453  *
07454  *     "Koala".intern         #=> :Koala
07455  *     s = 'cat'.to_sym       #=> :cat
07456  *     s == :cat              #=> true
07457  *     s = '@cat'.to_sym      #=> :@cat
07458  *     s == :@cat             #=> true
07459  *
07460  *  This can also be used to create symbols that cannot be represented using the
07461  *  <code>:xxx</code> notation.
07462  *
07463  *     'cat and dog'.to_sym   #=> :"cat and dog"
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  *  call-seq:
07479  *     str.ord   -> integer
07480  *
07481  *  Return the <code>Integer</code> ordinal of a one-character string.
07482  *
07483  *     "a".ord         #=> 97
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  *  call-seq:
07496  *     str.sum(n=16)   -> integer
07497  *
07498  *  Returns a basic <em>n</em>-bit checksum of the characters in <i>str</i>,
07499  *  where <em>n</em> is the optional <code>Fixnum</code> parameter, defaulting
07500  *  to 16. The result is simply the sum of the binary value of each character in
07501  *  <i>str</i> modulo <code>2**n - 1</code>. This is not a particularly good
07502  *  checksum.
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  *  call-seq:
07656  *     str.ljust(integer, padstr=' ')   -> new_str
07657  *
07658  *  If <i>integer</i> is greater than the length of <i>str</i>, returns a new
07659  *  <code>String</code> of length <i>integer</i> with <i>str</i> left justified
07660  *  and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
07661  *
07662  *     "hello".ljust(4)            #=> "hello"
07663  *     "hello".ljust(20)           #=> "hello               "
07664  *     "hello".ljust(20, '1234')   #=> "hello123412341234123"
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  *  call-seq:
07676  *     str.rjust(integer, padstr=' ')   -> new_str
07677  *
07678  *  If <i>integer</i> is greater than the length of <i>str</i>, returns a new
07679  *  <code>String</code> of length <i>integer</i> with <i>str</i> right justified
07680  *  and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
07681  *
07682  *     "hello".rjust(4)            #=> "hello"
07683  *     "hello".rjust(20)           #=> "               hello"
07684  *     "hello".rjust(20, '1234')   #=> "123412341234123hello"
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  *  call-seq:
07696  *     str.center(width, padstr=' ')   -> new_str
07697  *
07698  *  Centers +str+ in +width+.  If +width+ is greater than the length of +str+,
07699  *  returns a new String of length +width+ with +str+ centered and padded with
07700  *  +padstr+; otherwise, returns +str+.
07701  *
07702  *     "hello".center(4)         #=> "hello"
07703  *     "hello".center(20)        #=> "       hello        "
07704  *     "hello".center(20, '123') #=> "1231231hello12312312"
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  *  call-seq:
07715  *     str.partition(sep)              -> [head, sep, tail]
07716  *     str.partition(regexp)           -> [head, match, tail]
07717  *
07718  *  Searches <i>sep</i> or pattern (<i>regexp</i>) in the string
07719  *  and returns the part before it, the match, and the part
07720  *  after it.
07721  *  If it is not found, returns two empty strings and <i>str</i>.
07722  *
07723  *     "hello".partition("l")         #=> ["he", "l", "lo"]
07724  *     "hello".partition("x")         #=> ["hello", "", ""]
07725  *     "hello".partition(/.l/)        #=> ["h", "el", "lo"]
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  *  call-seq:
07765  *     str.rpartition(sep)             -> [head, sep, tail]
07766  *     str.rpartition(regexp)          -> [head, match, tail]
07767  *
07768  *  Searches <i>sep</i> or pattern (<i>regexp</i>) in the string from the end
07769  *  of the string, and returns the part before it, the match, and the part
07770  *  after it.
07771  *  If it is not found, returns two empty strings and <i>str</i>.
07772  *
07773  *     "hello".rpartition("l")         #=> ["hel", "l", "o"]
07774  *     "hello".rpartition("x")         #=> ["", "", "hello"]
07775  *     "hello".rpartition(/.l/)        #=> ["he", "ll", "o"]
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  *  call-seq:
07817  *     str.start_with?([prefixes]+)   -> true or false
07818  *
07819  *  Returns true if +str+ starts with one of the +prefixes+ given.
07820  *
07821  *    "hello".start_with?("hell")               #=> true
07822  *
07823  *    # returns true if one of the prefixes matches.
07824  *    "hello".start_with?("heaven", "hell")     #=> true
07825  *    "hello".start_with?("heaven", "paradise") #=> false
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  *  call-seq:
07846  *     str.end_with?([suffixes]+)   -> true or false
07847  *
07848  *  Returns true if +str+ ends with one of the +suffixes+ given.
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  *  call-seq:
07886  *     str.force_encoding(encoding)   -> str
07887  *
07888  *  Changes the encoding to +encoding+ and returns self.
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  *  call-seq:
07902  *     str.b   -> str
07903  *
07904  *  Returns a copied string whose encoding is ASCII-8BIT.
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  *  call-seq:
07919  *     str.valid_encoding?  -> true or false
07920  *
07921  *  Returns true for a string which encoded correctly.
07922  *
07923  *    "\xc2\xa1".force_encoding("UTF-8").valid_encoding?  #=> true
07924  *    "\xc2".force_encoding("UTF-8").valid_encoding?      #=> false
07925  *    "\x80".force_encoding("UTF-8").valid_encoding?      #=> false
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  *  call-seq:
07938  *     str.ascii_only?  -> true or false
07939  *
07940  *  Returns true for a string which has only ASCII characters.
07941  *
07942  *    "abc".force_encoding("UTF-8").ascii_only?          #=> true
07943  *    "abc\u{6666}".force_encoding("UTF-8").ascii_only?  #=> false
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 { /* ENC_CODERANGE_VALID */
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                  * p1~p: valid ascii/multibyte chars
08105                  * p ~e: invalid bytes + unknown bytes
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         /* ASCII incompatible */
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  *  call-seq:
08274  *    str.scrub -> new_str
08275  *    str.scrub(repl) -> new_str
08276  *    str.scrub{|bytes|} -> new_str
08277  *
08278  *  If the string is invalid byte sequence then replace invalid bytes with given replacement
08279  *  character, else returns self.
08280  *  If block is given, replace invalid bytes with returned value of the block.
08281  *
08282  *     "abc\u3042\x81".scrub #=> "abc\u3042\uFFFD"
08283  *     "abc\u3042\x81".scrub("*") #=> "abc\u3042*"
08284  *     "abc\u3042\xE3\x80".scrub{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"
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  *  call-seq:
08296  *    str.scrub! -> str
08297  *    str.scrub!(repl) -> str
08298  *    str.scrub!{|bytes|} -> str
08299  *
08300  *  If the string is invalid byte sequence then replace invalid bytes with given replacement
08301  *  character, else returns self.
08302  *  If block is given, replace invalid bytes with returned value of the block.
08303  *
08304  *     "abc\u3042\x81".scrub! #=> "abc\u3042\uFFFD"
08305  *     "abc\u3042\x81".scrub!("*") #=> "abc\u3042*"
08306  *     "abc\u3042\xE3\x80".scrub!{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"
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  * Document-class: Symbol
08319  *
08320  *  <code>Symbol</code> objects represent names and some strings
08321  *  inside the Ruby
08322  *  interpreter. They are generated using the <code>:name</code> and
08323  *  <code>:"string"</code> literals
08324  *  syntax, and by the various <code>to_sym</code> methods. The same
08325  *  <code>Symbol</code> object will be created for a given name or string
08326  *  for the duration of a program's execution, regardless of the context
08327  *  or meaning of that name. Thus if <code>Fred</code> is a constant in
08328  *  one context, a method in another, and a class in a third, the
08329  *  <code>Symbol</code> <code>:Fred</code> will be the same object in
08330  *  all three contexts.
08331  *
08332  *     module One
08333  *       class Fred
08334  *       end
08335  *       $f1 = :Fred
08336  *     end
08337  *     module Two
08338  *       Fred = 1
08339  *       $f2 = :Fred
08340  *     end
08341  *     def Fred()
08342  *     end
08343  *     $f3 = :Fred
08344  *     $f1.object_id   #=> 2514190
08345  *     $f2.object_id   #=> 2514190
08346  *     $f3.object_id   #=> 2514190
08347  *
08348  */
08349 
08350 
08351 /*
08352  *  call-seq:
08353  *     sym == obj   -> true or false
08354  *
08355  *  Equality---If <i>sym</i> and <i>obj</i> are exactly the same
08356  *  symbol, returns <code>true</code>.
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  *  call-seq:
08428  *     sym.inspect    -> string
08429  *
08430  *  Returns the representation of <i>sym</i> as a symbol literal.
08431  *
08432  *     :fred.inspect   #=> ":fred"
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  *  call-seq:
08468  *     sym.id2name   -> string
08469  *     sym.to_s      -> string
08470  *
08471  *  Returns the name or string corresponding to <i>sym</i>.
08472  *
08473  *     :fred.id2name   #=> "fred"
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  * call-seq:
08488  *   sym.to_sym   -> sym
08489  *   sym.intern   -> sym
08490  *
08491  * In general, <code>to_sym</code> returns the <code>Symbol</code> corresponding
08492  * to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned
08493  * in this case.
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  * call-seq:
08516  *   sym.to_proc
08517  *
08518  * Returns a _Proc_ object which respond to the given method by _sym_.
08519  *
08520  *   (1..3).collect(&:to_s)  #=> ["1", "2", "3"]
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  * call-seq:
08555  *
08556  *   sym.succ
08557  *
08558  * Same as <code>sym.to_s.succ.intern</code>.
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  * call-seq:
08569  *
08570  *   symbol <=> other_symbol       -> -1, 0, +1 or nil
08571  *
08572  * Compares +symbol+ with +other_symbol+ after calling #to_s on each of the
08573  * symbols. Returns -1, 0, +1 or nil depending on whether +symbol+ is less
08574  * than, equal to, or greater than +other_symbol+.
08575  *
08576  *  +nil+ is returned if the two values are incomparable.
08577  *
08578  * See String#<=> for more information.
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  * call-seq:
08592  *
08593  *   sym.casecmp(other)  -> -1, 0, +1 or nil
08594  *
08595  * Case-insensitive version of <code>Symbol#<=></code>.
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  * call-seq:
08609  *   sym =~ obj   -> fixnum or nil
08610  *   sym.match(obj)   -> fixnum or nil
08611  *
08612  * Returns <code>sym.to_s =~ obj</code>.
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  * call-seq:
08623  *   sym[idx]      -> char
08624  *   sym[b, n]     -> string
08625  *   sym.slice(idx)      -> char
08626  *   sym.slice(b, n)     -> string
08627  *
08628  * Returns <code>sym.to_s[]</code>.
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  * call-seq:
08639  *   sym.length    -> integer
08640  *   sym.size    -> integer
08641  *
08642  * Same as <code>sym.to_s.length</code>.
08643  */
08644 
08645 static VALUE
08646 sym_length(VALUE sym)
08647 {
08648     return rb_str_length(rb_id2str(SYM2ID(sym)));
08649 }
08650 
08651 /*
08652  * call-seq:
08653  *   sym.empty?   -> true or false
08654  *
08655  * Returns that _sym_ is :"" or not.
08656  */
08657 
08658 static VALUE
08659 sym_empty(VALUE sym)
08660 {
08661     return rb_str_empty(rb_id2str(SYM2ID(sym)));
08662 }
08663 
08664 /*
08665  * call-seq:
08666  *   sym.upcase    -> symbol
08667  *
08668  * Same as <code>sym.to_s.upcase.intern</code>.
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  * call-seq:
08679  *   sym.downcase  -> symbol
08680  *
08681  * Same as <code>sym.to_s.downcase.intern</code>.
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  * call-seq:
08692  *   sym.capitalize  -> symbol
08693  *
08694  * Same as <code>sym.to_s.capitalize.intern</code>.
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  * call-seq:
08705  *   sym.swapcase  -> symbol
08706  *
08707  * Same as <code>sym.to_s.swapcase.intern</code>.
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  * call-seq:
08718  *   sym.encoding   -> encoding
08719  *
08720  * Returns the Encoding object that represents the encoding of _sym_.
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  *  A <code>String</code> object holds and manipulates an arbitrary sequence of
08750  *  bytes, typically representing characters. String objects may be created
08751  *  using <code>String::new</code> or as literals.
08752  *
08753  *  Because of aliasing issues, users of strings should be aware of the methods
08754  *  that modify the contents of a <code>String</code> object.  Typically,
08755  *  methods with names ending in ``!'' modify their receiver, while those
08756  *  without a ``!'' return a new <code>String</code>.  However, there are
08757  *  exceptions, such as <code>String#[]=</code>.
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); /* in encoding.c */
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); /* in parse.y */
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 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7