2000-04-14 11:27:14 +00:00
|
|
|
#ifndef __ICONFIG_H
|
|
|
|
|
#define __ICONFIG_H
|
|
|
|
|
|
|
|
|
|
enum {
|
2015-09-19 18:00:23 +01:00
|
|
|
NODE_TYPE_KEY,
|
|
|
|
|
NODE_TYPE_VALUE,
|
|
|
|
|
NODE_TYPE_INCLUDE,
|
|
|
|
|
NODE_TYPE_BLOCK,
|
|
|
|
|
NODE_TYPE_LIST,
|
|
|
|
|
NODE_TYPE_COMMENT,
|
|
|
|
|
|
|
|
|
|
NODE_TYPE_COUNT
|
2000-04-14 11:27:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define has_node_value(a) \
|
2015-09-19 18:00:23 +01:00
|
|
|
((a)->type == NODE_TYPE_KEY || (a)->type == NODE_TYPE_VALUE || \
|
|
|
|
|
(a)->type == NODE_TYPE_INCLUDE)
|
|
|
|
|
|
2000-04-14 11:27:14 +00:00
|
|
|
#define is_node_list(a) \
|
|
|
|
|
((a)->type == NODE_TYPE_BLOCK || (a)->type == NODE_TYPE_LIST)
|
|
|
|
|
|
2008-03-11 14:55:46 +00:00
|
|
|
typedef struct _CONFIG_NODE CONFIG_NODE;
|
|
|
|
|
typedef struct _CONFIG_REC CONFIG_REC;
|
2015-09-19 18:00:23 +01:00
|
|
|
typedef struct _CONFIG_INCLUDE CONFIG_INCLUDE;
|
2008-03-11 14:55:46 +00:00
|
|
|
|
2001-01-01 07:45:54 +00:00
|
|
|
struct _CONFIG_NODE {
|
2000-04-14 11:27:14 +00:00
|
|
|
int type;
|
|
|
|
|
char *key;
|
|
|
|
|
void *value;
|
2001-01-01 07:45:54 +00:00
|
|
|
};
|
2000-04-14 11:27:14 +00:00
|
|
|
|
2015-09-19 18:00:23 +01:00
|
|
|
struct _CONFIG_INCLUDE {
|
|
|
|
|
/* the user probably specified a relative path from the root config, store
|
|
|
|
|
it for writing back, but set the rec->fname to the absolute path */
|
|
|
|
|
char *original_path;
|
|
|
|
|
CONFIG_REC *rec;
|
|
|
|
|
};
|
|
|
|
|
|
2000-04-14 11:27:14 +00:00
|
|
|
/* a = { x=y; y=z; }
|
|
|
|
|
|
|
|
|
|
node1: type = NODE_TYPE_BLOCK, key = "a", value = (GSList *) nodes
|
|
|
|
|
nodes: (node2, node3)
|
|
|
|
|
node2: type = NODE_TYPE_KEY, key = "x", value = (char *) "y"
|
|
|
|
|
node3: type = NODE_TYPE_KEY, key = "y", value = (char *) "z"
|
|
|
|
|
|
|
|
|
|
b = ( a, { b=c; d=e; } )
|
|
|
|
|
|
|
|
|
|
node1: type = NODE_TYPE_LIST, key = "b", value = (GSList *) nodes
|
|
|
|
|
nodes: (node2, node3)
|
|
|
|
|
node2: type = NODE_TYPE_VALUE, key = NULL, value = (char *) "a"
|
|
|
|
|
node4: type = NODE_TYPE_BLOCK, key = NULL, value = (GSList *) nodes2
|
|
|
|
|
nodes2: (node4, node5)
|
|
|
|
|
node4: type = NODE_TYPE_KEY, key = "b", value = (char *) "c"
|
|
|
|
|
node5: type = NODE_TYPE_KEY, key = "d", value = (char *) "e"
|
|
|
|
|
|
|
|
|
|
Comments node has key=NULL and value is the comment line. Empty lines are
|
|
|
|
|
also in comments so they won't be forgotten when the config file is
|
|
|
|
|
written.
|
|
|
|
|
|
2015-09-19 18:00:23 +01:00
|
|
|
Include nodes have key=NULL, the path value is stored in CONFIG_INCLUDE's
|
|
|
|
|
original_path member as it's usually converted to an absolute path. All of
|
|
|
|
|
the include node's modifications and caches are stored in the 'root' config
|
|
|
|
|
and a write of the root config causes all included configs to be written
|
|
|
|
|
whether a modification has been made in them or not. A list of included
|
|
|
|
|
file names is maintained in the root rec to prevent circular inclusions.
|
|
|
|
|
It could eventually be better to keep a list of GFiles and use g_file_equal
|
|
|
|
|
for the comparison, but right now it doesn't even cover symbolic links.
|
|
|
|
|
|
2000-04-14 11:27:14 +00:00
|
|
|
*/
|
|
|
|
|
|
2001-01-01 07:45:54 +00:00
|
|
|
struct _CONFIG_REC {
|
2015-09-19 18:00:23 +01:00
|
|
|
/* used for updating the root config's modifycounter from included configs */
|
|
|
|
|
CONFIG_REC *root_rec;
|
|
|
|
|
/* this list is only maintained in the root_rec, it's to prevent circular
|
|
|
|
|
inclusions */
|
|
|
|
|
GHashTable *includes;
|
2000-04-14 11:27:14 +00:00
|
|
|
char *fname;
|
2000-11-26 02:17:14 +00:00
|
|
|
int create_mode;
|
2015-09-19 18:00:23 +01:00
|
|
|
/* use config_rec_increase_modifycounter every time something changes */
|
|
|
|
|
int modifycounter;
|
2000-04-14 11:27:14 +00:00
|
|
|
|
|
|
|
|
char *last_error;
|
|
|
|
|
CONFIG_NODE *mainnode;
|
2000-05-10 13:57:42 +00:00
|
|
|
GHashTable *cache; /* path -> node (for querying) */
|
2000-11-26 02:17:14 +00:00
|
|
|
GHashTable *cache_nodes; /* node -> path (for removing) */
|
2000-04-14 11:27:14 +00:00
|
|
|
|
|
|
|
|
GScanner *scanner;
|
|
|
|
|
|
|
|
|
|
/* while writing to configuration file.. */
|
2009-01-16 17:12:27 +00:00
|
|
|
GIOChannel *handle;
|
2000-04-14 11:27:14 +00:00
|
|
|
int tmp_indent_level; /* indentation position */
|
|
|
|
|
int tmp_last_lf; /* last character was a line feed */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Open configuration. The file is created if it doesn't exist, unless
|
|
|
|
|
`create_mode' is -1. `fname' can be NULL if you just want to use
|
|
|
|
|
config_parse_data() */
|
|
|
|
|
CONFIG_REC *config_open(const char *fname, int create_mode);
|
|
|
|
|
/* Release all memory used by configuration */
|
|
|
|
|
void config_close(CONFIG_REC *rec);
|
|
|
|
|
/* Change file name of config file */
|
|
|
|
|
void config_change_file_name(CONFIG_REC *rec, const char *fname, int create_mode);
|
|
|
|
|
|
|
|
|
|
/* Parse configuration file */
|
|
|
|
|
int config_parse(CONFIG_REC *rec);
|
2008-03-11 13:26:33 +00:00
|
|
|
/* Parse configuration found from `data'. `input_name' specifies the
|
2000-04-14 11:27:14 +00:00
|
|
|
"configuration name" which is displayed in error messages. */
|
|
|
|
|
int config_parse_data(CONFIG_REC *rec, const char *data, const char *input_name);
|
|
|
|
|
|
|
|
|
|
/* Write configuration file. Write to `fname' if it's not NULL.
|
|
|
|
|
If `create_mode' is -1, use the one that was given to config_open(). */
|
|
|
|
|
int config_write(CONFIG_REC *rec, const char *fname, int create_mode);
|
|
|
|
|
|
|
|
|
|
#define config_last_error(rec) \
|
|
|
|
|
(rec)->last_error
|
|
|
|
|
|
|
|
|
|
/* Getting values
|
|
|
|
|
|
|
|
|
|
`section' is something like "maingroup/key/subkey", or with lists
|
|
|
|
|
"maingroup/(list/subkey"
|
|
|
|
|
|
|
|
|
|
`def' is returned if the value is not found. */
|
|
|
|
|
char *config_get_str(CONFIG_REC *rec, const char *section, const char *key, const char *def);
|
|
|
|
|
int config_get_int(CONFIG_REC *rec, const char *section, const char *key, int def);
|
|
|
|
|
int config_get_bool(CONFIG_REC *rec, const char *section, const char *key, int def);
|
|
|
|
|
|
2000-08-26 15:39:44 +00:00
|
|
|
/* Returns n'th node from list. */
|
2002-02-15 22:18:35 +00:00
|
|
|
CONFIG_NODE *config_node_nth(CONFIG_NODE *node, int index);
|
|
|
|
|
/* Returns index for given key */
|
|
|
|
|
int config_node_index(CONFIG_NODE *parent, const char *key);
|
2001-09-22 15:24:40 +00:00
|
|
|
|
|
|
|
|
/* Returns the first non-comment node in list */
|
|
|
|
|
GSList *config_node_first(GSList *list);
|
2001-09-22 14:53:54 +00:00
|
|
|
/* Returns the next non-comment node in list */
|
|
|
|
|
GSList *config_node_next(GSList *list);
|
2000-04-14 11:27:14 +00:00
|
|
|
|
|
|
|
|
/* Setting values */
|
|
|
|
|
int config_set_str(CONFIG_REC *rec, const char *section, const char *key, const char *value);
|
|
|
|
|
int config_set_int(CONFIG_REC *rec, const char *section, const char *key, int value);
|
|
|
|
|
int config_set_bool(CONFIG_REC *rec, const char *section, const char *key, int value);
|
|
|
|
|
|
|
|
|
|
/* Handling the configuration directly with nodes -
|
|
|
|
|
useful when you need to read all values in a block/list. */
|
2015-09-20 20:45:06 +01:00
|
|
|
CONFIG_NODE *config_node_find(CONFIG_NODE *parent, const char *key);
|
2000-04-14 11:27:14 +00:00
|
|
|
/* Find the section from node - if not found create it unless new_type is -1.
|
|
|
|
|
You can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */
|
2015-01-07 03:40:34 +01:00
|
|
|
CONFIG_NODE *config_node_section(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int new_type);
|
|
|
|
|
CONFIG_NODE *config_node_section_index(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key,
|
2002-02-15 22:18:35 +00:00
|
|
|
int index, int new_type);
|
2000-04-14 11:27:14 +00:00
|
|
|
/* Find the section with the whole path.
|
2008-03-11 13:26:33 +00:00
|
|
|
Create the path if necessary if `create' is TRUE. */
|
2000-04-14 11:27:14 +00:00
|
|
|
CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int create);
|
2009-01-14 17:19:42 +00:00
|
|
|
/* Return all values from the list `node' in a g_strsplit() array */
|
2000-04-26 08:10:09 +00:00
|
|
|
char **config_node_get_list(CONFIG_NODE *node);
|
|
|
|
|
/* Add all values in `array' to `node' */
|
2000-11-26 10:24:30 +00:00
|
|
|
void config_node_add_list(CONFIG_REC *rec, CONFIG_NODE *node, char **array);
|
2000-04-14 11:27:14 +00:00
|
|
|
|
|
|
|
|
char *config_node_get_str(CONFIG_NODE *parent, const char *key, const char *def);
|
|
|
|
|
int config_node_get_int(CONFIG_NODE *parent, const char *key, int def);
|
|
|
|
|
int config_node_get_bool(CONFIG_NODE *parent, const char *key, int def);
|
|
|
|
|
|
2008-03-11 14:32:04 +00:00
|
|
|
/*
|
|
|
|
|
* key != NULL && value == NULL
|
|
|
|
|
* remove node with key 'key', equivalent to
|
2009-01-14 17:19:42 +00:00
|
|
|
* config_node_remove(rec, parent, config_node_find(parent, key))
|
2008-03-11 14:32:04 +00:00
|
|
|
* key == NULL && value != NULL
|
|
|
|
|
* create a new node with type NODE_TYPE_VALUE and value 'value'
|
|
|
|
|
* key != NULL && value != NULL
|
|
|
|
|
* if a node with key 'key' exists change its value to 'value',
|
|
|
|
|
* otherwise create a new node with type NODE_TYPE_KEY, key 'key' and value 'value'
|
|
|
|
|
* */
|
2000-05-10 13:57:42 +00:00
|
|
|
void config_node_set_str(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, const char *value);
|
2000-11-26 10:24:30 +00:00
|
|
|
void config_node_set_int(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int value);
|
|
|
|
|
void config_node_set_bool(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int value);
|
2015-09-19 18:00:23 +01:00
|
|
|
/* if a relative path is specified then you can access the absolute path using
|
|
|
|
|
node->value->fname. the key is set to the specified include path */
|
|
|
|
|
void config_node_set_include(CONFIG_REC *rec, CONFIG_NODE *parent, const char *fname);
|
2000-04-14 11:27:14 +00:00
|
|
|
|
2008-03-11 14:32:04 +00:00
|
|
|
/* Remove one node from block/list. */
|
2000-05-10 13:57:42 +00:00
|
|
|
void config_node_remove(CONFIG_REC *rec, CONFIG_NODE *parent, CONFIG_NODE *node);
|
2000-04-26 08:10:09 +00:00
|
|
|
/* Remove n'th node from a list */
|
2000-05-10 13:57:42 +00:00
|
|
|
void config_node_list_remove(CONFIG_REC *rec, CONFIG_NODE *node, int index);
|
2000-04-14 11:27:14 +00:00
|
|
|
|
2000-08-26 15:39:44 +00:00
|
|
|
/* Clear all data inside node, but leave the node */
|
|
|
|
|
void config_node_clear(CONFIG_REC *rec, CONFIG_NODE *node);
|
2000-04-26 08:10:09 +00:00
|
|
|
/* Clear the entire configuration */
|
2000-04-14 11:27:14 +00:00
|
|
|
void config_nodes_remove_all(CONFIG_REC *rec);
|
|
|
|
|
|
|
|
|
|
#endif
|