1#pragma once 2 3// This module implements a configuration parser. Clients can query the 4// contents of a configuration file through the interface provided here. 5// The current implementation is read-only; mutations are only kept in 6// memory. This parser supports the INI file format. 7 8// Implementation notes: 9// - Key/value pairs that are not within a section are assumed to be under 10// the |CONFIG_DEFAULT_SECTION| section. 11// - Multiple sections with the same name will be merged as if they were in 12// a single section. 13// - Empty sections with no key/value pairs will be treated as if they do 14// not exist. In other words, |config_has_section| will return false for 15// empty sections. 16// - Duplicate keys in a section will overwrite previous values. 17// - All strings are case sensitive. 18 19#include <stdbool.h> 20 21// The default section name to use if a key/value pair is not defined within 22// a section. 23#define CONFIG_DEFAULT_SECTION "Global" 24 25typedef struct config_t config_t; 26typedef struct config_section_node_t config_section_node_t; 27 28// Creates a new config object with no entries (i.e. not backed by a file). 29// This function returns a config object or NULL on error. Clients must call 30// |config_free| on the returned handle when it is no longer required. 31config_t *config_new_empty(void); 32 33// Loads the specified file and returns a handle to the config file. If there 34// was a problem loading the file or allocating memory, this function returns 35// NULL. Clients must call |config_free| on the returned handle when it is no 36// longer required. |filename| must not be NULL and must point to a readable 37// file on the filesystem. 38config_t *config_new(const char *filename); 39 40// Frees resources associated with the config file. No further operations may 41// be performed on the |config| object after calling this function. |config| 42// may be NULL. 43void config_free(config_t *config); 44 45// Returns true if the config file contains a section named |section|. If 46// the section has no key/value pairs in it, this function will return false. 47// |config| and |section| must not be NULL. 48bool config_has_section(const config_t *config, const char *section); 49 50// Returns true if the config file has a key named |key| under |section|. 51// Returns false otherwise. |config|, |section|, and |key| must not be NULL. 52bool config_has_key(const config_t *config, const char *section, const char *key); 53 54// Returns the integral value for a given |key| in |section|. If |section| 55// or |key| do not exist, or the value cannot be fully converted to an integer, 56// this function returns |def_value|. |config|, |section|, and |key| must not 57// be NULL. 58int config_get_int(const config_t *config, const char *section, const char *key, int def_value); 59 60// Returns the boolean value for a given |key| in |section|. If |section| 61// or |key| do not exist, or the value cannot be converted to a boolean, this 62// function returns |def_value|. |config|, |section|, and |key| must not be NULL. 63bool config_get_bool(const config_t *config, const char *section, const char *key, bool def_value); 64 65// Returns the string value for a given |key| in |section|. If |section| or 66// |key| do not exist, this function returns |def_value|. The returned string 67// is owned by the config module and must not be freed. |config|, |section|, 68// and |key| must not be NULL. |def_value| may be NULL. 69const char *config_get_string(const config_t *config, const char *section, const char *key, const char *def_value); 70 71// Sets an integral value for the |key| in |section|. If |key| or |section| do 72// not already exist, this function creates them. |config|, |section|, and |key| 73// must not be NULL. 74void config_set_int(config_t *config, const char *section, const char *key, int value); 75 76// Sets a boolean value for the |key| in |section|. If |key| or |section| do 77// not already exist, this function creates them. |config|, |section|, and |key| 78// must not be NULL. 79void config_set_bool(config_t *config, const char *section, const char *key, bool value); 80 81// Sets a string value for the |key| in |section|. If |key| or |section| do 82// not already exist, this function creates them. |config|, |section|, |key|, and 83// |value| must not be NULL. 84void config_set_string(config_t *config, const char *section, const char *key, const char *value); 85 86// Removes |section| from the |config| (and, as a result, all keys in the section). 87// Returns true if |section| was found and removed from |config|, false otherwise. 88// Neither |config| nor |section| may be NULL. 89bool config_remove_section(config_t *config, const char *section); 90 91// Removes one specific |key| residing in |section| of the |config|. Returns true 92// if the section and key were found and the key was removed, false otherwise. 93// None of |config|, |section|, or |key| may be NULL. 94bool config_remove_key(config_t *config, const char *section, const char *key); 95 96// Returns an iterator to the first section in the config file. If there are no 97// sections, the iterator will equal the return value of |config_section_end|. 98// The returned pointer must be treated as an opaque handle and must not be freed. 99// The iterator is invalidated on any config mutating operation. |config| may not 100// be NULL. 101const config_section_node_t *config_section_begin(const config_t *config); 102 103// Returns an iterator to one past the last section in the config file. It does not 104// represent a valid section, but can be used to determine if all sections have been 105// iterated over. The returned pointer must be treated as an opaque handle and must 106// not be freed and must not be iterated on (must not call |config_section_next| on 107// it). |config| may not be NULL. 108const config_section_node_t *config_section_end(const config_t *config); 109 110// Moves |iter| to the next section. If there are no more sections, |iter| will 111// equal the value of |config_section_end|. |iter| may not be NULL and must be 112// a pointer returned by either |config_section_begin| or |config_section_next|. 113const config_section_node_t *config_section_next(const config_section_node_t *iter); 114 115// Returns the name of the section referred to by |iter|. The returned pointer is 116// owned by the config module and must not be freed by the caller. The pointer will 117// remain valid until |config_free| is called. |iter| may not be NULL and must not 118// equal the value returned by |config_section_end|. 119const char *config_section_name(const config_section_node_t *iter); 120 121// Saves |config| to a file given by |filename|. Note that this could be a destructive 122// operation: if |filename| already exists, it will be overwritten. The config 123// module does not preserve comments or formatting so if a config file was opened 124// with |config_new| and subsequently overwritten with |config_save|, all comments 125// and special formatting in the original file will be lost. Neither |config| nor 126// |filename| may be NULL. 127bool config_save(const config_t *config, const char *filename); 128