Ruby 1.9.2p136(2010-12-25revision30365)

string.c

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