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