2019-03-02 21:46:04 +00:00
|
|
|
const std = @import("std.zig");
|
2021-10-05 06:47:27 +00:00
|
|
|
const builtin = @import("builtin");
|
2017-12-24 03:08:53 +00:00
|
|
|
const debug = std.debug;
|
|
|
|
const mem = std.mem;
|
2019-02-08 23:18:47 +00:00
|
|
|
const testing = std.testing;
|
2016-08-12 05:25:13 +00:00
|
|
|
|
2020-02-25 06:52:27 +00:00
|
|
|
pub const line_sep = switch (builtin.os.tag) {
|
|
|
|
.windows => "\r\n",
|
2018-02-11 01:55:13 +00:00
|
|
|
else => "\n",
|
|
|
|
};
|
|
|
|
|
2019-12-17 20:43:49 +00:00
|
|
|
pub fn cmp(a: [*:0]const u8, b: [*:0]const u8) i8 {
|
2016-07-27 03:40:11 +00:00
|
|
|
var index: usize = 0;
|
2017-05-03 22:12:07 +00:00
|
|
|
while (a[index] == b[index] and a[index] != 0) : (index += 1) {}
|
2016-12-31 22:10:29 +00:00
|
|
|
if (a[index] > b[index]) {
|
|
|
|
return 1;
|
2016-09-27 02:33:33 +00:00
|
|
|
} else if (a[index] < b[index]) {
|
2016-12-31 22:10:29 +00:00
|
|
|
return -1;
|
2016-09-27 02:33:33 +00:00
|
|
|
} else {
|
2016-12-31 22:10:29 +00:00
|
|
|
return 0;
|
2017-12-22 05:50:30 +00:00
|
|
|
}
|
2016-05-07 17:52:52 +00:00
|
|
|
}
|
|
|
|
|
2017-03-16 20:02:35 +00:00
|
|
|
test "cstr fns" {
|
2021-05-04 17:47:26 +00:00
|
|
|
comptime try testCStrFnsImpl();
|
|
|
|
try testCStrFnsImpl();
|
2016-09-27 02:33:33 +00:00
|
|
|
}
|
2016-09-28 06:33:32 +00:00
|
|
|
|
2021-05-04 17:47:26 +00:00
|
|
|
fn testCStrFnsImpl() !void {
|
|
|
|
try testing.expect(cmp("aoeu", "aoez") == -1);
|
|
|
|
try testing.expect(mem.len("123456789") == 9);
|
2016-09-27 02:33:33 +00:00
|
|
|
}
|
2017-10-13 13:31:03 +00:00
|
|
|
|
2019-12-18 21:43:56 +00:00
|
|
|
/// Returns a mutable, null-terminated slice with the same length as `slice`.
|
2017-10-13 13:31:03 +00:00
|
|
|
/// Caller owns the returned memory.
|
2021-10-28 23:37:25 +00:00
|
|
|
pub fn addNullByte(allocator: mem.Allocator, slice: []const u8) ![:0]u8 {
|
2018-01-07 21:51:46 +00:00
|
|
|
const result = try allocator.alloc(u8, slice.len + 1);
|
2017-10-13 13:31:03 +00:00
|
|
|
mem.copy(u8, result, slice);
|
|
|
|
result[slice.len] = 0;
|
2019-12-18 21:43:56 +00:00
|
|
|
return result[0..slice.len :0];
|
|
|
|
}
|
|
|
|
|
|
|
|
test "addNullByte" {
|
2020-02-01 01:06:50 +00:00
|
|
|
const slice = try addNullByte(std.testing.allocator, "hello"[0..4]);
|
|
|
|
defer std.testing.allocator.free(slice);
|
2021-05-04 17:47:26 +00:00
|
|
|
try testing.expect(slice.len == 4);
|
|
|
|
try testing.expect(slice[4] == 0);
|
2017-10-13 13:31:03 +00:00
|
|
|
}
|
2017-12-27 00:44:08 +00:00
|
|
|
|
2018-11-13 13:08:37 +00:00
|
|
|
pub const NullTerminated2DArray = struct {
|
2021-10-28 23:37:25 +00:00
|
|
|
allocator: mem.Allocator,
|
2017-12-27 00:44:08 +00:00
|
|
|
byte_count: usize,
|
2019-12-17 20:43:49 +00:00
|
|
|
ptr: ?[*:null]?[*:0]u8,
|
2017-12-27 00:44:08 +00:00
|
|
|
|
|
|
|
/// Takes N lists of strings, concatenates the lists together, and adds a null terminator
|
|
|
|
/// Caller must deinit result
|
2021-10-28 23:37:25 +00:00
|
|
|
pub fn fromSlices(allocator: mem.Allocator, slices: []const []const []const u8) !NullTerminated2DArray {
|
2017-12-27 00:44:08 +00:00
|
|
|
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;
|
|
|
|
|
2018-05-31 14:56:59 +00:00
|
|
|
const buf = try allocator.alignedAlloc(u8, @alignOf(?*u8), byte_count);
|
2018-01-24 04:08:09 +00:00
|
|
|
errdefer allocator.free(buf);
|
2017-12-27 00:44:08 +00:00
|
|
|
|
|
|
|
var write_index = index_size;
|
2020-02-21 18:46:53 +00:00
|
|
|
const index_buf = mem.bytesAsSlice(?[*]u8, buf);
|
2017-12-27 00:44:08 +00:00
|
|
|
|
|
|
|
var i: usize = 0;
|
|
|
|
for (slices) |slice| {
|
|
|
|
for (slice) |inner| {
|
2018-06-04 05:09:15 +00:00
|
|
|
index_buf[i] = buf.ptr + write_index;
|
2017-12-27 00:44:08 +00:00
|
|
|
i += 1;
|
|
|
|
mem.copy(u8, buf[write_index..], inner);
|
|
|
|
write_index += inner.len;
|
|
|
|
buf[write_index] = 0;
|
|
|
|
write_index += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index_buf[i] = null;
|
|
|
|
|
2018-11-13 13:08:37 +00:00
|
|
|
return NullTerminated2DArray{
|
2017-12-27 00:44:08 +00:00
|
|
|
.allocator = allocator,
|
|
|
|
.byte_count = byte_count,
|
2019-12-17 20:43:49 +00:00
|
|
|
.ptr = @ptrCast(?[*:null]?[*:0]u8, buf.ptr),
|
2017-12-27 00:44:08 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-05-31 14:56:59 +00:00
|
|
|
pub fn deinit(self: *NullTerminated2DArray) void {
|
2018-06-04 05:09:15 +00:00
|
|
|
const buf = @ptrCast([*]u8, self.ptr);
|
2017-12-27 00:44:08 +00:00
|
|
|
self.allocator.free(buf[0..self.byte_count]);
|
|
|
|
}
|
|
|
|
};
|