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 | 40 | bool ini_parse(IniParser *ctx) | |
18 | { | ||
19 | 40 | const char *input = ctx->input.data; | |
20 |
2/2✓ Branch 0 (25→3) taken 85 times.
✓ Branch 1 (25→26) taken 5 times.
|
90 | for (size_t pos = ctx->pos, len = ctx->input.length; pos < len; ) { |
21 | 85 | StringView line = buf_slice_next_line(input, &pos, len); | |
22 | 85 | strview_trim_left(&line); | |
23 |
6/6✓ Branch 0 (5→6) taken 64 times.
✓ Branch 1 (5→8) taken 21 times.
✓ Branch 2 (6→7) taken 57 times.
✓ Branch 3 (6→8) taken 7 times.
✓ Branch 4 (7→8) taken 1 times.
✓ Branch 5 (7→9) taken 56 times.
|
85 | if (line.length < 2 || line.data[0] == '#' || line.data[0] == ';') { |
24 | // Skip past comment/blank lines and lines that are too short | ||
25 | // to be valid (shorter than "k=") | ||
26 | 50 | continue; | |
27 | } | ||
28 | |||
29 | 56 | strview_trim_right(&line); | |
30 | 56 | BUG_ON(line.length == 0); | |
31 | |||
32 |
2/2✓ Branch 0 (13→14) taken 15 times.
✓ Branch 1 (13→15) taken 41 times.
|
56 | if (strview_remove_matching_affixes(&line, strview("["), strview("]"))) { |
33 | // Keep track of (and skip past) section headings | ||
34 | 15 | ctx->section = line; | |
35 | 15 | ctx->name_count = 0; | |
36 | 15 | continue; | |
37 | } | ||
38 | |||
39 | 41 | size_t val_offset = 0; | |
40 | 41 | StringView name = get_delim(line.data, &val_offset, line.length, '='); | |
41 |
2/2✓ Branch 0 (16→17) taken 4 times.
✓ Branch 1 (16→18) taken 37 times.
|
41 | if (val_offset >= line.length) { |
42 | 4 | continue; // Invalid line (no delimiter) | |
43 | } | ||
44 | |||
45 | 37 | strview_trim_right(&name); | |
46 |
2/2✓ Branch 0 (19→20) taken 2 times.
✓ Branch 1 (19→21) taken 35 times.
|
37 | if (name.length == 0) { |
47 | 2 | continue; // Invalid line (empty name) | |
48 | } | ||
49 | |||
50 | 35 | StringView value = line; | |
51 | 35 | strview_remove_prefix(&value, val_offset); | |
52 | 35 | strview_trim_left(&value); | |
53 | |||
54 | 35 | ctx->name = name; | |
55 | 35 | ctx->value = value; | |
56 | 35 | ctx->name_count++; | |
57 | 35 | ctx->pos = pos; | |
58 | 35 | return true; | |
59 | } | ||
60 | |||
61 | 5 | return false; | |
62 | } | ||
63 |