Bug #6719 ยป 0001-altered-documentation-for-String.sub-where-verbage-w.patch
| string.c | ||
|---|---|---|
| #define STR_SET_LEN(str, n) do { \ | ||
|     if (STR_EMBED_P(str)) {\ | ||
| 	STR_SET_EMBED_LEN((str), (n));\ | ||
|   STR_SET_EMBED_LEN((str), (n));\ | ||
|     }\ | ||
|     else {\ | ||
| 	RSTRING(str)->as.heap.len = (n);\ | ||
|   RSTRING(str)->as.heap.len = (n);\ | ||
|     }\ | ||
| } while (0) | ||
| #define STR_DEC_LEN(str) do {\ | ||
|     if (STR_EMBED_P(str)) {\ | ||
| 	long n = RSTRING_LEN(str);\ | ||
| 	n--;\ | ||
| 	STR_SET_EMBED_LEN((str), n);\ | ||
|   long n = RSTRING_LEN(str);\ | ||
|   n--;\ | ||
|   STR_SET_EMBED_LEN((str), n);\ | ||
|     }\ | ||
|     else {\ | ||
| 	RSTRING(str)->as.heap.len--;\ | ||
|   RSTRING(str)->as.heap.len--;\ | ||
|     }\ | ||
| } while (0) | ||
| #define RESIZE_CAPA(str,capacity) do {\ | ||
|     if (STR_EMBED_P(str)) {\ | ||
| 	if ((capacity) > RSTRING_EMBED_LEN_MAX) {\ | ||
| 	    char *tmp = ALLOC_N(char, (capacity)+1);\ | ||
| 	    memcpy(tmp, RSTRING_PTR(str), RSTRING_LEN(str));\ | ||
| 	    RSTRING(str)->as.heap.ptr = tmp;\ | ||
| 	    RSTRING(str)->as.heap.len = RSTRING_LEN(str);\ | ||
|   if ((capacity) > RSTRING_EMBED_LEN_MAX) {\ | ||
|       char *tmp = ALLOC_N(char, (capacity)+1);\ | ||
|       memcpy(tmp, RSTRING_PTR(str), RSTRING_LEN(str));\ | ||
|       RSTRING(str)->as.heap.ptr = tmp;\ | ||
|       RSTRING(str)->as.heap.len = RSTRING_LEN(str);\ | ||
|             STR_SET_NOEMBED(str);\ | ||
| 	    RSTRING(str)->as.heap.aux.capa = (capacity);\ | ||
| 	}\ | ||
|       RSTRING(str)->as.heap.aux.capa = (capacity);\ | ||
|   }\ | ||
|     }\ | ||
|     else {\ | ||
| 	REALLOC_N(RSTRING(str)->as.heap.ptr, char, (capacity)+1);\ | ||
| 	if (!STR_NOCAPA_P(str))\ | ||
| 	    RSTRING(str)->as.heap.aux.capa = (capacity);\ | ||
|   REALLOC_N(RSTRING(str)->as.heap.ptr, char, (capacity)+1);\ | ||
|   if (!STR_NOCAPA_P(str))\ | ||
|       RSTRING(str)->as.heap.aux.capa = (capacity);\ | ||
|     }\ | ||
| } while (0) | ||
| ... | ... | |
|     const char *p = s; | ||
|     if (*cr == ENC_CODERANGE_BROKEN) | ||
| 	return e - s; | ||
|   return e - s; | ||
|     if (rb_enc_to_index(enc) == 0) { | ||
| 	/* enc is ASCII-8BIT.  ASCII-8BIT string never be broken. */ | ||
| 	p = search_nonascii(p, e); | ||
| 	*cr = (!p && *cr != ENC_CODERANGE_VALID) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID; | ||
| 	return e - s; | ||
|   /* enc is ASCII-8BIT.  ASCII-8BIT string never be broken. */ | ||
|   p = search_nonascii(p, e); | ||
|   *cr = (!p && *cr != ENC_CODERANGE_VALID) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID; | ||
|   return e - s; | ||
|     } | ||
|     else if (rb_enc_asciicompat(enc)) { | ||
| 	p = search_nonascii(p, e); | ||
| 	if (!p) { | ||
| 	    if (*cr != ENC_CODERANGE_VALID) *cr = ENC_CODERANGE_7BIT; | ||
| 	    return e - s; | ||
| 	} | ||
| 	while (p < e) { | ||
| 	    int ret = rb_enc_precise_mbclen(p, e, enc); | ||
| 	    if (!MBCLEN_CHARFOUND_P(ret)) { | ||
| 		*cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN; | ||
| 		return p - s; | ||
| 	    } | ||
| 	    p += MBCLEN_CHARFOUND_LEN(ret); | ||
| 	    if (p < e) { | ||
| 		p = search_nonascii(p, e); | ||
| 		if (!p) { | ||
| 		    *cr = ENC_CODERANGE_VALID; | ||
| 		    return e - s; | ||
| 		} | ||
| 	    } | ||
| 	} | ||
| 	*cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID; | ||
| 	return p - s; | ||
|   p = search_nonascii(p, e); | ||
|   if (!p) { | ||
|       if (*cr != ENC_CODERANGE_VALID) *cr = ENC_CODERANGE_7BIT; | ||
|       return e - s; | ||
|   } | ||
|   while (p < e) { | ||
|       int ret = rb_enc_precise_mbclen(p, e, enc); | ||
|       if (!MBCLEN_CHARFOUND_P(ret)) { | ||
|     *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN; | ||
|     return p - s; | ||
|       } | ||
|       p += MBCLEN_CHARFOUND_LEN(ret); | ||
|       if (p < e) { | ||
|     p = search_nonascii(p, e); | ||
|     if (!p) { | ||
|         *cr = ENC_CODERANGE_VALID; | ||
|         return e - s; | ||
|     } | ||
|       } | ||
|   } | ||
|   *cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID; | ||
|   return p - s; | ||
|     } | ||
|     else { | ||
| 	while (p < e) { | ||
| 	    int ret = rb_enc_precise_mbclen(p, e, enc); | ||
| 	    if (!MBCLEN_CHARFOUND_P(ret)) { | ||
| 		*cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN; | ||
| 		return p - s; | ||
| 	    } | ||
| 	    p += MBCLEN_CHARFOUND_LEN(ret); | ||
| 	} | ||
| 	*cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID; | ||
| 	return p - s; | ||
|   while (p < e) { | ||
|       int ret = rb_enc_precise_mbclen(p, e, enc); | ||
|       if (!MBCLEN_CHARFOUND_P(ret)) { | ||
|     *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN; | ||
|     return p - s; | ||
|       } | ||
|       p += MBCLEN_CHARFOUND_LEN(ret); | ||
|   } | ||
|   *cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID; | ||
|   return p - s; | ||
|     } | ||
| } | ||
| ... | ... | |
|     str_enc_copy(dest, src); | ||
|     switch (ENC_CODERANGE(src)) { | ||
|       case ENC_CODERANGE_7BIT: | ||
| 	ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); | ||
| 	break; | ||
|   ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); | ||
|   break; | ||
|       case ENC_CODERANGE_VALID: | ||
| 	if (!rb_enc_asciicompat(STR_ENC_GET(src)) || | ||
| 	    search_nonascii(RSTRING_PTR(dest), RSTRING_END(dest))) | ||
| 	    ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID); | ||
| 	else | ||
| 	    ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); | ||
| 	break; | ||
|   if (!rb_enc_asciicompat(STR_ENC_GET(src)) || | ||
|       search_nonascii(RSTRING_PTR(dest), RSTRING_END(dest))) | ||
|       ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID); | ||
|   else | ||
|       ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); | ||
|   break; | ||
|       default: | ||
| 	if (RSTRING_LEN(dest) == 0) { | ||
| 	    if (!rb_enc_asciicompat(STR_ENC_GET(src))) | ||
| 		ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID); | ||
| 	    else | ||
| 		ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); | ||
| 	} | ||
| 	break; | ||
|   if (RSTRING_LEN(dest) == 0) { | ||
|       if (!rb_enc_asciicompat(STR_ENC_GET(src))) | ||
|     ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID); | ||
|       else | ||
|     ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT); | ||
|   } | ||
|   break; | ||
|     } | ||
| } | ||
| ... | ... | |
|     int cr = ENC_CODERANGE(str); | ||
|     if (cr == ENC_CODERANGE_UNKNOWN) { | ||
| 	rb_encoding *enc = STR_ENC_GET(str); | ||
|   rb_encoding *enc = STR_ENC_GET(str); | ||
|         cr = coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc); | ||
|         ENC_CODERANGE_SET(str, cr); | ||
|     } | ||
| ... | ... | |
| str_mod_check(VALUE s, const char *p, long len) | ||
| { | ||
|     if (RSTRING_PTR(s) != p || RSTRING_LEN(s) != len){ | ||
| 	rb_raise(rb_eRuntimeError, "string modified"); | ||
|   rb_raise(rb_eRuntimeError, "string modified"); | ||
|     } | ||
| } | ||
| ... | ... | |
| rb_str_capacity(VALUE str) | ||
| { | ||
|     if (STR_EMBED_P(str)) { | ||
| 	return RSTRING_EMBED_LEN_MAX; | ||
|   return RSTRING_EMBED_LEN_MAX; | ||
|     } | ||
|     else if (STR_NOCAPA_P(str)) { | ||
| 	return RSTRING(str)->as.heap.len; | ||
|   return RSTRING(str)->as.heap.len; | ||
|     } | ||
|     else { | ||
| 	return RSTRING(str)->as.heap.aux.capa; | ||
|   return RSTRING(str)->as.heap.aux.capa; | ||
|     } | ||
| } | ||
| ... | ... | |
|     VALUE str; | ||
|     if (len < 0) { | ||
| 	rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|   rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|     } | ||
|     str = str_alloc(klass); | ||
|     if (len > RSTRING_EMBED_LEN_MAX) { | ||
| 	RSTRING(str)->as.heap.aux.capa = len; | ||
| 	RSTRING(str)->as.heap.ptr = ALLOC_N(char,len+1); | ||
| 	STR_SET_NOEMBED(str); | ||
|   RSTRING(str)->as.heap.aux.capa = len; | ||
|   RSTRING(str)->as.heap.ptr = ALLOC_N(char,len+1); | ||
|   STR_SET_NOEMBED(str); | ||
|     } | ||
|     else if (len == 0) { | ||
| 	ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT); | ||
|   ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT); | ||
|     } | ||
|     if (ptr) { | ||
| 	memcpy(RSTRING_PTR(str), ptr, len); | ||
|   memcpy(RSTRING_PTR(str), ptr, len); | ||
|     } | ||
|     STR_SET_LEN(str, len); | ||
|     RSTRING_PTR(str)[len] = '\0'; | ||
| ... | ... | |
| rb_str_new_cstr(const char *ptr) | ||
| { | ||
|     if (!ptr) { | ||
| 	rb_raise(rb_eArgError, "NULL pointer given"); | ||
|   rb_raise(rb_eArgError, "NULL pointer given"); | ||
|     } | ||
|     return rb_str_new(ptr, strlen(ptr)); | ||
| } | ||
| ... | ... | |
|     if (!from) from = rb_enc_get(str); | ||
|     if (from == to) return str; | ||
|     if ((rb_enc_asciicompat(to) && ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) || | ||
| 	to == rb_ascii8bit_encoding()) { | ||
| 	if (STR_ENC_GET(str) != to) { | ||
| 	    str = rb_str_dup(str); | ||
| 	    rb_enc_associate(str, to); | ||
| 	} | ||
| 	return str; | ||
|   to == rb_ascii8bit_encoding()) { | ||
|   if (STR_ENC_GET(str) != to) { | ||
|       str = rb_str_dup(str); | ||
|       rb_enc_associate(str, to); | ||
|   } | ||
|   return str; | ||
|     } | ||
|     len = RSTRING_LEN(str); | ||
| ... | ... | |
|     sp = (unsigned char*)RSTRING_PTR(str); | ||
|     dp = (unsigned char*)RSTRING_PTR(newstr); | ||
|     ret = rb_econv_convert(ec, &sp, (unsigned char*)RSTRING_END(str), | ||
| 			   &dp, (unsigned char*)RSTRING_END(newstr), 0); | ||
|          &dp, (unsigned char*)RSTRING_END(newstr), 0); | ||
|     rb_econv_close(ec); | ||
|     switch (ret) { | ||
|       case econv_destination_buffer_full: | ||
| 	/* destination buffer short */ | ||
| 	len = len < 2 ? 2 : len * 2; | ||
| 	rb_str_resize(newstr, len); | ||
| 	goto retry; | ||
|   /* destination buffer short */ | ||
|   len = len < 2 ? 2 : len * 2; | ||
|   rb_str_resize(newstr, len); | ||
|   goto retry; | ||
|       case econv_finished: | ||
| 	len = dp - (unsigned char*)RSTRING_PTR(newstr); | ||
| 	rb_str_set_len(newstr, len); | ||
| 	rb_enc_associate(newstr, to); | ||
| 	return newstr; | ||
|   len = dp - (unsigned char*)RSTRING_PTR(newstr); | ||
|   rb_str_set_len(newstr, len); | ||
|   rb_enc_associate(newstr, to); | ||
|   return newstr; | ||
|       default: | ||
| 	/* some error, return original */ | ||
| 	return str; | ||
|   /* some error, return original */ | ||
|   return str; | ||
|     } | ||
| } | ||
| ... | ... | |
|     str = rb_tainted_str_new(ptr, len); | ||
|     if (eenc == rb_usascii_encoding() && | ||
| 	rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) { | ||
| 	rb_enc_associate(str, rb_ascii8bit_encoding()); | ||
| 	return str; | ||
|   rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) { | ||
|   rb_enc_associate(str, rb_ascii8bit_encoding()); | ||
|   return str; | ||
|     } | ||
|     rb_enc_associate(str, eenc); | ||
|     return rb_str_conv_enc(str, eenc, rb_default_internal_encoding()); | ||
| ... | ... | |
| str_replace_shared(VALUE str2, VALUE str) | ||
| { | ||
|     if (RSTRING_LEN(str) <= RSTRING_EMBED_LEN_MAX) { | ||
| 	STR_SET_EMBED(str2); | ||
| 	memcpy(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str)+1); | ||
| 	STR_SET_EMBED_LEN(str2, RSTRING_LEN(str)); | ||
|   STR_SET_EMBED(str2); | ||
|   memcpy(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str)+1); | ||
|   STR_SET_EMBED_LEN(str2, RSTRING_LEN(str)); | ||
|     } | ||
|     else { | ||
| 	str = rb_str_new_frozen(str); | ||
| 	FL_SET(str2, STR_NOEMBED); | ||
| 	RSTRING(str2)->as.heap.len = RSTRING_LEN(str); | ||
| 	RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str); | ||
| 	RSTRING(str2)->as.heap.aux.shared = str; | ||
| 	FL_SET(str2, ELTS_SHARED); | ||
|   str = rb_str_new_frozen(str); | ||
|   FL_SET(str2, STR_NOEMBED); | ||
|   RSTRING(str2)->as.heap.len = RSTRING_LEN(str); | ||
|   RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str); | ||
|   RSTRING(str2)->as.heap.aux.shared = str; | ||
|   FL_SET(str2, ELTS_SHARED); | ||
|     } | ||
|     rb_enc_cr_str_exact_copy(str2, str); | ||
| ... | ... | |
|     RSTRING(str2)->as.heap.len = RSTRING_LEN(str); | ||
|     RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str); | ||
|     if (STR_SHARED_P(str)) { | ||
| 	VALUE shared = RSTRING(str)->as.heap.aux.shared; | ||
| 	assert(OBJ_FROZEN(shared)); | ||
| 	FL_SET(str2, ELTS_SHARED); | ||
| 	RSTRING(str2)->as.heap.aux.shared = shared; | ||
|   VALUE shared = RSTRING(str)->as.heap.aux.shared; | ||
|   assert(OBJ_FROZEN(shared)); | ||
|   FL_SET(str2, ELTS_SHARED); | ||
|   RSTRING(str2)->as.heap.aux.shared = shared; | ||
|     } | ||
|     else { | ||
| 	FL_SET(str, ELTS_SHARED); | ||
| 	RSTRING(str)->as.heap.aux.shared = str2; | ||
|   FL_SET(str, ELTS_SHARED); | ||
|   RSTRING(str)->as.heap.aux.shared = str2; | ||
|     } | ||
|     rb_enc_cr_str_exact_copy(str2, str); | ||
|     OBJ_INFECT(str2, str); | ||
| ... | ... | |
|     if (OBJ_FROZEN(orig)) return orig; | ||
|     klass = rb_obj_class(orig); | ||
|     if (STR_SHARED_P(orig) && (str = RSTRING(orig)->as.heap.aux.shared)) { | ||
| 	long ofs; | ||
| 	assert(OBJ_FROZEN(str)); | ||
| 	ofs = RSTRING_LEN(str) - RSTRING_LEN(orig); | ||
| 	if ((ofs > 0) || (klass != RBASIC(str)->klass) || | ||
| 	    (!OBJ_TAINTED(str) && OBJ_TAINTED(orig)) || | ||
| 	    ENCODING_GET(str) != ENCODING_GET(orig)) { | ||
| 	    str = str_new3(klass, str); | ||
| 	    RSTRING(str)->as.heap.ptr += ofs; | ||
| 	    RSTRING(str)->as.heap.len -= ofs; | ||
| 	    rb_enc_cr_str_exact_copy(str, orig); | ||
| 	    OBJ_INFECT(str, orig); | ||
| 	} | ||
|   long ofs; | ||
|   assert(OBJ_FROZEN(str)); | ||
|   ofs = RSTRING_LEN(str) - RSTRING_LEN(orig); | ||
|   if ((ofs > 0) || (klass != RBASIC(str)->klass) || | ||
|       (!OBJ_TAINTED(str) && OBJ_TAINTED(orig)) || | ||
|       ENCODING_GET(str) != ENCODING_GET(orig)) { | ||
|       str = str_new3(klass, str); | ||
|       RSTRING(str)->as.heap.ptr += ofs; | ||
|       RSTRING(str)->as.heap.len -= ofs; | ||
|       rb_enc_cr_str_exact_copy(str, orig); | ||
|       OBJ_INFECT(str, orig); | ||
|   } | ||
|     } | ||
|     else if (STR_EMBED_P(orig)) { | ||
| 	str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig)); | ||
| 	rb_enc_cr_str_exact_copy(str, orig); | ||
| 	OBJ_INFECT(str, orig); | ||
|   str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig)); | ||
|   rb_enc_cr_str_exact_copy(str, orig); | ||
|   OBJ_INFECT(str, orig); | ||
|     } | ||
|     else if (STR_ASSOC_P(orig)) { | ||
| 	VALUE assoc = RSTRING(orig)->as.heap.aux.shared; | ||
| 	FL_UNSET(orig, STR_ASSOC); | ||
| 	str = str_new4(klass, orig); | ||
| 	FL_SET(str, STR_ASSOC); | ||
| 	RSTRING(str)->as.heap.aux.shared = assoc; | ||
|   VALUE assoc = RSTRING(orig)->as.heap.aux.shared; | ||
|   FL_UNSET(orig, STR_ASSOC); | ||
|   str = str_new4(klass, orig); | ||
|   FL_SET(str, STR_ASSOC); | ||
|   RSTRING(str)->as.heap.aux.shared = assoc; | ||
|     } | ||
|     else { | ||
| 	str = str_new4(klass, orig); | ||
|   str = str_new4(klass, orig); | ||
|     } | ||
|     OBJ_FREEZE(str); | ||
|     return str; | ||
| ... | ... | |
| } | ||
| RUBY_ALIAS_FUNCTION(rb_str_new5(VALUE obj, const char *ptr, long len), | ||
| 	   rb_str_new_with_class, (obj, ptr, len)) | ||
|      rb_str_new_with_class, (obj, ptr, len)) | ||
| #define rb_str_new5 rb_str_new_with_class | ||
| static VALUE | ||
| ... | ... | |
|     VALUE str = str_alloc(rb_cString); | ||
|     if (capa < STR_BUF_MIN_SIZE) { | ||
| 	capa = STR_BUF_MIN_SIZE; | ||
|   capa = STR_BUF_MIN_SIZE; | ||
|     } | ||
|     FL_SET(str, STR_NOEMBED); | ||
|     RSTRING(str)->as.heap.aux.capa = capa; | ||
| ... | ... | |
| rb_str_free(VALUE str) | ||
| { | ||
|     if (!STR_EMBED_P(str) && !STR_SHARED_P(str)) { | ||
| 	xfree(RSTRING(str)->as.heap.ptr); | ||
|   xfree(RSTRING(str)->as.heap.ptr); | ||
|     } | ||
| } | ||
| ... | ... | |
| rb_str_memsize(VALUE str) | ||
| { | ||
|     if (!STR_EMBED_P(str) && !STR_SHARED_P(str)) { | ||
| 	return RSTRING(str)->as.heap.aux.capa; | ||
|   return RSTRING(str)->as.heap.aux.capa; | ||
|     } | ||
|     else { | ||
| 	return 0; | ||
|   return 0; | ||
|     } | ||
| } | ||
| ... | ... | |
|     str_discard(str); | ||
|     OBJ_INFECT(str, str2); | ||
|     if (RSTRING_LEN(str2) <= RSTRING_EMBED_LEN_MAX) { | ||
| 	STR_SET_EMBED(str); | ||
| 	memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), RSTRING_LEN(str2)+1); | ||
| 	STR_SET_EMBED_LEN(str, RSTRING_LEN(str2)); | ||
|   STR_SET_EMBED(str); | ||
|   memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), RSTRING_LEN(str2)+1); | ||
|   STR_SET_EMBED_LEN(str, RSTRING_LEN(str2)); | ||
|         rb_enc_associate(str, enc); | ||
|         ENC_CODERANGE_SET(str, cr); | ||
| 	return; | ||
|   return; | ||
|     } | ||
|     STR_SET_NOEMBED(str); | ||
|     STR_UNSET_NOCAPA(str); | ||
|     RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2); | ||
|     RSTRING(str)->as.heap.len = RSTRING_LEN(str2); | ||
|     if (STR_NOCAPA_P(str2)) { | ||
| 	FL_SET(str, RBASIC(str2)->flags & STR_NOCAPA); | ||
| 	RSTRING(str)->as.heap.aux.shared = RSTRING(str2)->as.heap.aux.shared; | ||
|   FL_SET(str, RBASIC(str2)->flags & STR_NOCAPA); | ||
|   RSTRING(str)->as.heap.aux.shared = RSTRING(str2)->as.heap.aux.shared; | ||
|     } | ||
|     else { | ||
| 	RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa; | ||
|   RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa; | ||
|     } | ||
|     STR_SET_EMBED(str2);	/* abandon str2 */ | ||
|     STR_SET_EMBED(str2);  /* abandon str2 */ | ||
|     RSTRING_PTR(str2)[0] = 0; | ||
|     STR_SET_EMBED_LEN(str2, 0); | ||
|     rb_enc_associate(str, enc); | ||
| ... | ... | |
|     VALUE str; | ||
|     if (RB_TYPE_P(obj, T_STRING)) { | ||
| 	return obj; | ||
|   return obj; | ||
|     } | ||
|     str = rb_funcall(obj, id_to_s, 0); | ||
|     if (!RB_TYPE_P(str, T_STRING)) | ||
| 	return rb_any_to_s(obj); | ||
|   return rb_any_to_s(obj); | ||
|     if (OBJ_TAINTED(obj)) OBJ_TAINT(str); | ||
|     return str; | ||
| } | ||
| ... | ... | |
|     len = RSTRING_LEN(str2); | ||
|     if (STR_ASSOC_P(str2)) { | ||
| 	str2 = rb_str_new4(str2); | ||
|   str2 = rb_str_new4(str2); | ||
|     } | ||
|     if (STR_SHARED_P(str2)) { | ||
| 	VALUE shared = RSTRING(str2)->as.heap.aux.shared; | ||
| 	assert(OBJ_FROZEN(shared)); | ||
| 	STR_SET_NOEMBED(str); | ||
| 	RSTRING(str)->as.heap.len = len; | ||
| 	RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2); | ||
| 	FL_SET(str, ELTS_SHARED); | ||
| 	FL_UNSET(str, STR_ASSOC); | ||
| 	RSTRING(str)->as.heap.aux.shared = shared; | ||
|   VALUE shared = RSTRING(str2)->as.heap.aux.shared; | ||
|   assert(OBJ_FROZEN(shared)); | ||
|   STR_SET_NOEMBED(str); | ||
|   RSTRING(str)->as.heap.len = len; | ||
|   RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2); | ||
|   FL_SET(str, ELTS_SHARED); | ||
|   FL_UNSET(str, STR_ASSOC); | ||
|   RSTRING(str)->as.heap.aux.shared = shared; | ||
|     } | ||
|     else { | ||
| 	str_replace_shared(str, str2); | ||
|   str_replace_shared(str, str2); | ||
|     } | ||
|     OBJ_INFECT(str, str2); | ||
| ... | ... | |
|     VALUE orig; | ||
|     if (argc > 0 && rb_scan_args(argc, argv, "01", &orig) == 1) | ||
| 	rb_str_replace(str, orig); | ||
|   rb_str_replace(str, orig); | ||
|     return str; | ||
| } | ||
| ... | ... | |
|     } | ||
|     else if (rb_enc_asciicompat(enc)) { | ||
|         c = 0; | ||
| 	if (cr == ENC_CODERANGE_7BIT || cr == ENC_CODERANGE_VALID) { | ||
| 	    while (p < e) { | ||
| 		if (ISASCII(*p)) { | ||
| 		    q = search_nonascii(p, e); | ||
| 		    if (!q) | ||
| 			return c + (e - p); | ||
| 		    c += q - p; | ||
| 		    p = q; | ||
| 		} | ||
| 		p += rb_enc_fast_mbclen(p, e, enc); | ||
| 		c++; | ||
| 	    } | ||
| 	} | ||
| 	else { | ||
| 	    while (p < e) { | ||
| 		if (ISASCII(*p)) { | ||
| 		    q = search_nonascii(p, e); | ||
| 		    if (!q) | ||
| 			return c + (e - p); | ||
| 		    c += q - p; | ||
| 		    p = q; | ||
| 		} | ||
| 		p += rb_enc_mbclen(p, e, enc); | ||
| 		c++; | ||
| 	    } | ||
| 	} | ||
|   if (cr == ENC_CODERANGE_7BIT || cr == ENC_CODERANGE_VALID) { | ||
|       while (p < e) { | ||
|     if (ISASCII(*p)) { | ||
|         q = search_nonascii(p, e); | ||
|         if (!q) | ||
|       return c + (e - p); | ||
|         c += q - p; | ||
|         p = q; | ||
|     } | ||
|     p += rb_enc_fast_mbclen(p, e, enc); | ||
|     c++; | ||
|       } | ||
|   } | ||
|   else { | ||
|       while (p < e) { | ||
|     if (ISASCII(*p)) { | ||
|         q = search_nonascii(p, e); | ||
|         if (!q) | ||
|       return c + (e - p); | ||
|         c += q - p; | ||
|         p = q; | ||
|     } | ||
|     p += rb_enc_mbclen(p, e, enc); | ||
|     c++; | ||
|       } | ||
|   } | ||
|         return c; | ||
|     } | ||
| ... | ... | |
|     *cr = 0; | ||
|     if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) { | ||
| 	return (e - p + rb_enc_mbminlen(enc) - 1) / rb_enc_mbminlen(enc); | ||
|   return (e - p + rb_enc_mbminlen(enc) - 1) / rb_enc_mbminlen(enc); | ||
|     } | ||
|     else if (rb_enc_asciicompat(enc)) { | ||
| 	c = 0; | ||
| 	while (p < e) { | ||
| 	    if (ISASCII(*p)) { | ||
| 		q = search_nonascii(p, e); | ||
| 		if (!q) { | ||
| 		    if (!*cr) *cr = ENC_CODERANGE_7BIT; | ||
| 		    return c + (e - p); | ||
| 		} | ||
| 		c += q - p; | ||
| 		p = q; | ||
| 	    } | ||
| 	    ret = rb_enc_precise_mbclen(p, e, enc); | ||
| 	    if (MBCLEN_CHARFOUND_P(ret)) { | ||
| 		*cr |= ENC_CODERANGE_VALID; | ||
| 		p += MBCLEN_CHARFOUND_LEN(ret); | ||
| 	    } | ||
| 	    else { | ||
| 		*cr = ENC_CODERANGE_BROKEN; | ||
| 		p++; | ||
| 	    } | ||
| 	    c++; | ||
| 	} | ||
| 	if (!*cr) *cr = ENC_CODERANGE_7BIT; | ||
| 	return c; | ||
|   c = 0; | ||
|   while (p < e) { | ||
|       if (ISASCII(*p)) { | ||
|     q = search_nonascii(p, e); | ||
|     if (!q) { | ||
|         if (!*cr) *cr = ENC_CODERANGE_7BIT; | ||
|         return c + (e - p); | ||
|     } | ||
|     c += q - p; | ||
|     p = q; | ||
|       } | ||
|       ret = rb_enc_precise_mbclen(p, e, enc); | ||
|       if (MBCLEN_CHARFOUND_P(ret)) { | ||
|     *cr |= ENC_CODERANGE_VALID; | ||
|     p += MBCLEN_CHARFOUND_LEN(ret); | ||
|       } | ||
|       else { | ||
|     *cr = ENC_CODERANGE_BROKEN; | ||
|     p++; | ||
|       } | ||
|       c++; | ||
|   } | ||
|   if (!*cr) *cr = ENC_CODERANGE_7BIT; | ||
|   return c; | ||
|     } | ||
|     for (c=0; p<e; c++) { | ||
| 	ret = rb_enc_precise_mbclen(p, e, enc); | ||
| 	if (MBCLEN_CHARFOUND_P(ret)) { | ||
| 	    *cr |= ENC_CODERANGE_VALID; | ||
| 	    p += MBCLEN_CHARFOUND_LEN(ret); | ||
| 	} | ||
| 	else { | ||
| 	    *cr = ENC_CODERANGE_BROKEN; | ||
|   ret = rb_enc_precise_mbclen(p, e, enc); | ||
|   if (MBCLEN_CHARFOUND_P(ret)) { | ||
|       *cr |= ENC_CODERANGE_VALID; | ||
|       p += MBCLEN_CHARFOUND_LEN(ret); | ||
|   } | ||
|   else { | ||
|       *cr = ENC_CODERANGE_BROKEN; | ||
|             if (p + rb_enc_mbminlen(enc) <= e) | ||
|                 p += rb_enc_mbminlen(enc); | ||
|             else | ||
|                 p = e; | ||
| 	} | ||
|   } | ||
|     } | ||
|     if (!*cr) *cr = ENC_CODERANGE_7BIT; | ||
|     return c; | ||
| ... | ... | |
|     if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID && | ||
|         enc == rb_utf8_encoding()) { | ||
| 	VALUE len = 0; | ||
| 	if ((int)sizeof(VALUE) * 2 < e - p) { | ||
| 	    const VALUE *s, *t; | ||
| 	    const VALUE lowbits = sizeof(VALUE) - 1; | ||
| 	    s = (const VALUE*)(~lowbits & ((VALUE)p + lowbits)); | ||
| 	    t = (const VALUE*)(~lowbits & (VALUE)e); | ||
| 	    while (p < (const char *)s) { | ||
| 		if (is_utf8_lead_byte(*p)) len++; | ||
| 		p++; | ||
| 	    } | ||
| 	    while (s < t) { | ||
| 		len += count_utf8_lead_bytes_with_word(s); | ||
| 		s++; | ||
| 	    } | ||
| 	    p = (const char *)s; | ||
| 	} | ||
| 	while (p < e) { | ||
| 	    if (is_utf8_lead_byte(*p)) len++; | ||
| 	    p++; | ||
| 	} | ||
| 	return (long)len; | ||
|   VALUE len = 0; | ||
|   if ((int)sizeof(VALUE) * 2 < e - p) { | ||
|       const VALUE *s, *t; | ||
|       const VALUE lowbits = sizeof(VALUE) - 1; | ||
|       s = (const VALUE*)(~lowbits & ((VALUE)p + lowbits)); | ||
|       t = (const VALUE*)(~lowbits & (VALUE)e); | ||
|       while (p < (const char *)s) { | ||
|     if (is_utf8_lead_byte(*p)) len++; | ||
|     p++; | ||
|       } | ||
|       while (s < t) { | ||
|     len += count_utf8_lead_bytes_with_word(s); | ||
|     s++; | ||
|       } | ||
|       p = (const char *)s; | ||
|   } | ||
|   while (p < e) { | ||
|       if (is_utf8_lead_byte(*p)) len++; | ||
|       p++; | ||
|   } | ||
|   return (long)len; | ||
|     } | ||
| #endif | ||
|     n = rb_enc_strlen_cr(p, e, enc, &cr); | ||
| ... | ... | |
| rb_str_empty(VALUE str) | ||
| { | ||
|     if (RSTRING_LEN(str) == 0) | ||
| 	return Qtrue; | ||
|   return Qtrue; | ||
|     return Qfalse; | ||
| } | ||
| ... | ... | |
|     str3 = rb_str_new(0, RSTRING_LEN(str1)+RSTRING_LEN(str2)); | ||
|     memcpy(RSTRING_PTR(str3), RSTRING_PTR(str1), RSTRING_LEN(str1)); | ||
|     memcpy(RSTRING_PTR(str3) + RSTRING_LEN(str1), | ||
| 	   RSTRING_PTR(str2), RSTRING_LEN(str2)); | ||
|      RSTRING_PTR(str2), RSTRING_LEN(str2)); | ||
|     RSTRING_PTR(str3)[RSTRING_LEN(str3)] = '\0'; | ||
|     if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2)) | ||
| 	OBJ_TAINT(str3); | ||
|   OBJ_TAINT(str3); | ||
|     ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc), | ||
| 			   ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2))); | ||
|          ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2))); | ||
|     return str3; | ||
| } | ||
| ... | ... | |
|     len = NUM2LONG(times); | ||
|     if (len < 0) { | ||
| 	rb_raise(rb_eArgError, "negative argument"); | ||
|   rb_raise(rb_eArgError, "negative argument"); | ||
|     } | ||
|     if (len && LONG_MAX/len <  RSTRING_LEN(str)) { | ||
| 	rb_raise(rb_eArgError, "argument too big"); | ||
|   rb_raise(rb_eArgError, "argument too big"); | ||
|     } | ||
|     str2 = rb_str_new5(str, 0, len *= RSTRING_LEN(str)); | ||
| ... | ... | |
|     volatile VALUE tmp = rb_check_array_type(arg); | ||
|     if (!NIL_P(tmp)) { | ||
| 	return rb_str_format(RARRAY_LENINT(tmp), RARRAY_PTR(tmp), str); | ||
|   return rb_str_format(RARRAY_LENINT(tmp), RARRAY_PTR(tmp), str); | ||
|     } | ||
|     return rb_str_format(1, &arg, str); | ||
| } | ||
| ... | ... | |
| str_modifiable(VALUE str) | ||
| { | ||
|     if (FL_TEST(str, STR_TMPLOCK)) { | ||
| 	rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked"); | ||
|   rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked"); | ||
|     } | ||
|     rb_check_frozen(str); | ||
|     if (!OBJ_UNTRUSTED(str) && rb_safe_level() >= 4) | ||
| 	rb_raise(rb_eSecurityError, "Insecure: can't modify string"); | ||
|   rb_raise(rb_eSecurityError, "Insecure: can't modify string"); | ||
| } | ||
| static inline int | ||
| ... | ... | |
|     if (len > capa) len = capa; | ||
|     ptr = ALLOC_N(char, capa + 1); | ||
|     if (RSTRING_PTR(str)) { | ||
| 	memcpy(ptr, RSTRING_PTR(str), len); | ||
|   memcpy(ptr, RSTRING_PTR(str), len); | ||
|     } | ||
|     STR_SET_NOEMBED(str); | ||
|     STR_UNSET_NOCAPA(str); | ||
| ... | ... | |
| rb_str_modify(VALUE str) | ||
| { | ||
|     if (!str_independent(str)) | ||
| 	str_make_independent(str); | ||
|   str_make_independent(str); | ||
|     ENC_CODERANGE_CLEAR(str); | ||
| } | ||
| ... | ... | |
| rb_str_modify_expand(VALUE str, long expand) | ||
| { | ||
|     if (expand < 0) { | ||
| 	rb_raise(rb_eArgError, "negative expanding string size"); | ||
|   rb_raise(rb_eArgError, "negative expanding string size"); | ||
|     } | ||
|     if (!str_independent(str)) { | ||
| 	str_make_independent_expand(str, expand); | ||
|   str_make_independent_expand(str, expand); | ||
|     } | ||
|     else if (expand > 0) { | ||
| 	long len = RSTRING_LEN(str); | ||
| 	long capa = len + expand; | ||
| 	if (!STR_EMBED_P(str)) { | ||
| 	    REALLOC_N(RSTRING(str)->as.heap.ptr, char, capa+1); | ||
| 	    RSTRING(str)->as.heap.aux.capa = capa; | ||
| 	} | ||
| 	else if (capa > RSTRING_EMBED_LEN_MAX) { | ||
| 	    str_make_independent_expand(str, expand); | ||
| 	} | ||
|   long len = RSTRING_LEN(str); | ||
|   long capa = len + expand; | ||
|   if (!STR_EMBED_P(str)) { | ||
|       REALLOC_N(RSTRING(str)->as.heap.ptr, char, capa+1); | ||
|       RSTRING(str)->as.heap.aux.capa = capa; | ||
|   } | ||
|   else if (capa > RSTRING_EMBED_LEN_MAX) { | ||
|       str_make_independent_expand(str, expand); | ||
|   } | ||
|     } | ||
|     ENC_CODERANGE_CLEAR(str); | ||
| } | ||
| ... | ... | |
| str_modify_keep_cr(VALUE str) | ||
| { | ||
|     if (!str_independent(str)) | ||
| 	str_make_independent(str); | ||
|   str_make_independent(str); | ||
|     if (ENC_CODERANGE(str) == ENC_CODERANGE_BROKEN) | ||
| 	/* Force re-scan later */ | ||
| 	ENC_CODERANGE_CLEAR(str); | ||
|   /* Force re-scan later */ | ||
|   ENC_CODERANGE_CLEAR(str); | ||
| } | ||
| static inline void | ||
| ... | ... | |
| { | ||
|     str_modifiable(str); | ||
|     if (!STR_SHARED_P(str) && !STR_EMBED_P(str)) { | ||
| 	xfree(RSTRING_PTR(str)); | ||
| 	RSTRING(str)->as.heap.ptr = 0; | ||
| 	RSTRING(str)->as.heap.len = 0; | ||
|   xfree(RSTRING_PTR(str)); | ||
|   RSTRING(str)->as.heap.ptr = 0; | ||
|   RSTRING(str)->as.heap.len = 0; | ||
|     } | ||
| } | ||
| ... | ... | |
|     /* sanity check */ | ||
|     rb_check_frozen(str); | ||
|     if (STR_ASSOC_P(str)) { | ||
| 	/* already associated */ | ||
| 	rb_ary_concat(RSTRING(str)->as.heap.aux.shared, add); | ||
|   /* already associated */ | ||
|   rb_ary_concat(RSTRING(str)->as.heap.aux.shared, add); | ||
|     } | ||
|     else { | ||
| 	if (STR_SHARED_P(str)) { | ||
| 	    VALUE assoc = RSTRING(str)->as.heap.aux.shared; | ||
| 	    str_make_independent(str); | ||
| 	    if (STR_ASSOC_P(assoc)) { | ||
| 		assoc = RSTRING(assoc)->as.heap.aux.shared; | ||
| 		rb_ary_concat(assoc, add); | ||
| 		add = assoc; | ||
| 	    } | ||
| 	} | ||
| 	else if (STR_EMBED_P(str)) { | ||
| 	    str_make_independent(str); | ||
| 	} | ||
| 	else if (RSTRING(str)->as.heap.aux.capa != RSTRING_LEN(str)) { | ||
| 	    RESIZE_CAPA(str, RSTRING_LEN(str)); | ||
| 	} | ||
| 	FL_SET(str, STR_ASSOC); | ||
| 	RBASIC(add)->klass = 0; | ||
| 	RSTRING(str)->as.heap.aux.shared = add; | ||
|   if (STR_SHARED_P(str)) { | ||
|       VALUE assoc = RSTRING(str)->as.heap.aux.shared; | ||
|       str_make_independent(str); | ||
|       if (STR_ASSOC_P(assoc)) { | ||
|     assoc = RSTRING(assoc)->as.heap.aux.shared; | ||
|     rb_ary_concat(assoc, add); | ||
|     add = assoc; | ||
|       } | ||
|   } | ||
|   else if (STR_EMBED_P(str)) { | ||
|       str_make_independent(str); | ||
|   } | ||
|   else if (RSTRING(str)->as.heap.aux.capa != RSTRING_LEN(str)) { | ||
|       RESIZE_CAPA(str, RSTRING_LEN(str)); | ||
|   } | ||
|   FL_SET(str, STR_ASSOC); | ||
|   RBASIC(add)->klass = 0; | ||
|   RSTRING(str)->as.heap.aux.shared = add; | ||
|     } | ||
| } | ||
| ... | ... | |
| { | ||
|     if (STR_SHARED_P(str)) str = RSTRING(str)->as.heap.aux.shared; | ||
|     if (STR_ASSOC_P(str)) { | ||
| 	return RSTRING(str)->as.heap.aux.shared; | ||
|   return RSTRING(str)->as.heap.aux.shared; | ||
|     } | ||
|     return Qfalse; | ||
| } | ||
| ... | ... | |
| { | ||
|     rb_encoding *enc = rb_enc_get(str); | ||
|     if (!rb_enc_asciicompat(enc)) { | ||
| 	rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s", rb_enc_name(enc)); | ||
|   rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s", rb_enc_name(enc)); | ||
|     } | ||
| } | ||
| ... | ... | |
| { | ||
|     VALUE s = *ptr; | ||
|     if (!RB_TYPE_P(s, T_STRING)) { | ||
| 	s = rb_str_to_str(s); | ||
| 	*ptr = s; | ||
|   s = rb_str_to_str(s); | ||
|   *ptr = s; | ||
|     } | ||
|     return s; | ||
| } | ||
| ... | ... | |
|     long len = RSTRING_LEN(str); | ||
|     if (!s || memchr(s, 0, len)) { | ||
| 	rb_raise(rb_eArgError, "string contains null byte"); | ||
|   rb_raise(rb_eArgError, "string contains null byte"); | ||
|     } | ||
|     if (s[len]) { | ||
| 	rb_str_modify(str); | ||
| 	s = RSTRING_PTR(str); | ||
| 	s[RSTRING_LEN(str)] = 0; | ||
|   rb_str_modify(str); | ||
|   s = RSTRING_PTR(str); | ||
|   s[RSTRING_LEN(str)] = 0; | ||
|     } | ||
|     return s; | ||
| } | ||
| ... | ... | |
|             if (ISASCII(*p)) { | ||
|                 p2 = search_nonascii(p, e2); | ||
|                 if (!p2) { | ||
| 		    nth -= e2 - p; | ||
| 		    *nthp = nth; | ||
|         nth -= e2 - p; | ||
|         *nthp = nth; | ||
|                     return (char *)e2; | ||
|                 } | ||
|                 nth -= p2 - p; | ||
| ... | ... | |
| str_nth(const char *p, const char *e, long nth, rb_encoding *enc, int singlebyte) | ||
| { | ||
|     if (singlebyte) | ||
| 	p += nth; | ||
|   p += nth; | ||
|     else { | ||
| 	p = str_nth_len(p, e, &nth, enc); | ||
|   p = str_nth_len(p, e, &nth, enc); | ||
|     } | ||
|     if (!p) return 0; | ||
|     if (p > e) p = e; | ||
| ... | ... | |
| rb_str_offset(VALUE str, long pos) | ||
| { | ||
|     return str_offset(RSTRING_PTR(str), RSTRING_END(str), pos, | ||
| 		      STR_ENC_GET(str), single_byte_optimizable(str)); | ||
|           STR_ENC_GET(str), single_byte_optimizable(str)); | ||
| } | ||
| #ifdef NONASCII_MASK | ||
| ... | ... | |
| { | ||
|     long nth = *nthp; | ||
|     if ((int)SIZEOF_VALUE * 2 < e - p && (int)SIZEOF_VALUE * 2 < nth) { | ||
| 	const VALUE *s, *t; | ||
| 	const VALUE lowbits = sizeof(VALUE) - 1; | ||
| 	s = (const VALUE*)(~lowbits & ((VALUE)p + lowbits)); | ||
| 	t = (const VALUE*)(~lowbits & (VALUE)e); | ||
| 	while (p < (const char *)s) { | ||
| 	    if (is_utf8_lead_byte(*p)) nth--; | ||
| 	    p++; | ||
| 	} | ||
| 	do { | ||
| 	    nth -= count_utf8_lead_bytes_with_word(s); | ||
| 	    s++; | ||
| 	} while (s < t && (int)sizeof(VALUE) <= nth); | ||
| 	p = (char *)s; | ||
|   const VALUE *s, *t; | ||
|   const VALUE lowbits = sizeof(VALUE) - 1; | ||
|   s = (const VALUE*)(~lowbits & ((VALUE)p + lowbits)); | ||
|   t = (const VALUE*)(~lowbits & (VALUE)e); | ||
|   while (p < (const char *)s) { | ||
|       if (is_utf8_lead_byte(*p)) nth--; | ||
|       p++; | ||
|   } | ||
|   do { | ||
|       nth -= count_utf8_lead_bytes_with_word(s); | ||
|       s++; | ||
|   } while (s < t && (int)sizeof(VALUE) <= nth); | ||
|   p = (char *)s; | ||
|     } | ||
|     while (p < e) { | ||
| 	if (is_utf8_lead_byte(*p)) { | ||
| 	    if (nth == 0) break; | ||
| 	    nth--; | ||
| 	} | ||
| 	p++; | ||
|   if (is_utf8_lead_byte(*p)) { | ||
|       if (nth == 0) break; | ||
|       nth--; | ||
|   } | ||
|   p++; | ||
|     } | ||
|     *nthp = nth; | ||
|     return (char *)p; | ||
| ... | ... | |
|     if (single_byte_optimizable(str) || pos < 0) | ||
|         return pos; | ||
|     else { | ||
| 	char *p = RSTRING_PTR(str); | ||
|   char *p = RSTRING_PTR(str); | ||
|         return enc_strlen(p, p + pos, STR_ENC_GET(str), ENC_CODERANGE(str)); | ||
|     } | ||
| } | ||
| ... | ... | |
|     if (len < 0) return 0; | ||
|     if (!blen) { | ||
| 	len = 0; | ||
|   len = 0; | ||
|     } | ||
|     if (single_byte_optimizable(str)) { | ||
| 	if (beg > blen) return 0; | ||
| 	if (beg < 0) { | ||
| 	    beg += blen; | ||
| 	    if (beg < 0) return 0; | ||
| 	} | ||
| 	if (beg + len > blen) | ||
| 	    len = blen - beg; | ||
| 	if (len < 0) return 0; | ||
| 	p = s + beg; | ||
| 	goto end; | ||
|   if (beg > blen) return 0; | ||
|   if (beg < 0) { | ||
|       beg += blen; | ||
|       if (beg < 0) return 0; | ||
|   } | ||
|   if (beg + len > blen) | ||
|       len = blen - beg; | ||
|   if (len < 0) return 0; | ||
|   p = s + beg; | ||
|   goto end; | ||
|     } | ||
|     if (beg < 0) { | ||
| 	if (len > -beg) len = -beg; | ||
| 	if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) { | ||
| 	    beg = -beg; | ||
| 	    while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0); | ||
| 	    p = e; | ||
| 	    if (!p) return 0; | ||
| 	    while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0); | ||
| 	    if (!p) return 0; | ||
| 	    len = e - p; | ||
| 	    goto end; | ||
| 	} | ||
| 	else { | ||
| 	    slen = str_strlen(str, enc); | ||
| 	    beg += slen; | ||
| 	    if (beg < 0) return 0; | ||
| 	    p = s + beg; | ||
| 	    if (len == 0) goto end; | ||
| 	} | ||
|   if (len > -beg) len = -beg; | ||
|   if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) { | ||
|       beg = -beg; | ||
|       while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0); | ||
|       p = e; | ||
|       if (!p) return 0; | ||
|       while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0); | ||
|       if (!p) return 0; | ||
|       len = e - p; | ||
|       goto end; | ||
|   } | ||
|   else { | ||
|       slen = str_strlen(str, enc); | ||
|       beg += slen; | ||
|       if (beg < 0) return 0; | ||
|       p = s + beg; | ||
|       if (len == 0) goto end; | ||
|   } | ||
|     } | ||
|     else if (beg > 0 && beg > RSTRING_LEN(str)) { | ||
| 	return 0; | ||
|   return 0; | ||
|     } | ||
|     if (len == 0) { | ||
| 	if (beg > str_strlen(str, enc)) return 0; | ||
| 	p = s + beg; | ||
|   if (beg > str_strlen(str, enc)) return 0; | ||
|   p = s + beg; | ||
|     } | ||
| #ifdef NONASCII_MASK | ||
|     else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID && | ||
| ... | ... | |
|     } | ||
| #endif | ||
|     else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) { | ||
| 	int char_sz = rb_enc_mbmaxlen(enc); | ||
|   int char_sz = rb_enc_mbmaxlen(enc); | ||
| 	p = s + beg * char_sz; | ||
| 	if (p > e) { | ||
| 	    return 0; | ||
| 	} | ||
|   p = s + beg * char_sz; | ||
|   if (p > e) { | ||
|       return 0; | ||
|   } | ||
|         else if (len * char_sz > e - p) | ||
|             len = e - p; | ||
|         else | ||
| 	    len *= char_sz; | ||
|       len *= char_sz; | ||
|     } | ||
|     else if ((p = str_nth_len(s, e, &beg, enc)) == e) { | ||
| 	if (beg > 0) return 0; | ||
| 	len = 0; | ||
|   if (beg > 0) return 0; | ||
|   len = 0; | ||
|     } | ||
|     else { | ||
| 	len = str_offset(p, e, len, enc, 0); | ||
|   len = str_offset(p, e, len, enc, 0); | ||
|     } | ||
|   end: | ||
|     *lenp = len; | ||
| ... | ... | |
|     if (!p) return Qnil; | ||
|     if (len > RSTRING_EMBED_LEN_MAX && p + len == RSTRING_END(str)) { | ||
| 	str2 = rb_str_new4(str); | ||
| 	str2 = str_new3(rb_obj_class(str2), str2); | ||
| 	RSTRING(str2)->as.heap.ptr += RSTRING(str2)->as.heap.len - len; | ||
| 	RSTRING(str2)->as.heap.len = len; | ||
|   str2 = rb_str_new4(str); | ||
|   str2 = str_new3(rb_obj_class(str2), str2); | ||
|   RSTRING(str2)->as.heap.ptr += RSTRING(str2)->as.heap.len - len; | ||
|   RSTRING(str2)->as.heap.len = len; | ||
|     } | ||
|     else { | ||
| 	str2 = rb_str_new5(str, p, len); | ||
| 	rb_enc_cr_str_copy_for_substr(str2, str); | ||
| 	OBJ_INFECT(str2, str); | ||
|   str2 = rb_str_new5(str, p, len); | ||
|   rb_enc_cr_str_copy_for_substr(str2, str); | ||
|   OBJ_INFECT(str2, str); | ||
|     } | ||
|     return str2; | ||
| ... | ... | |
| rb_str_freeze(VALUE str) | ||
| { | ||
|     if (STR_ASSOC_P(str)) { | ||
| 	VALUE ary = RSTRING(str)->as.heap.aux.shared; | ||
| 	OBJ_FREEZE(ary); | ||
|   VALUE ary = RSTRING(str)->as.heap.aux.shared; | ||
|   OBJ_FREEZE(ary); | ||
|     } | ||
|     return rb_obj_freeze(str); | ||
| } | ||
| ... | ... | |
| rb_str_locktmp(VALUE str) | ||
| { | ||
|     if (FL_TEST(str, STR_TMPLOCK)) { | ||
| 	rb_raise(rb_eRuntimeError, "temporal locking already locked string"); | ||
|   rb_raise(rb_eRuntimeError, "temporal locking already locked string"); | ||
|     } | ||
|     FL_SET(str, STR_TMPLOCK); | ||
|     return str; | ||
| ... | ... | |
| rb_str_unlocktmp(VALUE str) | ||
| { | ||
|     if (!FL_TEST(str, STR_TMPLOCK)) { | ||
| 	rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string"); | ||
|   rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string"); | ||
|     } | ||
|     FL_UNSET(str, STR_TMPLOCK); | ||
|     return str; | ||
| ... | ... | |
|     str_modifiable(str); | ||
|     if (STR_SHARED_P(str)) { | ||
| 	rb_raise(rb_eRuntimeError, "can't set length of shared string"); | ||
|   rb_raise(rb_eRuntimeError, "can't set length of shared string"); | ||
|     } | ||
|     if (len > (capa = (long)rb_str_capacity(str))) { | ||
| 	rb_bug("probable buffer overflow: %ld for %ld", len, capa); | ||
|   rb_bug("probable buffer overflow: %ld for %ld", len, capa); | ||
|     } | ||
|     STR_SET_LEN(str, len); | ||
|     RSTRING_PTR(str)[len] = '\0'; | ||
| ... | ... | |
|     int independent; | ||
|     if (len < 0) { | ||
| 	rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|   rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|     } | ||
|     independent = str_independent(str); | ||
|     ENC_CODERANGE_CLEAR(str); | ||
|     slen = RSTRING_LEN(str); | ||
|     if (len != slen) { | ||
| 	if (STR_EMBED_P(str)) { | ||
| 	    if (len <= RSTRING_EMBED_LEN_MAX) { | ||
| 		STR_SET_EMBED_LEN(str, len); | ||
| 		RSTRING(str)->as.ary[len] = '\0'; | ||
| 		return str; | ||
| 	    } | ||
| 	    str_make_independent_expand(str, len - slen); | ||
| 	    STR_SET_NOEMBED(str); | ||
| 	} | ||
| 	else if (len <= RSTRING_EMBED_LEN_MAX) { | ||
| 	    char *ptr = RSTRING(str)->as.heap.ptr; | ||
| 	    STR_SET_EMBED(str); | ||
| 	    if (slen > len) slen = len; | ||
| 	    if (slen > 0) MEMCPY(RSTRING(str)->as.ary, ptr, char, slen); | ||
| 	    RSTRING(str)->as.ary[len] = '\0'; | ||
| 	    STR_SET_EMBED_LEN(str, len); | ||
| 	    if (independent) xfree(ptr); | ||
| 	    return str; | ||
| 	} | ||
| 	else if (!independent) { | ||
| 	    str_make_independent_expand(str, len - slen); | ||
| 	} | ||
| 	else if (slen < len || slen - len > 1024) { | ||
| 	    REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1); | ||
| 	} | ||
| 	if (!STR_NOCAPA_P(str)) { | ||
| 	    RSTRING(str)->as.heap.aux.capa = len; | ||
| 	} | ||
| 	RSTRING(str)->as.heap.len = len; | ||
| 	RSTRING(str)->as.heap.ptr[len] = '\0';	/* sentinel */ | ||
|   if (STR_EMBED_P(str)) { | ||
|       if (len <= RSTRING_EMBED_LEN_MAX) { | ||
|     STR_SET_EMBED_LEN(str, len); | ||
|     RSTRING(str)->as.ary[len] = '\0'; | ||
|     return str; | ||
|       } | ||
|       str_make_independent_expand(str, len - slen); | ||
|       STR_SET_NOEMBED(str); | ||
|   } | ||
|   else if (len <= RSTRING_EMBED_LEN_MAX) { | ||
|       char *ptr = RSTRING(str)->as.heap.ptr; | ||
|       STR_SET_EMBED(str); | ||
|       if (slen > len) slen = len; | ||
|       if (slen > 0) MEMCPY(RSTRING(str)->as.ary, ptr, char, slen); | ||
|       RSTRING(str)->as.ary[len] = '\0'; | ||
|       STR_SET_EMBED_LEN(str, len); | ||
|       if (independent) xfree(ptr); | ||
|       return str; | ||
|   } | ||
|   else if (!independent) { | ||
|       str_make_independent_expand(str, len - slen); | ||
|   } | ||
|   else if (slen < len || slen - len > 1024) { | ||
|       REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1); | ||
|   } | ||
|   if (!STR_NOCAPA_P(str)) { | ||
|       RSTRING(str)->as.heap.aux.capa = len; | ||
|   } | ||
|   RSTRING(str)->as.heap.len = len; | ||
|   RSTRING(str)->as.heap.ptr[len] = '\0';  /* sentinel */ | ||
|     } | ||
|     return str; | ||
| } | ||
| ... | ... | |
|     rb_str_modify(str); | ||
|     if (len == 0) return 0; | ||
|     if (STR_ASSOC_P(str)) { | ||
| 	FL_UNSET(str, STR_ASSOC); | ||
| 	capa = RSTRING(str)->as.heap.aux.capa = RSTRING_LEN(str); | ||
|   FL_UNSET(str, STR_ASSOC); | ||
|   capa = RSTRING(str)->as.heap.aux.capa = RSTRING_LEN(str); | ||
|     } | ||
|     else if (STR_EMBED_P(str)) { | ||
| 	capa = RSTRING_EMBED_LEN_MAX; | ||
|   capa = RSTRING_EMBED_LEN_MAX; | ||
|     } | ||
|     else { | ||
| 	capa = RSTRING(str)->as.heap.aux.capa; | ||
|   capa = RSTRING(str)->as.heap.aux.capa; | ||
|     } | ||
|     if (RSTRING_LEN(str) >= LONG_MAX - len) { | ||
| 	rb_raise(rb_eArgError, "string sizes too big"); | ||
|   rb_raise(rb_eArgError, "string sizes too big"); | ||
|     } | ||
|     total = RSTRING_LEN(str)+len; | ||
|     if (capa <= total) { | ||
| 	while (total > capa) { | ||
| 	    if (capa + 1 >= LONG_MAX / 2) { | ||
| 		capa = (total + 4095) / 4096; | ||
| 		break; | ||
| 	    } | ||
| 	    capa = (capa + 1) * 2; | ||
| 	} | ||
| 	RESIZE_CAPA(str, capa); | ||
|   while (total > capa) { | ||
|       if (capa + 1 >= LONG_MAX / 2) { | ||
|     capa = (total + 4095) / 4096; | ||
|     break; | ||
|       } | ||
|       capa = (capa + 1) * 2; | ||
|   } | ||
|   RESIZE_CAPA(str, capa); | ||
|     } | ||
|     if (off != -1) { | ||
|         ptr = RSTRING_PTR(str) + off; | ||
| ... | ... | |
| { | ||
|     if (len == 0) return str; | ||
|     if (len < 0) { | ||
| 	rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|   rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|     } | ||
|     return str_buf_cat(str, ptr, len); | ||
| } | ||
| ... | ... | |
| rb_str_cat(VALUE str, const char *ptr, long len) | ||
| { | ||
|     if (len < 0) { | ||
| 	rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|   rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|     } | ||
|     if (STR_ASSOC_P(str)) { | ||
| 	char *p; | ||
| 	rb_str_modify_expand(str, len); | ||
| 	p = RSTRING(str)->as.heap.ptr; | ||
| 	memcpy(p + RSTRING(str)->as.heap.len, ptr, len); | ||
| 	len = RSTRING(str)->as.heap.len += len; | ||
| 	p[len] = '\0'; /* sentinel */ | ||
| 	return str; | ||
|   char *p; | ||
|   rb_str_modify_expand(str, len); | ||
|   p = RSTRING(str)->as.heap.ptr; | ||
|   memcpy(p + RSTRING(str)->as.heap.len, ptr, len); | ||
|   len = RSTRING(str)->as.heap.len += len; | ||
|   p[len] = '\0'; /* sentinel */ | ||
|   return str; | ||
|     } | ||
|     return rb_str_buf_cat(str, ptr, len); | ||
| ... | ... | |
|             } | ||
|             goto incompatible; | ||
|         } | ||
| 	if (ptr_cr == ENC_CODERANGE_UNKNOWN) { | ||
| 	    ptr_cr = coderange_scan(ptr, len, ptr_enc); | ||
| 	} | ||
|   if (ptr_cr == ENC_CODERANGE_UNKNOWN) { | ||
|       ptr_cr = coderange_scan(ptr, len, ptr_enc); | ||
|   } | ||
|         if (str_cr == ENC_CODERANGE_UNKNOWN) { | ||
|             if (ENCODING_IS_ASCII8BIT(str) || ptr_cr != ENC_CODERANGE_7BIT) { | ||
|                 str_cr = rb_enc_str_coderange(str); | ||
| ... | ... | |
|     } | ||
|     else if (str_cr == ENC_CODERANGE_VALID) { | ||
|         res_encindex = str_encindex; | ||
| 	if (ptr_cr == ENC_CODERANGE_7BIT || ptr_cr == ENC_CODERANGE_VALID) | ||
| 	    res_cr = str_cr; | ||
| 	else | ||
| 	    res_cr = ptr_cr; | ||
|   if (ptr_cr == ENC_CODERANGE_7BIT || ptr_cr == ENC_CODERANGE_VALID) | ||
|       res_cr = str_cr; | ||
|   else | ||
|       res_cr = ptr_cr; | ||
|     } | ||
|     else { /* str_cr == ENC_CODERANGE_BROKEN */ | ||
|         res_encindex = str_encindex; | ||
| ... | ... | |
|     } | ||
|     if (len < 0) { | ||
| 	rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|   rb_raise(rb_eArgError, "negative string size (or size too big)"); | ||
|     } | ||
|     str_buf_cat(str, ptr, len); | ||
|     ENCODING_CODERANGE_SET(str, res_encindex, res_cr); | ||
| ... | ... | |
|     rb_encoding *enc = STR_ENC_GET(str1); | ||
|     if (FIXNUM_P(str2) || RB_TYPE_P(str2, T_BIGNUM)) { | ||
| 	if (rb_num_to_uint(str2, &code) == 0) { | ||
| 	} | ||
| 	else if (FIXNUM_P(str2)) { | ||
| 	    rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(str2)); | ||
| 	} | ||
| 	else { | ||
| 	    rb_raise(rb_eRangeError, "bignum out of char range"); | ||
| 	} | ||
|   if (rb_num_to_uint(str2, &code) == 0) { | ||
|   } | ||
|   else if (FIXNUM_P(str2)) { | ||
|       rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(str2)); | ||
|   } | ||
|   else { | ||
|       rb_raise(rb_eRangeError, "bignum out of char range"); | ||
|   } | ||
|     } | ||
|     else { | ||
| 	return rb_str_append(str1, str2); | ||
|   return rb_str_append(str1, str2); | ||
|     } | ||
|     if (enc == rb_usascii_encoding()) { | ||
| 	/* US-ASCII automatically extended to ASCII-8BIT */ | ||
| 	char buf[1]; | ||
| 	buf[0] = (char)code; | ||
| 	if (code > 0xFF) { | ||
| 	    rb_raise(rb_eRangeError, "%u out of char range", code); | ||
| 	} | ||
| 	rb_str_cat(str1, buf, 1); | ||
| 	if (code > 127) { | ||
| 	    rb_enc_associate(str1, rb_ascii8bit_encoding()); | ||
| 	    ENC_CODERANGE_SET(str1, ENC_CODERANGE_VALID); | ||
| 	} | ||
|   /* US-ASCII automatically extended to ASCII-8BIT */ | ||
|   char buf[1]; | ||
|   buf[0] = (char)code; | ||
|   if (code > 0xFF) { | ||
|       rb_raise(rb_eRangeError, "%u out of char range", code); | ||
|   } | ||
|   rb_str_cat(str1, buf, 1); | ||
|   if (code > 127) { | ||
|       rb_enc_associate(str1, rb_ascii8bit_encoding()); | ||
|       ENC_CODERANGE_SET(str1, ENC_CODERANGE_VALID); | ||
|   } | ||
|     } | ||
|     else { | ||
| 	long pos = RSTRING_LEN(str1); | ||
| 	int cr = ENC_CODERANGE(str1); | ||
| 	int len; | ||
| 	char *buf; | ||
| 	switch (len = rb_enc_codelen(code, enc)) { | ||
| 	  case ONIGERR_INVALID_CODE_POINT_VALUE: | ||
| 	    rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc)); | ||