diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-09-26 01:54:45 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-26 01:54:45 -0400 |
| commit | 68bb3945708c43109c48bda3664176307d45b62c (patch) | |
| tree | afb9731e10cef9d192560b52cd9ae2cf179775c4 /lib/std/cstr.zig | |
| parent | 6128bc728d1e1024a178c16c2149f5b1a167a013 (diff) | |
| parent | 4637e8f9699af9c3c6cf4df50ef5bb67c7a318a4 (diff) | |
| download | zig-68bb3945708c43109c48bda3664176307d45b62c.tar.gz zig-68bb3945708c43109c48bda3664176307d45b62c.zip | |
Merge pull request #3315 from ziglang/mv-std-lib
Move std/ to lib/std/
Diffstat (limited to 'lib/std/cstr.zig')
| -rw-r--r-- | lib/std/cstr.zig | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/std/cstr.zig b/lib/std/cstr.zig new file mode 100644 index 0000000000..dd28e50449 --- /dev/null +++ b/lib/std/cstr.zig @@ -0,0 +1,94 @@ +const std = @import("std.zig"); +const builtin = @import("builtin"); +const debug = std.debug; +const mem = std.mem; +const testing = std.testing; + +pub const line_sep = switch (builtin.os) { + builtin.Os.windows => "\r\n", + else => "\n", +}; + +pub fn cmp(a: [*]const u8, b: [*]const u8) i8 { + var index: usize = 0; + while (a[index] == b[index] and a[index] != 0) : (index += 1) {} + if (a[index] > b[index]) { + return 1; + } else if (a[index] < b[index]) { + return -1; + } else { + return 0; + } +} + +test "cstr fns" { + comptime testCStrFnsImpl(); + testCStrFnsImpl(); +} + +fn testCStrFnsImpl() void { + testing.expect(cmp(c"aoeu", c"aoez") == -1); + testing.expect(mem.len(u8, c"123456789") == 9); +} + +/// Returns a mutable slice with 1 more byte of length which is a null byte. +/// Caller owns the returned memory. +pub fn addNullByte(allocator: *mem.Allocator, slice: []const u8) ![]u8 { + const result = try allocator.alloc(u8, slice.len + 1); + mem.copy(u8, result, slice); + result[slice.len] = 0; + return result; +} + +pub const NullTerminated2DArray = struct { + allocator: *mem.Allocator, + byte_count: usize, + ptr: ?[*]?[*]u8, + + /// Takes N lists of strings, concatenates the lists together, and adds a null terminator + /// Caller must deinit result + pub fn fromSlices(allocator: *mem.Allocator, slices: []const []const []const u8) !NullTerminated2DArray { + var new_len: usize = 1; // 1 for the list null + var byte_count: usize = 0; + for (slices) |slice| { + new_len += slice.len; + for (slice) |inner| { + byte_count += inner.len; + } + byte_count += slice.len; // for the null terminators of inner + } + + const index_size = @sizeOf(usize) * new_len; // size of the ptrs + byte_count += index_size; + + const buf = try allocator.alignedAlloc(u8, @alignOf(?*u8), byte_count); + errdefer allocator.free(buf); + + var write_index = index_size; + const index_buf = @bytesToSlice(?[*]u8, buf); + + var i: usize = 0; + for (slices) |slice| { + for (slice) |inner| { + index_buf[i] = buf.ptr + write_index; + i += 1; + mem.copy(u8, buf[write_index..], inner); + write_index += inner.len; + buf[write_index] = 0; + write_index += 1; + } + } + index_buf[i] = null; + + return NullTerminated2DArray{ + .allocator = allocator, + .byte_count = byte_count, + .ptr = @ptrCast(?[*]?[*]u8, buf.ptr), + }; + } + + pub fn deinit(self: *NullTerminated2DArray) void { + const buf = @ptrCast([*]u8, self.ptr); + self.allocator.free(buf[0..self.byte_count]); + } +}; |
