diff --git a/build.zig b/build.zig new file mode 100644 index 0000000000000000000000000000000000000000..b47f682c58763b46ddfb8587ce76b7c62554c234 --- /dev/null +++ b/build.zig @@ -0,0 +1,19 @@ +const std = @import("std"); +const deps = @import("./deps.zig"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const mode = b.option(std.builtin.Mode, "mode", "") orelse .Debug; + + const tests = b.addTest(.{ + .root_source_file = b.path("test.zig"), + .target = target, + .optimize = mode, + }); + deps.addAllTo(tests); + + const test_step = b.step("test", "Run all library tests"); + const tests_run = b.addRunArtifact(tests); + tests_run.has_side_effects = true; + test_step.dependOn(&tests_run.step); +} diff --git a/test.zig b/test.zig new file mode 100644 index 0000000000000000000000000000000000000000..dfe486e0cb612b59fc476cc13beca1bb1a2cd1d2 --- /dev/null +++ b/test.zig @@ -0,0 +1,11 @@ +const std = @import("std"); +const yaml = @import("yaml"); + +const file = @embedFile("./zigmod.yml"); + +test { + const doc = try yaml.parse(std.testing.allocator, file); + defer doc.deinit(std.testing.allocator); + + try std.testing.expectEqualStrings("g982zq6e8wsvnmduerpbf8787hu85brugmngn8wf", doc.mapping.get_string("id").?); +} diff --git a/yaml.zig b/yaml.zig index 52361bd049ee0eb70587e08250569ca5ab44cdb7..4a2749c8cafb10b9988c51cedf32c48747ded8e7 100644 --- a/yaml.zig +++ b/yaml.zig @@ -11,10 +11,19 @@ const c = @cImport({ pub const Stream = struct { docs: []const Document, + + pub fn deinit(self: *const Stream, alloc: std.mem.Allocator) void { + for (self.docs) |*item| item.deinit(alloc); + alloc.free(self.docs); + } }; pub const Document = struct { mapping: Mapping, + + pub fn deinit(self: *const Document, alloc: std.mem.Allocator) void { + self.mapping.deinit(alloc); + } }; pub const Item = union(enum) { @@ -25,6 +34,22 @@ pub const Item = union(enum) { string: string, stream: Stream, + pub fn deinit(self: *const Item, alloc: std.mem.Allocator) void { + switch (self.*) { + .event => {}, + .kv => |kv| kv.deinit(alloc), + .mapping => |m| m.deinit(alloc), + .sequence => |s| { + for (s) |*item| item.deinit(alloc); + alloc.free(s); + }, + .string => |s| { + _ = s; + }, + .stream => |s| s.deinit(alloc), + } + } + pub fn format(self: Item, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) @TypeOf(writer).Error!void { _ = fmt; _ = options; @@ -60,6 +85,11 @@ pub const Sequence = []const Item; pub const Key = struct { key: string, value: Value, + + pub fn deinit(self: *const Key, alloc: std.mem.Allocator) void { + // alloc.free(self.key); + self.value.deinit(alloc); + } }; pub const Value = union(enum) { @@ -67,6 +97,22 @@ pub const Value = union(enum) { mapping: Mapping, sequence: Sequence, + pub fn deinit(self: *const Value, alloc: std.mem.Allocator) void { + switch (self.*) { + .string => |s| { + _ = s; + // alloc.free(s); + }, + .mapping => |*m| { + m.deinit(alloc); + }, + .sequence => |s| { + for (s) |*item| item.deinit(alloc); + alloc.free(s); + }, + } + } + pub fn format(self: Value, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) @TypeOf(writer).Error!void { _ = fmt; _ = options; @@ -94,6 +140,11 @@ pub const Value = union(enum) { pub const Mapping = struct { items: []const Key, + pub fn deinit(self: *const Mapping, alloc: std.mem.Allocator) void { + for (self.items) |*item| item.deinit(alloc); + alloc.free(self.items); + } + pub fn get(self: Mapping, k: string) ?Value { for (self.items) |item| { if (std.mem.eql(u8, item.key, k)) { @@ -118,7 +169,7 @@ pub const Mapping = struct { pub fn get_string_array(self: Mapping, alloc: std.mem.Allocator, k: string) ![]string { var list = std.ArrayList(string).init(alloc); - defer list.deinit(); + errdefer list.deinit(); if (self.get(k)) |val| { if (val == .sequence) { for (val.sequence) |item| { @@ -161,10 +212,12 @@ pub fn parse(alloc: std.mem.Allocator, input: string) !Document { defer c.yaml_parser_delete(&parser); const lines = try split(alloc, input, "\n"); + defer alloc.free(lines); _ = c.yaml_parser_set_input_string(&parser, input.ptr, input.len); var all_events = std.ArrayList(Token).init(alloc); + defer all_events.deinit(); var event: Token = undefined; while (true) { const p = c.yaml_parser_parse(&parser, &event); @@ -188,6 +241,7 @@ pub fn parse(alloc: std.mem.Allocator, input: string) !Document { .index = 0, }; const stream = try p.parse(); + defer alloc.free(stream.docs); return stream.docs[0]; }