summaryrefslogtreecommitdiff
path: root/pom.h
blob: 465d0428f48c88138588020de2d0809278ac4009 (plain)
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/// \file
/// POM configuration parser for C.
///
/// ## Thread-safety
///
/// A single configuration should not be used in multiple threads
/// (even for seemingly "read-only" operations)
/// without proper synchronization.
///
/// Other than that, all these functions are fully thread-safe.

/// \mainpage libpom doxygen documentation
/// 
/// See \ref pom.h for all types/functions.
#ifndef POM_H_
#define POM_H_

#ifndef POM_NO_STDIO
#include <stdio.h>
#endif
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>

/// A POM configuration
typedef struct pom_conf pom_conf;
/// A POM-related error
typedef struct pom_error pom_error;

/// Load a configuration using a `read`-like function.
///
/// On success, a configuration is returned and `*error` is set to `NULL`
/// if `error` is not `NULL`.
///
/// On failure, `NULL` is returned, and `*error` is filled out if `error` is not `NULL`,
/// in which case it must be freed with `free`.
///
/// Most of the time, you won't need this function:
/// use \ref pom_load_file to load from a `FILE *`,
/// \ref pom_load_path to load from a path,
/// and \ref pom_load_string to load from a string.
///
/// `read_func` will be passed the `userdata` pointer passed to this function,
/// a buffer, and the length of that buffer (which will be nonzero).
/// It must fill out the buffer as much as possible,
/// and return the number of bytes read.
/// A return value less than `len` indicates the end of the file was reached.
///
/// `filename` is only used for errors.
pom_conf *pom_load(const char *filename, size_t (*read_func)(void *userdata, char *buf, size_t len), void *userdata, pom_error **error);
#ifndef POM_NO_STDIO
/// Load configuration from a `FILE *`.
///
/// On success, a configuration is returned and `*error` is set to `NULL`
/// if `error` is not `NULL`.
///
/// On failure, `NULL` is returned, and `*error` is filled out if `error` is not `NULL`,
/// in which case it must be freed with `free`.
///
/// `filename` is only used for errors.
pom_conf *pom_load_file(const char *filename, FILE *file, pom_error **error);
/// Load configuration from a file path.
///
/// On success, a configuration is returned and `*error` is set to `NULL`
/// if `error` is not `NULL`.
///
/// On failure, `NULL` is returned, and `*error` is filled out if `error` is not `NULL`,
/// in which case it must be freed with `free`.
pom_conf *pom_load_path(const char *path, pom_error **error);
#endif
/// Load configuration from a string.
///
/// On success, a configuration is returned and `*error` is set to `NULL`
/// if `error` is not `NULL`.
///
/// On failure, `NULL` is returned, and `*error` is filled out if `error` is not `NULL`,
/// in which case it must be freed with `free`.
///
/// `filename` is only used for errors.
pom_conf *pom_load_string(const char *filename, const char *string, pom_error **error);
/// Get the message of this error.
///
/// This will be a string such as `"Duplicate key: foo.bar"`
///
/// See also \ref pom_error_print and \ref pom_error_to_string, which
/// are probably actually what you want in most cases.
const char *pom_error_message(const pom_error *error);
/// Get the name of the file where this error occured.
const char *pom_error_file(const pom_error *error);
/// Get line number where this error occured.
uint64_t pom_error_line(const pom_error *error);
/// Get next error in error list.
const pom_error *pom_error_next(const pom_error *error);
#ifndef POM_NO_STDIO
/// Print error to `stderr`.
///
/// Includes every error in an error list (see \ref pom_error_next).
void pom_error_print(const pom_error *error);
#endif
/// Convert error to string. Return value must be freed.
///
/// Includes every error in an error list (see \ref pom_error_next).
char *pom_error_to_string(const pom_error *error);
/// Get error from a POM function. Returns `NULL` if there was no error.
///
/// This does not need to be freed, and remainly valid only until \ref pom_conf_free,
/// `pom_conf_get_<type>`, or `pom_conf_get_<type>_or_default`
/// is called on `conf`.
const pom_error *pom_conf_error(const pom_conf *conf);
#ifndef POM_NO_STDIO
/// Print last error to `stderr`.
void pom_conf_print_last_error(const pom_conf *conf);
#endif
/// Get value of `key` in configuration, or `NULL` if key is not present.
const char *pom_conf_get(const pom_conf *conf, const char *key);
/// Get value of `key` in configuration, or use `dflt` if not present.
const char *pom_conf_get_or_default(const pom_conf *conf, const char *key, const char *dflt);
/// Get signed integer value of `key`.
///
/// If `key` is not set, returns `false`, and \ref pom_conf_error will be `NULL`
/// (`*value` is set to 0 in this case).
///
/// If `key` is set but not a valid integer,
/// returns `false`, and \ref pom_conf_error will be non-`NULL`
/// (`*value` is set to 0 in this case).
bool pom_conf_get_int(const pom_conf *conf, const char *key, int64_t *value);
/// Get signed integer value of `key`, or `dflt` if not present.
///
/// If `key` is set but not a valid integer,
/// returns `false`, and \ref pom_conf_error will be non-`NULL`
/// (`*value` is still set to `dflt` in this case).
bool pom_conf_get_int_or_default(const pom_conf *conf, const char *key, int64_t *value, int64_t dflt);
/// Get unsigned integer value of `key`.
///
/// If `key` is not set, returns `false`, and \ref pom_conf_error will be `NULL`
/// (`*value` is set to 0 in this case).
///
/// If `key` is set but not a valid unsigned integer,
/// returns `false`, and \ref pom_conf_error will be non-`NULL`
/// (`*value` is set to 0 in this case).
bool pom_conf_get_uint(const pom_conf *conf, const char *key, uint64_t *value);
/// Get unsigned integer value of `key`, or `dflt` if not present.
///
/// If `key` is set but not a valid unsigned integer,
/// returns `false`, and \ref pom_conf_error will be non-`NULL`
/// (`*value` is still set to `dflt` in this case).
bool pom_conf_get_uint_or_default(const pom_conf *conf, const char *key, uint64_t *value, uint64_t dflt);
/// Get floating-point value of `key`.
///
/// If `key` is not set, returns `false`, and \ref pom_conf_error will be `NULL`
/// (`*value` is set to 0.0 in this case).
///
/// If `key` is set but not a valid floating-point number,
/// returns `false`, and \ref pom_conf_error will be non-`NULL`
/// (`*value` is set to 0.0 in this case).
bool pom_conf_get_float(const pom_conf *conf, const char *key, double *value);
/// Get floating-point value of `key`, or `dflt` if not present.
///
/// If `key` is set but not a valid floating-point number,
/// returns `false`, and \ref pom_conf_error will be non-`NULL`
/// (`*value` is still set to `dflt` in this case).
bool pom_conf_get_float_or_default(const pom_conf *conf, const char *key, double *value, double dflt);
/// Get comma-separated list value of `key`, or `NULL` if not present. The return value must be freed with `free`.
///
/// The list is `NULL`-terminated.
///
/// Commas can be escaped in list entries using `\,`.
///
/// (`free`ing the list also frees the entries thanks to a "hack" where list entries are stored
///  inline after the entry pointers.)
char **pom_conf_get_list(const pom_conf *conf, const char *key);
/// Extract section out of POM configuration.
///
/// The returned section doesn't need to be freed, and is valid until
/// \ref pom_conf_free is called on the original configuration.
const pom_conf *pom_conf_section(const pom_conf *conf, const char *section);
/// Create a copy of `conf`.
///
/// The copy must be freed with \ref pom_conf_free.
///
/// Returns `NULL` (but does not set `conf`'s error) in the (rare) case of out-of-memory.
///
/// The copy is entirely independent from `conf` — it can be passed to a separate
/// thread without worry.
pom_conf *pom_conf_copy(const pom_conf *conf);
/// Merge keys from `other` into `conf`, preferring keys in `other`.
void pom_conf_merge(pom_conf *conf, const pom_conf *other);
/// Get all unread keys in `conf`.
///
/// The returned array is `NULL`-terminated, and must be freed with `free`.
///
/// (The entries of the array are stored inline with the array,
/// so they are freed when it is.)
char **pom_conf_unread_keys(pom_conf *conf);
#ifndef POM_NO_STDIO
/// Print `key: value` for each `key` in `conf` to `stdout`.
void pom_conf_print(const pom_conf *conf);
#endif
/// Free a POM configuration.
void pom_conf_free(pom_conf *conf);

#endif