| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | | const assert = @import("debug.zig").assert; |
| 1 | const debug = @import("debug.zig"); |
| 2 | const assert = debug.assert; |
| 2 | 3 | const math = @import("math.zig"); |
| 3 | 4 | const os = @import("os/index.zig"); |
| 4 | 5 | const io = @import("io.zig"); |
| ... | ... | @@ -285,6 +286,44 @@ const SplitIterator = struct { |
| 285 | 286 | } |
| 286 | 287 | }; |
| 287 | 288 | |
| 289 | /// Naively combines a series of strings with a separator. |
| 290 | /// Allocates memory for the result, which must be freed by the caller. |
| 291 | pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 { |
| 292 | comptime assert(strings.len >= 1); |
| 293 | var total_strings_len: usize = strings.len; // 1 sep per string |
| 294 | { |
| 295 | comptime var string_i = 0; |
| 296 | inline while (string_i < strings.len) : (string_i += 1) { |
| 297 | const arg = ([]const u8)(strings[string_i]); |
| 298 | total_strings_len += arg.len; |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | const buf = %return allocator.alloc(u8, total_strings_len); |
| 303 | %defer allocator.free(buf); |
| 304 | |
| 305 | var buf_index: usize = 0; |
| 306 | comptime var string_i = 0; |
| 307 | inline while (true) { |
| 308 | const arg = ([]const u8)(strings[string_i]); |
| 309 | string_i += 1; |
| 310 | copy(u8, buf[buf_index..], arg); |
| 311 | buf_index += arg.len; |
| 312 | if (string_i >= strings.len) break; |
| 313 | if (buf[buf_index - 1] != sep) { |
| 314 | buf[buf_index] = sep; |
| 315 | buf_index += 1; |
| 316 | } |
| 317 | } |
| 318 | |
| 319 | return buf[0..buf_index]; |
| 320 | } |
| 321 | |
| 322 | test "mem.join" { |
| 323 | assert(eql(u8, %%join(&debug.global_allocator, ',', "a", "b", "c"), "a,b,c")); |
| 324 | assert(eql(u8, %%join(&debug.global_allocator, ',', "a"), "a")); |
| 325 | } |
| 326 | |
| 288 | 327 | test "testStringEquality" { |
| 289 | 328 | assert(eql(u8, "abcd", "abcd")); |
| 290 | 329 | assert(!eql(u8, "abcdef", "abZdef")); |