~lattis/muon

ref: f9a8cbad39b665a9496cd3adb4756e85ee5ec97c muon/src/formats/ini.c -rw-r--r-- 2.3 KiB
f9a8cbadStone Tickle print stdout/stderr of failing test 8 months ago
                                                                                
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "posix.h"

#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#include "error.h"
#include "formats/ini.h"
#include "iterator.h"
#include "log.h"
#include "platform/filesystem.h"
#include "platform/mem.h"

typedef enum iteration_result ((*each_line_callback)(void *ctx, char *line, size_t len));

static void
each_line(char *buf, uint64_t len, void *ctx, each_line_callback cb)
{
	char *line, *b;

	line = buf;

	while ((b = strchr(line, '\n'))) {
		*b = '\0';

		if (cb(ctx, line, b - line) != ir_cont) {
			break;
		}

		line = b + 1;

		if ((size_t)(line - buf) >= len) {
			break;
		}
	}
}

struct each_line_ctx {
	struct source src;
	void *octx;
	char *sect;
	inihcb cb;
	uint32_t line;
	bool success;
};

static bool
is_whitespace(char c)
{
	return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}

static enum iteration_result
each_line_cb(void *_ctx, char *line, size_t len)
{
	struct each_line_ctx *ctx = _ctx;
	char *ptr, *key, *val;

	if (*line == '\0' || *line == ';' || *line == '#') {
		goto done_with_line;
	} else if (*line == '[') {
		if (!(ptr = strchr(line, ']'))) {
			error_messagef(&ctx->src, ctx->line, strlen(line) + 1, "expected ']'");
			ctx->success = false;
			goto done_with_line;
		}

		*ptr = '\0';

		ctx->sect = line + 1;

		if (!ctx->cb(ctx->octx, &ctx->src, ctx->sect, NULL, NULL, ctx->line)) {
			ctx->success = false;
		}
		goto done_with_line;
	}

	if (!(ptr = strchr(line, '='))) {
		error_messagef(&ctx->src, ctx->line, strlen(line) + 1, "expected '='");
		ctx->success = false;
		goto done_with_line;
	}

	*ptr = '\0';

	key = line;
	val = ptr - 1;
	while (is_whitespace(*val)) {
		*val = '\0';
		--val;
	}

	val = ptr + 1;
	while (is_whitespace(*val)) {
		++val;
	}

	if (!ctx->cb(ctx->octx, &ctx->src, ctx->sect, key, val, ctx->line)) {
		ctx->success = false;
	}

done_with_line:
	if (!ctx->success) {
		return ir_done;
	}

	++ctx->line;

	return ir_cont;
}

bool
ini_parse(const char *path, char **buf, inihcb cb, void *octx)
{
	*buf = NULL;
	bool ret = false;

	struct each_line_ctx ctx = {
		.octx = octx,
		.cb = cb,
		.line = 1,
		.success = true,
	};

	uint64_t len;
	if (!fs_read_entire_file(path, &ctx.src)) {
		goto ret;
	}

	len = ctx.src.len;
	*buf = z_malloc(len);
	memcpy(*buf, ctx.src.src, len);

	each_line(*buf, len, &ctx, each_line_cb);

	ret = true;
ret:
	fs_source_destroy(&ctx.src);
	return ret && ctx.success;
}