• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..10-Aug-2021-

Makefile.amH A D10-Aug-2021349 149

Makefile.makH A D10-Aug-2021226 148

README.scconfH A D10-Aug-20219.4 KiB330253

internal.hH A D10-Aug-20211.6 KiB6331

lex-parse.lH A D10-Aug-20212 KiB9351

parse.cH A D10-Aug-20219.9 KiB428345

scconf.cH A D10-Aug-20218.6 KiB428355

scconf.hH A D10-Aug-20215.7 KiB20068

sclex.cH A D10-Aug-20214 KiB202161

write.cH A D10-Aug-20214.3 KiB200155

README.scconf

1A short introduction to scconf as an API and a file format
2==========================================================
3written by Jamie Honan <jhonan@optusnet.com.au>
4
5The scconf system is a small system library for handling
6scconf files. Why should anyone care about scconf format?
7It is a handy format for short pieces of structured data.
8
9Handy because:
10  - it is readable, which makes support easy
11  - it is easy to parse and write
12  - it is extensible, you can add fields without breaking things
13
14It isn't
15  - XML, so it doesn't need xml parsing
16  - suitable for large amounts of data, like a database or text files
17
18It doesn't have
19  - anything else but data. No locking, no threads etc.
20
21It has hierarchical data blocks, it has lists.
22
23Similar, but different:
24  - .ini files. scconf is block structured, has lists and arrays
25  - xml. xml is more complete, but requires a lot of overhead
26  - sexp. sexp resembles lisp with it's use of parenthesis. sexp
27    has modes for binary. scconf really doesn't have binary
28  - yaml. yaml is larger
29
30What does it look like?
31=======================
32
33Like this:
34
35transport_stream {
36        id = 0x0009;
37        original_network_id = 0x1000;
38        sat_tuning_info {
39                frequency = 12278000;
40                symbol_rate = 30000000;
41                polarization = 0;
42        }
43        service {
44                id = 0x0064;
45                pmt_pid = 0x0101;
46                type = 144;
47                name = "aGuide";
48                provider_name = "A";
49        }
50        service {
51                id = 0x238D;
52                pmt_pid = 0x0623;
53                type = 144;
54                name = "aCar";
55                provider_name = "A";
56        }
57}
58
59Why doesn't it have X, why don't you use XML?
60=============================================
61
62Maybe it should. Maybe XML is the answer. Maybe a database
63is more appropriate. It's all a trade-off. You choose.
64
65
66API
67===
68
69There are four useful structures. scconf_block, scconf_list,
70scconf_item, and a scconf_context.
71
72A context is similar to a file, except in memory. Within
73a context there is a root block. Within each block
74there are one or more items. Items can be sub-blocks, lists, or
75comments. Every item can have a name, or key.
76
77A list can have one or more values; boolean, integer or string.
78
79A context contains a root block, which contains one or more blocks.
80
81A block is :
82
83key [[,] name [[,] name ... ] ] {
84	block_contents
85}
86
87block_contents is one or more block_items
88
89block_items is one of
90
91  # comment string \n
92or
93  key [[,] name [[,] name ... ] ] = value [[,] value ... ]];
94or
95  block
96
97Initialising and file handling
98==============================
99
100Allocate scconf_context
101The filename can be NULL. The file is not read at this point,
102but in the function scconf_parse.
103
104scconf_context *scconf_new(const char *filename);
105
106
107Free scconf_context
108
109void scconf_free(scconf_context * config);
110
111
112Parse configuration
113Returns 1 = ok, 0 = error, -1 = error opening config file
114
115int scconf_parse(scconf_context * config);
116
117
118 Write config to a file
119 If the filename is NULL, use the config->filename
120 Returns 0 = ok, else = errno
121
122int scconf_write(scconf_context * config, const char *filename);
123
124
125Finding items and blocks
126========================
127
128 Find a block by key
129 If the block is NULL, the root block is used
130
131const scconf_block *scconf_find_block(const scconf_context * config,
132	const scconf_block * block, const char *item_name);
133
134This finds a block in the given context. This function doesn't descend
135the hierarchy, it only finds blocks in the top level of either
136the context (the root block) or of the block given in the block
137parameter (if not NULL).
138
139The block pointer returned points to data held by the context, hence
140the const qualifier.
141
142
143 Find blocks by key and possibly name
144 If the block is NULL, the root block is used
145 The key can be used to specify what the blocks first name should be
146
147scconf_block **scconf_find_blocks(const scconf_context * config,
148	const scconf_block * block, const char *item_name, const char *key);
149
150This function is similar to scconf_find_block above, except that an array
151of pointers to matched blocks is returned. Each pointer points
152to data held by the context. The last entry in the returned table
153is the null pointer.
154
155The table should be freed after use, but the individual pointers to blocks
156point to data held by the context.
157
158The key values for blocks is matched. If name is not NULL, the block
159name must also match.
160
161
162 Get a list of values for option
163
164const scconf_list *scconf_find_list(const scconf_block * block, const char *option);
165
166Find an item that has a value (i.e. is not a block nor a comment), and
167return the values for that item as a list.
168
169The list is held in memory owned by the context.
170
171
172 Return the first string of the option
173 If no option found, return def
174
175const char *scconf_get_str(const scconf_block * block, const char *option, const char *def);
176
177This is similar to scconf_find_list, but instead of returning the whole
178list, just return the first value, as a string. If this is not possible,
179return the default value.
180
181Again the value returned is either a pointer the default value or to
182memory held by the context.
183
184
185 Return the first value of the option as integer
186 If no option found, return def
187
188int scconf_get_int(const scconf_block * block, const char *option, int def);
189
190This is similar to scconf_get_str, but an integer value is returned.
191
192
193 Return the first value of the option as boolean
194 If no option found, return def
195
196int scconf_get_bool(const scconf_block * block, const char *option, int def);
197
198This completes the types that can be returned by a find.
199
200
201For parsing blocks and items
202============================
203
204A table of scconf_entry values is used, terminated by a NULL name value.
205
206This table is passed to the routine scconf_parse_entries. This
207function walks the current context or block, and adds the data
208to the scconf_entry table entries.
209Sub-blocks can be walked, using SCCONF_BLOCK, and callbacks can be issued
210using SCCONF_CALLBACK.
211
212This is a handy method for accessing scconf data from within a program.
213
214typedef struct _scconf_entry {
215	const char *name;
216			 * Look for blocks with this key, or check if this
217			 * block has an item with this key. Run the block
218			 * or blocks found against the rest of this entry
219			 * Stop after the first one, unless
220			 * SCCONF_ALL_BLOCKS is set in flags
221	unsigned int type;
222			 * SCCONF_CALLBACK
223			 * 	parm contains a function ptr of type
224			 *      int (*callback)(scconf_context* context,
225			 *      	scconf_block* block,
226			 *      	scconf_entry* entry,
227			 *      	int depth);
228			 *      run the callback with the block found
229			 *
230			 * SCCONF_BLOCK
231			 *      param contains a pointer to another entry table
232			 *      use the found block against every entry
233			 *	in the pointed entry table
234			 *
235			 * SCCONF_LIST
236			 * SCCONF_BOOLEAN
237		  	 * SCCONF_INTEGER
238			 * SCCONF_STRING
239			 *      find the entry with the key given in name in
240			 *      the found block. Return the value found
241			 *      to parm as follows:
242			 *    SCCONF_INTEGER:
243			 *		if parm not NULL, then
244			 *		points to integer location to put
245			 *		the value
246			 *    SCCONF_BOOLEAN:
247			 *		if parm not NULL, then
248			 *		points to integer location to put
249			 *		the value
250			 *    SCCONF_STRING:
251			 *		if parm not NULL, then
252			 *		  if flag bit SCCONF_ALLOC not set
253			 *		     then parm points to a buffer
254			 *		  else
255			 *		     parm points to a pointer where
256			 *		     the pointer to an allocated
257			 *		     buffer should be stored.
258			 *		     if arg is not NULL, points
259			 *		     to a location where the buffer
260			 *		     length (size_t) is to be stored
261			 *    SCCONF_LIST:
262			 *		if parm not NULL, then
263			 *		  if flag bit SCCONF_ALLOC not set
264			 *		     then parm points to a location
265			 *		     where a pointer to the list
266			 *		     can be stored
267			 *		  else
268			 *		     then parm points to a location
269			 *		     where a pointer to a copy of list
270			 *		     can be stored
271			 *
272			 *
273	unsigned int flags;
274			 * SCCONF_PRESENT
275			 *       This bit is or'ed in when found
276			 * SCCONF_MANDATORY
277			 *       If not found, this is a fault
278			 * SCCONF_ALLOC
279			 *       C.f. type above
280			 * SCCONF_ALL_BLOCKS
281			 *       C.f. name above
282			 * SCCONF_VERBOSE
283			 *       For debugging
284	void *parm;
285	void *arg;
286} scconf_entry;
287
288
289For adding blocks and items
290===========================
291
292A table of scconf_entry values is used, terminated by a NULL name value.
293
294This table is passed to the routine scconf_write_entries. This
295function adds the scconf_entry table entries to the current block.
296Sub-blocks can be added, and callbacks can be issued.
297
298This is a handy method for adding scconf data from within a program.
299
300typedef struct _scconf_entry {
301	const char *name;
302			 * key value for blocks and items *
303	unsigned int type;
304			 * SCCONF_CALLBACK
305			 * 	parm contains a function ptr of type
306			 *      int (*callback)(scconf_context* context,
307			 *      	scconf_block* block,
308			 *      	scconf_entry* entry,
309			 *      	int depth);
310			 *
311			 * SCCONF_BLOCK
312			 *      param contains a pointer to another entry table
313			 *      the entry table is added as a block to the
314			 *      current block, with name as the key, and
315			 *      arg is a list of names
316			 *
317			 * SCCONF_LIST
318			 * SCCONF_BOOLEAN
319		  	 * SCCONF_INTEGER
320			 * SCCONF_STRING
321			 *      these add key=value pairs to the current
322			 *      block. The value is in parm.
323			 *
324	unsigned int flags;
325			 * SCCONF_PRESENT
326			 *       This bit is or'ed in when item added
327	void *parm;
328	void *arg;
329} scconf_entry;
330