mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
Merge pull request #3649 from rtfeldman/3640-str-split-edge-case
Fix `Str.split` edge case when string and delimiter are equal
This commit is contained in:
commit
66365fba6e
1 changed files with 89 additions and 3 deletions
|
@ -766,7 +766,6 @@ fn strFromFloatHelp(comptime T: type, float: T) RocStr {
|
|||
}
|
||||
|
||||
// Str.split
|
||||
|
||||
pub fn strSplit(string: RocStr, delimiter: RocStr) callconv(.C) RocList {
|
||||
const segment_count = countSegments(string, delimiter);
|
||||
const list = RocList.allocate(@alignOf(RocStr), segment_count, @sizeOf(RocStr));
|
||||
|
@ -790,7 +789,7 @@ fn strSplitHelp(array: [*]RocStr, string: RocStr, delimiter: RocStr) void {
|
|||
const delimiter_bytes_ptrs = delimiter.asU8ptr();
|
||||
const delimiter_len = delimiter.len();
|
||||
|
||||
if (str_len > delimiter_len and delimiter_len > 0) {
|
||||
if (str_len >= delimiter_len and delimiter_len > 0) {
|
||||
const end_index: usize = str_len - delimiter_len + 1;
|
||||
while (str_index <= end_index) {
|
||||
var delimiter_index: usize = 0;
|
||||
|
@ -892,6 +891,46 @@ test "strSplitHelp: no delimiter" {
|
|||
try expect(array[0].eq(expected[0]));
|
||||
}
|
||||
|
||||
test "strSplitHelp: empty start" {
|
||||
const str_arr = "/a";
|
||||
const str = RocStr.init(str_arr, str_arr.len);
|
||||
|
||||
const delimiter_arr = "/";
|
||||
const delimiter = RocStr.init(delimiter_arr, delimiter_arr.len);
|
||||
|
||||
const array_len: usize = 2;
|
||||
var array: [array_len]RocStr = [_]RocStr{
|
||||
undefined,
|
||||
undefined,
|
||||
};
|
||||
const array_ptr: [*]RocStr = &array;
|
||||
|
||||
strSplitHelp(array_ptr, str, delimiter);
|
||||
|
||||
const one = RocStr.init("a", 1);
|
||||
|
||||
var expected = [2]RocStr{
|
||||
RocStr.empty(), one,
|
||||
};
|
||||
|
||||
defer {
|
||||
for (array) |rocStr| {
|
||||
rocStr.deinit();
|
||||
}
|
||||
|
||||
for (expected) |rocStr| {
|
||||
rocStr.deinit();
|
||||
}
|
||||
|
||||
str.deinit();
|
||||
delimiter.deinit();
|
||||
}
|
||||
|
||||
try expectEqual(array.len, expected.len);
|
||||
try expect(array[0].eq(expected[0]));
|
||||
try expect(array[1].eq(expected[1]));
|
||||
}
|
||||
|
||||
test "strSplitHelp: empty end" {
|
||||
const str_arr = "1---- ---- ---- ---- ----2---- ---- ---- ---- ----";
|
||||
const str = RocStr.init(str_arr, str_arr.len);
|
||||
|
@ -935,6 +974,38 @@ test "strSplitHelp: empty end" {
|
|||
try expect(array[2].eq(expected[2]));
|
||||
}
|
||||
|
||||
test "strSplitHelp: string equals delimiter" {
|
||||
const str_delimiter_arr = "/";
|
||||
const str_delimiter = RocStr.init(str_delimiter_arr, str_delimiter_arr.len);
|
||||
|
||||
const array_len: usize = 2;
|
||||
var array: [array_len]RocStr = [_]RocStr{
|
||||
undefined,
|
||||
undefined,
|
||||
};
|
||||
const array_ptr: [*]RocStr = &array;
|
||||
|
||||
strSplitHelp(array_ptr, str_delimiter, str_delimiter);
|
||||
|
||||
var expected = [2]RocStr{ RocStr.empty(), RocStr.empty() };
|
||||
|
||||
defer {
|
||||
for (array) |rocStr| {
|
||||
rocStr.deinit();
|
||||
}
|
||||
|
||||
for (expected) |rocStr| {
|
||||
rocStr.deinit();
|
||||
}
|
||||
|
||||
str_delimiter.deinit();
|
||||
}
|
||||
|
||||
try expectEqual(array.len, expected.len);
|
||||
try expect(array[0].eq(expected[0]));
|
||||
try expect(array[1].eq(expected[1]));
|
||||
}
|
||||
|
||||
test "strSplitHelp: delimiter on sides" {
|
||||
const str_arr = "tttghittt";
|
||||
const str = RocStr.init(str_arr, str_arr.len);
|
||||
|
@ -1031,7 +1102,7 @@ pub fn countSegments(string: RocStr, delimiter: RocStr) callconv(.C) usize {
|
|||
|
||||
var count: usize = 1;
|
||||
|
||||
if (str_len > delimiter_len and delimiter_len > 0) {
|
||||
if (str_len >= delimiter_len and delimiter_len > 0) {
|
||||
var str_index: usize = 0;
|
||||
const end_cond: usize = str_len - delimiter_len + 1;
|
||||
|
||||
|
@ -1119,6 +1190,21 @@ test "countSegments: delimiter interspered" {
|
|||
try expectEqual(segments_count, 3);
|
||||
}
|
||||
|
||||
test "countSegments: string equals delimiter" {
|
||||
// Str.split "/" "/" == ["", ""]
|
||||
// 2 segments
|
||||
const str_delimiter_arr = "/";
|
||||
const str_delimiter = RocStr.init(str_delimiter_arr, str_delimiter_arr.len);
|
||||
|
||||
defer {
|
||||
str_delimiter.deinit();
|
||||
}
|
||||
|
||||
const segments_count = countSegments(str_delimiter, str_delimiter);
|
||||
|
||||
try expectEqual(segments_count, 2);
|
||||
}
|
||||
|
||||
// Str.countGraphemeClusters
|
||||
const grapheme = @import("helpers/grapheme.zig");
|
||||
pub fn countGraphemeClusters(string: RocStr) callconv(.C) usize {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue