summaryrefslogtreecommitdiff
path: root/src/lib/conf/conf_load.c
blob: e1192fef44fd761b065410aeaf3c8b3df74060ac (plain) (blame)
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
#include "conf_private.h"

/**
 * @addtogroup Lib-Conf-Functions
 * @{
 */

/**
 * @cond IGNORE
 */

/**
 * @brief Frees an allocated configuration value.
 * @param data Pointer to allocated conf value.
 *
 * This function is called by eina_hash_free() when we ask to free
 * the conf->variables hash table.
 */
void
conf_load_line_free(void *data)
{
   free(data);
}

/**
 * @brief Parse a line into a tuple of variable + value.
 * @param conf Conf structure.
 * @param line Line to parse.
 *
 * This function is called by conf_load_map_filter for any
 * line found in the configuration file.
 */
void
conf_load_line_parse(Conf *conf,
                     char *line)
{
   char **split,
         *variable,
         *value;
   Eina_Strbuf *buf;

   DBG("conf[%p] line[%s]", conf, line);

   if (line[0] == '#')
     return;

   split = eina_str_split(line, "=", 2);
   if (!split)
     {
        ERR("Failed to alloc 2D array");
        return;
     }

   if ((!split[0]) || (!split[1]))
     {
        ERR("Failed to split line correctly");
        return;
     }

   buf = eina_strbuf_new();
   if (!buf)
     {
        ERR("Failed to allocate string buffer");
        free(split[0]);
        free(split);
        return;
     }

   eina_strbuf_append(buf, split[0]);
   eina_strbuf_trim(buf);
   variable = eina_strbuf_string_steal(buf);

   eina_strbuf_append(buf, split[1]);
   eina_strbuf_trim(buf);
   value = eina_strbuf_string_steal(buf);

   eina_hash_add(conf->variables, variable, strdup(value));

   free(split[0]);
   free(split);
   free(variable);
   free(value);
   eina_strbuf_free(buf);
}

/**
 * @brief Read configuration file line by line.
 * @param data Conf_Load structure.
 * @param handler UNUSED.
 * @param map Data from configuration file.
 * @param length Length of data.
 *
 * @return EINA_TRUE.
 *
 * This function is called by eio_file_map_all(),
 * <b>from its own thread</b>, when it successfully loaded
 * the configuration file.
 */
Eina_Bool
conf_load_map_filter(void *data,
                     Eio_File *handler EINA_UNUSED,
                     void *map,
                     size_t length)
{
   Conf_Load *cl;
   Conf *conf;
   const char *s,
              *p1;
   char *line;

   cl = data;
   conf = cl->conf;
   s = map;

   while (1)
     {
        if ((size_t)(s-(const char *)map) == length)
          break;

        p1 = strchr(s, '\n');
        if (!p1)
          goto end_loop;

        if (p1 == s)
          goto end_loop;

        line = strndup(s, p1 -s);
        if (line[p1-s-1] == '\r')
          line[p1-s-1] = 0;

        conf_load_line_parse(conf, line);

        free((char *)line);

        s = p1;

        end_loop:
        s++;
     }

   return EINA_TRUE;
}

/**
 * @brief Call callback from app to tell we ended to load configuration file.
 *
 * @param data Conf_Load structure.
 * @param handler UNUSED.
 * @param map UNUSED.
 * @param length UNUSED.
 *
 * This function is called by eio_file_map_all() from the main loop.<br />
 * It is usefull for us to warn our caller that we ended parsing of file,
 * from main loop.
 */
void
conf_load_map_main(void *data,
                   Eio_File *handler EINA_UNUSED,
                   void *map EINA_UNUSED,
                   size_t length EINA_UNUSED)
{
   Conf_Load *cl;

   cl = data;
   DBG("cl[%p]", cl);

   cl->cb.done((void *)cl->cb.data, cl->conf);
   conf_free(cl->conf);
   free(cl);
}

/**
 * @brief Call callback from app to tell we got an error.
 *
 * @param data Conf_Load structure.
 * @param handler UNUSED.
 * @param error See errno(3)
 *
 * This function gets called by eio_file_map_all() if eio failed to mmap
 * file. This call is made from the main loop.
 */
void
conf_load_map_error(void *data,
                    Eio_File *handler EINA_UNUSED,
                    int error)
{
   Conf_Load *cl;

   cl = data;
   ERR("Error while mmaping file %s : %s", cl->conf->file, strerror(error));

   cl->cb.error((void *)cl->cb.data, cl->conf,
                "Error while mmaping file");
   conf_free(cl->conf);
   free(cl);
}

/**
 * @endcond
 */

/**
 * @}
 */