1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
const std = @import("std");
const toml = @import("toml");
const Allocator = std.mem.Allocator;
const Io = std.Io;
const tvalue = toml.value_mod;
pub const ReadError = Allocator.Error || Io.Cancelable || error{ FileNotFound, ReadFailed };
pub fn readFileAlloc(allocator: Allocator, io: Io, path: []const u8) ReadError![]u8 {
const file = Io.Dir.cwd().openFile(io, path, .{ .mode = .read_only }) catch |err| switch (err) {
error.FileNotFound => return error.FileNotFound,
error.Canceled => return error.Canceled,
else => return error.ReadFailed,
};
defer file.close(io);
const len = file.length(io) catch return error.ReadFailed;
const bytes = try allocator.alloc(u8, @intCast(len));
errdefer allocator.free(bytes);
_ = file.readPositionalAll(io, bytes, 0) catch |err| switch (err) {
error.Canceled => return error.Canceled,
else => return error.ReadFailed,
};
return bytes;
}
pub fn mergeTable(alloc: Allocator, dst: *toml.Value, src: *const toml.Value) Allocator.Error!void {
std.debug.assert(dst.* == .table);
if (src.* != .table) return;
var it = toml.tableIterator(src);
while (it.next()) |entry| {
const existing = dst.get(entry.key);
if (existing != null and existing.?.* == .table and entry.value.* == .table) {
try mergeTable(alloc, @constCast(existing.?), entry.value);
} else {
const copy = try cloneValue(alloc, entry.value);
const key_copy = try alloc.dupe(u8, entry.key);
try tvalue.tableSet(alloc, dst, key_copy, copy);
}
}
}
fn cloneValue(alloc: Allocator, src: *const toml.Value) Allocator.Error!*toml.Value {
const out = try alloc.create(toml.Value);
switch (src.*) {
.table => {
out.* = .{ .table = .{} };
var it = toml.tableIterator(src);
while (it.next()) |entry| {
const child = try cloneValue(alloc, entry.value);
const key_copy = try alloc.dupe(u8, entry.key);
try tvalue.tableSet(alloc, out, key_copy, child);
}
},
.array => |*a| {
out.* = .{ .array = .{} };
for (a.items.items) |*item| {
const child = try cloneValue(alloc, item);
try tvalue.arrayAppend(alloc, out, child.*);
}
},
.string => |s| out.* = .{ .string = try alloc.dupe(u8, s) },
else => out.* = src.*,
}
return out;
}
|