Line | Branch | Exec | Source |
---|---|---|---|
1 | #include "ini.h" | ||
2 | #include "util/debug.h" | ||
3 | #include "util/str-util.h" | ||
4 | |||
5 | /* | ||
6 | * This is a "pull" style INI parser that returns true (and fills | ||
7 | * ctx->name and ctx->value) for each name=value pair encountered, | ||
8 | * or false when there's nothing further to parse. The current | ||
9 | * section name is tracked as ctx->section and lines that aren't | ||
10 | * actionable by the caller (i.e. section/comment/blank/invalid | ||
11 | * lines) are skipped over without returning anything. | ||
12 | * | ||
13 | * Note that "inline" comments are not supported, since the | ||
14 | * EditorConfig specification forbids them and that's the only | ||
15 | * use case in this codebase (see commit a61b90f630cd6a32). | ||
16 | */ | ||
17 | 39 | bool ini_parse(IniParser *ctx) | |
18 | { | ||
19 | 39 | const char *input = ctx->input; | |
20 | 39 | const size_t len = ctx->input_len; | |
21 | 39 | size_t pos = ctx->pos; | |
22 | |||
23 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 5 times.
|
86 | while (pos < len) { |
24 | 81 | StringView line = buf_slice_next_line(input, &pos, len); | |
25 | 81 | strview_trim_left(&line); | |
26 |
5/6✓ Branch 0 taken 60 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
|
81 | if (line.length < 2 || line.data[0] == '#' || line.data[0] == ';') { |
27 | // Skip past comment/blank lines and lines that are too short | ||
28 | // to be valid (shorter than "k=") | ||
29 | 47 | continue; | |
30 | } | ||
31 | |||
32 | 54 | strview_trim_right(&line); | |
33 | 54 | BUG_ON(line.length == 0); | |
34 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 40 times.
|
54 | if (line.data[0] == '[') { |
35 | // Keep track of (and skip past) section headings | ||
36 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | if (strview_has_suffix(&line, "]")) { |
37 | 14 | ctx->section = string_view(line.data + 1, line.length - 2); | |
38 | 14 | ctx->name_count = 0; | |
39 | } | ||
40 | 14 | continue; | |
41 | } | ||
42 | |||
43 | 40 | size_t val_offset = 0; | |
44 | 40 | StringView name = get_delim(line.data, &val_offset, line.length, '='); | |
45 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
|
40 | if (val_offset >= line.length) { |
46 | 4 | continue; // Invalid line (no delimiter) | |
47 | } | ||
48 | |||
49 | 36 | strview_trim_right(&name); | |
50 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
|
36 | if (name.length == 0) { |
51 | 2 | continue; // Invalid line (empty name) | |
52 | } | ||
53 | |||
54 | 34 | StringView value = line; | |
55 | 34 | strview_remove_prefix(&value, val_offset); | |
56 | 34 | strview_trim_left(&value); | |
57 | |||
58 | 34 | ctx->name = name; | |
59 | 34 | ctx->value = value; | |
60 | 34 | ctx->name_count++; | |
61 | 34 | ctx->pos = pos; | |
62 | 34 | return true; | |
63 | } | ||
64 | |||
65 | return false; | ||
66 | } | ||
67 |