loc_cfg.cpp revision fe660078f05f448ececb0b1170ecd79e600db440
1/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation, nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#define LOG_NDDEBUG 0
31#define LOG_TAG "LocSvc_utils_cfg"
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <pthread.h>
36#include <string.h>
37#include <ctype.h>
38#include <unistd.h>
39#include <time.h>
40#include <loc_cfg.h>
41#include <log_util.h>
42#include <loc_misc_utils.h>
43#ifdef USE_GLIB
44#include <glib.h>
45#endif
46#include "platform_lib_includes.h"
47
48/*=============================================================================
49 *
50 *                          GLOBAL DATA DECLARATION
51 *
52 *============================================================================*/
53
54/* Parameter data */
55static uint8_t DEBUG_LEVEL = 0xff;
56static uint8_t TIMESTAMP = 0;
57
58/* Parameter spec table */
59static loc_param_s_type loc_param_table[] =
60{
61    {"DEBUG_LEVEL",    &DEBUG_LEVEL, NULL,    'n'},
62    {"TIMESTAMP",      &TIMESTAMP,   NULL,    'n'},
63};
64int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type);
65
66typedef struct loc_param_v_type
67{
68    char* param_name;
69    char* param_str_value;
70    int param_int_value;
71    double param_double_value;
72}loc_param_v_type;
73
74/*===========================================================================
75FUNCTION loc_set_config_entry
76
77DESCRIPTION
78   Potentially sets a given configuration table entry based on the passed in
79   configuration value. This is done by using a string comparison of the
80   parameter names and those found in the configuration file.
81
82PARAMETERS:
83   config_entry: configuration entry in the table to possibly set
84   config_value: value to store in the entry if the parameter names match
85
86DEPENDENCIES
87   N/A
88
89RETURN VALUE
90   None
91
92SIDE EFFECTS
93   N/A
94===========================================================================*/
95int loc_set_config_entry(loc_param_s_type* config_entry, loc_param_v_type* config_value)
96{
97    int ret=-1;
98    if(NULL == config_entry || NULL == config_value)
99    {
100        LOC_LOGE("%s: INVALID config entry or parameter", __FUNCTION__);
101        return ret;
102    }
103
104    if (strcmp(config_entry->param_name, config_value->param_name) == 0 &&
105        config_entry->param_ptr)
106    {
107        switch (config_entry->param_type)
108        {
109        case 's':
110            if (strcmp(config_value->param_str_value, "NULL") == 0)
111            {
112                *((char*)config_entry->param_ptr) = '\0';
113            }
114            else {
115                strlcpy((char*) config_entry->param_ptr,
116                        config_value->param_str_value,
117                        LOC_MAX_PARAM_STRING + 1);
118            }
119            /* Log INI values */
120            LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__,
121                     config_entry->param_name, (char*)config_entry->param_ptr);
122
123            if(NULL != config_entry->param_set)
124            {
125                *(config_entry->param_set) = 1;
126            }
127            ret = 0;
128            break;
129        case 'n':
130            *((int *)config_entry->param_ptr) = config_value->param_int_value;
131            /* Log INI values */
132            LOC_LOGD("%s: PARAM %s = %d", __FUNCTION__,
133                     config_entry->param_name, config_value->param_int_value);
134
135            if(NULL != config_entry->param_set)
136            {
137                *(config_entry->param_set) = 1;
138            }
139            ret = 0;
140            break;
141        case 'f':
142            *((double *)config_entry->param_ptr) = config_value->param_double_value;
143            /* Log INI values */
144            LOC_LOGD("%s: PARAM %s = %f", __FUNCTION__,
145                     config_entry->param_name, config_value->param_double_value);
146
147            if(NULL != config_entry->param_set)
148            {
149                *(config_entry->param_set) = 1;
150            }
151            ret = 0;
152            break;
153        default:
154            LOC_LOGE("%s: PARAM %s parameter type must be n, f, or s",
155                     __FUNCTION__, config_entry->param_name);
156        }
157    }
158    return ret;
159}
160
161/*===========================================================================
162FUNCTION loc_fill_conf_item
163
164DESCRIPTION
165   Takes a line of configuration item and sets defined values based on
166   the passed in configuration table. This table maps strings to values to
167   set along with the type of each of these values.
168
169PARAMETERS:
170   input_buf : buffer contanis config item
171   config_table: table definition of strings to places to store information
172   table_length: length of the configuration table
173
174DEPENDENCIES
175   N/A
176
177RETURN VALUE
178   0: No config or incomplete config or invalid parameter
179   1: Filled a record
180
181SIDE EFFECTS
182   N/A
183===========================================================================*/
184int loc_fill_conf_item(char* input_buf,
185                       loc_param_s_type* config_table, uint32_t table_length)
186{
187    int ret = 0;
188
189    if (input_buf && config_table) {
190        char *lasts;
191        loc_param_v_type config_value;
192        memset(&config_value, 0, sizeof(config_value));
193
194        /* Separate variable and value */
195        config_value.param_name = strtok_r(input_buf, "=", &lasts);
196        /* skip lines that do not contain "=" */
197        if (config_value.param_name) {
198            config_value.param_str_value = strtok_r(NULL, "=", &lasts);
199
200            /* skip lines that do not contain two operands */
201            if (config_value.param_str_value) {
202                /* Trim leading and trailing spaces */
203                loc_util_trim_space(config_value.param_name);
204                loc_util_trim_space(config_value.param_str_value);
205
206                /* Parse numerical value */
207                if ((strlen(config_value.param_str_value) >=3) &&
208                    (config_value.param_str_value[0] == '0') &&
209                    (tolower(config_value.param_str_value[1]) == 'x'))
210                {
211                    /* hex */
212                    config_value.param_int_value = (int) strtol(&config_value.param_str_value[2],
213                                                                (char**) NULL, 16);
214                }
215                else {
216                    config_value.param_double_value = (double) atof(config_value.param_str_value); /* float */
217                    config_value.param_int_value = atoi(config_value.param_str_value); /* dec */
218                }
219
220                for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
221                {
222                    if(!loc_set_config_entry(&config_table[i], &config_value)) {
223                        ret = 1;
224                    }
225                }
226            }
227        }
228    }
229
230    return ret;
231}
232
233/*===========================================================================
234FUNCTION loc_read_conf_r (repetitive)
235
236DESCRIPTION
237   Reads the specified configuration file and sets defined values based on
238   the passed in configuration table. This table maps strings to values to
239   set along with the type of each of these values.
240   The difference between this and loc_read_conf is that this function returns
241   the file pointer position at the end of filling a config table. Also, it
242   reads a fixed number of parameters at a time which is equal to the length
243   of the configuration table. This functionality enables the caller to
244   repeatedly call the function to read data from the same file.
245
246PARAMETERS:
247   conf_fp : file pointer
248   config_table: table definition of strings to places to store information
249   table_length: length of the configuration table
250
251DEPENDENCIES
252   N/A
253
254RETURN VALUE
255   0: Table filled successfully
256   1: No more parameters to read
257  -1: Error filling table
258
259SIDE EFFECTS
260   N/A
261===========================================================================*/
262int loc_read_conf_r(FILE *conf_fp, loc_param_s_type* config_table, uint32_t table_length)
263{
264    int ret=0;
265
266    unsigned int num_params=table_length;
267    if(conf_fp == NULL) {
268        LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__);
269        ret = -1;
270        goto err;
271    }
272
273    /* Clear all validity bits */
274    for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
275    {
276        if(NULL != config_table[i].param_set)
277        {
278            *(config_table[i].param_set) = 0;
279        }
280    }
281
282    char input_buf[LOC_MAX_PARAM_LINE];  /* declare a char array */
283
284    LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
285    while(num_params)
286    {
287        if(!fgets(input_buf, LOC_MAX_PARAM_LINE, conf_fp)) {
288            LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__);
289            break;
290        }
291
292        num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
293    }
294
295err:
296    return ret;
297}
298
299/*===========================================================================
300FUNCTION loc_udpate_conf
301
302DESCRIPTION
303   Parses the passed in buffer for configuration items, and update the table
304   that is also passed in.
305
306Reads the specified configuration file and sets defined values based on
307   the passed in configuration table. This table maps strings to values to
308   set along with the type of each of these values.
309
310PARAMETERS:
311   conf_data: configuration items in bufferas a string
312   length: strlen(conf_data)
313   config_table: table definition of strings to places to store information
314   table_length: length of the configuration table
315
316DEPENDENCIES
317   N/A
318
319RETURN VALUE
320   number of the records in the table that is updated at time of return.
321
322SIDE EFFECTS
323   N/A
324===========================================================================*/
325int loc_update_conf(const char* conf_data, int32_t length,
326                    loc_param_s_type* config_table, uint32_t table_length)
327{
328    int ret = -1;
329
330    if (conf_data && length && config_table && table_length) {
331        // make a copy, so we do not tokenize the original data
332        char* conf_copy = (char*)malloc(length+1);
333        memcpy(conf_copy, conf_data, length);
334        // we hard NULL the end of string to be safe
335        conf_copy[length] = 0;
336        // start with one record off
337        uint32_t num_params = table_length - 1;
338        char* saveptr = NULL;
339        char* input_buf = strtok_r(conf_copy, "\n", &saveptr);
340        ret = 0;
341
342        LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
343        while(num_params && input_buf) {
344            ret++;
345            num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
346            input_buf = strtok_r(NULL, "\n", &saveptr);
347        }
348    }
349
350    return ret;
351}
352
353/*===========================================================================
354FUNCTION loc_read_conf
355
356DESCRIPTION
357   Reads the specified configuration file and sets defined values based on
358   the passed in configuration table. This table maps strings to values to
359   set along with the type of each of these values.
360
361PARAMETERS:
362   conf_file_name: configuration file to read
363   config_table: table definition of strings to places to store information
364   table_length: length of the configuration table
365
366DEPENDENCIES
367   N/A
368
369RETURN VALUE
370   None
371
372SIDE EFFECTS
373   N/A
374===========================================================================*/
375void loc_read_conf(const char* conf_file_name, loc_param_s_type* config_table,
376                   uint32_t table_length)
377{
378    FILE *conf_fp = NULL;
379    char input_buf[LOC_MAX_PARAM_LINE];  /* declare a char array */
380    char *lasts;
381    loc_param_v_type config_value;
382    uint32_t i;
383
384    if((conf_fp = fopen(conf_file_name, "r")) != NULL)
385    {
386        LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
387        if(table_length && config_table) {
388            loc_read_conf_r(conf_fp, config_table, table_length);
389            rewind(conf_fp);
390        }
391        loc_read_conf_r(conf_fp, loc_param_table, loc_param_num);
392        fclose(conf_fp);
393    }
394    /* Initialize logging mechanism with parsed data */
395    loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
396}
397