Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions mrbgems/mruby-encoding/test/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -435,3 +435,33 @@
assert_equal Encoding::UTF_8, "あ".center(3).encoding
end
end

assert('a byte-read string cut in three') do
# `partition` and `rpartition` cut their pieces out of the receiver's bytes,
# so the head and the tail are read the way the receiver was. The middle
# piece is the separator that was handed in and is read the way that was;
# where no separator is found there is none to hand back, and the empty
# pieces stand for places in the receiver instead.
if UTF8STRING
b = "a\xABb".b
bin = Encoding::BINARY
utf = Encoding::UTF_8
assert_equal ["", "a", "\xABb"], b.partition("a")
assert_equal ["a\xAB", "b", ""], b.rpartition("b")
assert_equal [bin, utf, bin], b.partition("a").map { |piece| piece.encoding }
assert_equal [bin, utf, bin], b.rpartition("b").map { |piece| piece.encoding }
assert_true b.partition("a")[2].valid_encoding?
# where the separator is found nowhere, the two empty pieces stand for
# places in the receiver and are read the way it is
assert_equal [bin, bin, bin], b.partition("x").map { |piece| piece.encoding }
assert_equal [bin, bin, bin], b.rpartition("x").map { |piece| piece.encoding }
# an empty separator cuts nothing off either end
assert_equal [bin, utf, bin], b.partition("").map { |piece| piece.encoding }
assert_equal [bin, utf, bin], b.rpartition("").map { |piece| piece.encoding }
# a separator read as bytes hands its own reading to the middle piece alone
assert_equal [utf, bin, utf], "aあb".partition("a".b).map { |piece| piece.encoding }
assert_equal [utf, bin, utf], "aあb".rpartition("b".b).map { |piece| piece.encoding }
# a receiver read as UTF-8 goes on being read that way
assert_equal [utf, utf, utf], "あい".partition("あ").map { |piece| piece.encoding }
end
end
35 changes: 23 additions & 12 deletions mrbgems/mruby-string-ext/src/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -2086,6 +2086,17 @@ str_clear(mrb_state *mrb, mrb_value self)
return self;
}

/* A piece cut out of a string holds nothing but bytes of it, so it is read the
way the string is. An empty piece stands for a place in the string and is
read the same way, having no bytes to say otherwise. */
static mrb_value
str_cut_piece(mrb_state *mrb, mrb_value str, const char *p, mrb_int len)
{
mrb_value piece = mrb_str_new(mrb, p, len);
RSTR_COPY_BINARY_FLAG(mrb_str_ptr(piece), mrb_str_ptr(str));
return piece;
}

/*
* call-seq:
* str.partition(sep) -> [head, sep, tail]
Expand Down Expand Up @@ -2115,8 +2126,8 @@ str_partition(mrb_state *mrb, mrb_value self)
mrb_value result_ary = mrb_ary_new_capa(mrb, 3);

if (sep_len == 0) {
mrb_ary_push(mrb, result_ary, mrb_str_new_lit(mrb, ""));
mrb_ary_push(mrb, result_ary, mrb_str_new_lit(mrb, ""));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, self_ptr, 0));
mrb_ary_push(mrb, result_ary, mrb_str_dup(mrb, sep));
mrb_ary_push(mrb, result_ary, mrb_str_dup(mrb, self));
return result_ary;
}
Expand All @@ -2137,14 +2148,14 @@ str_partition(mrb_state *mrb, mrb_value self)
mrb_int pre_len = found_ptr - self_ptr;
mrb_int post_len = self_len - pre_len - sep_len;

mrb_ary_push(mrb, result_ary, mrb_str_new(mrb, self_ptr, pre_len));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, self_ptr, pre_len));
mrb_ary_push(mrb, result_ary, mrb_str_dup(mrb, sep));
mrb_ary_push(mrb, result_ary, mrb_str_new(mrb, found_ptr + sep_len, post_len));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, found_ptr + sep_len, post_len));
}
else {
mrb_ary_push(mrb, result_ary, mrb_str_dup(mrb, self));
mrb_ary_push(mrb, result_ary, mrb_str_new_lit(mrb, ""));
mrb_ary_push(mrb, result_ary, mrb_str_new_lit(mrb, ""));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, self_ptr, 0));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, self_ptr, 0));
}

return result_ary;
Expand Down Expand Up @@ -2180,8 +2191,8 @@ str_rpartition(mrb_state *mrb, mrb_value self)

if (sep_len == 0) {
mrb_ary_push(mrb, result_ary, mrb_str_dup(mrb, self));
mrb_ary_push(mrb, result_ary, mrb_str_new_lit(mrb, ""));
mrb_ary_push(mrb, result_ary, mrb_str_new_lit(mrb, ""));
mrb_ary_push(mrb, result_ary, mrb_str_dup(mrb, sep));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, self_ptr, 0));
return result_ary;
}

Expand All @@ -2201,13 +2212,13 @@ str_rpartition(mrb_state *mrb, mrb_value self)
mrb_int pre_len = found_ptr - self_ptr;
mrb_int post_len = self_len - pre_len - sep_len;

mrb_ary_push(mrb, result_ary, mrb_str_new(mrb, self_ptr, pre_len));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, self_ptr, pre_len));
mrb_ary_push(mrb, result_ary, mrb_str_dup(mrb, sep));
mrb_ary_push(mrb, result_ary, mrb_str_new(mrb, found_ptr + sep_len, post_len));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, found_ptr + sep_len, post_len));
}
else {
mrb_ary_push(mrb, result_ary, mrb_str_new_lit(mrb, ""));
mrb_ary_push(mrb, result_ary, mrb_str_new_lit(mrb, ""));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, self_ptr, 0));
mrb_ary_push(mrb, result_ary, str_cut_piece(mrb, self, self_ptr, 0));
mrb_ary_push(mrb, result_ary, mrb_str_dup(mrb, self));
}

Expand Down
Loading