aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Ini.zig
blob: 19653391862a68f9e248731cb58cd6c29442d9b0 (plain)
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
bytes: []const u8,

pub const SectionIterator = struct {
    ini: Ini,
    next_index: ?usize,
    header: []const u8,

    pub fn next(it: *SectionIterator) ?[]const u8 {
        const bytes = it.ini.bytes;
        const start = it.next_index orelse return null;
        const end = mem.indexOfPos(u8, bytes, start, "\n[") orelse bytes.len;
        const result = bytes[start..end];
        if (mem.indexOfPos(u8, bytes, start, it.header)) |next_index| {
            it.next_index = next_index + it.header.len;
        } else {
            it.next_index = null;
        }
        return result;
    }
};

/// Asserts that `header` includes "\n[" at the beginning and "]\n" at the end.
/// `header` must remain valid for the lifetime of the iterator.
pub fn iterateSection(ini: Ini, header: []const u8) SectionIterator {
    assert(mem.startsWith(u8, header, "\n["));
    assert(mem.endsWith(u8, header, "]\n"));
    const first_header = header[1..];
    const next_index = if (mem.indexOf(u8, ini.bytes, first_header)) |i|
        i + first_header.len
    else
        null;
    return .{
        .ini = ini,
        .next_index = next_index,
        .header = header,
    };
}

const std = @import("std.zig");
const mem = std.mem;
const assert = std.debug.assert;
const Ini = @This();
const testing = std.testing;

test iterateSection {
    const example =
        \\[package]
        \\name=libffmpeg
        \\version=5.1.2
        \\
        \\[dependency]
        \\id=libz
        \\url=url1
        \\
        \\[dependency]
        \\id=libmp3lame
        \\url=url2
    ;
    var ini: Ini = .{ .bytes = example };
    var it = ini.iterateSection("\n[dependency]\n");
    const section1 = it.next() orelse return error.TestFailed;
    try testing.expectEqualStrings("id=libz\nurl=url1\n", section1);
    const section2 = it.next() orelse return error.TestFailed;
    try testing.expectEqualStrings("id=libmp3lame\nurl=url2", section2);
    try testing.expect(it.next() == null);
}