Skip to content

Commit a2e2e83

Browse files
committed
string.c: move String#bytesplice to the core
1 parent 12e232c commit a2e2e83

File tree

4 files changed

+145
-144
lines changed

4 files changed

+145
-144
lines changed

mrbgems/mruby-string-ext/src/string.c

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,86 +1278,6 @@ mrb_str_uminus(mrb_state *mrb, mrb_value str)
12781278
return mrb_obj_freeze(mrb, mrb_str_dup(mrb, str));
12791279
}
12801280

1281-
static mrb_value
1282-
str_bytesplice(mrb_state *mrb, mrb_value str, mrb_int idx1, mrb_int len1, mrb_value replace, mrb_int idx2, mrb_int len2)
1283-
{
1284-
struct RString *s = RSTRING(str);
1285-
if (RSTR_LEN(s) <= idx1 || RSTRING_LEN(replace) <= idx2) {
1286-
mrb_raise(mrb, E_INDEX_ERROR, "index out of string");
1287-
}
1288-
if (RSTR_LEN(s) <= idx1+len1) {
1289-
len1 = RSTR_LEN(s) - idx1;
1290-
}
1291-
if (RSTRING_LEN(replace) <= idx2+len2) {
1292-
len2 = RSTRING_LEN(replace) - idx2;
1293-
}
1294-
if (len2 == 0) return replace;
1295-
mrb_str_modify(mrb, s);
1296-
if (len1 >= len2) {
1297-
memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);
1298-
if (len1 > len2) {
1299-
memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, RSTR_LEN(s)-(idx1+len1));
1300-
RSTR_SET_LEN(s, RSTR_LEN(s)-(len1-len2));
1301-
}
1302-
}
1303-
else { /* len1 < len2 */
1304-
mrb_int slen = RSTR_LEN(s);
1305-
mrb_str_resize(mrb, str, slen+len2-len1);
1306-
memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, slen-(idx1+len1));
1307-
memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);
1308-
}
1309-
return replace;
1310-
}
1311-
1312-
/*
1313-
* call-seq:
1314-
* bytesplice(index, length, str) -> string
1315-
* bytesplice(index, length, str, str_index, str_length) -> string
1316-
* bytesplice(range, str) -> string
1317-
* bytesplice(range, str, str_range) -> string
1318-
*
1319-
* Replaces some or all of the content of +self+ with +str+, and returns +self+.
1320-
* The portion of the string affected is determined using
1321-
* the same criteria as String#byteslice, except that +length+ cannot be omitted.
1322-
* If the replacement string is not the same length as the text it is replacing,
1323-
* the string will be adjusted accordingly.
1324-
*
1325-
* If +str_index+ and +str_length+, or +str_range+ are given, the content of +self+ is replaced by str.byteslice(str_index, str_length) or str.byteslice(str_range); however the substring of +str+ is not allocated as a new string.
1326-
*
1327-
* The form that take an Integer will raise an IndexError if the value is out
1328-
* of range; the Range form will raise a RangeError.
1329-
* If the beginning or ending offset does not land on character (codepoint)
1330-
* boundary, an IndexError will be raised.
1331-
*/
1332-
static mrb_value
1333-
mrb_str_bytesplice(mrb_state *mrb, mrb_value str)
1334-
{
1335-
mrb_int idx1, len1, idx2, len2;
1336-
mrb_value range1, range2, replace;
1337-
switch (mrb_get_argc(mrb)) {
1338-
case 3:
1339-
mrb_get_args(mrb, "ooo", &range1, &replace, &range2);
1340-
if (mrb_integer_p(range1)) {
1341-
mrb_get_args(mrb, "iiS", &idx1, &len1, &replace);
1342-
return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));
1343-
}
1344-
if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) != MRB_RANGE_OK) break;
1345-
if (mrb_range_beg_len(mrb, range2, &idx2, &len2, RSTRING_LEN(replace), FALSE) != MRB_RANGE_OK) break;
1346-
return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);
1347-
case 5:
1348-
mrb_get_args(mrb, "iiSii", &idx1, &len1, &replace, &idx2, &len2);
1349-
return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);
1350-
case 2:
1351-
mrb_get_args(mrb, "oS", &range1, &replace);
1352-
if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) == MRB_RANGE_OK) {
1353-
return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));
1354-
}
1355-
default:
1356-
break;
1357-
}
1358-
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arumgnts");
1359-
}
1360-
13611281
void
13621282
mrb_mruby_string_ext_gem_init(mrb_state* mrb)
13631283
{
@@ -1395,7 +1315,6 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb)
13951315
mrb_define_method(mrb, s, "casecmp?", mrb_str_casecmp_p, MRB_ARGS_REQ(1));
13961316
mrb_define_method(mrb, s, "+@", mrb_str_uplus, MRB_ARGS_REQ(1));
13971317
mrb_define_method(mrb, s, "-@", mrb_str_uminus, MRB_ARGS_REQ(1));
1398-
mrb_define_method(mrb, s, "bytesplice", mrb_str_bytesplice, MRB_ARGS_ANY());
13991318

