diff options
Diffstat (limited to 'src/string.c')
| -rw-r--r-- | src/string.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/src/string.c b/src/string.c index 742046361..6fdb7fe72 100644 --- a/src/string.c +++ b/src/string.c @@ -478,15 +478,14 @@ str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) return str_subseq(mrb, str, beg, len); } -static mrb_int -str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) +MRB_API mrb_int +mrb_str_index(mrb_state *mrb, mrb_value str, const char *sptr, mrb_int slen, mrb_int offset) { mrb_int pos; - char *s, *sptr; - mrb_int len, slen; + char *s; + mrb_int len; len = RSTRING_LEN(str); - slen = RSTRING_LEN(sub); if (offset < 0) { offset += len; if (offset < 0) return -1; @@ -498,14 +497,24 @@ str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) } if (slen == 0) return offset; /* need proceed one character at a time */ - sptr = RSTRING_PTR(sub); - slen = RSTRING_LEN(sub); len = RSTRING_LEN(str) - offset; pos = mrb_memsearch(sptr, slen, s, len); if (pos < 0) return pos; return pos + offset; } +static mrb_int +str_index_str(mrb_state *mrb, mrb_value str, mrb_value str2, mrb_int offset) +{ + const char *ptr; + mrb_int len; + + ptr = RSTRING_PTR(str2); + len = RSTRING_LEN(str2); + + return mrb_str_index(mrb, str, ptr, len, offset); +} + static void check_frozen(mrb_state *mrb, struct RString *s) { @@ -520,9 +529,9 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) long len; check_frozen(mrb, s1); + if (s1 == s2) return mrb_obj_value(s1); s1->flags &= ~MRB_STR_NO_UTF; s1->flags |= s2->flags&MRB_STR_NO_UTF; - if (s1 == s2) return mrb_obj_value(s1); len = RSTR_LEN(s2); if (RSTR_SHARED_P(s1)) { str_decref(mrb, s1->as.heap.aux.shared); @@ -685,13 +694,20 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) p = RSTR_PTR(s); len = s->as.heap.len; - ptr = (char *)mrb_malloc(mrb, (size_t)len + 1); + if (len < RSTRING_EMBED_LEN_MAX) { + RSTR_SET_EMBED_FLAG(s); + RSTR_SET_EMBED_LEN(s, len); + ptr = RSTR_PTR(s); + } + else { + ptr = (char *)mrb_malloc(mrb, (size_t)len + 1); + s->as.heap.ptr = ptr; + s->as.heap.aux.capa = len; + } if (p) { memcpy(ptr, p, len); } ptr[len] = '\0'; - s->as.heap.ptr = ptr; - s->as.heap.aux.capa = len; str_decref(mrb, shared); } RSTR_UNSET_SHARED_FLAG(s); @@ -1089,7 +1105,7 @@ num_index: return str; case MRB_TT_STRING: - if (str_index(mrb, str, indx, 0) != -1) + if (str_index_str(mrb, str, indx, 0) != -1) return mrb_str_dup(mrb, indx); return mrb_nil_value(); @@ -1514,13 +1530,13 @@ mrb_str_hash(mrb_state *mrb, mrb_value str) struct RString *s = mrb_str_ptr(str); mrb_int len = RSTR_LEN(s); char *p = RSTR_PTR(s); - mrb_int key = 0; + uint64_t key = 0; while (len--) { key = key*65599 + *p; p++; } - return key + (key>>5); + return (mrb_int)(key + (key>>5)); } /* 15.2.10.5.20 */ @@ -1556,7 +1572,7 @@ mrb_str_include(mrb_state *mrb, mrb_value self) mrb_value str2; mrb_get_args(mrb, "S", &str2); - if (str_index(mrb, self, str2, 0) < 0) + if (str_index_str(mrb, self, str2, 0) < 0) return mrb_bool_value(FALSE); return mrb_bool_value(TRUE); } @@ -1583,14 +1599,14 @@ mrb_str_include(mrb_state *mrb, mrb_value self) * "hello".index(/[aeiou]/, -3) #=> 4 */ static mrb_value -mrb_str_index(mrb_state *mrb, mrb_value str) +mrb_str_index_m(mrb_state *mrb, mrb_value str) { mrb_value *argv; mrb_int argc; mrb_value sub; mrb_int pos, clen; - mrb_get_args(mrb, "*", &argv, &argc); + mrb_get_args(mrb, "*!", &argv, &argc); if (argc == 2) { mrb_get_args(mrb, "oi", &sub, &pos); } @@ -1624,7 +1640,7 @@ mrb_str_index(mrb_state *mrb, mrb_value str) } /* fall through */ case MRB_TT_STRING: - pos = str_index(mrb, str, sub, pos); + pos = str_index_str(mrb, str, sub, pos); break; } @@ -1861,7 +1877,7 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str) mrb_value sub; mrb_int pos, len = RSTRING_CHAR_LEN(str); - mrb_get_args(mrb, "*", &argv, &argc); + mrb_get_args(mrb, "*!", &argv, &argc); if (argc == 2) { mrb_get_args(mrb, "oi", &sub, &pos); if (pos < 0) { @@ -1954,10 +1970,11 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) int argc; mrb_value spat = mrb_nil_value(); enum {awk, string, regexp} split_type = string; - long i = 0, lim_p; + mrb_int i = 0; mrb_int beg; mrb_int end; mrb_int lim = 0; + mrb_bool lim_p; mrb_value result, tmp; argc = mrb_get_args(mrb, "|oi", &spat, &lim); @@ -2744,7 +2761,7 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "hash", mrb_str_hash_m, MRB_ARGS_NONE()); /* 15.2.10.5.20 */ mrb_define_method(mrb, s, "include?", mrb_str_include, MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */ - mrb_define_method(mrb, s, "index", mrb_str_index, MRB_ARGS_ANY()); /* 15.2.10.5.22 */ + mrb_define_method(mrb, s, "index", mrb_str_index_m, MRB_ARGS_ANY()); /* 15.2.10.5.22 */ mrb_define_method(mrb, s, "initialize", mrb_str_init, MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */ mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */ mrb_define_method(mrb, s, "intern", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.25 */ |
