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