Line |
Branch |
Exec |
Source |
1 |
|
|
/* |
2 |
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
|
|
* |
4 |
|
|
* Copyright 2024 Mike Becker, Olaf Wintermann All rights reserved. |
5 |
|
|
* |
6 |
|
|
* Redistribution and use in source and binary forms, with or without |
7 |
|
|
* modification, are permitted provided that the following conditions are met: |
8 |
|
|
* |
9 |
|
|
* 1. Redistributions of source code must retain the above copyright |
10 |
|
|
* notice, this list of conditions and the following disclaimer. |
11 |
|
|
* |
12 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
|
|
* notice, this list of conditions and the following disclaimer in the |
14 |
|
|
* documentation and/or other materials provided with the distribution. |
15 |
|
|
* |
16 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
17 |
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
20 |
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 |
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 |
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 |
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 |
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 |
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 |
|
|
* POSSIBILITY OF SUCH DAMAGE. |
27 |
|
|
*/ |
28 |
|
|
/** |
29 |
|
|
* @file properties.h |
30 |
|
|
* @brief Interface for parsing data from properties files. |
31 |
|
|
* @author Mike Becker |
32 |
|
|
* @author Olaf Wintermann |
33 |
|
|
* @copyright 2-Clause BSD License |
34 |
|
|
*/ |
35 |
|
|
|
36 |
|
|
#ifndef UCX_PROPERTIES_H |
37 |
|
|
#define UCX_PROPERTIES_H |
38 |
|
|
|
39 |
|
|
#include "common.h" |
40 |
|
|
#include "string.h" |
41 |
|
|
#include "map.h" |
42 |
|
|
#include "buffer.h" |
43 |
|
|
|
44 |
|
|
#include <stdio.h> |
45 |
|
|
#include <string.h> |
46 |
|
|
|
47 |
|
|
#ifdef __cplusplus |
48 |
|
|
extern "C" { |
49 |
|
|
#endif |
50 |
|
|
|
51 |
|
|
/** |
52 |
|
|
* Configures the expected characters for the properties parser. |
53 |
|
|
*/ |
54 |
|
|
struct cx_properties_config_s { |
55 |
|
|
/** |
56 |
|
|
* The key/value delimiter that shall be used. |
57 |
|
|
* This is '=' by default. |
58 |
|
|
*/ |
59 |
|
|
char delimiter; |
60 |
|
|
|
61 |
|
|
/** |
62 |
|
|
* The first comment character. |
63 |
|
|
* This is '#' by default. |
64 |
|
|
*/ |
65 |
|
|
char comment1; |
66 |
|
|
|
67 |
|
|
/** |
68 |
|
|
* The second comment character. |
69 |
|
|
* This is not set by default. |
70 |
|
|
*/ |
71 |
|
|
char comment2; |
72 |
|
|
|
73 |
|
|
/** |
74 |
|
|
* The third comment character. |
75 |
|
|
* This is not set by default. |
76 |
|
|
*/ |
77 |
|
|
char comment3; |
78 |
|
|
|
79 |
|
|
/* |
80 |
|
|
* The character, when appearing at the end of a line, continues that line. |
81 |
|
|
* This is '\' by default. |
82 |
|
|
*/ |
83 |
|
|
/** |
84 |
|
|
* Reserved for future use. |
85 |
|
|
*/ |
86 |
|
|
char continuation; |
87 |
|
|
}; |
88 |
|
|
|
89 |
|
|
/** |
90 |
|
|
* Typedef for the properties config. |
91 |
|
|
*/ |
92 |
|
|
typedef struct cx_properties_config_s CxPropertiesConfig; |
93 |
|
|
|
94 |
|
|
/** |
95 |
|
|
* Default properties configuration. |
96 |
|
|
*/ |
97 |
|
|
cx_attr_export |
98 |
|
|
extern const CxPropertiesConfig cx_properties_config_default; |
99 |
|
|
|
100 |
|
|
/** |
101 |
|
|
* Status codes for the properties interface. |
102 |
|
|
*/ |
103 |
|
|
enum cx_properties_status { |
104 |
|
|
/** |
105 |
|
|
* Everything is fine. |
106 |
|
|
*/ |
107 |
|
|
CX_PROPERTIES_NO_ERROR, |
108 |
|
|
/** |
109 |
|
|
* The input buffer does not contain more data. |
110 |
|
|
*/ |
111 |
|
|
CX_PROPERTIES_NO_DATA, |
112 |
|
|
/** |
113 |
|
|
* The input ends unexpectedly. |
114 |
|
|
* |
115 |
|
|
* This either happens when the last line does not terminate with a line |
116 |
|
|
* break, or when the input ends with a parsed key but no value. |
117 |
|
|
*/ |
118 |
|
|
CX_PROPERTIES_INCOMPLETE_DATA, |
119 |
|
|
/** |
120 |
|
|
* Not used as a status and never returned by any function. |
121 |
|
|
* |
122 |
|
|
* You can use this enumerator to check for all "good" status results |
123 |
|
|
* by checking if the status is less than @c CX_PROPERTIES_OK. |
124 |
|
|
* |
125 |
|
|
* A "good" status means, that you can refill data and continue parsing. |
126 |
|
|
*/ |
127 |
|
|
CX_PROPERTIES_OK, |
128 |
|
|
/** |
129 |
|
|
* Input buffer is @c NULL. |
130 |
|
|
*/ |
131 |
|
|
CX_PROPERTIES_NULL_INPUT, |
132 |
|
|
/** |
133 |
|
|
* The line contains a delimiter, but no key. |
134 |
|
|
*/ |
135 |
|
|
CX_PROPERTIES_INVALID_EMPTY_KEY, |
136 |
|
|
/** |
137 |
|
|
* The line contains data, but no delimiter. |
138 |
|
|
*/ |
139 |
|
|
CX_PROPERTIES_INVALID_MISSING_DELIMITER, |
140 |
|
|
/** |
141 |
|
|
* More internal buffer was needed, but could not be allocated. |
142 |
|
|
*/ |
143 |
|
|
CX_PROPERTIES_BUFFER_ALLOC_FAILED, |
144 |
|
|
/** |
145 |
|
|
* Initializing the properties source failed. |
146 |
|
|
* |
147 |
|
|
* @see cx_properties_read_init_func |
148 |
|
|
*/ |
149 |
|
|
CX_PROPERTIES_READ_INIT_FAILED, |
150 |
|
|
/** |
151 |
|
|
* Reading from a properties source failed. |
152 |
|
|
* |
153 |
|
|
* @see cx_properties_read_func |
154 |
|
|
*/ |
155 |
|
|
CX_PROPERTIES_READ_FAILED, |
156 |
|
|
/** |
157 |
|
|
* Sinking a k/v-pair failed. |
158 |
|
|
* |
159 |
|
|
* @see cx_properties_sink_func |
160 |
|
|
*/ |
161 |
|
|
CX_PROPERTIES_SINK_FAILED, |
162 |
|
|
}; |
163 |
|
|
|
164 |
|
|
/** |
165 |
|
|
* Typedef for the properties status enum. |
166 |
|
|
*/ |
167 |
|
|
typedef enum cx_properties_status CxPropertiesStatus; |
168 |
|
|
|
169 |
|
|
/** |
170 |
|
|
* Interface for working with properties data. |
171 |
|
|
*/ |
172 |
|
|
struct cx_properties_s { |
173 |
|
|
/** |
174 |
|
|
* The configuration. |
175 |
|
|
*/ |
176 |
|
|
CxPropertiesConfig config; |
177 |
|
|
|
178 |
|
|
/** |
179 |
|
|
* The text input buffer. |
180 |
|
|
*/ |
181 |
|
|
CxBuffer input; |
182 |
|
|
|
183 |
|
|
/** |
184 |
|
|
* Internal buffer. |
185 |
|
|
*/ |
186 |
|
|
CxBuffer buffer; |
187 |
|
|
}; |
188 |
|
|
|
189 |
|
|
/** |
190 |
|
|
* Typedef for the properties interface. |
191 |
|
|
*/ |
192 |
|
|
typedef struct cx_properties_s CxProperties; |
193 |
|
|
|
194 |
|
|
|
195 |
|
|
/** |
196 |
|
|
* Typedef for a properties sink. |
197 |
|
|
*/ |
198 |
|
|
typedef struct cx_properties_sink_s CxPropertiesSink; |
199 |
|
|
|
200 |
|
|
/** |
201 |
|
|
* A function that consumes a k/v-pair in a sink. |
202 |
|
|
* |
203 |
|
|
* The sink could be e.g. a map and the sink function would be calling |
204 |
|
|
* a map function to store the k/v-pair. |
205 |
|
|
* |
206 |
|
|
* @param prop the properties interface that wants to sink a k/v-pair |
207 |
|
|
* @param sink the sink |
208 |
|
|
* @param key the key |
209 |
|
|
* @param value the value |
210 |
|
|
* @retval zero success |
211 |
|
|
* @retval non-zero sinking the k/v-pair failed |
212 |
|
|
*/ |
213 |
|
|
cx_attr_nonnull |
214 |
|
|
typedef int(*cx_properties_sink_func)( |
215 |
|
|
CxProperties *prop, |
216 |
|
|
CxPropertiesSink *sink, |
217 |
|
|
cxstring key, |
218 |
|
|
cxstring value |
219 |
|
|
); |
220 |
|
|
|
221 |
|
|
/** |
222 |
|
|
* Defines a sink for k/v-pairs. |
223 |
|
|
*/ |
224 |
|
|
struct cx_properties_sink_s { |
225 |
|
|
/** |
226 |
|
|
* The sink object. |
227 |
|
|
*/ |
228 |
|
|
void *sink; |
229 |
|
|
/** |
230 |
|
|
* Optional custom data. |
231 |
|
|
*/ |
232 |
|
|
void *data; |
233 |
|
|
/** |
234 |
|
|
* A function for consuming k/v-pairs into the sink. |
235 |
|
|
*/ |
236 |
|
|
cx_properties_sink_func sink_func; |
237 |
|
|
}; |
238 |
|
|
|
239 |
|
|
|
240 |
|
|
/** |
241 |
|
|
* Typedef for a properties source. |
242 |
|
|
*/ |
243 |
|
|
typedef struct cx_properties_source_s CxPropertiesSource; |
244 |
|
|
|
245 |
|
|
/** |
246 |
|
|
* A function that reads data from a source. |
247 |
|
|
* |
248 |
|
|
* When the source is depleted, implementations SHALL provide an empty |
249 |
|
|
* string in the @p target and return zero. |
250 |
|
|
* A non-zero return value is only permitted in case of an error. |
251 |
|
|
* |
252 |
|
|
* The meaning of the optional parameters is implementation-dependent. |
253 |
|
|
* |
254 |
|
|
* @param prop the properties interface that wants to read from the source |
255 |
|
|
* @param src the source |
256 |
|
|
* @param target a string buffer where the read data shall be stored |
257 |
|
|
* @retval zero success |
258 |
|
|
* @retval non-zero reading the data failed |
259 |
|
|
*/ |
260 |
|
|
cx_attr_nonnull |
261 |
|
|
typedef int(*cx_properties_read_func)( |
262 |
|
|
CxProperties *prop, |
263 |
|
|
CxPropertiesSource *src, |
264 |
|
|
cxstring *target |
265 |
|
|
); |
266 |
|
|
|
267 |
|
|
/** |
268 |
|
|
* A function that may initialize additional memory for the source. |
269 |
|
|
* |
270 |
|
|
* @param prop the properties interface that wants to read from the source |
271 |
|
|
* @param src the source |
272 |
|
|
* @retval zero initialization was successful |
273 |
|
|
* @retval non-zero otherwise |
274 |
|
|
*/ |
275 |
|
|
cx_attr_nonnull |
276 |
|
|
typedef int(*cx_properties_read_init_func)( |
277 |
|
|
CxProperties *prop, |
278 |
|
|
CxPropertiesSource *src |
279 |
|
|
); |
280 |
|
|
|
281 |
|
|
/** |
282 |
|
|
* A function that cleans memory initialized by the read_init_func. |
283 |
|
|
* |
284 |
|
|
* @param prop the properties interface that wants to read from the source |
285 |
|
|
* @param src the source |
286 |
|
|
*/ |
287 |
|
|
cx_attr_nonnull |
288 |
|
|
typedef void(*cx_properties_read_clean_func)( |
289 |
|
|
CxProperties *prop, |
290 |
|
|
CxPropertiesSource *src |
291 |
|
|
); |
292 |
|
|
|
293 |
|
|
/** |
294 |
|
|
* Defines a properties source. |
295 |
|
|
*/ |
296 |
|
|
struct cx_properties_source_s { |
297 |
|
|
/** |
298 |
|
|
* The source object. |
299 |
|
|
* |
300 |
|
|
* For example a file stream or a string. |
301 |
|
|
*/ |
302 |
|
|
void *src; |
303 |
|
|
/** |
304 |
|
|
* Optional additional data pointer. |
305 |
|
|
*/ |
306 |
|
|
void *data_ptr; |
307 |
|
|
/** |
308 |
|
|
* Optional size information. |
309 |
|
|
*/ |
310 |
|
|
size_t data_size; |
311 |
|
|
/** |
312 |
|
|
* A function that reads data from the source. |
313 |
|
|
*/ |
314 |
|
|
cx_properties_read_func read_func; |
315 |
|
|
/** |
316 |
|
|
* Optional function that may prepare the source for reading data. |
317 |
|
|
*/ |
318 |
|
|
cx_properties_read_init_func read_init_func; |
319 |
|
|
/** |
320 |
|
|
* Optional function that cleans additional memory allocated by the |
321 |
|
|
* read_init_func. |
322 |
|
|
*/ |
323 |
|
|
cx_properties_read_clean_func read_clean_func; |
324 |
|
|
}; |
325 |
|
|
|
326 |
|
|
/** |
327 |
|
|
* Initialize a properties interface. |
328 |
|
|
* |
329 |
|
|
* @param prop the properties interface |
330 |
|
|
* @param config the properties configuration |
331 |
|
|
* @see cxPropertiesInitDefault() |
332 |
|
|
*/ |
333 |
|
|
cx_attr_nonnull |
334 |
|
|
cx_attr_export |
335 |
|
|
void cxPropertiesInit(CxProperties *prop, CxPropertiesConfig config); |
336 |
|
|
|
337 |
|
|
/** |
338 |
|
|
* Destroys the properties interface. |
339 |
|
|
* |
340 |
|
|
* @note Even when you are certain that you did not use the interface in a |
341 |
|
|
* way that caused a memory allocation, you should call this function anyway. |
342 |
|
|
* Future versions of the library might add features that need additional memory |
343 |
|
|
* and you really don't want to search the entire code where you might need |
344 |
|
|
* add call to this function. |
345 |
|
|
* |
346 |
|
|
* @param prop the properties interface |
347 |
|
|
*/ |
348 |
|
|
cx_attr_nonnull |
349 |
|
|
cx_attr_export |
350 |
|
|
void cxPropertiesDestroy(CxProperties *prop); |
351 |
|
|
|
352 |
|
|
/** |
353 |
|
|
* Destroys and re-initializes the properties interface. |
354 |
|
|
* |
355 |
|
|
* You might want to use this, to reset the parser after |
356 |
|
|
* encountering a syntax error. |
357 |
|
|
* |
358 |
|
|
* @param prop the properties interface |
359 |
|
|
*/ |
360 |
|
|
cx_attr_nonnull |
361 |
|
|
static inline void cxPropertiesReset(CxProperties *prop) { |
362 |
|
|
CxPropertiesConfig config = prop->config; |
363 |
|
|
cxPropertiesDestroy(prop); |
364 |
|
|
cxPropertiesInit(prop, config); |
365 |
|
|
} |
366 |
|
|
|
367 |
|
|
/** |
368 |
|
|
* Initialize a properties parser with the default configuration. |
369 |
|
|
* |
370 |
|
|
* @param prop (@c CxProperties*) the properties interface |
371 |
|
|
* @see cxPropertiesInit() |
372 |
|
|
*/ |
373 |
|
|
#define cxPropertiesInitDefault(prop) \ |
374 |
|
|
cxPropertiesInit(prop, cx_properties_config_default) |
375 |
|
|
|
376 |
|
|
/** |
377 |
|
|
* Fills the input buffer with data. |
378 |
|
|
* |
379 |
|
|
* After calling this function, you can parse the data by calling |
380 |
|
|
* cxPropertiesNext(). |
381 |
|
|
* |
382 |
|
|
* @remark The properties interface tries to avoid allocations. |
383 |
|
|
* When you use this function and cxPropertiesNext() interleaving, |
384 |
|
|
* no allocations are performed. However, you must not free the |
385 |
|
|
* pointer to the data in that case. When you invoke the fill |
386 |
|
|
* function more than once before calling cxPropertiesNext(), |
387 |
|
|
* the additional data is appended - inevitably leading to |
388 |
|
|
* an allocation of a new buffer and copying the previous contents. |
389 |
|
|
* |
390 |
|
|
* @param prop the properties interface |
391 |
|
|
* @param buf a pointer to the data |
392 |
|
|
* @param len the length of the data |
393 |
|
|
* @retval zero success |
394 |
|
|
* @retval non-zero a memory allocation was necessary but failed |
395 |
|
|
* @see cxPropertiesFill() |
396 |
|
|
*/ |
397 |
|
|
cx_attr_nonnull |
398 |
|
|
cx_attr_access_r(2, 3) |
399 |
|
|
cx_attr_export |
400 |
|
|
int cxPropertiesFilln( |
401 |
|
|
CxProperties *prop, |
402 |
|
|
const char *buf, |
403 |
|
|
size_t len |
404 |
|
|
); |
405 |
|
|
|
406 |
|
|
#ifdef __cplusplus |
407 |
|
|
} // extern "C" |
408 |
|
|
cx_attr_nonnull |
409 |
|
|
static inline int cxPropertiesFill( |
410 |
|
|
CxProperties *prop, |
411 |
|
|
cxstring str |
412 |
|
|
) { |
413 |
|
|
return cxPropertiesFilln(prop, str.ptr, str.length); |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
cx_attr_nonnull |
417 |
|
|
static inline int cxPropertiesFill( |
418 |
|
|
CxProperties *prop, |
419 |
|
|
cxmutstr str |
420 |
|
|
) { |
421 |
|
|
return cxPropertiesFilln(prop, str.ptr, str.length); |
422 |
|
|
} |
423 |
|
|
|
424 |
|
|
cx_attr_nonnull |
425 |
|
|
cx_attr_cstr_arg(2) |
426 |
|
|
static inline int cxPropertiesFill( |
427 |
|
|
CxProperties *prop, |
428 |
|
|
const char *str |
429 |
|
|
) { |
430 |
|
|
return cxPropertiesFilln(prop, str, strlen(str)); |
431 |
|
|
} |
432 |
|
|
|
433 |
|
|
extern "C" { |
434 |
|
|
#else // __cplusplus |
435 |
|
|
/** |
436 |
|
|
* Fills the input buffer with data. |
437 |
|
|
* |
438 |
|
|
* After calling this function, you can parse the data by calling |
439 |
|
|
* cxPropertiesNext(). |
440 |
|
|
* |
441 |
|
|
* @attention The properties interface tries to avoid allocations. |
442 |
|
|
* When you use this function and cxPropertiesNext() interleaving, |
443 |
|
|
* no allocations are performed. However, you must not free the |
444 |
|
|
* pointer to the data in that case. When you invoke the fill |
445 |
|
|
* function more than once before calling cxPropertiesNext(), |
446 |
|
|
* the additional data is appended - inevitably leading to |
447 |
|
|
* an allocation of a new buffer and copying the previous contents. |
448 |
|
|
* |
449 |
|
|
* @param prop the properties interface |
450 |
|
|
* @param str the text to fill in |
451 |
|
|
* @retval zero success |
452 |
|
|
* @retval non-zero a memory allocation was necessary but failed |
453 |
|
|
* @see cxPropertiesFilln() |
454 |
|
|
*/ |
455 |
|
|
#define cxPropertiesFill(prop, str) _Generic((str), \ |
456 |
|
|
cxstring: cx_properties_fill_cxstr, \ |
457 |
|
|
cxmutstr: cx_properties_fill_mutstr, \ |
458 |
|
|
char*: cx_properties_fill_str, \ |
459 |
|
|
const char*: cx_properties_fill_str) \ |
460 |
|
|
(prop, str) |
461 |
|
|
|
462 |
|
|
/** |
463 |
|
|
* @copydoc cxPropertiesFill() |
464 |
|
|
*/ |
465 |
|
|
cx_attr_nonnull |
466 |
|
11 |
static inline int cx_properties_fill_cxstr( |
467 |
|
|
CxProperties *prop, |
468 |
|
|
cxstring str |
469 |
|
|
) { |
470 |
|
11 |
return cxPropertiesFilln(prop, str.ptr, str.length); |
471 |
|
|
} |
472 |
|
|
|
473 |
|
|
/** |
474 |
|
|
* @copydoc cxPropertiesFill() |
475 |
|
|
*/ |
476 |
|
|
cx_attr_nonnull |
477 |
|
|
static inline int cx_properties_fill_mutstr( |
478 |
|
|
CxProperties *prop, |
479 |
|
|
cxmutstr str |
480 |
|
|
) { |
481 |
|
|
return cxPropertiesFilln(prop, str.ptr, str.length); |
482 |
|
|
} |
483 |
|
|
|
484 |
|
|
/** |
485 |
|
|
* @copydoc cxPropertiesFill() |
486 |
|
|
*/ |
487 |
|
|
cx_attr_nonnull |
488 |
|
|
cx_attr_cstr_arg(2) |
489 |
|
|
static inline int cx_properties_fill_str( |
490 |
|
|
CxProperties *prop, |
491 |
|
|
const char *str |
492 |
|
|
) { |
493 |
|
|
return cxPropertiesFilln(prop, str, strlen(str)); |
494 |
|
|
} |
495 |
|
|
#endif |
496 |
|
|
|
497 |
|
|
/** |
498 |
|
|
* Specifies stack memory that shall be used as internal buffer. |
499 |
|
|
* |
500 |
|
|
* @param prop the properties interface |
501 |
|
|
* @param buf a pointer to stack memory |
502 |
|
|
* @param capacity the capacity of the stack memory |
503 |
|
|
*/ |
504 |
|
|
cx_attr_nonnull |
505 |
|
|
cx_attr_export |
506 |
|
|
void cxPropertiesUseStack( |
507 |
|
|
CxProperties *prop, |
508 |
|
|
char *buf, |
509 |
|
|
size_t capacity |
510 |
|
|
); |
511 |
|
|
|
512 |
|
|
/** |
513 |
|
|
* Retrieves the next key/value-pair. |
514 |
|
|
* |
515 |
|
|
* This function returns zero as long as there are key/value-pairs found. |
516 |
|
|
* If no more key/value-pairs are found, #CX_PROPERTIES_NO_DATA is returned. |
517 |
|
|
* |
518 |
|
|
* When an incomplete line is encountered, #CX_PROPERTIES_INCOMPLETE_DATA is |
519 |
|
|
* returned, and you can add more data with #cxPropertiesFill(). |
520 |
|
|
* |
521 |
|
|
* @remark The incomplete line will be stored in an internal buffer, which is |
522 |
|
|
* allocated on the heap, by default. If you want to avoid allocations, |
523 |
|
|
* you can specify sufficient space with cxPropertiesUseStack() after |
524 |
|
|
* initialization with cxPropertiesInit(). |
525 |
|
|
* |
526 |
|
|
* @attention The returned strings will point into a buffer that might not be |
527 |
|
|
* available later. It is strongly recommended to copy the strings for further |
528 |
|
|
* use. |
529 |
|
|
* |
530 |
|
|
* @param prop the properties interface |
531 |
|
|
* @param key a pointer to the cxstring that shall contain the property name |
532 |
|
|
* @param value a pointer to the cxstring that shall contain the property value |
533 |
|
|
* @retval CX_PROPERTIES_NO_ERROR (zero) a key/value pair was found |
534 |
|
|
* @retval CX_PROPERTIES_NO_DATA there is no (more) data in the input buffer |
535 |
|
|
* @retval CX_PROPERTIES_INCOMPLETE_DATA the data in the input buffer is incomplete |
536 |
|
|
* (fill more data and try again) |
537 |
|
|
* @retval CX_PROPERTIES_NULL_INPUT the input buffer was never filled |
538 |
|
|
* @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
539 |
|
|
* @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
540 |
|
|
* @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
541 |
|
|
*/ |
542 |
|
|
cx_attr_nonnull |
543 |
|
|
cx_attr_nodiscard |
544 |
|
|
cx_attr_export |
545 |
|
|
CxPropertiesStatus cxPropertiesNext( |
546 |
|
|
CxProperties *prop, |
547 |
|
|
cxstring *key, |
548 |
|
|
cxstring *value |
549 |
|
|
); |
550 |
|
|
|
551 |
|
|
/** |
552 |
|
|
* Creates a properties sink for an UCX map. |
553 |
|
|
* |
554 |
|
|
* The values stored in the map will be pointers to freshly allocated, |
555 |
|
|
* zero-terminated C strings (@c char*), which means the @p map should have been |
556 |
|
|
* created with #CX_STORE_POINTERS. |
557 |
|
|
* |
558 |
|
|
* The default stdlib allocator will be used, unless you specify a custom |
559 |
|
|
* allocator in the optional @c data field of the returned sink. |
560 |
|
|
* |
561 |
|
|
* @param map the map that shall consume the k/v-pairs. |
562 |
|
|
* @return the sink |
563 |
|
|
* @see cxPropertiesLoad() |
564 |
|
|
*/ |
565 |
|
|
cx_attr_nonnull |
566 |
|
|
cx_attr_nodiscard |
567 |
|
|
cx_attr_export |
568 |
|
|
CxPropertiesSink cxPropertiesMapSink(CxMap *map); |
569 |
|
|
|
570 |
|
|
/** |
571 |
|
|
* Creates a properties source based on an UCX string. |
572 |
|
|
* |
573 |
|
|
* @param str the string |
574 |
|
|
* @return the properties source |
575 |
|
|
* @see cxPropertiesLoad() |
576 |
|
|
*/ |
577 |
|
|
cx_attr_nodiscard |
578 |
|
|
cx_attr_export |
579 |
|
|
CxPropertiesSource cxPropertiesStringSource(cxstring str); |
580 |
|
|
|
581 |
|
|
/** |
582 |
|
|
* Creates a properties source based on C string with the specified length. |
583 |
|
|
* |
584 |
|
|
* @param str the string |
585 |
|
|
* @param len the length |
586 |
|
|
* @return the properties source |
587 |
|
|
* @see cxPropertiesLoad() |
588 |
|
|
*/ |
589 |
|
|
cx_attr_nonnull |
590 |
|
|
cx_attr_nodiscard |
591 |
|
|
cx_attr_access_r(1, 2) |
592 |
|
|
cx_attr_export |
593 |
|
|
CxPropertiesSource cxPropertiesCstrnSource(const char *str, size_t len); |
594 |
|
|
|
595 |
|
|
/** |
596 |
|
|
* Creates a properties source based on a C string. |
597 |
|
|
* |
598 |
|
|
* The length will be determined with strlen(), so the string MUST be |
599 |
|
|
* zero-terminated. |
600 |
|
|
* |
601 |
|
|
* @param str the string |
602 |
|
|
* @return the properties source |
603 |
|
|
* @see cxPropertiesLoad() |
604 |
|
|
*/ |
605 |
|
|
cx_attr_nonnull |
606 |
|
|
cx_attr_nodiscard |
607 |
|
|
cx_attr_cstr_arg(1) |
608 |
|
|
cx_attr_export |
609 |
|
|
CxPropertiesSource cxPropertiesCstrSource(const char *str); |
610 |
|
|
|
611 |
|
|
/** |
612 |
|
|
* Creates a properties source based on an FILE. |
613 |
|
|
* |
614 |
|
|
* @param file the file |
615 |
|
|
* @param chunk_size how many bytes may be read in one operation |
616 |
|
|
* |
617 |
|
|
* @return the properties source |
618 |
|
|
* @see cxPropertiesLoad() |
619 |
|
|
*/ |
620 |
|
|
cx_attr_nonnull |
621 |
|
|
cx_attr_nodiscard |
622 |
|
|
cx_attr_access_r(1) |
623 |
|
|
cx_attr_export |
624 |
|
|
CxPropertiesSource cxPropertiesFileSource(FILE *file, size_t chunk_size); |
625 |
|
|
|
626 |
|
|
|
627 |
|
|
/** |
628 |
|
|
* Loads properties data from a source and transfers it to a sink. |
629 |
|
|
* |
630 |
|
|
* This function tries to read as much data from the source as possible. |
631 |
|
|
* When the source was completely consumed and at least on k/v-pair was found, |
632 |
|
|
* the return value will be #CX_PROPERTIES_NO_ERROR. |
633 |
|
|
* When the source was consumed but no k/v-pairs were found, the return value |
634 |
|
|
* will be #CX_PROPERTIES_NO_DATA. |
635 |
|
|
* In case the source data ends unexpectedly, the #CX_PROPERTIES_INCOMPLETE_DATA |
636 |
|
|
* is returned. In that case you should call this function again with the same |
637 |
|
|
* sink and either an updated source or the same source if the source is able to |
638 |
|
|
* yield the missing data. |
639 |
|
|
* |
640 |
|
|
* The other result codes apply, according to their description. |
641 |
|
|
* |
642 |
|
|
* @param prop the properties interface |
643 |
|
|
* @param sink the sink |
644 |
|
|
* @param source the source |
645 |
|
|
* @retval CX_PROPERTIES_NO_ERROR (zero) a key/value pair was found |
646 |
|
|
* @retval CX_PROPERTIES_READ_INIT_FAILED initializing the source failed |
647 |
|
|
* @retval CX_PROPERTIES_READ_FAILED reading from the source failed |
648 |
|
|
* @retval CX_PROPERTIES_SINK_FAILED sinking the properties into the sink failed |
649 |
|
|
* @retval CX_PROPERTIES_NO_DATA the source did not provide any key/value pairs |
650 |
|
|
* @retval CX_PROPERTIES_INCOMPLETE_DATA the source did not provide enough data |
651 |
|
|
* @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
652 |
|
|
* @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
653 |
|
|
* @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
654 |
|
|
*/ |
655 |
|
|
cx_attr_nonnull |
656 |
|
|
cx_attr_export |
657 |
|
|
CxPropertiesStatus cxPropertiesLoad( |
658 |
|
|
CxProperties *prop, |
659 |
|
|
CxPropertiesSink sink, |
660 |
|
|
CxPropertiesSource source |
661 |
|
|
); |
662 |
|
|
|
663 |
|
|
#ifdef __cplusplus |
664 |
|
|
} // extern "C" |
665 |
|
|
#endif |
666 |
|
|
|
667 |
|
|
#endif // UCX_PROPERTIES_H |
668 |
|
|
|