600 lines
16 KiB
C
600 lines
16 KiB
C
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
|
/*
|
|
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "ini_config.h"
|
|
|
|
#define LOG_TAG "ini_handler"
|
|
#define LOG_NDEBUG 0
|
|
|
|
#include "ini_log.h"
|
|
|
|
#include "ini_core.h"
|
|
#include "ini_handler.h"
|
|
#include "ini_platform.h"
|
|
|
|
static void trim(char *str, char ch);
|
|
static void trim_all(char *str);
|
|
static INI_SECTION* getSection(const char* section, INI_HANDLER_DATA *pHandlerData);
|
|
static INI_LINE* getKeyLineAtSec(INI_SECTION* pSec, const char* key);
|
|
static int setKeyValue(void* user, const char* section, const char* name, const char* value, int set_mode);
|
|
static int handler(void* user, const char* section, const char* name, const char* value);
|
|
static INI_LINE* newLine(const char* name, const char* value);
|
|
static INI_SECTION* newSection(const char* section, INI_LINE* pLINE);
|
|
|
|
#if CC_MEMORY_ALLOC_FREE_TRACE == 1
|
|
static void alloc_mem(const char *fun_name, const char *var_name, void *ptr);
|
|
static void free_mem(const char *fun_name, const char *var_name, void *ptr);
|
|
static void printAllocMemND(const char *fun_name);
|
|
static void printFreeMemND(const char *fun_name);
|
|
static void clearMemND(void);
|
|
#endif
|
|
|
|
int bin_file_read(const char* filename, unsigned char *file_buf) {
|
|
int tmp_ret = -1, rd_cnt = 0, file_size = 0;
|
|
unsigned char *tmp_buf = NULL;
|
|
|
|
file_size = iniGetFileSize(filename);
|
|
if (file_size <= 0)
|
|
return -1;
|
|
|
|
tmp_buf = (unsigned char *) malloc(file_size * 2);
|
|
if (tmp_buf != NULL) {
|
|
rd_cnt = iniReadFileToBuffer(filename, 0, file_size, tmp_buf);
|
|
if (rd_cnt > 0) {
|
|
if (file_size > CC_MAX_INI_FILE_SIZE) {
|
|
ALOGE("%s: file \"%s\" size out of support!\n", __FUNCTION__, filename);
|
|
tmp_ret = -1;
|
|
} else {
|
|
memcpy(file_buf, tmp_buf, file_size);
|
|
tmp_ret = file_size;
|
|
}
|
|
}
|
|
|
|
free(tmp_buf);
|
|
tmp_buf = NULL;
|
|
}
|
|
|
|
return tmp_ret;
|
|
}
|
|
|
|
int ini_file_parse(const char* filename, INI_HANDLER_DATA *pHandlerData) {
|
|
int tmp_ret = -1, rd_cnt = 0, file_size = 0;
|
|
unsigned char *tmp_buf = NULL;
|
|
|
|
file_size = iniGetFileSize(filename);
|
|
if (file_size <= 0)
|
|
return -1;
|
|
|
|
tmp_buf = (unsigned char *) malloc(file_size * 2);
|
|
if (tmp_buf != NULL) {
|
|
strncpy(pHandlerData->mpFileName, filename, CC_MAX_INI_FILE_NAME_LEN - 1);
|
|
|
|
memset((void *)tmp_buf, '\0', (file_size * 2) * sizeof(char));
|
|
rd_cnt = iniReadFileToBuffer(filename, 0, file_size, tmp_buf);
|
|
if (rd_cnt > 0) {
|
|
tmp_ret = ini_mem_parse(tmp_buf, pHandlerData);
|
|
}
|
|
|
|
free(tmp_buf);
|
|
tmp_buf = NULL;
|
|
}
|
|
|
|
return tmp_ret;
|
|
}
|
|
|
|
int ini_mem_parse(unsigned char* file_buf, INI_HANDLER_DATA *pHandlerData) {
|
|
//ALOGD("%s, entering...\n", __FUNCTION__);
|
|
return ini_parse_mem((char *)file_buf, handler, (void *)pHandlerData);
|
|
}
|
|
|
|
int ini_set_save_file_name(const char* filename, INI_HANDLER_DATA *pHandlerData) {
|
|
//ALOGD("%s, entering...\n", __FUNCTION__);
|
|
|
|
strncpy(pHandlerData->mpFileName, filename, CC_MAX_INI_FILE_NAME_LEN - 1);
|
|
return 0;
|
|
}
|
|
|
|
static void ini_line_free(INI_LINE *pline)
|
|
{
|
|
if (pline->Value) {
|
|
memset(pline->Value, 0, pline->value_size);
|
|
free(pline->Value);
|
|
}
|
|
|
|
#if CC_MEMORY_ALLOC_FREE_TRACE == 1
|
|
free_mem(__func__, "pLine", pline);
|
|
#endif
|
|
|
|
memset(pline, 0, sizeof(INI_LINE));
|
|
free(pline);
|
|
}
|
|
|
|
void ini_free_mem(INI_HANDLER_DATA *pHandlerData) {
|
|
//ALOGD("%s, entering...\n", __FUNCTION__);
|
|
|
|
if (!pHandlerData)
|
|
return;
|
|
|
|
INI_SECTION *pNextSec = NULL;
|
|
INI_SECTION *pSec = pHandlerData->mpFirstSection;
|
|
INI_LINE *pNextLine = NULL;
|
|
INI_LINE *pLine = NULL;
|
|
|
|
while (pSec) {
|
|
pNextSec = pSec->pNext;
|
|
pLine = pSec->pLine;
|
|
|
|
while (pLine) {
|
|
pNextLine = pLine->pNext;
|
|
ini_line_free(pLine);
|
|
pLine = pNextLine;
|
|
}
|
|
|
|
#if CC_MEMORY_ALLOC_FREE_TRACE == 1
|
|
free_mem(__func__, "pSec", pSec);
|
|
#endif
|
|
|
|
memset(pSec, 0, sizeof(INI_SECTION));
|
|
free(pSec);
|
|
pSec = pNextSec;
|
|
}
|
|
|
|
pHandlerData->mpFirstSection = NULL;
|
|
pHandlerData->mpCurSection = NULL;
|
|
|
|
#if CC_MEMORY_ALLOC_FREE_TRACE == 1
|
|
printAllocMemND(__func__);
|
|
printFreeMemND(__func__);
|
|
clearMemND();
|
|
#endif
|
|
}
|
|
|
|
static void trim(char *str, char ch) {
|
|
char* pStr;
|
|
|
|
pStr = str;
|
|
while (*pStr != '\0') {
|
|
if (*pStr == ch) {
|
|
char* pTmp = pStr;
|
|
while (*pTmp != '\0') {
|
|
*pTmp = *(pTmp + 1);
|
|
pTmp++;
|
|
}
|
|
} else {
|
|
pStr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void trim_all(char *str) {
|
|
char* pStr = NULL;
|
|
|
|
pStr = strchr(str, '\n');
|
|
if (pStr != NULL) {
|
|
*pStr = 0;
|
|
}
|
|
|
|
int Len = strlen(str);
|
|
if (Len > 0) {
|
|
if (str[Len - 1] == '\r') {
|
|
str[Len - 1] = '\0';
|
|
}
|
|
}
|
|
|
|
pStr = strchr(str, '#');
|
|
if (pStr != NULL) {
|
|
*pStr = 0;
|
|
}
|
|
|
|
pStr = strchr(str, ';');
|
|
if (pStr != NULL) {
|
|
*pStr = 0;
|
|
}
|
|
|
|
trim(str, ' ');
|
|
trim(str, '{');
|
|
trim(str, '\\');
|
|
trim(str, '}');
|
|
trim(str, '\"');
|
|
return;
|
|
}
|
|
|
|
void ini_print_all(INI_HANDLER_DATA *pHandlerData) {
|
|
INI_SECTION* pSec = NULL;
|
|
INI_LINE* pLine = NULL;
|
|
char *str;
|
|
int i, j, n, m;
|
|
|
|
str = (char *)malloc(512);
|
|
if (!str) {
|
|
printf("%s: malloc print memory error\n", __func__);
|
|
return;
|
|
}
|
|
for (pSec = pHandlerData->mpFirstSection; pSec != NULL; pSec = pSec->pNext) {
|
|
printf("[%s]\n", pSec->Name);
|
|
pLine = pSec->pLine;
|
|
while (pLine) {
|
|
if (pLine->value_size >= 510) {
|
|
printf(" %s = ", pLine->Name);
|
|
n = pLine->value_size / 510;
|
|
m = pLine->value_size % 510;
|
|
for (i = 0; i < n; i++) {
|
|
j = i * 510;
|
|
strncpy(str, pLine->Value + j, 510);
|
|
str[510] = '\0';
|
|
printf("%s\n", str);
|
|
}
|
|
if (m) {
|
|
j = n * 510;
|
|
strncpy(str, pLine->Value + j, m);
|
|
str[m] = '\0';
|
|
printf("%s\n", str);
|
|
}
|
|
} else {
|
|
printf(" %s = %s\n", pLine->Name, pLine->Value);
|
|
}
|
|
|
|
pLine = pLine->pNext;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
memset(str, 0, 512);
|
|
free(str);
|
|
}
|
|
|
|
void ini_list_section(INI_HANDLER_DATA *pHandlerData) {
|
|
INI_SECTION* pSec = NULL;
|
|
for (pSec = pHandlerData->mpFirstSection; pSec != NULL; pSec = pSec->pNext) {
|
|
printf(" %s\n", pSec->Name);
|
|
}
|
|
}
|
|
|
|
int _ini_section_exist(const char *section, INI_HANDLER_DATA *pHandlerData)
|
|
{
|
|
INI_SECTION *pSec = NULL;
|
|
int ret = 0;
|
|
|
|
for (pSec = pHandlerData->mpFirstSection; pSec; pSec = pSec->pNext) {
|
|
if (strcmp(pSec->Name, section) == 0)
|
|
ret = 1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static INI_SECTION* getSection(const char* section, INI_HANDLER_DATA *pHandlerData) {
|
|
INI_SECTION* pSec = NULL;
|
|
for (pSec = pHandlerData->mpFirstSection; pSec != NULL; pSec = pSec->pNext) {
|
|
if (strcmp(pSec->Name, section) == 0)
|
|
return pSec;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static INI_LINE* getKeyLineAtSec(INI_SECTION* pSec, const char* key) {
|
|
INI_LINE* pLine = NULL;
|
|
for (pLine = pSec->pLine; pLine != NULL; pLine = pLine->pNext) {
|
|
if (strcmp(pLine->Name, key) == 0)
|
|
return pLine;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const char* ini_get_string(const char* section, const char* key,
|
|
const char* def_value, INI_HANDLER_DATA *pHandlerData) {
|
|
INI_SECTION* pSec = getSection(section, pHandlerData);
|
|
if (pSec == NULL) {
|
|
//ALOGD("%s, section %s is NULL\n", __FUNCTION__, section);
|
|
return def_value;
|
|
}
|
|
|
|
INI_LINE* pLine = getKeyLineAtSec(pSec, key);
|
|
if (pLine == NULL) {
|
|
//ALOGD("%s, key \"%s\" is NULL\n", __FUNCTION__, key);
|
|
return def_value;
|
|
}
|
|
|
|
return pLine->Value;
|
|
}
|
|
|
|
int ini_set_string(const char *section, const char *key, const char *value, INI_HANDLER_DATA *pHandlerData) {
|
|
setKeyValue(pHandlerData, section, key, value, 1);
|
|
return 0;
|
|
}
|
|
|
|
int ini_save_to_file(const char *filename, INI_HANDLER_DATA *pHandlerData) {
|
|
#if (defined CC_COMPILE_IN_PC || defined CC_COMPILE_IN_ANDROID)
|
|
const char *fname = NULL;
|
|
FILE *fp = NULL;
|
|
|
|
if (filename == NULL) {
|
|
if (strlen(pHandlerData->mpFileName) == 0) {
|
|
ALOGE("%s, save file name is NULL!!!\n", __FUNCTION__);
|
|
return -1;
|
|
} else {
|
|
fname = pHandlerData->mpFileName;
|
|
}
|
|
} else {
|
|
fname = filename;
|
|
}
|
|
|
|
if ((fp = fopen (fname, "wb")) == NULL) {
|
|
ALOGE("%s, Open file \"%s\" ERROR (%s)!!!\n", __FUNCTION__, fname, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
INI_SECTION* pSec = NULL;
|
|
for (pSec = pHandlerData->mpFirstSection; pSec != NULL; pSec = pSec->pNext) {
|
|
fprintf(fp, "[%s]\r\n", pSec->Name);
|
|
INI_LINE* pLine = NULL;
|
|
for (pLine = pSec->pLine; pLine != NULL; pLine = pLine->pNext) {
|
|
fprintf(fp, "%s = %s\r\n", pLine->Name, pLine->Value);
|
|
}
|
|
}
|
|
|
|
fflush(fp);
|
|
fsync(fileno(fp));
|
|
|
|
fclose(fp);
|
|
fp = NULL;
|
|
|
|
return 0;
|
|
#elif (defined CC_COMPILE_IN_UBOOT)
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static int ini_set_line_exist_key_val(INI_LINE *pline, const char *value, unsigned int set_mode)
|
|
{
|
|
char *pvalue = NULL;
|
|
int pre_len, new_len, n;
|
|
|
|
if (!pline || !value)
|
|
return -1;
|
|
|
|
pre_len = pline->value_size;
|
|
new_len = strlen(value) + 1;
|
|
|
|
if (set_mode == 1) {
|
|
pvalue = (char *)malloc(new_len);
|
|
if (!pvalue)
|
|
return -1;
|
|
memset(pvalue, 0, new_len);
|
|
|
|
memset(pline->Value, 0, pre_len);
|
|
free(pline->Value);
|
|
pline->Value = pvalue;
|
|
strcpy(pline->Value, value);
|
|
pline->value_size = new_len;
|
|
return 0;
|
|
}
|
|
|
|
pvalue = (char *)malloc(pre_len + new_len - 1);
|
|
if (!pvalue)
|
|
return -1;
|
|
memset(pvalue, 0, (pre_len + new_len - 1));
|
|
|
|
n = sprintf(pvalue, "%s", pline->Value);
|
|
|
|
memset(pline->Value, 0, pre_len);
|
|
free(pline->Value);
|
|
|
|
pline->Value = pvalue;
|
|
sprintf(pline->Value + n, "%s", value);
|
|
pline->value_size = pre_len + new_len - 1;
|
|
return 0;
|
|
}
|
|
|
|
static INI_LINE* newLine(const char* name, const char* value) {
|
|
INI_LINE* pLine = NULL;
|
|
char *pvalue = NULL;
|
|
unsigned int val_size;
|
|
|
|
pLine = (INI_LINE*) malloc(sizeof(INI_LINE));
|
|
if (pLine != NULL) {
|
|
memset(pLine, 0, sizeof(INI_LINE));
|
|
val_size = strlen(value) + 1;
|
|
pvalue = (char *)malloc(val_size);
|
|
if (!pvalue) {
|
|
ALOGE("%s: malloc value error, size %d\n", __func__, val_size);
|
|
free(pLine);
|
|
return NULL;
|
|
}
|
|
memset(pvalue, 0, val_size);
|
|
|
|
pLine->pNext = NULL;
|
|
strncpy(pLine->Name, name, sizeof(pLine->Name) - 1);
|
|
pLine->Name[sizeof(pLine->Name) - 1] = '\0';
|
|
|
|
pLine->Value = pvalue;
|
|
strcpy(pLine->Value, value);
|
|
pLine->value_size = val_size;
|
|
pLine->Value[val_size - 1] = '\0';
|
|
|
|
#if CC_MEMORY_ALLOC_FREE_TRACE == 1
|
|
alloc_mem(__FUNCTION__, "pLine", pLine);
|
|
#endif
|
|
}
|
|
|
|
return pLine;
|
|
}
|
|
|
|
static INI_SECTION* newSection(const char* section, INI_LINE* pLine) {
|
|
INI_SECTION* pSec = NULL;
|
|
|
|
pSec = (INI_SECTION*) malloc(sizeof(INI_SECTION));
|
|
if (pSec != NULL) {
|
|
memset(pSec, 0, sizeof(INI_SECTION));
|
|
pSec->pLine = pLine;
|
|
pSec->pNext = NULL;
|
|
strncpy(pSec->Name, section, sizeof(pSec->Name) - 1);
|
|
pSec->Name[sizeof(pSec->Name) - 1] = '\0';
|
|
|
|
#if CC_MEMORY_ALLOC_FREE_TRACE == 1
|
|
alloc_mem(__FUNCTION__, "pSec", pSec);
|
|
#endif
|
|
}
|
|
|
|
return pSec;
|
|
}
|
|
|
|
static int setKeyValue(void* user, const char* section, const char* key, const char* value, int set_mode) {
|
|
INI_LINE* pLine = NULL;
|
|
INI_SECTION *pSec = NULL;
|
|
INI_HANDLER_DATA *pHandlerData = (INI_HANDLER_DATA *) user;
|
|
int ret;
|
|
|
|
if (section == NULL || key == NULL || value == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
trim_all((char *) value);
|
|
if (value[0] == '\0') {
|
|
return 1;
|
|
}
|
|
|
|
if (strlen(key) > CC_MAX_INI_LINE_NAME_LEN) {
|
|
ALOGE("key name is too long, limit %d.\n", CC_MAX_INI_LINE_NAME_LEN);
|
|
return 1;
|
|
}
|
|
if (strlen(value) > CC_MAX_INI_FILE_LINE_LEN) {
|
|
ALOGE("value is too long, limit %d.\n", CC_MAX_INI_FILE_LINE_LEN);
|
|
return 1;
|
|
}
|
|
|
|
if (pHandlerData->mpFirstSection == NULL) {
|
|
pLine = newLine(key, value);
|
|
if (!pLine)
|
|
goto ini_set_key_value_end;
|
|
pSec = newSection(section, pLine);
|
|
if (!pSec) {
|
|
ini_line_free(pLine);
|
|
goto ini_set_key_value_end;
|
|
}
|
|
|
|
pHandlerData->mpFirstSection = pSec;
|
|
pHandlerData->mpCurSection = pSec;
|
|
pSec->pCurLine = pLine;
|
|
} else {
|
|
pSec = getSection(section, pHandlerData);
|
|
if (pSec == NULL) {
|
|
pLine = newLine(key, value);
|
|
if (!pLine)
|
|
goto ini_set_key_value_end;
|
|
pSec = newSection(section, pLine);
|
|
if (!pSec) {
|
|
ini_line_free(pLine);
|
|
goto ini_set_key_value_end;
|
|
}
|
|
|
|
pHandlerData->mpCurSection->pNext = pSec;
|
|
pHandlerData->mpCurSection = pSec;
|
|
pSec->pCurLine = pLine;
|
|
} else {
|
|
pLine = getKeyLineAtSec(pSec, key);
|
|
if (pLine == NULL) {
|
|
pLine = newLine(key, value);
|
|
if (!pLine)
|
|
goto ini_set_key_value_end;
|
|
|
|
pSec->pCurLine->pNext = pLine;
|
|
pSec->pCurLine = pLine;
|
|
} else {
|
|
ret = ini_set_line_exist_key_val(pLine, value, set_mode);
|
|
if (ret)
|
|
goto ini_set_key_value_end;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
ini_set_key_value_end:
|
|
printf("%s: section[%s]: key_name: %s, error\n", __func__, section, key);
|
|
return 0;
|
|
}
|
|
|
|
static int handler(void* user, const char* section, const char* name,
|
|
const char* value) {
|
|
//ALOGD("%s, section = %s, name = %s, value = %s\n", __FUNCTION__, section, name, value);
|
|
setKeyValue(user, section, name, value, 0);
|
|
return 1;
|
|
}
|
|
|
|
#if CC_MEMORY_ALLOC_FREE_TRACE == 1
|
|
|
|
#define CC_MEM_RECORD_CNT (1024)
|
|
|
|
typedef struct tag_memnd {
|
|
char fun_name[50];
|
|
char var_name[50];
|
|
void *ptr;
|
|
} memnd;
|
|
|
|
static memnd gMemAllocItems[CC_MEM_RECORD_CNT];
|
|
static int gMemAllocInd = 0;
|
|
|
|
static memnd gMemFreeItems[CC_MEM_RECORD_CNT];
|
|
static int gMemFreeInd = 0;
|
|
|
|
static void alloc_mem(const char *fun_name, const char *var_name, void *ptr) {
|
|
strncpy(gMemAllocItems[gMemAllocInd].fun_name, fun_name,
|
|
sizeof(gMemAllocItems[gMemAllocInd].fun_name) - 1);
|
|
gMemAllocItems[gMemAllocInd].fun_name[sizeof(gMemAllocItems[gMemAllocInd].fun_name) - 1]
|
|
= '\0';
|
|
strncpy(gMemAllocItems[gMemAllocInd].var_name, var_name,
|
|
sizeof(gMemAllocItems[gMemAllocInd].var_name) - 1);
|
|
gMemAllocItems[gMemAllocInd].var_name[sizeof(gMemAllocItems[gMemAllocInd].var_name) - 1]
|
|
= '\0';
|
|
gMemAllocItems[gMemAllocInd].ptr = ptr;
|
|
|
|
gMemAllocInd += 1;
|
|
}
|
|
|
|
static void free_mem(const char *fun_name, const char *var_name, void *ptr) {
|
|
strncpy(gMemFreeItems[gMemFreeInd].fun_name, fun_name,
|
|
sizeof(gMemFreeItems[gMemFreeInd].fun_name) - 1);
|
|
gMemFreeItems[gMemFreeInd].fun_name[sizeof(gMemFreeItems[gMemFreeInd].fun_name) - 1]
|
|
= '\0';
|
|
strncpy(gMemFreeItems[gMemFreeInd].var_name, var_name,
|
|
sizeof(gMemFreeItems[gMemFreeInd].var_name) - 1);
|
|
gMemFreeItems[gMemFreeInd].var_name[sizeof(gMemFreeItems[gMemFreeInd].var_name) - 1]
|
|
= '\0';
|
|
|
|
gMemFreeItems[gMemFreeInd].ptr = ptr;
|
|
|
|
gMemFreeInd += 1;
|
|
}
|
|
|
|
static void printMemND(const char *fun_name, memnd *tmp_nd, int tmp_cnt) {
|
|
#if CC_MEMORY_ALLOC_FREE_TRACE_PRINT_ALL == 1
|
|
int i = 0;
|
|
|
|
ALOGD("fun_name = %s, total_cnt = %d\n", fun_name, tmp_cnt);
|
|
|
|
for (i = 0; i < tmp_cnt; i++) {
|
|
ALOGD("fun_name = %s, var_name = %s, ptr = %p\n", tmp_nd[i].fun_name, tmp_nd[i].var_name, tmp_nd[i].ptr);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void printFreeMemND(const char *fun_name) {
|
|
printMemND(__FUNCTION__, gMemFreeItems, gMemFreeInd);
|
|
}
|
|
|
|
static void printAllocMemND(const char *fun_name) {
|
|
printMemND(__FUNCTION__, gMemAllocItems, gMemAllocInd);
|
|
}
|
|
|
|
static void clearMemND(void) {
|
|
gMemAllocInd = 0;
|
|
gMemFreeInd = 0;
|
|
memset((void *)gMemAllocItems, 0, sizeof(memnd) * CC_MEM_RECORD_CNT);
|
|
memset((void *)gMemFreeItems, 0, sizeof(memnd) * CC_MEM_RECORD_CNT);
|
|
}
|
|
#endif
|