diff options
Diffstat (limited to 'src/conf.zig')
| -rw-r--r-- | src/conf.zig | 102 |
1 files changed, 50 insertions, 52 deletions
diff --git a/src/conf.zig b/src/conf.zig index 419c369..97238c3 100644 --- a/src/conf.zig +++ b/src/conf.zig @@ -1,21 +1,23 @@ const std = @import("std"); const assert = std.debug.assert; +const fs = @import("fs.zig"); + pub const Var = struct { key: []const u8, val: []const u8, - pub fn format(self: Var, w: *std.io.Writer) !void { + pub fn format(self: Var, w: *std.Io.Writer) !void { const spacebuf = [_]u8{' '} ** 32; const equal_sign = " = "; try w.writeAll(self.key); try w.writeAll(equal_sign); - if (std.mem.indexOfScalar(u8, self.val, '\n')) |eol0| { + if (std.mem.findScalar(u8, self.val, '\n')) |eol0| { try w.writeAll(self.val[0 .. eol0 + 1]); var val = self.val[eol0 + 1 ..]; while (val.len > 0) { - const eol = std.mem.indexOfScalar(u8, val, '\n') orelse val.len - 1; + const eol = std.mem.findScalar(u8, val, '\n') orelse val.len - 1; const line = val[0 .. eol + 1]; var spaces = self.key.len; while (spaces > 0) { @@ -86,45 +88,44 @@ pub const Config = struct { return .{ .allocator = allocator, .buf = &.{}, .len = 0 }; } - pub fn from_file(allocator: std.mem.Allocator, path: []const u8) !Parse_Result { - var file = std.fs.openFileAbsolute(path, .{}) catch |err| { - return switch (err) { - error.FileNotFound => .{ .conf = .init(allocator) }, - else => err, - }; + pub fn from_file(allocator: std.mem.Allocator, path: *const fs.Path) !Parse_Result { + var read_buf: [512]u8 = undefined; + var r = fs.file_reader(path, &read_buf) catch |err| { + if (err == error.FileNotFound) return .{ .conf = .init(allocator) }; + return err; }; - defer file.close(); - - var read_buf: [1024]u8 = undefined; - var reader = file.reader(&read_buf); - return parse(allocator, &reader.interface, read_buf.len); + defer r.deinit(); + return parse(allocator, &r.interface, read_buf.len); } - fn parse(allocator: std.mem.Allocator, reader: *std.io.Reader, comptime max_line_len: usize) !Parse_Result { + /// Parse the string in the given buffer. The buffer is reused to store the raw config data. + fn parse(allocator: std.mem.Allocator, reader: *std.Io.Reader, comptime max_line_len: usize) !Parse_Result { const spaces = " \t\r"; - var allocating: std.io.Writer.Allocating = .init(allocator); - + var allocating: std.Io.Writer.Allocating = .init(allocator); var header: Var_Header = undefined; var header_off: usize = 0; var need_key = true; var file_line: usize = 0; while (true) { file_line += 1; - const raw_line = reader.takeDelimiterExclusive('\n') catch |err| switch (err) { - error.StreamTooLong => { - return .{ - .err = .{ - .msg = std.fmt.comptimePrint("key/value line exceeds the maximum of {} bytes", .{max_line_len}), - .line = file_line, - }, - }; - }, - error.EndOfStream => { - break; - }, - else => unreachable, + const raw_line = reader.takeDelimiterExclusive('\n') catch |err| { + switch (err) { + error.StreamTooLong => { + return .{ + .err = .{ + .msg = std.fmt.comptimePrint("key/value line exceeds the maximum of {} bytes", .{max_line_len}), + .line = file_line, + }, + }; + }, + error.EndOfStream => { + break; + }, + else => unreachable, + } }; + if (reader.bufferedLen() > 0) reader.toss(1); const line = std.mem.trim(u8, raw_line, spaces); if (line.len == 0 or line[0] == '#') { @@ -142,8 +143,8 @@ pub const Config = struct { }; }; - const key = std.mem.trimRight(u8, line[0..eq], spaces); - const val = std.mem.trimLeft(u8, line[eq + 1 ..], spaces); + const key = std.mem.trimEnd(u8, line[0..eq], spaces); + const val = std.mem.trimStart(u8, line[eq + 1 ..], spaces); if (key.len == 0) { // We have a value continuation here. So we append a newline @@ -235,11 +236,10 @@ pub const Config = struct { }; test "parse config - empty" { - var input = std.io.Reader.fixed(""); - var buf: [32]u8 = undefined; - var reader = std.io.Reader.limited(&input, std.io.Limit.limited(input.buffer.len), &buf); + const input = ""; + var input_r = std.Io.Reader.fixed(input); - var result = try Config.parse(std.testing.allocator, &reader.interface, buf.len); + var result = try Config.parse(std.testing.allocator, &input_r, input.len); try std.testing.expect(result == .conf); try std.testing.expectEqualSlices(u8, "", result.conf.buf[0..result.conf.len]); defer result.conf.deinit(); @@ -248,12 +248,11 @@ test "parse config - empty" { try std.testing.expect(vars.next() == null); } -test "parse config - singe line" { - var input = std.io.Reader.fixed("foo one = bar one"); - var buf: [32]u8 = undefined; - var reader = std.io.Reader.limited(&input, std.io.Limit.limited(input.buffer.len), &buf); +test "parse config - single line" { + const input = "foo one = bar one"; + var input_r = std.Io.Reader.fixed(input); - var result = try Config.parse(std.testing.allocator, &reader.interface, buf.len); + var result = try Config.parse(std.testing.allocator, &input_r, input.len); try std.testing.expect(result == .conf); try std.testing.expectEqualSlices( u8, @@ -272,8 +271,8 @@ test "parse config - singe line" { } test "parse config - mixed" { - var input = std.io.Reader.fixed( - \\foo_one = bar one + const input = + \\ foo_one = bar one \\foo_two = bar two 1 \\ = bar two 2 \\ = @@ -292,11 +291,10 @@ test "parse config - mixed" { \\ \\foo_five = \\ - ); - var buf: [32]u8 = undefined; - var reader = std.io.Reader.limited(&input, std.io.Limit.limited(input.buffer.len), &buf); + ; + var input_r = std.Io.Reader.fixed(input); - var result = try Config.parse(std.testing.allocator, &reader.interface, buf.len); + var result = try Config.parse(std.testing.allocator, &input_r, input.len); try std.testing.expect(result == .conf); try std.testing.expectEqualSlices( u8, @@ -336,7 +334,8 @@ test "parse config - mixed" { } test "parse config - with comment" { - var input = std.io.Reader.fixed( + const input = + \\ \\# first var: \\foo_one = bar one \\# second var: @@ -348,11 +347,10 @@ test "parse config - with comment" { \\foo_three = \\ = bar three 2 \\ = bar three 3 - ); - var buf: [32]u8 = undefined; - var reader = std.io.Reader.limited(&input, std.io.Limit.limited(input.buffer.len), &buf); + ; + var input_r = std.Io.Reader.fixed(input); - var result = try Config.parse(std.testing.allocator, &reader.interface, buf.len); + var result = try Config.parse(std.testing.allocator, &input_r, input.len); try std.testing.expect(result == .conf); try std.testing.expectEqualSlices( u8, |