| ... | @@ -681,7 +681,53 @@ pub const SplitIterator = struct { | ... | @@ -681,7 +681,53 @@ pub const SplitIterator = struct { |
| 681 | | 681 | |
| 682 | /// Naively combines a series of strings with a separator. | 682 | /// Naively combines a series of strings with a separator. |
| 683 | /// Allocates memory for the result, which must be freed by the caller. | 683 | /// Allocates memory for the result, which must be freed by the caller. |
| 684 | pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 { | 684 | pub fn join(allocator: *Allocator, sep: u8, strings: []const []const u8) ![]u8 { |
| | 685 | assert(strings.len >= 1); |
| | 686 | var total_strings_len: usize = strings.len; // 1 sep per string |
| | 687 | { |
| | 688 | var string_i: usize = 0; |
| | 689 | while (string_i < strings.len) : (string_i += 1) { |
| | 690 | const arg = ([]const u8)(strings[string_i]); |
| | 691 | total_strings_len += arg.len; |
| | 692 | } |
| | 693 | } |
| | 694 | |
| | 695 | const buf = try allocator.alloc(u8, total_strings_len); |
| | 696 | errdefer allocator.free(buf); |
| | 697 | |
| | 698 | var buf_index: usize = 0; |
| | 699 | var string_i: usize = 0; |
| | 700 | while (true) { |
| | 701 | const arg = ([]const u8)(strings[string_i]); |
| | 702 | string_i += 1; |
| | 703 | copy(u8, buf[buf_index..], arg); |
| | 704 | buf_index += arg.len; |
| | 705 | if (string_i >= strings.len) break; |
| | 706 | buf[buf_index] = sep; |
| | 707 | buf_index += 1; |
| | 708 | } |
| | 709 | |
| | 710 | return allocator.shrink(u8, buf, buf_index); |
| | 711 | } |
| | 712 | |
| | 713 | test "mem.join" { |
| | 714 | var str: []u8 = try join(debug.global_allocator, ',', [][]const u8{"a", "b", "c"} ); |
| | 715 | errdefer debug.global_allocator.free( str ); |
| | 716 | assert(eql(u8, str, "a,b,c")); |
| | 717 | debug.global_allocator.free( str ); |
| | 718 | |
| | 719 | str = try join(debug.global_allocator, ',', [][]const u8{"a"}); |
| | 720 | assert(eql(u8, str, "a")); |
| | 721 | debug.global_allocator.free( str ); |
| | 722 | |
| | 723 | str = try join(debug.global_allocator, ',', [][]const u8{"a", ([]const u8)(""), "b", ([]const u8)(""), "c"}); |
| | 724 | assert(eql(u8, str, "a,,b,,c")); |
| | 725 | debug.global_allocator.free( str ); |
| | 726 | } |
| | 727 | |
| | 728 | /// Naively combines a series of strings with a separator inline. |
| | 729 | /// Allocates memory for the result, which must be freed by the caller. |
| | 730 | pub fn joinInline(allocator: *Allocator, sep: u8, strings: ...) ![]u8 { |
| 685 | comptime assert(strings.len >= 1); | 731 | comptime assert(strings.len >= 1); |
| 686 | var total_strings_len: usize = strings.len; // 1 sep per string | 732 | var total_strings_len: usize = strings.len; // 1 sep per string |
| 687 | { | 733 | { |
| ... | @@ -703,18 +749,17 @@ pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 { | ... | @@ -703,18 +749,17 @@ pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 { |
| 703 | copy(u8, buf[buf_index..], arg); | 749 | copy(u8, buf[buf_index..], arg); |
| 704 | buf_index += arg.len; | 750 | buf_index += arg.len; |
| 705 | if (string_i >= strings.len) break; | 751 | if (string_i >= strings.len) break; |
| 706 | if (buf[buf_index - 1] != sep) { | 752 | buf[buf_index] = sep; |
| 707 | buf[buf_index] = sep; | 753 | buf_index += 1; |
| 708 | buf_index += 1; | | |
| 709 | } | | |
| 710 | } | 754 | } |
| 711 | | 755 | |
| 712 | return allocator.shrink(u8, buf, buf_index); | 756 | return allocator.shrink(u8, buf, buf_index); |
| 713 | } | 757 | } |
| 714 | | 758 | |
| 715 | test "mem.join" { | 759 | test "mem.joinInline" { |
| 716 | assert(eql(u8, try join(debug.global_allocator, ',', "a", "b", "c"), "a,b,c")); | 760 | assert(eql(u8, try joinInline(debug.global_allocator, ',', "a", "b", "c"), "a,b,c")); |
| 717 | assert(eql(u8, try join(debug.global_allocator, ',', "a"), "a")); | 761 | assert(eql(u8, try joinInline(debug.global_allocator, ',', "a", "b", ([]const u8)(""), "c"), "a,b,,c")); |
| | 762 | assert(eql(u8, try joinInline(debug.global_allocator, ',', "a"), "a")); |
| 718 | } | 763 | } |
| 719 | | 764 | |
| 720 | test "testStringEquality" { | 765 | test "testStringEquality" { |