aboutsummaryrefslogtreecommitdiff
path: root/lib/base/nconfig.h
blob: 12a3c6c4e16922c41e0861ac128fe4737c279485 (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
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 */