14001319
mrb_define_method(mrb, s, "__lines", mrb_str_lines, MRB_ARGS_NONE());
14011320

mrbgems/mruby-string-ext/test/string.rb

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -726,66 +726,3 @@ def assert_upto(exp, receiver, *args)
726726
a = -(a.freeze)
727727
assert_true(a.frozen?)
728728
end
729-
730-
assert('String#bytesplice') do
731-
# range, replace (len1=len2)
732-
a = "0123456789"
733-
assert_equal "ab", a.bytesplice(1..2, "ab")
734-
assert_equal "0ab3456789", a
735-
736-
# range, replace (len1>len2)
737-
a = "0123456789"
738-
assert_equal "ab", a.bytesplice(1..3, "ab")
739-
assert_equal "0ab456789", a
740-
741-
# range, replace (len1<len2)
742-
a = "0123456789"
743-
assert_equal "ab", a.bytesplice(1..1, "ab")
744-
assert_equal "0ab23456789", a
745-
746-
# idx, len, replace (len1=len2)
747-
a = "0123456789"
748-
assert_equal "ab", a.bytesplice(1, 2, "ab")
749-
assert_equal "0ab3456789", a
750-
751-
# idx, len, replace (len1>len2)
752-
a = "0123456789"
753-
assert_equal "ab", a.bytesplice(1, 3, "ab")
754-
assert_equal "0ab456789", a
755-
756-
# idx, len, replace (len1<len2)
757-
a = "0123456789"
758-
assert_equal "ab", a.bytesplice(1, 1, "ab")
759-
assert_equal "0ab23456789", a
760-
761-
b = "abcdefg"
762-
# range, replace, range (len1=len2)
763-
a = "0123456789"
764-
assert_equal b, a.bytesplice(1..2, b, 0..1)
765-
assert_equal "0ab3456789", a
766-
767-
# range, replace, range (len1>len2)
768-
a = "0123456789"
769-
assert_equal b, a.bytesplice(1..3, b, 1..2)
770-
assert_equal "0bc456789", a
771-
772-
# range, replace, range (len1<len2)
773-
a = "0123456789"
774-
assert_equal b, a.bytesplice(1..1, b, 2..3)
775-
assert_equal "0cd23456789", a
776-
777-
# idx, len, replace, idx, len (len1=len2)
778-
a = "0123456789"
779-
assert_equal b, a.bytesplice(1, 2, b, 0, 2)
780-
assert_equal "0ab3456789", a
781-
782-
# idx, len, replace, idx, len (len1>len2)
783-
a = "0123456789"
784-
assert_equal b, a.bytesplice(1, 3, b, 1, 2)
785-
assert_equal "0bc456789", a
786-
787-
# idx, len, replace, idx, len (len1<len2)
788-
a = "0123456789"
789-
assert_equal b, a.bytesplice(1, 1, b, 2, 2)
790-
assert_equal "0cd23456789", a
791-
end

