feedback: add NULL check routine
[platform/core/system/libsvi.git] / src / parser.c
1 /*
2  * libfeedback
3  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <errno.h>
21
22 #include "parser.h"
23 #include "profiles.h"
24 #include "log.h"
25
26 #define MAX_DATA        256
27 #define MAX_LINE        256
28 #define MAX_SECTION     64
29 #define WHITESPACE      " \t"
30 #define NEWLINE         "\n\r"
31 #define COMMENT         '#'
32
33 #define MATCH(a, b)             (!strncmp(a, b, strlen(a)))
34 #define SET_CONF(a, b)          (a = (b > 0.0 ? b : a))
35
36 struct parse_result {
37         char *section;
38         char *name;
39         char *value;
40 };
41
42 static inline char *trim_str(char *s)
43 {
44         char *t;
45         /* left trim */
46         s += strspn(s, WHITESPACE);
47
48         /* right trim */
49         for (t = strchr(s, 0); t > s; t--)
50                 if (!strchr(WHITESPACE, t[-1]))
51                         break;
52         *t = 0;
53         return s;
54 }
55
56 static int config_parse(const char *file_name,
57                 int cb(struct parse_result *result, void *user_data),
58                 void *user_data)
59 {
60         FILE *f = NULL;
61         struct parse_result result;
62         /* use stack for parsing */
63         char line[MAX_LINE];
64         char section[MAX_SECTION];
65         char *start, *end, *name, *value;
66         int lineno = 0, ret = 0;
67
68         if (!file_name || !cb) {
69                 ret = -EINVAL;
70                 goto error;
71         }
72
73         /* open conf file */
74         f = fopen(file_name, "r");
75         if (!f) {
76                 _E("Failed to open file %s", file_name);
77                 ret = -EIO;
78                 goto error;
79         }
80
81         /* parsing line by line */
82         while (fgets(line, MAX_LINE, f) != NULL) {
83                 lineno++;
84
85                 start = line;
86                 start[strcspn(start, NEWLINE)] = '\0';
87                 start = trim_str(start);
88
89                 if (*start == COMMENT) {
90                         continue;
91                 } else if (*start == '[') {
92                         /* parse section */
93                         end = strchr(start, ']');
94                         if (!end || *end != ']') {
95                                 ret = -EBADMSG;
96                                 goto error;
97                         }
98
99                         *end = '\0';
100                         strncpy(section, start + 1, sizeof(section));
101                         section[MAX_SECTION-1] = '\0';
102                 } else if (*start) {
103                         /* parse name & value */
104                         end = strchr(start, '=');
105                         if (!end || *end != '=') {
106                                 ret = -EBADMSG;
107                                 goto error;
108                         }
109                         *end = '\0';
110                         name = trim_str(start);
111                         value = trim_str(end + 1);
112                         end = strchr(value, COMMENT);
113                         if (end && *end == COMMENT) {
114                                 *end = '\0';
115                                 value = trim_str(value);
116                         }
117
118                         result.section = section;
119                         result.name = name;
120                         result.value = value;
121                         /* callback with parse result */
122                         ret = cb(&result, user_data);
123                         if (ret < 0) {
124                                 ret = -EBADMSG;
125                                 goto error;
126                         }
127                 }
128         }
129         _D("Success to load %s", file_name);
130         fclose(f);
131         return 0;
132
133 error:
134         if (f)
135                 fclose(f);
136         _E("Failed to read %s:%d!", file_name, lineno);
137         return ret;
138 }
139
140 static int load_config(struct parse_result *result, void *user_data)
141 {
142         struct feedback_config_info *info = (struct feedback_config_info *)user_data;
143         char *name;
144         char *value;
145         int i;
146
147         if (!info)
148                 return -EINVAL;
149
150         if (!MATCH(result->section, info->name))
151                 return -ENOENT;
152
153         if (!result->name || !result->value)
154                 return -ENOENT;
155
156         name = result->name;
157         value = result->value;
158
159         for (i = 0; i < profile->max_pattern; i++) {
160                 if (!MATCH(name, (char *)profile->str_pattern[i]))
161                         continue;
162
163                 info->data[i].origin = strdup(value);
164                 if (!info->data[i].origin)
165                         _E("fail to copy %s sound data",
166                                         profile->str_pattern[i]);
167                 break;
168         }
169
170         return 0;
171 }
172
173 int feedback_load_config(const char *path,
174                 struct feedback_config_info *info)
175 {
176         int ret;
177
178         if (!path || !info)
179                 return -EINVAL;
180
181         info->data = calloc(1,
182                         sizeof(struct feedback_data) * profile->max_pattern);
183         if (!info->data) {
184                 _E("fail to allocate %s data", path);
185                 return -ENOMEM;
186         }
187
188         ret = config_parse(path, load_config, info);
189         if (ret < 0)
190                 _E("Failed to load %s, %d Use default value!",
191                                 path, ret);
192
193         return ret;
194 }
195
196 void feedback_free_config(struct feedback_config_info *info)
197 {
198         int i;
199
200         if (!info || !(info->data))
201                 return;
202
203         if (!profile)
204                 return;
205
206         for (i = 0; i < profile->max_pattern; i++) {
207                 if (info->data[i].origin) {
208                         free(info->data[i].origin);
209                         info->data[i].origin = NULL;
210                 }
211                 if (info->data[i].changed) {
212                         free(info->data[i].changed);
213                         info->data[i].changed = NULL;
214                 }
215         }
216
217         free(info->data);
218 }