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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
|
#ifndef NC_NCONFIG_H
#define NC_NCONFIG_H 1
#include <stdio.h>
#include <stdlib.h>
/*
* Superblock definitions
*/
#define NC_SB_MAGIC ("\0\11\22") // Superblock identifier
/*
* Key type definitions
*/
#define NC_DIR 0x01 // The key is a directory
#define NC_STRING 0x02 // The key contains a string
#define NC_INT 0x03 // The key contains a signed integer
#define NC_UINT 0x04 // The key contains an unsigned integer
#define NC_RAW 0x05 // The key contains raw data
#define NC_DOUBLE 0x06 // The key contains a double
#define NC_LINK 0x07 // The key points somewhere else
/*
* File access definitions
*/
#define NC_O_RO 0x01 // Open file in read-only mode
#define NC_O_RW 0x02 // Open file in read-write mode
/*
* Lock types
*/
#define NC_L_NONE 0x00 // No lock
#define NC_L_RO 0x01 // Read-only lock
#define NC_L_RW 0x02 // Read-write lock
/*
* Error codes
*/
#define NC_ERR_OK 0 // Everything is OK
#define NC_ERR_TYPE -1 // Type mismatch
#define NC_ERR_NDIR -2 // Key is not a directory
#define NC_ERR_PERM -3 // Operation is not allowed
#define NC_ERR_NMEM -4 // Not enough memory to complete operation
#define NC_ERR_NEXIST -5 // Key does not exist
#define NC_ERR_NFILE -6 // No file is assigned/open
#define NC_ERR_CORRUPT -7 // File is corrupted
#define NC_ERR_NVAL -8 // Invalid value
#define NC_ERR_RDONLY -9 // File is open in read-only mode
#define NC_ERR_NOSUPPORT -10 // Support is not compiled-in
/*
* Truth value definitions
*/
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*
* Header of the config file.
*/
struct nc_sb_s {
char magic[4]; // superblock magic
unsigned size; // Current file size
unsigned ent_inc; // directory increment
unsigned chunk_inc; // Memory chunks increment
unsigned size_inc; // file size increment
unsigned chunk_ttl; // size of chunkmap
unsigned chunk; // pointer to chunkmap
unsigned root; // pointer to root direntry
unsigned modtime; // file version
};
/*
* Free chunk descriptor
*/
struct nc_chunk_s {
unsigned offset;
unsigned size;
};
/*
* In-file directory entry
*/
struct nc_de_s {
unsigned name;
unsigned type;
unsigned parent;
unsigned offset;
unsigned pages;
unsigned crc;
};
/*
* Ls reporting
*/
struct nc_ls_s {
const char *name;
unsigned type;
};
class NConfig
{
public:
/*
* Class constructor
* pass TRUE as parameter to enable
* write protection when leaving library
*/
NConfig(int protect = FALSE);
virtual ~NConfig();
/*
* Set file name (prior to open)
* Errors:
* NC_ERR_PERM file is already open
* NC_ERR_NVAL no file name is given
*/
int setName(const char *name);
/*
* Open the configuration file, re-open it
* Errors:
* NC_ERR_NFILE no file name is assigned
* NC_ERR_TYPE file open mode is invalid
* NC_ERR_PERM file cannot be opened/created
* NC_ERR_NMEM unable to mmap the file
* NC_ERR_CORRUPT superblock magic mismatch
*/
int open(const int how = NC_O_RW);
/*
* Close the configuration file
* No errors defined
*/
void close();
void flush(); // flush file if not mmap'ed
/*
* Create a new file
* resize is filesize increment is system pages
* dirent is directory increment
* mchunks is memory block increment
* Errors:
* NC_ERR_PERM file already exists
* NC_ERR_NFILE cannot create new file
* NC_ERR_NVAL file is already open
*/
int createNew(unsigned resize = 4, unsigned dirent = 32, unsigned mchunks = 32);
/*
* Get an unsigned integer
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_NEXIST the key does not exist
* NC_ERR_TYPE the key exists, but is of different type
*/
int getKey(const char *name, unsigned &value);
int getKey(const char *name, unsigned long long &value);
/*
* Get a signed integer
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_NEXIST the key does not exist
* NC_ERR_TYPE the key exists, but is of different type
*/
int getKey(const char *name, int &value);
int getKey(const char *name, signed long long &value);
/*
* Get a string
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_NEXIST the key does not exist
* NC_ERR_TYPE the key exists, but is of different type
*/
int getKey(const char *name, char *&value);
/*
* Get a long double
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_NEXIST the key does not exist
* NC_ERR_TYPE the key exists, but is of different type
*/
int getKey(const char *name, double &value);
int getKey(const char *name, long double &value);
/*
* Get raw data
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_NEXIST the key does not exist
* NC_ERR_TYPE the key exists, but is of different type
*/
int getKey(const char *name, char *&value, unsigned &len);
/*
* Insert an unsigned integer
* NC_ERR_NFILE no file is open
* NC_ERR_RDONLY file is open in read-only mode
* NC_ERR_PERM intermediate key is not a directory
* NC_ERR_TYPE key already exists, but is not an usigned integer
* NC_ERR_NEXIST key does not exist (should NEVER happen)
*/
int setKey(const char *name, const unsigned value);
int setKey(const char *name, const unsigned long long value);
/*
* Insert an integer
* NC_ERR_NFILE no file is open
* NC_ERR_RDONLY file is open in read-only mode
* NC_ERR_PERM intermediate key is not a directory
* NC_ERR_TYPE key already exists, but is not a signed integer
* NC_ERR_NEXIST key does not exist (should NEVER happen)
*/
int setKey(const char *name, const int value);
int setKey(const char *name, const signed long long value);
/*
* Insert a string
* NC_ERR_NFILE no file is open
* NC_ERR_RDONLY file is open in read-only mode
* NC_ERR_PERM intermediate key is not a directory
* NC_ERR_TYPE key already exists, but is not a string
* NC_ERR_NEXIST key does not exist (should NEVER happen)
*/
int setKey(const char *name, const char *value);
/*
* Insert raw data
* NC_ERR_NFILE no file is open
* NC_ERR_RDONLY file is open in read-only mode
* NC_ERR_PERM intermediate key is not a directory
* NC_ERR_TYPE key already exists, but is not raw data
* NC_ERR_NEXIST key does not exist (should NEVER happen)
*/
int setKey(const char *name, const char *value, const unsigned len);
/*
* Insert a double
* NC_ERR_NFILE no file is open
* NC_ERR_RDONLY file is open in read-only mode
* NC_ERR_PERM intermediate key is not a directory
* NC_ERR_TYPE key already exists, but is not raw data
* NC_ERR_NEXIST key does not exist (should NEVER happen)
*/
int setKey(const char *name, const double value);
int setKey(const char *name, const long double value);
/*
* Rename a key
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_RDONLY file is open read-only
* NC_ERR_NEXIST the key does not exist
* NC_ERR_PERM key with specified name already exists
*/
int renameKey(const char *oldname, const char *newname);
/*
* Delete a key
* No errors defined
*/
void delKey(const char *name);
/*
* Create a directory
* entries parameter specifies number of direntries to preallocate
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_RDONLY file is open in read-only mode
* NC_ERR_PERM intermediate key is not a directory
* NC_ERR_TYPE key already exists, but is not a directory
* NC_ERR_NEXIST key does not exist (should NEVER happen)
*/
int createDir(const char *name, unsigned entries = 0);
/*
* Change working directory
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_NDIR target key is not a directory
* NC_ERR_NEXIST target key direcotry does not exist
*/
int chDir(const char *name);
/*
* Print working directory
* Errors:
* Returns NULL on error
*/
const char *pwDir();
/*
* List all keys in current/specified directory
* Result is a NULL-terminated array of nc_ls_s
* structures.
* Errors:
* Returns NULL on error
* Note:
* You need to free the returned pointer,
* as well as all the names in it.
*/
struct nc_ls_s *ls(const char *dir = NULL);
/*
* Lock file
* This will block until lock becomes available
* type is either:
* NC_L_RO for read-only lock
* NC_L_RW for read-write lock
* No errors defined
*
* NOTE: lock may get promoted
*/
void lockFile(int type, int force = FALSE);
/*
* Unlock file
* No errors defined
*/
void unLockFile();
/*
* Print out (to stderr) information about current file
* No errors defined
*/
void status();
/*
* Return version string
*/
static char *version();
/*
* Dump current file to XML
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_PERM could not write XML output
*/
int toXML(const char *filename);
/*
* Load XML to current file
* a file has to be open
* force can be
* TRUE - existing keys will be deleted
* FALSE - import will ignore a key if existing key type conflicts
* Errors:
* NC_ERR_NFILE no file is open
* NC_ERR_PERM file is open read-only
*/
int fromXML(const char *filename, int force = TRUE);
protected:
int fd, omode, lock, careful;
char *fname, *data, *cname;
unsigned lsize, update;
unsigned revision, olck;
struct nc_sb_s *sb;
struct nc_de_s *rdir, *cdir;
struct nc_chunk_s *chunks;
int _setKey(const char *, const unsigned, const char *, const unsigned);
void _delKey(const char *, struct nc_de_s *, int);
void expand(unsigned);
void fast_free(unsigned);
unsigned getChunk(unsigned);
void freeChunk(unsigned);
static inline unsigned alignSize(unsigned);
struct nc_de_s *getDirEnt(const char *, struct nc_de_s * = NULL);
struct nc_de_s *insert(unsigned, struct nc_de_s *);
char *canonize(const char *);
char *getName(const struct nc_de_s *);
void _remap(const size_t, const size_t);
inline unsigned crc(const char *, unsigned);
void store(nc_de_s *, FILE *);
void restore(void *, int);
};
#endif /* NC_NCONFIG_H */
|