src/string.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2945,6 +2945,87 @@ sub_replace(mrb_state *mrb, mrb_value self)
29452945
return result;
29462946
}
29472947

2948+
2949+
static mrb_value
2950+
str_bytesplice(mrb_state *mrb, mrb_value str, mrb_int idx1, mrb_int len1, mrb_value replace, mrb_int idx2, mrb_int len2)
2951+
{
2952+
struct RString *s = RSTRING(str);
2953+
if (RSTR_LEN(s) <= idx1 || RSTRING_LEN(replace) <= idx2) {
2954+
mrb_raise(mrb, E_INDEX_ERROR, "index out of string");
2955+
}
2956+
if (RSTR_LEN(s) <= idx1+len1) {
2957+
len1 = RSTR_LEN(s) - idx1;
2958+
}
2959+
if (RSTRING_LEN(replace) <= idx2+len2) {
2960+
len2 = RSTRING_LEN(replace) - idx2;
2961+
}
2962+
if (len2 == 0) return replace;
2963+
mrb_str_modify(mrb, s);
2964+
if (len1 >= len2) {
2965+
memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);
2966+
if (len1 > len2) {
2967+
memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, RSTR_LEN(s)-(idx1+len1));
2968+
RSTR_SET_LEN(s, RSTR_LEN(s)-(len1-len2));
2969+
}
2970+
}
2971+
else { /* len1 < len2 */
2972+
mrb_int slen = RSTR_LEN(s);
2973+
mrb_str_resize(mrb, str, slen+len2-len1);
2974+
memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, slen-(idx1+len1));
2975+
memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);
2976+
}
2977+
return replace;
2978+
}
2979+
2980+
/*
2981+
* call-seq:
2982+
* bytesplice(index, length, str) -> string
2983+
* bytesplice(index, length, str, str_index, str_length) -> string
2984+
* bytesplice(range, str) -> string
2985+
* bytesplice(range, str, str_range) -> string
2986+
*
2987+
* Replaces some or all of the content of +self+ with +str+, and returns +self+.
2988+
* The portion of the string affected is determined using
2989+
* the same criteria as String#byteslice, except that +length+ cannot be omitted.
2990+
* If the replacement string is not the same length as the text it is replacing,
2991+
* the string will be adjusted accordingly.
2992+
*
2993+
* If +str_index+ and +str_length+, or +str_range+ are given, the content of +self+ is replaced by str.byteslice(str_index, str_length) or str.byteslice(str_range); however the substring of +str+ is not allocated as a new string.
2994+
*
2995+
* The form that take an Integer will raise an IndexError if the value is out
2996+
* of range; the Range form will raise a RangeError.
2997+
* If the beginning or ending offset does not land on character (codepoint)
2998+
* boundary, an IndexError will be raised.
2999+
*/
3000+
static mrb_value
3001+
mrb_str_bytesplice(mrb_state *mrb, mrb_value str)
3002+
{
3003+
mrb_int idx1, len1, idx2, len2;
3004+
mrb_value range1, range2, replace;
3005+
switch (mrb_get_argc(mrb)) {
3006+
case 3:
3007+
mrb_get_args(mrb, "ooo", &range1, &replace, &range2);
3008+
if (mrb_integer_p(range1)) {
3009+
mrb_get_args(mrb, "iiS", &idx1, &len1, &replace);
3010+
return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));
3011+
}
3012+
if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) != MRB_RANGE_OK) break;
3013+
if (mrb_range_beg_len(mrb, range2, &idx2, &len2, RSTRING_LEN(replace), FALSE) != MRB_RANGE_OK) break;
3014+
return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);
3015+
case 5:
3016+
mrb_get_args(mrb, "iiSii", &idx1, &len1, &replace, &idx2, &len2);
3017+
return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);
3018+
case 2:
3019+
mrb_get_args(mrb, "oS", &range1, &replace);
3020+
if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) == MRB_RANGE_OK) {
3021+
return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));
3022+
}
3023+
default:
3024+
break;
3025+
}
3026+
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arumgnts");
3027+
}
3028+
29483029
/* ---------------------------*/
29493030
void
29503031
mrb_init_string(mrb_state *mrb)
@@ -3008,6 +3089,7 @@ mrb_init_string(mrb_state *mrb)
30083089
mrb_define_method(mrb, s, "byteindex", mrb_str_byteindex_m, MRB_ARGS_ARG(1,1));
30093090
mrb_define_method(mrb, s, "byterindex", mrb_str_byterindex_m, MRB_ARGS_ARG(1,1));
30103091
mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_ARG(1,1));
3092+
mrb_define_method(mrb, s, "bytesplice", mrb_str_bytesplice, MRB_ARGS_ANY());
30113093

