summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'string.c')
-rw-r--r--string.c183
1 files changed, 74 insertions, 109 deletions
diff --git a/string.c b/string.c
index e8afb55ff02..4d7928ff403 100644
--- a/string.c
+++ b/string.c
@@ -35,7 +35,7 @@ extern VALUE rb_rs;
VALUE
rb_str_new(ptr, len)
- char *ptr;
+ const char *ptr;
int len;
{
NEWOBJ(str, struct RString);
@@ -54,14 +54,14 @@ rb_str_new(ptr, len)
VALUE
rb_str_new2(ptr)
- char *ptr;
+ const char *ptr;
{
return rb_str_new(ptr, strlen(ptr));
}
VALUE
rb_tainted_str_new(ptr, len)
- char *ptr;
+ const char *ptr;
int len;
{
VALUE str = rb_str_new(ptr, len);
@@ -72,7 +72,7 @@ rb_tainted_str_new(ptr, len)
VALUE
rb_tainted_str_new2(ptr)
- char *ptr;
+ const char *ptr;
{
VALUE str = rb_str_new2(ptr);
@@ -300,61 +300,32 @@ rb_str_format(str, arg)
}
VALUE
-rb_str_substr(str, start, len)
+rb_str_substr(str, beg, len)
VALUE str;
- int start, len;
+ int beg, len;
{
VALUE str2;
- if (len == 0) return rb_str_new(0,0);
- if (len < 0) {
- rb_raise(rb_eIndexError, "negative length %d", len);
- }
- if (start < 0) {
- start = RSTRING(str)->len + start;
+ if (len < 0) return Qnil;
+ if (beg > RSTRING(str)->len) return Qnil;
+ if (beg < 0) {
+ beg += RSTRING(str)->len;
+ if (beg < 0) return Qnil;
}
- if (RSTRING(str)->len <= start) {
- return rb_str_new(0,0);
+ if (beg + len > RSTRING(str)->len) {
+ len = RSTRING(str)->len - beg;
}
- if (RSTRING(str)->len < start + len) {
- len = RSTRING(str)->len - start;
+ if (len < 0) {
+ len = 0;
}
+ if (len == 0) return rb_str_new(0,0);
- str2 = rb_str_new(RSTRING(str)->ptr+start, len);
+ str2 = rb_str_new(RSTRING(str)->ptr+beg, len);
if (OBJ_TAINTED(str)) OBJ_TAINT(str2);
return str2;
}
-static VALUE
-rb_str_subseq(str, beg, end)
- VALUE str;
- int beg, end;
-{
- int b, e, len;
-
- b = beg; e = end;
- if (beg < 0) {
- beg = RSTRING(str)->len + beg;
- }
- if (end < 0) {
- end = RSTRING(str)->len + end;
- }
- if (beg > end) {
- if (e != -1) {
- rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", b, e);
- }
- return rb_str_new(0, 0);
- }
-
- if (beg >= RSTRING(str)->len) {
- len = 0;
- }
-
- len = end - beg + 1;
- return rb_str_substr(str, beg, len);
-}
-
void
rb_str_modify(str)
VALUE str;
@@ -424,7 +395,7 @@ rb_str_resize(str, len)
VALUE
rb_str_cat(str, ptr, len)
VALUE str;
- char *ptr;
+ const char *ptr;
int len;
{
if (len > 0) {
@@ -572,11 +543,16 @@ rb_str_index(str, sub, offset)
char *s, *e, *p;
int len;
+ if (offset < 0) {
+ offset += RSTRING(str)->len;
+ if (offset < 0) return -1;
+ }
if (RSTRING(str)->len - offset < RSTRING(sub)->len) return -1;
s = RSTRING(str)->ptr+offset;
p = RSTRING(sub)->ptr;
len = RSTRING(sub)->len;
- e = s + RSTRING(str)->len - len + 1;
+ if (len == 0) return offset;
+ e = RSTRING(str)->ptr + RSTRING(str)->len - len + 1;
while (s < e) {
if (*s == *(RSTRING(sub)->ptr) && memcmp(s, p, len) == 0) {
return (s-(RSTRING(str)->ptr));
@@ -761,20 +737,20 @@ rb_str_succ_bang(str)
}
VALUE
-rb_str_upto(beg, end)
+rb_str_upto(beg, end, excl)
VALUE beg, end;
+ int excl;
{
VALUE current;
if (TYPE(end) != T_STRING) end = rb_str_to_str(end);
- if (RTEST(rb_funcall(beg, '>', 1, end)))
- return Qnil;
current = beg;
for (;;) {
rb_yield(current);
- if (rb_str_equal(current, end)) break;
+ if (!excl && rb_str_equal(current, end)) break;
current = rb_str_succ(current);
+ if (excl && rb_str_equal(current, end)) break;
if (RSTRING(current)->len > RSTRING(end)->len)
break;
}
@@ -783,6 +759,13 @@ rb_str_upto(beg, end)
}
static VALUE
+rb_str_upto_method(beg, end)
+ VALUE beg, end;
+{
+ return rb_str_upto(beg, end, 0);
+}
+
+static VALUE
rb_str_aref(str, indx)
VALUE str;
VALUE indx;
@@ -813,9 +796,14 @@ rb_str_aref(str, indx)
default:
/* check if indx is Range */
{
- int beg, end;
- if (rb_range_beg_end(indx, &beg, &end)) {
- return rb_str_subseq(str, beg, end);
+ int beg, len;
+ switch (rb_range_beg_len(indx, &beg, &len, RSTRING(str)->len, 0)) {
+ case Qfalse:
+ break;
+ case Qnil:
+ return Qnil;
+ default:
+ return rb_str_substr(str, beg, len);
}
}
rb_raise(rb_eIndexError, "invalid index for string");
@@ -861,37 +849,6 @@ rb_str_replace(str, beg, len, val)
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
}
-/* rb_str_replace2() understands negative offset */
-static void
-rb_str_replace2(str, beg, end, val)
- VALUE str, val;
- int beg, end;
-{
- int b, e, len;
-
- b = beg; e = end;
- if (beg < 0) {
- beg = RSTRING(str)->len + beg;
- }
- if (end < 0) {
- end = RSTRING(str)->len + end;
- }
- if (beg > end) {
- if (e != -1) {
- rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", b, e);
- }
- end = beg - 1;
- }
- if (beg >= RSTRING(str)->len) {
- beg = RSTRING(str)->len;
- len = 0;
- }
- else {
- len = end - beg + 1;
- }
- rb_str_replace(str, beg, len, val);
-}
-
static VALUE rb_str_sub_bang _((int, VALUE*, VALUE));
static VALUE
@@ -904,19 +861,23 @@ rb_str_aset(str, indx, val)
switch (TYPE(indx)) {
case T_FIXNUM:
- idx = NUM2INT(indx);
+ beg = idx = NUM2INT(indx);
if (idx < 0) {
- idx = RSTRING(str)->len + idx;
+ idx += RSTRING(str)->len;
}
- if (idx < 0 || RSTRING(str)->len <= idx) {
- rb_raise(rb_eIndexError, "index %d out of range [0..%d]", idx,
- RSTRING(str)->len - 1);
+ if (idx < 0 || RSTRING(str)->len < idx) {
+ rb_raise(rb_eIndexError, "index %d out of string", NUM2INT(beg));
}
- if (TYPE(val) == T_STRING) {
- rb_str_replace(str, idx, 1, val);
+ if (FIXNUM_P(val)) {
+ if (RSTRING(str)->len == idx) {
+ RSTRING(str)->len += 1;
+ REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len);
+ }
+ RSTRING(str)->ptr[idx] = NUM2INT(val) & 0xff;
}
else {
- RSTRING(str)->ptr[idx] = NUM2INT(val) & 0xff;
+ if (TYPE(val) != T_STRING) val = rb_str_to_str(val);
+ rb_str_replace(str, idx, 1, val);
}
return val;
@@ -932,18 +893,18 @@ rb_str_aset(str, indx, val)
case T_STRING:
beg = rb_str_index(str, indx, 0);
if (beg != -1) {
- end = beg + RSTRING(indx)->len - 1;
- rb_str_replace2(str, beg, end, val);
+ if (TYPE(val) != T_STRING) val = rb_str_to_str(val);
+ rb_str_replace(str, beg, RSTRING(indx)->len, val);
}
return val;
default:
/* check if indx is Range */
{
- int beg, end;
- if (rb_range_beg_end(indx, &beg, &end)) {
+ int beg, len;
+ if (rb_range_beg_len(indx, &beg, &len, RSTRING(str)->len, 2)) {
if (TYPE(val) != T_STRING) val = rb_str_to_str(val);
- rb_str_replace2(str, beg, end, val);
+ rb_str_replace(str, beg, len, val);
return val;
}
}
@@ -962,17 +923,21 @@ rb_str_aset_method(argc, argv, str)
rb_str_modify(str);
if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
- int beg;
- int len;
+ int beg, len;
if (TYPE(arg3) != T_STRING) arg3 = rb_str_to_str(arg3);
beg = NUM2INT(arg1);
- if (beg < 0) {
- beg = RSTRING(str)->len + beg;
- if (beg < 0) beg = 0;
- }
len = NUM2INT(arg2);
if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len);
+ if (beg < 0) {
+ beg += RSTRING(str)->len;
+ }
+ if (beg < 0 || RSTRING(str)->len < beg) {
+ if (beg < 0) {
+ beg -= RSTRING(str)->len;
+ }
+ rb_raise(rb_eIndexError, "index %d out of string", beg);
+ }
if (beg + len > RSTRING(str)->len) {
len = RSTRING(str)->len - beg;
}
@@ -2069,14 +2034,14 @@ rb_str_split_method(argc, argv, str)
if (BEG(idx) == END(idx))
tmp = rb_str_new(0, 0);
else
- tmp = rb_str_subseq(str, BEG(idx), END(idx)-1);
+ tmp = rb_str_substr(str, BEG(idx), END(idx)-BEG(idx));
rb_ary_push(result, tmp);
}
if (!NIL_P(limit) && lim <= ++i) break;
}
}
if (!NIL_P(limit) || RSTRING(str)->len > beg || lim < 0) {
- rb_ary_push(result, rb_str_subseq(str, beg, -1));
+ rb_ary_push(result, rb_str_substr(str, beg, RSTRING(str)->len-beg));
}
if (NIL_P(limit) && lim == 0) {
while (RARRAY(result)->len > 0 &&
@@ -2090,7 +2055,7 @@ rb_str_split_method(argc, argv, str)
VALUE
rb_str_split(str, sep0)
VALUE str;
- char *sep0;
+ const char *sep0;
{
VALUE sep;
@@ -2579,7 +2544,7 @@ Init_String()
rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0);
rb_define_method(rb_cString, "next", rb_str_succ, 0);
rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0);
- rb_define_method(rb_cString, "upto", rb_str_upto, 1);
+ rb_define_method(rb_cString, "upto", rb_str_upto_method, 1);
rb_define_method(rb_cString, "index", rb_str_index_method, -1);
rb_define_method(rb_cString, "rindex", rb_str_rindex, -1);
rb_define_method(rb_cString, "replace", rb_str_replace_method, 1);