authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-07 10:55:23-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-07 10:55:23-05:00
log38a77161949dbae036d4172ceba2f698de9f18a1
treee0146b01b28783cfe52138c982bfd65fffd7bad1
parent130f42274230ed380c730fcc658c565f443be540
signature Commit is signed but in an unrecognized format.

fixups


1 files changed, 35 insertions(+), 70 deletions(-)

std/mem.zig+35-70
...@@ -856,65 +856,31 @@ pub const TokenIterator = struct {...@@ -856,65 +856,31 @@ pub const TokenIterator = struct {
856 }856 }
857};857};
858858
859/// Naively combines a series of strings with a separator.859pub const SplitIterator = struct {
860/// Allocates memory for the result, which must be freed by the caller.860 buffer: []const u8,
861pub fn join(allocator: *Allocator, sep: u8, strings: []const []const u8) ![]u8 {861 index: ?usize,
862 assert(strings.len >= 1);862 delimiter: []const u8,
863 var total_strings_len: usize = strings.len; // 1 sep per string863
864 {864 /// Returns a slice of the next field, or null if splitting is complete.
865 var string_i: usize = 0;865 pub fn next(self: *SplitIterator) ?[]const u8 {
866 while (string_i < strings.len) : (string_i += 1) {866 const start = self.index orelse return null;
867 const arg = ([]const u8)(strings[string_i]);867 const end = if (indexOfPos(u8, self.buffer, start, self.delimiter)) |delim_start| blk: {
868 total_strings_len += arg.len;868 self.index = delim_start + self.delimiter.len;
869 }869 break :blk delim_start;
870 }870 } else blk: {
871871 self.index = null;
872 const buf = try allocator.alloc(u8, total_strings_len);872 break :blk self.buffer.len;
873 errdefer allocator.free(buf);873 };
874874 return self.buffer[start..end];
875 var buf_index: usize = 0;
876 var string_i: usize = 0;
877 while (true) {
878 const arg = ([]const u8)(strings[string_i]);
879 string_i += 1;
880 copy(u8, buf[buf_index..], arg);
881 buf_index += arg.len;
882 if (string_i >= strings.len) break;
883 buf[buf_index] = sep;
884 buf_index += 1;
885 }875 }
886876
887 return allocator.shrink(u8, buf, buf_index);877 /// Returns a slice of the remaining bytes. Does not affect iterator state.
888}878 pub fn rest(self: SplitIterator) []const u8 {
889879 const end = self.buffer.len;
890test "mem.join" {880 const start = self.index orelse end;
891 var str: []u8 = try join(debug.global_allocator, ',', [][]const u8{ "a", "b", "c" });881 return self.buffer[start..end];
892 errdefer debug.global_allocator.free(str);
893 assert(eql(u8, str, "a,b,c"));
894 debug.global_allocator.free(str);
895
896 str = try join(debug.global_allocator, ',', [][]const u8{"a"});
897 assert(eql(u8, str, "a"));
898 debug.global_allocator.free(str);
899
900 str = try join(debug.global_allocator, ',', [][]const u8{ "a", ([]const u8)(""), "b", ([]const u8)(""), "c" });
901 assert(eql(u8, str, "a,,b,,c"));
902 debug.global_allocator.free(str);
903}
904
905/// Naively combines a series of strings with a separator inline.
906/// Allocates memory for the result, which must be freed by the caller.
907pub fn joinInline(allocator: *Allocator, sep: u8, strings: ...) ![]u8 {
908 comptime assert(strings.len >= 1);
909 var total_strings_len: usize = strings.len; // 1 sep per string
910 {
911 comptime var string_i = 0;
912 inline while (string_i < strings.len) : (string_i += 1) {
913 const arg = ([]const u8)(strings[string_i]);
914 total_strings_len += arg.len;
915 }
916 }882 }
917}883};
918884
919/// Naively combines a series of slices with a separator.885/// Naively combines a series of slices with a separator.
920/// Allocates memory for the result, which must be freed by the caller.886/// Allocates memory for the result, which must be freed by the caller.
...@@ -931,26 +897,25 @@ pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []cons...@@ -931,26 +897,25 @@ pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []cons
931 const buf = try allocator.alloc(u8, total_len);897 const buf = try allocator.alloc(u8, total_len);
932 errdefer allocator.free(buf);898 errdefer allocator.free(buf);
933899
934 var buf_index: usize = 0;900 copy(u8, buf, slices[0]);
935 comptime var string_i = 0;901 var buf_index: usize = slices[0].len;
936 inline while (true) {902 for (slices[1..]) |slice| {
937 const arg = ([]const u8)(strings[string_i]);903 copy(u8, buf[buf_index..], separator);
938 string_i += 1;904 buf_index += separator.len;
939 copy(u8, buf[buf_index..], arg);905 copy(u8, buf[buf_index..], slice);
940 buf_index += arg.len;906 buf_index += slice.len;
941 if (string_i >= strings.len) break;
942 buf[buf_index] = sep;
943 buf_index += 1;
944 }907 }
945908
946 // No need for shrink since buf is exactly the correct size.909 // No need for shrink since buf is exactly the correct size.
947 return buf;910 return buf;
948}911}
949912
950test "mem.joinInline" {913test "mem.join" {
951 assert(eql(u8, try joinInline(debug.global_allocator, ',', "a", "b", "c"), "a,b,c"));914 var buf: [1024]u8 = undefined;
952 assert(eql(u8, try joinInline(debug.global_allocator, ',', "a", "b", ([]const u8)(""), "c"), "a,b,,c"));915 const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
953 assert(eql(u8, try joinInline(debug.global_allocator, ',', "a"), "a"));916 assert(eql(u8, try join(a, ",", [][]const u8{ "a", "b", "c" }), "a,b,c"));
917 assert(eql(u8, try join(a, ",", [][]const u8{"a"}), "a"));
918 assert(eql(u8, try join(a, ",", [][]const u8{ "a", "", "b", "", "c" }), "a,,b,,c"));
954}919}
955920
956test "testStringEquality" {921test "testStringEquality" {