-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.c
157 lines (137 loc) · 3.72 KB
/
config.c
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CONFIG_MAX_ITEMS 128
#define CONFIG_MAX_STRINGDATA (4096 * 3)
static char buffer[CONFIG_MAX_STRINGDATA];
static size_t buffer_next = 0;
typedef struct {
char *key;
char *val;
size_t klen;
size_t vlen;
} kv_t;
static kv_t entry[CONFIG_MAX_ITEMS];
static size_t entry_count;
size_t config_to_string(char *ptr, size_t max) {
char *start = ptr;
if (max == 0) {
return 0;
}
for (size_t n = 0; n < entry_count; n++) {
if ((entry[n].klen + entry[n].vlen + 3) > max) {
// require space for: space + key + equal + value + null
break;
}
if (n > 0) {
*ptr++ = ' ';
max--;
}
memcpy(ptr, entry[n].key, entry[n].klen);
ptr += entry[n].klen;
max -= entry[n].klen;
if (entry[n].vlen) {
*ptr++ = '=';
max--;
memcpy(ptr, entry[n].val, entry[n].vlen);
ptr += entry[n].vlen;
max -= entry[n].vlen;
}
}
*ptr++ = 0;
return ptr - start;
}
static void entry_add(const char *key, size_t klen, const char *val, size_t vlen) {
if (klen == 0) {
// empty keys are not allowed
return;
}
if ((klen > 1024) || (vlen > 1024)) {
// huge keys and values are not allowed
return;
}
if ((sizeof(buffer) - buffer_next) < (klen + vlen + 2)) {
// give up if it won't fit
return;
}
size_t n;
for (n = 0; n < entry_count; n++) {
if ((entry[n].klen == klen) && !memcmp(key, entry[n].key, klen)) {
goto write_value;
}
}
if (n == CONFIG_MAX_ITEMS) {
// no space in table
return;
}
// new entry
entry_count++;
entry[n].key = buffer + buffer_next;
entry[n].klen = klen;
memcpy(entry[n].key, key, klen);
entry[n].key[klen] = 0;
buffer_next += klen + 1;
write_value:
entry[n].val = buffer + buffer_next;
entry[n].vlen = vlen;
memcpy(entry[n].val, val, vlen);
entry[n].val[vlen] = 0;
buffer_next += vlen + 1;
}
void config_set(const char *key, const char *val) { entry_add(key, strlen(key), val, strlen(val)); }
void config_init(const char *ptr, size_t len) {
const char *key;
const char *val;
restart:
while (len > 0) {
if (isspace(*ptr)) {
ptr++;
len--;
continue;
}
key = ptr;
while (len > 0) {
if (*ptr == '=') {
size_t klen = ptr - key;
ptr++;
len--;
val = ptr;
while ((len > 0) && !isspace(*ptr)) {
len--;
ptr++;
}
size_t vlen = ptr - val;
entry_add(key, klen, val, vlen);
goto restart;
}
if (isspace(*ptr)) {
break;
}
ptr++;
len--;
}
size_t klen = ptr - key;
entry_add(key, klen, NULL, 0);
}
}
const char *config_get(const char *key, const char *_default) {
size_t klen = strlen(key);
for (size_t n = 0; n < entry_count; n++) {
if ((entry[n].klen == klen) && !memcmp(key, entry[n].key, klen)) {
return entry[n].val;
}
}
return _default;
}
uint32_t config_get_uint32(const char *key, uint32_t _default) {
const char *val = config_get(key, NULL);
if (val == NULL) {
return _default;
}
return atol(val);
}