Files

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