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));
|