authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-09 22:36:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-11 15:39:48-08:00
log4f6981bbe3d7bed5af60a58d012e4d2225a9c838
tree11c1cb56513c6b322463eaa368ee4fbd30fa000a
parentf945c2a1c8384319f9588a8f95ff8c97821213fe

add std.Ini for basic .ini file parsing


1 files changed, 66 insertions(+), 0 deletions(-)

lib/std/Ini.zig created+66
......@@ -0,0 +1,66 @@
1bytes: []const u8,
2
3pub const SectionIterator = struct {
4 ini: Ini,
5 next_index: ?usize,
6 header: []const u8,
7
8 pub fn next(it: *SectionIterator) ?[]const u8 {
9 const bytes = it.ini.bytes;
10 const start = it.next_index orelse return null;
11 const end = mem.indexOfPos(u8, bytes, start, "\n[") orelse bytes.len;
12 const result = bytes[start..end];
13 if (mem.indexOfPos(u8, bytes, start, it.header)) |next_index| {
14 it.next_index = next_index + it.header.len;
15 } else {
16 it.next_index = null;
17 }
18 return result;
19 }
20};
21
22/// Asserts that `header` includes "\n[" at the beginning and "]\n" at the end.
23/// `header` must remain valid for the lifetime of the iterator.
24pub fn iterateSection(ini: Ini, header: []const u8) SectionIterator {
25 assert(mem.startsWith(u8, header, "\n["));
26 assert(mem.endsWith(u8, header, "]\n"));
27 const first_header = header[1..];
28 const next_index = if (mem.indexOf(u8, ini.bytes, first_header)) |i|
29 i + first_header.len
30 else
31 null;
32 return .{
33 .ini = ini,
34 .next_index = next_index,
35 .header = header,
36 };
37}
38
39const std = @import("std.zig");
40const mem = std.mem;
41const assert = std.debug.assert;
42const Ini = @This();
43const testing = std.testing;
44
45test iterateSection {
46 const example =
47 \\[package]
48 \\name=libffmpeg
49 \\version=5.1.2
50 \\
51 \\[dependency]
52 \\id=libz
53 \\url=url1
54 \\
55 \\[dependency]
56 \\id=libmp3lame
57 \\url=url2
58 ;
59 var ini: Ini = .{ .bytes = example };
60 var it = ini.iterateSection("\n[dependency]\n");
61 const section1 = it.next() orelse return error.TestFailed;
62 try testing.expectEqualStrings("id=libz\nurl=url1\n", section1);
63 const section2 = it.next() orelse return error.TestFailed;
64 try testing.expectEqualStrings("id=libmp3lame\nurl=url2", section2);
65 try testing.expect(it.next() == null);
66}