blob: efcdf466e01f5910254f2b526693efabbfe758fc [file] [log] [blame]
Lei Qian7bf98232018-09-20 17:56:38 +08001/*
2 * Copyright (C) 2017 Amlogic Corporation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Author: Shoufu Zhao <shoufu.zhao@amlogic.com>
19 */
20
21#define LOG_TAG "IniParser"
22#define LOG_NDEBUG 0
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <assert.h>
27#include <string.h>
28#include <ctype.h>
29#include <unistd.h>
30#include <errno.h>
31
32#include <utils/Log.h>
33
34#include "ini.h"
35#include "IniParser.h"
36
37IniParser::IniParser() {
38 ALOGD("%s, entering...\n", __FUNCTION__);
39 mpFirstSection = NULL;
40 mpCurSection = NULL;
41
42 mpFileName[0] = '\0';
43}
44
45IniParser::~IniParser() {
46 ALOGD("%s, entering...\n", __FUNCTION__);
47 free();
48}
49
50int IniParser::parse(const char* filename) {
51 ALOGD("%s, entering...\n", __FUNCTION__);
52
53 strncpy(mpFileName, filename, CC_MAX_INI_FILE_NAME_LEN - 1);
54 return ini_parse(filename, handler, this);
55}
56
57int IniParser::parse_mem(char* file_buf) {
58 ALOGD("%s, entering...\n", __FUNCTION__);
59 return ini_parse_mem(file_buf, handler, this);
60}
61
62int IniParser::SetSaveFileName(const char* filename) {
63 ALOGD("%s, entering...\n", __FUNCTION__);
64
65 strncpy(mpFileName, filename, CC_MAX_INI_FILE_NAME_LEN - 1);
66 return 0;
67}
68
69void IniParser::free() {
70 ALOGD("%s, entering...\n", __FUNCTION__);
71
72 INI_SECTION* pNextSec = NULL;
73 for (INI_SECTION* pSec = mpFirstSection; pSec != NULL;) {
74 pNextSec = pSec->pNext;
75
76 INI_LINE* pNextLine = NULL;
77 for (INI_LINE* pLine = pSec->pLine; pLine != NULL;) {
78 pNextLine = pLine->pNext;
79
80 if (pLine != NULL) {
81#if CC_MEMORY_NEW_DEL_TRACE == 1
82 del_mem(__FUNCTION__, "pLine", pLine);
83#endif
84
85 delete pLine;
86 pLine = NULL;
87 }
88
89 pLine = pNextLine;
90 }
91
92 if (pSec != NULL) {
93#if CC_MEMORY_NEW_DEL_TRACE == 1
94 del_mem(__FUNCTION__, "pSec", pSec);
95#endif
96
97 delete pSec;
98 pSec = NULL;
99 }
100
101 pSec = pNextSec;
102 }
103
104 mpFirstSection = NULL;
105 mpCurSection = NULL;
106
107#if CC_MEMORY_NEW_DEL_TRACE == 1
108 printNewMemND(__FUNCTION__);
109 printDelMemND(__FUNCTION__);
110 clearMemND();
111#endif
112}
113
114void IniParser::trim(char *str, char ch) {
115 char* pStr;
116
117 pStr = str;
118 while (*pStr != '\0') {
119 if (*pStr == ch) {
120 char* pTmp = pStr;
121 while (*pTmp != '\0') {
122 *pTmp = *(pTmp + 1);
123 pTmp++;
124 }
125 } else {
126 pStr++;
127 }
128 }
129}
130
131void IniParser::trim(char *str) {
132 char* pStr = NULL;
133
134 pStr = strchr(str, '\n');
135 if (pStr != NULL) {
136 *pStr = 0;
137 }
138
139 int Len = strlen(str);
140 if (Len > 0) {
141 if (str[Len - 1] == '\r') {
142 str[Len - 1] = '\0';
143 }
144 }
145
146 pStr = strchr(str, '#');
147 if (pStr != NULL) {
148 *pStr = 0;
149 }
150
151 pStr = strchr(str, ';');
152 if (pStr != NULL) {
153 *pStr = 0;
154 }
155
156 trim(str, ' ');
157 trim(str, '{');
158 trim(str, '\\');
159 trim(str, '}');
160 trim(str, '\"');
161 return;
162}
163
164void IniParser::print() {
165 for (INI_SECTION* pSec = mpFirstSection; pSec != NULL; pSec = pSec->pNext) {
166 ALOGD("[%s]\n", pSec->Name);
167 for (INI_LINE* pLine = pSec->pLine; pLine != NULL; pLine = pLine->pNext) {
168 ALOGD("%s = %s\n", pLine->Name, pLine->Value);
169 }
170 ALOGD("\n\n\n");
171 }
172}
173
174INI_SECTION* IniParser::getSection(void* user, const char* section) {
175 IniParser* parser = (IniParser*) user;
176 if (parser == NULL) {
177 return NULL;
178 }
179
180 for (INI_SECTION* pSec = parser->mpFirstSection; pSec != NULL; pSec = pSec->pNext) {
181 if (strncmp(pSec->Name, section, strlen(section)) == 0) {
182 return pSec;
183 }
184 }
185
186 return NULL;
187}
188
189INI_LINE* IniParser::getKeyLineAtSec(INI_SECTION* pSec, const char* key) {
190 for (INI_LINE* pLine = pSec->pLine; pLine != NULL; pLine = pLine->pNext) {
191 if (strncmp(pLine->Name, key, strlen(key)) == 0) {
192 return pLine;
193 }
194 }
195 return NULL;
196}
197
198const char* IniParser::GetString(const char* section, const char* key,
199 const char* def_value) {
200 INI_SECTION* pSec = getSection(this, section);
201 if (pSec == NULL) {
202 //ALOGD("%s, section %s is NULL\n", __FUNCTION__, section);
203 return def_value;
204 }
205
206 INI_LINE* pLine = getKeyLineAtSec(pSec, key);
207 if (pLine == NULL) {
208 //ALOGD("%s, key \"%s\" is NULL\n", __FUNCTION__, key);
209 return def_value;
210 }
211
212 return pLine->Value;
213}
214
215int IniParser::SaveToFile(const char *filename) {
216 const char *fname = NULL;
217 FILE *fp = NULL;
218
219 if (filename == NULL) {
220 if (strlen(mpFileName) == 0) {
221 ALOGE("%s, save file name is NULL!!!\n", __FUNCTION__);
222 return -1;
223 } else {
224 fname = mpFileName;
225 }
226 } else {
227 fname = filename;
228 }
229
230 if ((fp = fopen (fname, "wb")) == NULL) {
231 ALOGE("%s, Open file \"%s\" ERROR (%s)!!!\n", __FUNCTION__, fname, strerror(errno));
232 return -1;
233 }
234
235 for (INI_SECTION* pSec = mpFirstSection; pSec != NULL; pSec = pSec->pNext) {
236 fprintf(fp, "[%s]\r\n", pSec->Name);
237 for (INI_LINE* pLine = pSec->pLine; pLine != NULL; pLine = pLine->pNext) {
238 fprintf(fp, "%s = %s\r\n", pLine->Name, pLine->Value);
239 }
240 }
241
242 fflush(fp);
243 fsync(fileno(fp));
244
245 fclose(fp);
246 fp = NULL;
247
248 return 0;
249}
250
251int IniParser::SetString(const char *section, const char *key, const char *value) {
252 setKeyValue(this, section, key, value, 1);
253 SaveToFile(NULL);
254 return 0;
255}
256
257INI_LINE* IniParser::newLine(const char* name, const char* value) {
258 INI_LINE* pLine = NULL;
259
260 pLine = new INI_LINE();
261 if (pLine != NULL) {
262 pLine->pNext = NULL;
wei.du06ada4c2021-06-24 04:04:01 -0400263 strcpy(pLine->Name, name);
264 strcpy(pLine->Value, value);
Lei Qian7bf98232018-09-20 17:56:38 +0800265
266#if CC_MEMORY_NEW_DEL_TRACE == 1
267 new_mem(__FUNCTION__, "pLine", pLine);
268#endif
269 }
270
271 return pLine;
272}
273
274INI_SECTION* IniParser::newSection(const char* section, INI_LINE* pLine) {
275 INI_SECTION* pSec = NULL;
276
277 pSec = new INI_SECTION();
278 if (pSec != NULL) {
279 pSec->pLine = pLine;
280 pSec->pNext = NULL;
wei.du06ada4c2021-06-24 04:04:01 -0400281 strcpy(pSec->Name, section);
Lei Qian7bf98232018-09-20 17:56:38 +0800282
283#if CC_MEMORY_NEW_DEL_TRACE == 1
284 new_mem(__FUNCTION__, "pSec", pSec);
285#endif
286 }
287
288 return pSec;
289}
290
291int IniParser::setKeyValue(void* user, const char* section, const char* key, const char* value, int set_mode) {
292 IniParser* parser = NULL;
293 INI_LINE* pLine = NULL;
294 INI_SECTION *pSec = NULL;
295
296 if (user == NULL || section == NULL || key == NULL || value == NULL) {
297 return 1;
298 }
299
300 parser = (IniParser*) user;
301
302 parser->trim((char *) value);
303 if (value[0] == '\0') {
304 return 1;
305 }
306
307 if (parser->mpFirstSection == NULL) {
308 pLine = newLine(key, value);
309 pSec = newSection(section, pLine);
310
311 parser->mpFirstSection = pSec;
312 parser->mpCurSection = pSec;
313 pSec->pCurLine = pLine;
314 } else {
315 pSec = getSection(user, section);
316 if (pSec == NULL) {
317 pLine = newLine(key, value);
318 pSec = newSection(section, pLine);
319
320 parser->mpCurSection->pNext = pSec;
321 parser->mpCurSection = pSec;
322 pSec->pCurLine = pLine;
323
324 pSec->pCurLine = pLine;
325 } else {
326 pLine = getKeyLineAtSec(pSec, key);
327 if (pLine == NULL) {
328 pLine = newLine(key, value);
329
330 pSec->pCurLine->pNext = pLine;
331 pSec->pCurLine = pLine;
332 } else {
333 if (set_mode == 1) {
wei.du06ada4c2021-06-24 04:04:01 -0400334 strcpy(pLine->Value, value);
Lei Qian7bf98232018-09-20 17:56:38 +0800335 } else {
wei.du06ada4c2021-06-24 04:04:01 -0400336 strcat(pLine->Value, value);
Lei Qian7bf98232018-09-20 17:56:38 +0800337 }
338 }
339 }
340 }
341
342 return 0;
343}
344
345int IniParser::handler(void* user, const char* section, const char* name,
346 const char* value) {
347 //ALOGD("%s, section = %s, name = %s, value = %s\n", __FUNCTION__, section, name, value);
348 setKeyValue(user, section, name, value, 0);
349 return 1;
350}
351
352#if CC_MEMORY_NEW_DEL_TRACE == 1
353
354#define CC_MEM_RECORD_CNT (1024)
355
356typedef struct tag_memnd {
wei.du06ada4c2021-06-24 04:04:01 -0400357 char fun_name[50];
358 char var_name[50];
Lei Qian7bf98232018-09-20 17:56:38 +0800359 void *ptr;
360} memnd;
361
362static memnd gMemNewItems[CC_MEM_RECORD_CNT];
363static int gMemNewInd = 0;
364
365static memnd gMemDelItems[CC_MEM_RECORD_CNT];
366static int gMemDelInd = 0;
367
368static void new_mem(const char *fun_name, const char *var_name, void *ptr) {
wei.du06ada4c2021-06-24 04:04:01 -0400369 strcpy(gMemNewItems[gMemNewInd].fun_name, fun_name);
370 strcpy(gMemNewItems[gMemNewInd].var_name, var_name);
Lei Qian7bf98232018-09-20 17:56:38 +0800371 gMemNewItems[gMemNewInd].ptr = ptr;
372
373 gMemNewInd += 1;
374}
375
376static void del_mem(const char *fun_name, const char *var_name, void *ptr) {
wei.du06ada4c2021-06-24 04:04:01 -0400377 strcpy(gMemDelItems[gMemDelInd].fun_name, fun_name);
378 strcpy(gMemDelItems[gMemDelInd].var_name, var_name);
Lei Qian7bf98232018-09-20 17:56:38 +0800379 gMemDelItems[gMemDelInd].ptr = ptr;
380
381 gMemDelInd += 1;
382}
383
384static void printMemND(const char *fun_name, memnd *tmp_nd, int tmp_cnt) {
385 //int i = 0;
386
387 ALOGD("fun_name = %s, fun_name = %s, total_cnt = %d\n", fun_name, (char *)tmp_nd, tmp_cnt);
388
389#if CC_MEMORY_NEW_DEL_TRACE_PRINT_ALL == 1
390 for (i = 0; i < tmp_cnt; i++) {
391 ALOGD("fun_name = %s, var_name = %s, ptr = %p\n", tmp_nd[i].fun_name, tmp_nd[i].var_name, tmp_nd[i].ptr);
392 }
393#endif
394}
395
396static void printDelMemND(const char *fun_name) {
397 ALOGD("fun_name = %s\n", fun_name);
398 printMemND(__FUNCTION__, gMemDelItems, gMemDelInd);
399}
400
401static void printNewMemND(const char *fun_name) {
402 ALOGD("fun_name = %s\n", fun_name);
403 printMemND(__FUNCTION__, gMemNewItems, gMemNewInd);
404}
405
406static void clearMemND() {
407 //int i = 0;
408
409 gMemNewInd = 0;
410 gMemDelInd = 0;
411 memset((void *)gMemNewItems, 0, sizeof(memnd) * CC_MEM_RECORD_CNT);
412 memset((void *)gMemDelItems, 0, sizeof(memnd) * CC_MEM_RECORD_CNT);
413}
414#endif