30123094
mrb_define_method(mrb, s, "__sub_replace", sub_replace, MRB_ARGS_REQ(3)); /* internal */
30133095
}

test/t/string.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,3 +898,66 @@
898898
assert_equal("o", str1.byteslice(4.0))
899899
assert_equal("\x82ab", str2.byteslice(2.0, 3.0))
900900
end
901+
902+
assert('String#bytesplice') do
903+
# range, replace (len1=len2)
904+
a = "0123456789"
905+
assert_equal "ab", a.bytesplice(1..2, "ab")
906+
assert_equal "0ab3456789", a
907+
908+
# range, replace (len1>len2)
909+
a = "0123456789"
910+
assert_equal "ab", a.bytesplice(1..3, "ab")
911+
assert_equal "0ab456789", a
912+
913+
# range, replace (len1<len2)
914+
a = "0123456789"
915+
assert_equal "ab", a.bytesplice(1..1, "ab")
916+
assert_equal "0ab23456789", a
917+
918+
# idx, len, replace (len1=len2)
919+
a = "0123456789"
920+
assert_equal "ab", a.bytesplice(1, 2, "ab")
921+
assert_equal "0ab3456789", a
922+
923+
# idx, len, replace (len1>len2)
924+
a = "0123456789"
925+
assert_equal "ab", a.bytesplice(1, 3, "ab")
926+
assert_equal "0ab456789", a
927+
928+
# idx, len, replace (len1<len2)
929+
a = "0123456789"
930+
assert_equal "ab", a.bytesplice(1, 1, "ab")
931+
assert_equal "0ab23456789", a
932+
933+
b = "abcdefg"
934+
# range, replace, range (len1=len2)
935+
a = "0123456789"
936+
assert_equal b, a.bytesplice(1..2, b, 0..1)
937+
assert_equal "0ab3456789", a
938+
939+
# range, replace, range (len1>len2)
940+
a = "0123456789"
941+
assert_equal b, a.bytesplice(1..3, b, 1..2)
942+
assert_equal "0bc456789", a
943+
944+
# range, replace, range (len1<len2)
945+
a = "0123456789"
946+
assert_equal b, a.bytesplice(1..1, b, 2..3)
947+
assert_equal "0cd23456789", a
948+
949+
# idx, len, replace, idx, len (len1=len2)
950+
a = "0123456789"
951+
assert_equal b, a.bytesplice(1, 2, b, 0, 2)
952+
assert_equal "0ab3456789", a
953+
954+
# idx, len, replace, idx, len (len1>len2)
955+
a = "0123456789"
956+
assert_equal b, a.bytesplice(1, 3, b, 1, 2)
957+
assert_equal "0bc456789", a
958+
959+
# idx, len, replace, idx, len (len1<len2)
960+
a = "0123456789"
961+
assert_equal b, a.bytesplice(1, 1, b, 2, 2)
962+
assert_equal "0cd23456789", a
963+
end

0 commit comments

Comments
 (0)