1 2 #ifndef JCONF_H 3 #define JCONF_H 4 5 /* 6 * JSON based configuration format class. 7 */ 8 9 /************************************************************************* 10 Copyright 2008 Graeme W. Gill 11 12 Permission is hereby granted, free of charge, to any person obtaining a copy 13 of this software and associated documentation files (the "Software"), to deal 14 in the Software without restriction, including without limitation the rights 15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 copies of the Software, and to permit persons to whom the Software is 17 furnished to do so, subject to the following conditions: 18 19 The above copyright notice and this permission notice shall be included in 20 all copies or substantial portions of the Software. 21 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 THE SOFTWARE. 29 30 *************************************************************************/ 31 32 33 /* General description: 34 35 Key names are UNIX style '/' separated paths, stored 36 in UTF8 format. The paths should not start with a '/'. 37 38 Duplicate key names are supported, but typically 39 will be avoided by the library user. 40 41 Five types are supported, NULL, 32 bit boolean, 64 bit real, 42 64 bit integer and string. Strings are always nul terminated. 43 44 */ 45 46 /* jcnf error codes */ 47 typedef enum { 48 jc_ok = 0, /* No error */ 49 jc_malloc, /* malloc, calloc or realloc failed */ 50 jc_lock_error, /* Error opening lock file */ 51 jc_locked, /* File is locked by someone else */ 52 jc_unlock, /* Unlock failed */ 53 jc_noexisting, /* No existing file to read */ 54 jc_stat, /* Unable to stat file */ 55 jc_changed, /* File has changed since it was read */ 56 jc_read_fail, /* Failure to read from the file */ 57 jc_parse_fail, /* Failure to parse from the file */ 58 jc_write_open, /* Failed to open file for writing */ 59 jc_write_fail, /* Failed to write to file */ 60 jc_write_close, /* Failed to close file after writing */ 61 jc_update_nomod, /* Attempt to update file that wasn't opened for modifications */ 62 jc_bad_addkey_params, /* Bad add_key() parameters */ 63 jc_unknown_key_type, /* An unrecognisd key type was encountered */ 64 jc_ix_oorange, /* Key index is out of range */ 65 jc_no_keyname, /* No key name provided when it is expected */ 66 jc_string_not_terminated /* String doesn't include nul */ 67 } jc_error; 68 69 /* Argument types */ 70 typedef enum { 71 jc_read = 0, /* Just read the config file */ 72 jc_modify = 1 /* Read the config file in preparation to write it */ 73 } jc_mod; 74 75 typedef enum { 76 jc_no_create = 0, /* Don't create the config if it doesn't exist */ 77 jc_create = 1 /* Create the config if it doesn't exist */ 78 } jc_crte; 79 80 /* Internal jcnf structure */ 81 82 /* The different type of values supported */ 83 typedef enum { 84 jc_null = 0, /* Null value */ 85 jc_boolean = 1, /* Boolean */ 86 jc_real = 2, /* double floating point */ 87 jc_integer = 3, /* 64 bit integer */ 88 jc_string = 4 /* UTF8 string, nul terminated */ 89 } jc_type; 90 91 /* A value */ 92 struct _jc_key { 93 char *key; /* Key path */ 94 jc_type type; /* Type of value */ 95 char *c_comment; /* C Comment */ 96 char *cpp_comment; /* C++ Comment */ 97 unsigned char *data; /* Pointer to data */ 98 size_t dataSize; /* Size of data */ 99 }; typedef struct _jc_key jc_key; 100 101 /* A recursion depth record used during parsing */ 102 struct _jc_recd { 103 char *key; /* Key name, or */ 104 int aix; /* Array index, -2 = no array */ 105 }; typedef struct _jc_recd jc_recd; 106 107 /* jcnf Object, representing the keys in a jcnf file */ 108 struct _jcnf { 109 jc_key **keys; /* Array of pointers to keys */ 110 int nkeys; /* Number of valid key pointers */ 111 int akeys; /* Number of allocated key poiters */ 112 jc_key *lk; /* Last key created */ 113 114 /* Parsing support, key recursion depth */ 115 jc_recd *recds; 116 int nrecd; /* Number of ised recd */ 117 int arecd; /* Allocate rec depth */ 118 119 /* Config & status */ 120 char *fname; /* filename */ 121 FILE *fp; /* opened, locked file */ 122 off_t rsize; /* Size of file when read */ 123 time_t rtime; /* Time the file was read */ 124 int modify; /* Opened for modifications */ 125 int create; /* Create if it doesn't exist */ 126 int locked; /* nz if file is locked */ 127 int modified; /* nz if keys have been modified */ 128 129 /* Locate the index of the next key matching the key name, starting */ 130 /* at the given index. Update the index to the matching key. */ 131 /* Look for an exact match if exact != 0, or leading match if exact = 0 */ 132 /* Search backwards if bwd != 0 or forwards if bwd = 0 */ 133 /* Set *ix = -1 to begin search from the end. */ 134 /* Return jc_ix_oorange if no more matchs. */ 135 jc_error (*locate_key)(struct _jcnf *p, int *ix, char *key, int exact, int bwd); 136 137 /* Retrieve a keys information. Return pointers may be NULL. */ 138 /* If ix >= 0, return the key of the given index. */ 139 /* jc_ix_oorange is returned when past end. */ 140 /* If ix == -1, return the first from the beginning matching key name. */ 141 /* (Returned data is internal to jcnf object, so call must copy it). */ 142 jc_error (*get_key)(struct _jcnf *p, int ix, char **key, jc_type *type, unsigned char **data, 143 size_t *dataSize, char **comment); 144 145 /* Set a keys information. */ 146 /* If ix >= 0, set the key of the given index. */ 147 /* jc_ix_oorange is returned when past end. */ 148 /* If ix == -1, overwrite an existing key with the same name, */ 149 /* or add a new key with that name at the end if there is no existing key. */ 150 jc_error (*set_key)(struct _jcnf *p, int ix, char *key, jc_type type, unsigned char *data, 151 size_t dataSize, char *comment); 152 153 /* Add a key value to the jcnf at the end, irrespective of whether there is */ 154 /* an existing key with that name. */ 155 jc_error (*add_key)(struct _jcnf *p, char *key, jc_type type, unsigned char *data, 156 size_t dataSize, char *comment); 157 158 /* Delete a key. */ 159 /* If ix >= 0, delete the key of the given index. */ 160 /* jc_ix_oorange is returned when past end. */ 161 /* If ix == -1, delete the key with the given name. */ 162 jc_error (*delete_key)(struct _jcnf *p, int ix, char *key); 163 164 /* Diagnostic - Print the value of a key */ 165 jc_error (*print_key)(struct _jcnf *p, int ix, FILE *fp); 166 167 /* Switch from read only to update of the config file. */ 168 /* (This re-opens the file and checks that it hasn't been */ 169 /* modified since it was read) */ 170 jc_error (*enable_modify)(struct _jcnf *p); 171 172 /* Save and changes out to the file, unlock it and and close it. */ 173 /* It can't be udated again after this. */ 174 jc_error (*update)(struct _jcnf *p); 175 176 /* Delete this object */ 177 void (*del)(struct _jcnf *p); 178 179 }; typedef struct _jcnf jcnf; 180 181 /* Create a new jcnf and read it's keys from the file. */ 182 /* Return NULL on error */ 183 jcnf *new_jcnf( 184 jc_error *pev, /* return error code on error */ 185 char *fname, /* Corresponding filename */ 186 jc_mod modify, /* Flag, nz to open for modification */ 187 jc_crte create /* Flag, nz to create if it doesn't exist (modify must be set) */ 188 ); 189 190 /* Utilities */ 191 192 /* Return a pointer to the nth element of the key name. */ 193 /* Return null if it is out of range or malloc failed. */ 194 /* Free the returned value when done. */ 195 char *jc_get_nth_elem(char *path, int n); 196 197 #endif /* JCNF_H */ 198 199 200