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 {
856856 }
857857};
858858
859/// Naively combines a series of strings with a separator.
860/// Allocates memory for the result, which must be freed by the caller.
861pub fn join(allocator: *Allocator, sep: u8, strings: []const []const u8) ![]u8 {
862 assert(strings.len >= 1);
863 var total_strings_len: usize = strings.len; // 1 sep per string
864 {
865 var string_i: usize = 0;
866 while (string_i < strings.len) : (string_i += 1) {
867 const arg = ([]const u8)(strings[string_i]);
868 total_strings_len += arg.len;
869 }
870 }
871
872 const buf = try allocator.alloc(u8, total_strings_len);
873 errdefer allocator.free(buf);
874
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;
859pub const SplitIterator = struct {
860 buffer: []const u8,
861 index: ?usize,
862 delimiter: []const u8,
863
864 /// Returns a slice of the next field, or null if splitting is complete.
865 pub fn next(self: *SplitIterator) ?[]const u8 {
866 const start = self.index orelse return null;
867 const end = if (indexOfPos(u8, self.buffer, start, self.delimiter)) |delim_start| blk: {
868 self.index = delim_start + self.delimiter.len;
869 break :blk delim_start;
870 } else blk: {
871 self.index = null;
872 break :blk self.buffer.len;
873 };
874 return self.buffer[start..end];
885875 }
886876
887 return allocator.shrink(u8, buf, buf_index);
888}
889
890test "mem.join" {
891 var str: []u8 = try join(debug.global_allocator, ',', [][]const u8{ "a", "b", "c" });
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 }
877 /// Returns a slice of the remaining bytes. Does not affect iterator state.
878 pub fn rest(self: SplitIterator) []const u8 {
879 const end = self.buffer.len;
880 const start = self.index orelse end;
881 return self.buffer[start..end];
916882 }
917}
883};
918884
919885/// Naively combines a series of slices with a separator.
920886/// 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
931897 const buf = try allocator.alloc(u8, total_len);
932898 errdefer allocator.free(buf);
933899
934 var buf_index: usize = 0;
935 comptime var string_i = 0;
936 inline while (true) {
937 const arg = ([]const u8)(strings[string_i]);
938 string_i += 1;
939 copy(u8, buf[buf_index..], arg);
940 buf_index += arg.len;
941 if (string_i >= strings.len) break;
942 buf[buf_index] = sep;
943 buf_index += 1;
900 copy(u8, buf, slices[0]);
901 var buf_index: usize = slices[0].len;
902 for (slices[1..]) |slice| {
903 copy(u8, buf[buf_index..], separator);
904 buf_index += separator.len;
905 copy(u8, buf[buf_index..], slice);
906 buf_index += slice.len;
944907 }
945908
946909 // No need for shrink since buf is exactly the correct size.
947910 return buf;
948911}
949912
950test "mem.joinInline" {
951 assert(eql(u8, try joinInline(debug.global_allocator, ',', "a", "b", "c"), "a,b,c"));
952 assert(eql(u8, try joinInline(debug.global_allocator, ',', "a", "b", ([]const u8)(""), "c"), "a,b,,c"));
953 assert(eql(u8, try joinInline(debug.global_allocator, ',', "a"), "a"));
913test "mem.join" {
914 var buf: [1024]u8 = undefined;
915 const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
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"));
954919}
955920
956921test "testStringEquality" {