diff --git a/std/mem.zig b/std/mem.zig index 66fc801101..83d41a3040 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -1,4 +1,5 @@ -const assert = @import("debug.zig").assert; +const debug = @import("debug.zig"); +const assert = debug.assert; const math = @import("math.zig"); const os = @import("os/index.zig"); const io = @import("io.zig"); @@ -285,6 +286,44 @@ const SplitIterator = struct { } }; +/// Naively combines a series of strings with a separator. +/// Allocates memory for the result, which must be freed by the caller. +pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 { + comptime assert(strings.len >= 1); + var total_strings_len: usize = strings.len; // 1 slash per string + { + comptime var string_i = 0; + inline while (string_i < strings.len) : (string_i += 1) { + const arg = ([]const u8)(strings[string_i]); + total_strings_len += arg.len; + } + } + + const buf = %return allocator.alloc(u8, total_strings_len); + %defer allocator.free(buf); + + var buf_index: usize = 0; + comptime var string_i = 0; + inline while (true) { + const arg = ([]const u8)(strings[string_i]); + string_i += 1; + copy(u8, buf[buf_index..], arg); + buf_index += arg.len; + if (string_i >= strings.len) break; + if (buf[buf_index - 1] != sep) { + buf[buf_index] = sep; + buf_index += 1; + } + } + + return buf[0..buf_index]; +} + +test "mem.join" { + assert(eql(u8, %%join(&debug.global_allocator, ',', "a", "b", "c"), "a,b,c")); + assert(eql(u8, %%join(&debug.global_allocator, ',', "a"), "a")); +} + test "testStringEquality" { assert(eql(u8, "abcd", "abcd")); assert(!eql(u8, "abcdef", "abZdef")); diff --git a/std/os/path.zig b/std/os/path.zig index ce767f6bae..5477d44420 100644 --- a/std/os/path.zig +++ b/std/os/path.zig @@ -21,34 +21,7 @@ pub const delimiter = switch (builtin.os) { /// Naively combines a series of paths with the native path seperator. /// Allocates memory for the result, which must be freed by the caller. pub fn join(allocator: &Allocator, paths: ...) -> %[]u8 { - comptime assert(paths.len >= 2); - var total_paths_len: usize = paths.len; // 1 slash per path - { - comptime var path_i = 0; - inline while (path_i < paths.len) : (path_i += 1) { - const arg = ([]const u8)(paths[path_i]); - total_paths_len += arg.len; - } - } - - const buf = %return allocator.alloc(u8, total_paths_len); - %defer allocator.free(buf); - - var buf_index: usize = 0; - comptime var path_i = 0; - inline while (true) { - const arg = ([]const u8)(paths[path_i]); - path_i += 1; - mem.copy(u8, buf[buf_index..], arg); - buf_index += arg.len; - if (path_i >= paths.len) break; - if (buf[buf_index - 1] != sep) { - buf[buf_index] = sep; - buf_index += 1; - } - } - - return buf[0..buf_index]; + mem.join(allocator, sep, paths) } test "os.path.join" {