Safe Communication Framework 0.1.0 build feea4f9
ERTMS/ETCS safe communication (Subset-037 EuroRadio, Subset-098 RBC/RBC), CENELEC EN 50128 SIL 4 oriented
Loading...
Searching...
No Matches
config.c
Go to the documentation of this file.
1
9
10#include <ctype.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <strings.h> /* strcasecmp */
15
17static char *trim(char *s)
18{
19 size_t len;
20 size_t start = 0U;
21
22 if (s == NULL)
23 {
24 return s;
25 }
26 while ((s[start] != '\0') && (isspace((unsigned char)s[start]) != 0))
27 {
28 start++;
29 }
30 if (start > 0U)
31 {
32 (void)memmove(s, &s[start], strlen(&s[start]) + 1U);
33 }
34 len = strlen(s);
35 while ((len > 0U) && (isspace((unsigned char)s[len - 1U]) != 0))
36 {
37 s[len - 1U] = '\0';
38 len--;
39 }
40 return s;
41}
42
44static void strip_inline_comment(char *s)
45{
46 size_t i;
47
48 for (i = 0U; s[i] != '\0'; i++)
49 {
50 if ((s[i] == '#') && ((i == 0U) || (isspace((unsigned char)s[i - 1U]) != 0)))
51 {
52 s[i] = '\0';
53 return;
54 }
55 }
56}
57
58static bool store_entry(safecomm_config_t *cfg, const char *key, const char *value)
59{
60 if (cfg->count >= SAFECOMM_CONFIG_MAX_ENTRIES)
61 {
62 return false;
63 }
64 if ((strlen(key) >= SAFECOMM_CONFIG_MAX_KEY_LEN) || (strlen(value) >= SAFECOMM_CONFIG_MAX_VALUE_LEN))
65 {
66 return false;
67 }
68 (void)strcpy(cfg->entries[cfg->count].key, key);
69 (void)strcpy(cfg->entries[cfg->count].value, value);
70 cfg->count++;
71 return true;
72}
73
75{
76 FILE *fp;
77 char line[SAFECOMM_CONFIG_MAX_LINE_LEN];
78
79 if ((path == NULL) || (out == NULL))
80 {
82 }
83 (void)memset(out, 0, sizeof(*out));
84
85 fp = fopen(path, "re");
86 if (fp == NULL)
87 {
89 }
90
91 while (fgets(line, (int)sizeof(line), fp) != NULL)
92 {
93 char *eq;
94 char *key;
95 char *value;
96 size_t line_len = strlen(line);
97
98 if ((line_len + 1U) == sizeof(line) && (line[line_len - 1U] != '\n'))
99 {
100 (void)fclose(fp);
101 return SAFECOMM_STATUS_BUFFER_TOO_SMALL; /* line longer than the buffer */
102 }
103
104 (void)trim(line);
105 if ((line[0] == '\0') || (line[0] == '#'))
106 {
107 continue;
108 }
109
110 eq = strchr(line, '=');
111 if (eq == NULL)
112 {
113 continue; /* not a key=value line — ignored, not an error */
114 }
115 *eq = '\0';
116 key = trim(line);
117 value = eq + 1;
119 value = trim(value);
120
121 if (key[0] == '\0')
122 {
123 continue;
124 }
125 if (!store_entry(out, key, value))
126 {
127 (void)fclose(fp);
129 }
130 }
131
132 if (ferror(fp) != 0)
133 {
134 (void)fclose(fp);
136 }
137 (void)fclose(fp);
138 return SAFECOMM_STATUS_OK;
139}
140
141const char *safecomm_config_get_str(const safecomm_config_t *cfg, const char *key)
142{
143 uint32_t i;
144
145 if ((cfg == NULL) || (key == NULL))
146 {
147 return NULL;
148 }
149 for (i = 0U; i < cfg->count; i++)
150 {
151 if (strcmp(cfg->entries[i].key, key) == 0)
152 {
153 return cfg->entries[i].value;
154 }
155 }
156 return NULL;
157}
158
159safecomm_status_t safecomm_config_get_u32(const safecomm_config_t *cfg, const char *key, uint32_t *out)
160{
161 const char *s = safecomm_config_get_str(cfg, key);
162 unsigned long parsed;
163 char *end = NULL;
164
165 if ((out == NULL) || (s == NULL) || (s[0] == '\0'))
166 {
168 }
169 parsed = strtoul(s, &end, 10);
170 if ((end == s) || (*end != '\0') || (parsed > 0xFFFFFFFFUL))
171 {
173 }
174 *out = (uint32_t)parsed;
175 return SAFECOMM_STATUS_OK;
176}
177
178safecomm_status_t safecomm_config_get_bool(const safecomm_config_t *cfg, const char *key, bool *out)
179{
180 const char *s = safecomm_config_get_str(cfg, key);
181
182 if ((out == NULL) || (s == NULL))
183 {
185 }
186 if ((strcasecmp(s, "true") == 0) || (strcmp(s, "1") == 0))
187 {
188 *out = true;
189 return SAFECOMM_STATUS_OK;
190 }
191 if ((strcasecmp(s, "false") == 0) || (strcmp(s, "0") == 0))
192 {
193 *out = false;
194 return SAFECOMM_STATUS_OK;
195 }
197}
static char * trim(char *s)
Definition config.c:17
static void strip_inline_comment(char *s)
Definition config.c:44
File-based configuration for the Safe Communication Framework.
safecomm_status_t safecomm_config_load(const char *path, safecomm_config_t *out)
Load path into out (fully overwrites it).
Definition config.c:74
#define SAFECOMM_CONFIG_MAX_ENTRIES
Definition config.h:52
const char * safecomm_config_get_str(const safecomm_config_t *cfg, const char *key)
Raw string value for key.
Definition config.c:141
safecomm_status_t safecomm_config_get_bool(const safecomm_config_t *cfg, const char *key, bool *out)
Boolean value for key ("true"/"false"/"1"/"0", case-insensitive).
Definition config.c:178
safecomm_status_t safecomm_config_get_u32(const safecomm_config_t *cfg, const char *key, uint32_t *out)
Unsigned-integer value for key.
Definition config.c:159
safecomm_status_t
Result of a Safe Communication Framework operation.
Definition status.h:17
@ SAFECOMM_STATUS_INVALID_PARAM
Definition status.h:19
@ SAFECOMM_STATUS_BUFFER_TOO_SMALL
Definition status.h:28
@ SAFECOMM_STATUS_OK
Definition status.h:18
@ SAFECOMM_STATUS_TRANSPORT
Definition status.h:23
A loaded configuration file. Caller-allocated, opaque in use.
Definition config.h:66