ini_file_reader support #@set directive
parent
f76f3f6206
commit
5c7ba700b6
3
HISTORY
3
HISTORY
|
|
@ -1,8 +1,9 @@
|
||||||
|
|
||||||
Version 1.34 2017-01-19
|
Version 1.34 2017-01-31
|
||||||
* ini_file_reader: LOCAL_IP support CIDR addresses
|
* ini_file_reader: LOCAL_IP support CIDR addresses
|
||||||
* ini_file_reader: return the last when get single value,
|
* ini_file_reader: return the last when get single value,
|
||||||
such as iniGetStrValue and iniGetIntValue
|
such as iniGetStrValue and iniGetIntValue
|
||||||
|
* ini_file_reader support #@set directive
|
||||||
|
|
||||||
Version 1.33 2017-01-04
|
Version 1.33 2017-01-04
|
||||||
* add function hash_get_prime_capacity
|
* add function hash_get_prime_capacity
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,14 @@
|
||||||
#define _PREPROCESS_TAG_STR_ENDIF "#@endif"
|
#define _PREPROCESS_TAG_STR_ENDIF "#@endif"
|
||||||
#define _PREPROCESS_TAG_STR_FOR "#@for "
|
#define _PREPROCESS_TAG_STR_FOR "#@for "
|
||||||
#define _PREPROCESS_TAG_STR_ENDFOR "#@endfor"
|
#define _PREPROCESS_TAG_STR_ENDFOR "#@endfor"
|
||||||
|
#define _PREPROCESS_TAG_STR_SET "#@set "
|
||||||
|
|
||||||
#define _PREPROCESS_TAG_LEN_IF (sizeof(_PREPROCESS_TAG_STR_IF) - 1)
|
#define _PREPROCESS_TAG_LEN_IF (sizeof(_PREPROCESS_TAG_STR_IF) - 1)
|
||||||
#define _PREPROCESS_TAG_LEN_ELSE (sizeof(_PREPROCESS_TAG_STR_ELSE) - 1)
|
#define _PREPROCESS_TAG_LEN_ELSE (sizeof(_PREPROCESS_TAG_STR_ELSE) - 1)
|
||||||
#define _PREPROCESS_TAG_LEN_ENDIF (sizeof(_PREPROCESS_TAG_STR_ENDIF) - 1)
|
#define _PREPROCESS_TAG_LEN_ENDIF (sizeof(_PREPROCESS_TAG_STR_ENDIF) - 1)
|
||||||
#define _PREPROCESS_TAG_LEN_FOR (sizeof(_PREPROCESS_TAG_STR_FOR) - 1)
|
#define _PREPROCESS_TAG_LEN_FOR (sizeof(_PREPROCESS_TAG_STR_FOR) - 1)
|
||||||
#define _PREPROCESS_TAG_LEN_ENDFOR (sizeof(_PREPROCESS_TAG_STR_ENDFOR) - 1)
|
#define _PREPROCESS_TAG_LEN_ENDFOR (sizeof(_PREPROCESS_TAG_STR_ENDFOR) - 1)
|
||||||
|
#define _PREPROCESS_TAG_LEN_SET (sizeof(_PREPROCESS_TAG_STR_SET) - 1)
|
||||||
|
|
||||||
#define _PREPROCESS_VARIABLE_STR_LOCAL_IP "%{LOCAL_IP}"
|
#define _PREPROCESS_VARIABLE_STR_LOCAL_IP "%{LOCAL_IP}"
|
||||||
#define _PREPROCESS_VARIABLE_STR_LOCAL_HOST "%{LOCAL_HOST}"
|
#define _PREPROCESS_VARIABLE_STR_LOCAL_HOST "%{LOCAL_HOST}"
|
||||||
|
|
@ -900,7 +902,7 @@ static bool iniMatchCIDR(const char *target, const char *ip_addr,
|
||||||
if (inet_pton(AF_INET, target, &addr) != 1)
|
if (inet_pton(AF_INET, target, &addr) != 1)
|
||||||
{
|
{
|
||||||
logError("file: "__FILE__", line: %d, "
|
logError("file: "__FILE__", line: %d, "
|
||||||
"invalid ip: %s", __LINE__, ip_addr, target);
|
"invalid ip: %s", __LINE__, target);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
target_hip = ntohl(addr.s_addr);
|
target_hip = ntohl(addr.s_addr);
|
||||||
|
|
@ -936,23 +938,30 @@ static bool iniMatchIP(const char *target, char **values, const int count)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool iniCalcCondition(char *condition, const int condition_len)
|
static bool iniCalcCondition(char *condition, const int condition_len,
|
||||||
|
IniContext *pContext)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* current only support %{VARIABLE} in [x,y,..]
|
* current only support %{VARIABLE} in [x,y,..]
|
||||||
* support variables are: LOCAL_IP and LOCAL_HOST
|
* support variables are: LOCAL_IP, LOCAL_HOST and
|
||||||
|
* variables by #@set directive.
|
||||||
* such as: %{LOCAL_IP} in [10.0.11.89,10.0.11.99]
|
* such as: %{LOCAL_IP} in [10.0.11.89,10.0.11.99]
|
||||||
* local ip support CIDR addresses such as 172.16.12.0/22
|
* local ip support CIDR addresses such as 172.16.12.0/22
|
||||||
**/
|
**/
|
||||||
#define _PREPROCESS_VARIABLE_TYPE_LOCAL_IP 1
|
#define _PREPROCESS_VARIABLE_TYPE_LOCAL_IP 1
|
||||||
#define _PREPROCESS_VARIABLE_TYPE_LOCAL_HOST 2
|
#define _PREPROCESS_VARIABLE_TYPE_LOCAL_HOST 2
|
||||||
|
#define _PREPROCESS_VARIABLE_TYPE_SET 3
|
||||||
#define _PREPROCESS_MAX_LIST_VALUE_COUNT 32
|
#define _PREPROCESS_MAX_LIST_VALUE_COUNT 32
|
||||||
char *p;
|
char *p;
|
||||||
char *pEnd;
|
char *pEnd;
|
||||||
|
char *pBraceEnd;
|
||||||
char *pSquareEnd;
|
char *pSquareEnd;
|
||||||
char *values[_PREPROCESS_MAX_LIST_VALUE_COUNT];
|
char *values[_PREPROCESS_MAX_LIST_VALUE_COUNT];
|
||||||
|
char *varStr = NULL;
|
||||||
|
int varLen = 0;
|
||||||
int varType;
|
int varType;
|
||||||
int count;
|
int count;
|
||||||
|
int len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
pEnd = condition + condition_len;
|
pEnd = condition + condition_len;
|
||||||
|
|
@ -976,33 +985,54 @@ static bool iniCalcCondition(char *condition, const int condition_len)
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pEnd - p < 12)
|
len = pEnd - p;
|
||||||
|
if (len < 8 || !(*p == '%' && *(p+1) == '{'))
|
||||||
{
|
{
|
||||||
logWarning("file: "__FILE__", line: %d, "
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
"unkown condition: %.*s", __LINE__,
|
"invalid condition: %.*s, "
|
||||||
condition_len, condition);
|
"correct format: %%{variable} in [...]",
|
||||||
|
__LINE__, condition_len, condition);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(p, _PREPROCESS_VARIABLE_STR_LOCAL_IP,
|
if ((len > _PREPROCESS_VARIABLE_LEN_LOCAL_IP) &&
|
||||||
_PREPROCESS_VARIABLE_LEN_LOCAL_IP) == 0)
|
(memcmp(p, _PREPROCESS_VARIABLE_STR_LOCAL_IP,
|
||||||
|
_PREPROCESS_VARIABLE_LEN_LOCAL_IP) == 0))
|
||||||
{
|
{
|
||||||
varType = _PREPROCESS_VARIABLE_TYPE_LOCAL_IP;
|
varType = _PREPROCESS_VARIABLE_TYPE_LOCAL_IP;
|
||||||
p += _PREPROCESS_VARIABLE_LEN_LOCAL_IP;
|
p += _PREPROCESS_VARIABLE_LEN_LOCAL_IP;
|
||||||
}
|
}
|
||||||
else if (memcmp(p, _PREPROCESS_VARIABLE_STR_LOCAL_HOST,
|
else if ((len > _PREPROCESS_VARIABLE_LEN_LOCAL_HOST) &&
|
||||||
|
memcmp(p, _PREPROCESS_VARIABLE_STR_LOCAL_HOST,
|
||||||
_PREPROCESS_VARIABLE_LEN_LOCAL_HOST) == 0)
|
_PREPROCESS_VARIABLE_LEN_LOCAL_HOST) == 0)
|
||||||
{
|
{
|
||||||
varType = _PREPROCESS_VARIABLE_TYPE_LOCAL_HOST;
|
varType = _PREPROCESS_VARIABLE_TYPE_LOCAL_HOST;
|
||||||
p += _PREPROCESS_VARIABLE_LEN_LOCAL_HOST;
|
p += _PREPROCESS_VARIABLE_LEN_LOCAL_HOST;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
varType = _PREPROCESS_VARIABLE_TYPE_SET;
|
||||||
|
pBraceEnd = (char *)memchr(p + 2, '}', len - 2);
|
||||||
|
if (pBraceEnd == NULL)
|
||||||
{
|
{
|
||||||
logWarning("file: "__FILE__", line: %d, "
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
"unkown condition: %.*s", __LINE__,
|
"invalid condition: %.*s, expect }",
|
||||||
|
__LINE__, condition_len, condition);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
varStr = p + 2;
|
||||||
|
varLen = pBraceEnd - varStr;
|
||||||
|
if (varLen == 0)
|
||||||
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"invalid condition: %.*s, "
|
||||||
|
"expect variable name", __LINE__,
|
||||||
condition_len, condition);
|
condition_len, condition);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
p = pBraceEnd + 1;
|
||||||
|
}
|
||||||
|
|
||||||
while (p < pEnd && (*p == ' ' || *p == '\t'))
|
while (p < pEnd && (*p == ' ' || *p == '\t'))
|
||||||
{
|
{
|
||||||
|
|
@ -1030,7 +1060,8 @@ static bool iniCalcCondition(char *condition, const int condition_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
*pSquareEnd = '\0';
|
*pSquareEnd = '\0';
|
||||||
count = splitEx(p + 1, ',', values, _PREPROCESS_MAX_LIST_VALUE_COUNT);
|
count = splitEx(p + 1, ',', values,
|
||||||
|
_PREPROCESS_MAX_LIST_VALUE_COUNT);
|
||||||
for (i=0; i<count; i++)
|
for (i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
values[i] = trim(values[i]);
|
values[i] = trim(values[i]);
|
||||||
|
|
@ -1048,7 +1079,7 @@ static bool iniCalcCondition(char *condition, const int condition_len)
|
||||||
}
|
}
|
||||||
return iniMatchValue(host, values, count);
|
return iniMatchValue(host, values, count);
|
||||||
}
|
}
|
||||||
else
|
else if (varType == _PREPROCESS_VARIABLE_TYPE_LOCAL_IP)
|
||||||
{
|
{
|
||||||
const char *local_ip;
|
const char *local_ip;
|
||||||
local_ip = get_first_local_ip();
|
local_ip = get_first_local_ip();
|
||||||
|
|
@ -1061,12 +1092,185 @@ static bool iniCalcCondition(char *condition, const int condition_len)
|
||||||
local_ip = get_next_local_ip(local_ip);
|
local_ip = get_next_local_ip(local_ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *value;
|
||||||
|
value = (char *)hash_find(pContext->set.vars, varStr, varLen);
|
||||||
|
if (value == NULL)
|
||||||
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"variable \"%.*s\" not exist", __LINE__,
|
||||||
|
varLen, varStr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return iniMatchValue(value, values, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *iniFindTag(char *content, char *pStart,
|
||||||
|
const char *tagStr, const int tagLen)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
p = strstr(pStart, tagStr);
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (isLeadingSpacesLine(content, p))
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
pStart = p + tagLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *iniFindAloneTag(char *content, const int content_len,
|
||||||
|
char *pStart, const char *tagStr, const int tagLen)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
while ((p=iniFindTag(content, pStart, tagStr, tagLen)) != NULL)
|
||||||
|
{
|
||||||
|
if (isTrailingSpacesLine(p + tagLen, content + content_len))
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iniDoProccessSet(char *pSet, char **ppSetEnd,
|
||||||
|
IniContext *pContext)
|
||||||
|
{
|
||||||
|
char *pStart;
|
||||||
|
char buff[FAST_INI_ITEM_NAME_LEN + FAST_INI_ITEM_VALUE_LEN];
|
||||||
|
char output[256];
|
||||||
|
int result;
|
||||||
|
int len;
|
||||||
|
char *parts[2];
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
int value_len;
|
||||||
|
|
||||||
|
pStart = pSet + _PREPROCESS_TAG_LEN_SET;
|
||||||
|
*ppSetEnd = strchr(pStart, '\n');
|
||||||
|
if (*ppSetEnd == NULL)
|
||||||
|
{
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = *ppSetEnd - pStart;
|
||||||
|
if (len <= 1 || len >= (int)sizeof(buff))
|
||||||
|
{
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buff, pStart, len);
|
||||||
|
*(buff + len) = '\0';
|
||||||
|
|
||||||
|
if (splitEx(buff, '=', parts, 2) != 2)
|
||||||
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"invalid set format: %s%s",
|
||||||
|
__LINE__, _PREPROCESS_TAG_STR_SET, buff);
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pContext->set.vars == NULL)
|
||||||
|
{
|
||||||
|
pContext->set.vars = (HashArray *)malloc(sizeof(HashArray));
|
||||||
|
if (pContext->set.vars == NULL)
|
||||||
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"malloc %d bytes fail",
|
||||||
|
__LINE__, (int)sizeof(HashArray));
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
if ((result=hash_init_ex(pContext->set.vars,
|
||||||
|
simple_hash, 17, 0.75, 0, true)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
key = trim(parts[0]);
|
||||||
|
value = trim(parts[1]);
|
||||||
|
value_len = strlen(value);
|
||||||
|
if (value_len > 3 && (*value == '$' && *(value + 1) == '(')
|
||||||
|
&& *(value + value_len - 1) == ')')
|
||||||
|
{
|
||||||
|
char *cmd;
|
||||||
|
cmd = value + 2;
|
||||||
|
*(value + value_len - 1) = '\0';
|
||||||
|
if ((result=getExecResult(cmd, output, sizeof(output))) != 0)
|
||||||
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"exec %s fail, errno: %d, error info: %s",
|
||||||
|
__LINE__, cmd, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
value = trim(output);
|
||||||
|
value_len = strlen(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash_insert_ex(pContext->set.vars, key, strlen(key),
|
||||||
|
value, value_len + 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iniProccessSet(char *content, char *pEnd,
|
||||||
|
IniContext *pContext)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
char *pStart;
|
||||||
|
char *pSet;
|
||||||
|
char *pSetEnd;
|
||||||
|
|
||||||
|
pStart = content + pContext->set.offset;
|
||||||
|
while (pStart < pEnd)
|
||||||
|
{
|
||||||
|
pSet = iniFindTag(content, pStart, _PREPROCESS_TAG_STR_SET,
|
||||||
|
_PREPROCESS_TAG_LEN_SET);
|
||||||
|
if (pSet == NULL || pSet >= pEnd)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result=iniDoProccessSet(pSet, &pSetEnd, pContext)) == 0)
|
||||||
|
{
|
||||||
|
pStart = pSetEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (result == EINVAL)
|
||||||
|
{
|
||||||
|
char *pNewLine;;
|
||||||
|
pNewLine = pSet + _PREPROCESS_TAG_LEN_SET;
|
||||||
|
while (pNewLine < pEnd && *pNewLine != '\n')
|
||||||
|
{
|
||||||
|
++pNewLine;
|
||||||
|
}
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"invalid set format: %.*s", __LINE__,
|
||||||
|
(int)(pNewLine - pSet), pSet);
|
||||||
|
}
|
||||||
|
pStart = pSet + _PREPROCESS_TAG_LEN_SET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pContext->set.offset = pEnd - content;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static char *iniProccessIf(char *content, const int content_len,
|
static char *iniProccessIf(char *content, const int content_len,
|
||||||
IniContext *pContext, int *new_content_len)
|
int *offset, IniContext *pContext, int *new_content_len)
|
||||||
{
|
{
|
||||||
char *pStart;
|
char *pStart;
|
||||||
char *pEnd;
|
char *pEnd;
|
||||||
|
|
@ -1082,26 +1286,43 @@ static char *iniProccessIf(char *content, const int content_len,
|
||||||
char *pDest;
|
char *pDest;
|
||||||
|
|
||||||
*new_content_len = content_len;
|
*new_content_len = content_len;
|
||||||
pStart = strstr(content, _PREPROCESS_TAG_STR_IF);
|
pStart = iniFindTag(content, content + (*offset),
|
||||||
|
_PREPROCESS_TAG_STR_IF, _PREPROCESS_TAG_LEN_IF);
|
||||||
if (pStart == NULL)
|
if (pStart == NULL)
|
||||||
{
|
{
|
||||||
|
*offset = *new_content_len;
|
||||||
|
iniProccessSet(content, content + content_len, pContext);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iniProccessSet(content, pStart, pContext);
|
||||||
|
|
||||||
pCondition = pStart + _PREPROCESS_TAG_LEN_IF;
|
pCondition = pStart + _PREPROCESS_TAG_LEN_IF;
|
||||||
pIfPart = strchr(pCondition, '\n');
|
pIfPart = strchr(pCondition, '\n');
|
||||||
if (pIfPart == NULL)
|
if (pIfPart == NULL)
|
||||||
{
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"expect new line (\\n) for %s",
|
||||||
|
__LINE__, pStart);
|
||||||
|
*offset = *new_content_len;
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
conditionLen = pIfPart - pCondition;
|
conditionLen = pIfPart - pCondition;
|
||||||
|
|
||||||
pEnd = strstr(pIfPart, _PREPROCESS_TAG_STR_ENDIF);
|
pEnd = iniFindAloneTag(content, content_len, pIfPart,
|
||||||
|
_PREPROCESS_TAG_STR_ENDIF, _PREPROCESS_TAG_LEN_ENDIF);
|
||||||
if (pEnd == NULL)
|
if (pEnd == NULL)
|
||||||
{
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"expect %s for %.*s",
|
||||||
|
__LINE__, _PREPROCESS_TAG_STR_ENDIF,
|
||||||
|
(int)(pIfPart - pStart), pStart);
|
||||||
|
*offset = *new_content_len;
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
pElse = strstr(pIfPart, _PREPROCESS_TAG_STR_ELSE);
|
pElse = iniFindAloneTag(content, content_len, pIfPart,
|
||||||
|
_PREPROCESS_TAG_STR_ELSE, _PREPROCESS_TAG_LEN_ELSE);
|
||||||
if (pElse == NULL || pElse > pEnd)
|
if (pElse == NULL || pElse > pEnd)
|
||||||
{
|
{
|
||||||
ifPartLen = pEnd - pIfPart;
|
ifPartLen = pEnd - pIfPart;
|
||||||
|
|
@ -1114,6 +1335,7 @@ static char *iniProccessIf(char *content, const int content_len,
|
||||||
pElsePart = strchr(pElse + _PREPROCESS_TAG_LEN_ELSE, '\n');
|
pElsePart = strchr(pElse + _PREPROCESS_TAG_LEN_ELSE, '\n');
|
||||||
if (pElsePart == NULL)
|
if (pElsePart == NULL)
|
||||||
{
|
{
|
||||||
|
*offset = (pEnd + _PREPROCESS_TAG_LEN_ENDIF) - content;
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1123,6 +1345,7 @@ static char *iniProccessIf(char *content, const int content_len,
|
||||||
newContent = iniAllocContent(pContext, content_len);
|
newContent = iniAllocContent(pContext, content_len);
|
||||||
if (newContent == NULL)
|
if (newContent == NULL)
|
||||||
{
|
{
|
||||||
|
*offset = (pEnd + _PREPROCESS_TAG_LEN_ENDIF) - content;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1133,8 +1356,9 @@ static char *iniProccessIf(char *content, const int content_len,
|
||||||
memcpy(pDest, content, copyLen);
|
memcpy(pDest, content, copyLen);
|
||||||
pDest += copyLen;
|
pDest += copyLen;
|
||||||
}
|
}
|
||||||
|
*offset = copyLen;
|
||||||
|
|
||||||
if (iniCalcCondition(pCondition, conditionLen))
|
if (iniCalcCondition(pCondition, conditionLen, pContext))
|
||||||
{
|
{
|
||||||
if (ifPartLen > 0)
|
if (ifPartLen > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1350,7 +1574,7 @@ static int iniParseForRange(char *range, const int range_len,
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *iniProccessFor(char *content, const int content_len,
|
static char *iniProccessFor(char *content, const int content_len,
|
||||||
IniContext *pContext, int *new_content_len)
|
int *offset, IniContext *pContext, int *new_content_len)
|
||||||
{
|
{
|
||||||
char *pStart;
|
char *pStart;
|
||||||
char *pEnd;
|
char *pEnd;
|
||||||
|
|
@ -1374,22 +1598,33 @@ static char *iniProccessFor(char *content, const int content_len,
|
||||||
char *pDest;
|
char *pDest;
|
||||||
|
|
||||||
*new_content_len = content_len;
|
*new_content_len = content_len;
|
||||||
pStart = strstr(content, _PREPROCESS_TAG_STR_FOR);
|
pStart = iniFindTag(content, content + (*offset),
|
||||||
|
_PREPROCESS_TAG_STR_FOR, _PREPROCESS_TAG_LEN_FOR);
|
||||||
if (pStart == NULL)
|
if (pStart == NULL)
|
||||||
{
|
{
|
||||||
|
*offset = *new_content_len;
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
pForRange = pStart + _PREPROCESS_TAG_LEN_FOR;
|
pForRange = pStart + _PREPROCESS_TAG_LEN_FOR;
|
||||||
pForBlock = strchr(pForRange, '\n');
|
pForBlock = strchr(pForRange, '\n');
|
||||||
if (pForBlock == NULL)
|
if (pForBlock == NULL)
|
||||||
{
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"expect new line (\\n) for %s",
|
||||||
|
__LINE__, pStart);
|
||||||
|
*offset = *new_content_len;
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
rangeLen = pForBlock - pForRange;
|
rangeLen = pForBlock - pForRange;
|
||||||
|
|
||||||
pEnd = strstr(pForBlock, _PREPROCESS_TAG_STR_ENDFOR);
|
pEnd = iniFindAloneTag(content, content_len, pForBlock,
|
||||||
|
_PREPROCESS_TAG_STR_ENDFOR, _PREPROCESS_TAG_LEN_ENDFOR);
|
||||||
if (pEnd == NULL)
|
if (pEnd == NULL)
|
||||||
{
|
{
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"expect %s for %s", __LINE__,
|
||||||
|
_PREPROCESS_TAG_STR_ENDFOR, pStart);
|
||||||
|
*offset = *new_content_len;
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
forBlockLen = pEnd - pForBlock;
|
forBlockLen = pEnd - pForBlock;
|
||||||
|
|
@ -1397,27 +1632,37 @@ static char *iniProccessFor(char *content, const int content_len,
|
||||||
if (iniParseForRange(pForRange, rangeLen, &id, &idLen,
|
if (iniParseForRange(pForRange, rangeLen, &id, &idLen,
|
||||||
&start, &end, &step) != 0)
|
&start, &end, &step) != 0)
|
||||||
{
|
{
|
||||||
return NULL;
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"invalid statement: %.*s",
|
||||||
|
__LINE__, (int)(pForBlock - pStart), pStart);
|
||||||
|
*offset = (pEnd + _PREPROCESS_TAG_LEN_ENDFOR) - content;
|
||||||
|
return content;
|
||||||
}
|
}
|
||||||
if (step == 0)
|
if (step == 0)
|
||||||
{
|
{
|
||||||
logWarning("file: "__FILE__", line: %d, "
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
"invalid step: %d for range: %.*s", __LINE__,
|
"invalid step: %d for range: %.*s, set step to 1",
|
||||||
step, rangeLen, pForRange);
|
__LINE__, step, rangeLen, pForRange);
|
||||||
return NULL;
|
step = 1;
|
||||||
|
count = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
count = (end - start) / step;
|
count = (end - start) / step;
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
{
|
{
|
||||||
logWarning("file: "__FILE__", line: %d, "
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
"invalid step: %d for range: %.*s", __LINE__,
|
"invalid step: %d for range: %.*s", __LINE__,
|
||||||
step, rangeLen, pForRange);
|
step, rangeLen, pForRange);
|
||||||
return NULL;
|
count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newContent = iniAllocContent(pContext, content_len + (forBlockLen + 16) * count);
|
newContent = iniAllocContent(pContext, content_len +
|
||||||
|
(forBlockLen + 16) * count);
|
||||||
if (newContent == NULL)
|
if (newContent == NULL)
|
||||||
{
|
{
|
||||||
|
*offset = (pEnd + _PREPROCESS_TAG_LEN_ENDFOR) - content;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1428,6 +1673,7 @@ static char *iniProccessFor(char *content, const int content_len,
|
||||||
memcpy(pDest, content, copyLen);
|
memcpy(pDest, content, copyLen);
|
||||||
pDest += copyLen;
|
pDest += copyLen;
|
||||||
}
|
}
|
||||||
|
*offset = copyLen;
|
||||||
|
|
||||||
tagLen = sprintf(tag, "{$%.*s}", idLen, id);
|
tagLen = sprintf(tag, "{$%.*s}", idLen, id);
|
||||||
for (i=start; i<=end; i+=step)
|
for (i=start; i<=end; i+=step)
|
||||||
|
|
@ -1482,31 +1728,34 @@ static int iniLoadItemsFromBuffer(char *content, IniContext *pContext)
|
||||||
char *new_content;
|
char *new_content;
|
||||||
int content_len;
|
int content_len;
|
||||||
int new_content_len;
|
int new_content_len;
|
||||||
|
int offset;
|
||||||
|
|
||||||
new_content = content;
|
new_content = content;
|
||||||
new_content_len = strlen(content);
|
new_content_len = strlen(content);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
offset = 0;
|
||||||
pContent = new_content;
|
pContent = new_content;
|
||||||
content_len = new_content_len;
|
content_len = new_content_len;
|
||||||
if ((new_content=iniProccessIf(pContent, content_len,
|
if ((new_content=iniProccessIf(pContent, content_len,
|
||||||
pContext, &new_content_len)) == NULL)
|
&offset, pContext, &new_content_len)) == NULL)
|
||||||
{
|
{
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
} while (new_content != pContent);
|
} while (offset < new_content_len);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
offset = 0;
|
||||||
pContent = new_content;
|
pContent = new_content;
|
||||||
content_len = new_content_len;
|
content_len = new_content_len;
|
||||||
if ((new_content=iniProccessFor(pContent, content_len,
|
if ((new_content=iniProccessFor(pContent, content_len,
|
||||||
pContext, &new_content_len)) == NULL)
|
&offset, pContext, &new_content_len)) == NULL)
|
||||||
{
|
{
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
} while (new_content != pContent);
|
} while (offset < new_content_len);
|
||||||
|
|
||||||
return iniDoLoadItemsFromBuffer(new_content, pContext);
|
return iniDoLoadItemsFromBuffer(new_content, pContext);
|
||||||
}
|
}
|
||||||
|
|
@ -1585,8 +1834,13 @@ void iniFreeContext(IniContext *pContext)
|
||||||
|
|
||||||
hash_walk(&pContext->sections, iniFreeHashData, NULL);
|
hash_walk(&pContext->sections, iniFreeHashData, NULL);
|
||||||
hash_destroy(&pContext->sections);
|
hash_destroy(&pContext->sections);
|
||||||
|
|
||||||
iniFreeDynamicContent(pContext);
|
iniFreeDynamicContent(pContext);
|
||||||
|
|
||||||
|
if (pContext->set.vars != NULL)
|
||||||
|
{
|
||||||
|
hash_destroy(pContext->set.vars);
|
||||||
|
pContext->set.vars = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,10 @@ typedef struct
|
||||||
IniSection *current_section; //for load from ini file
|
IniSection *current_section; //for load from ini file
|
||||||
char config_path[MAX_PATH_SIZE]; //save the config filepath
|
char config_path[MAX_PATH_SIZE]; //save the config filepath
|
||||||
bool ignore_annotation;
|
bool ignore_annotation;
|
||||||
|
struct {
|
||||||
|
int offset; //deal offset
|
||||||
|
HashArray *vars; //variables with #@set
|
||||||
|
} set;
|
||||||
} IniContext;
|
} IniContext;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -2422,3 +2422,32 @@ int file_try_unlock(int fd)
|
||||||
return do_lock_file(fd, F_SETLK, F_UNLCK);
|
return do_lock_file(fd, F_SETLK, F_UNLCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isLeadingSpacesLine(const char *content, const char *current)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
p = current - 1;
|
||||||
|
while (p >= content)
|
||||||
|
{
|
||||||
|
if (!(*p == ' ' || *p == '\t'))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--p;
|
||||||
|
}
|
||||||
|
return (p < content || *p == '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTrailingSpacesLine(const char *tail, const char *end)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
p = tail;
|
||||||
|
while (p < end)
|
||||||
|
{
|
||||||
|
if (!(*p == ' ' || *p == '\t'))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
return (p == end || *p == '\n');
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -608,6 +608,22 @@ int file_try_write_lock(int fd);
|
||||||
*/
|
*/
|
||||||
int file_try_unlock(int fd);
|
int file_try_unlock(int fd);
|
||||||
|
|
||||||
|
/** is a leading spaces line
|
||||||
|
* parameters:
|
||||||
|
* content: the whole string content
|
||||||
|
* current: the current line
|
||||||
|
* return: error no, 0 for success, != 0 fail
|
||||||
|
*/
|
||||||
|
bool isLeadingSpacesLine(const char *content, const char *current);
|
||||||
|
|
||||||
|
/** is a trailing spaces line
|
||||||
|
* parameters:
|
||||||
|
* tail: the current line tail
|
||||||
|
* end: the string end ptr
|
||||||
|
* return: error no, 0 for success, != 0 fail
|
||||||
|
*/
|
||||||
|
bool isTrailingSpacesLine(const char *tail, const char *end);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
|
|
||||||
|
#@set author_name = yuqing
|
||||||
|
#@set os_name = $(uname -a | awk '{print $1;}')
|
||||||
|
|
||||||
|
#@if %{os_name} in [Linux, Darwin]
|
||||||
[AccessLogSpaceCharConvert]
|
[AccessLogSpaceCharConvert]
|
||||||
# format: src = dest
|
# format: src = dest
|
||||||
# src can be a printable char or a backslash char pair such as \t
|
# src can be a printable char or a backslash char pair such as \t
|
||||||
|
|
@ -20,3 +24,4 @@
|
||||||
\s = "\s"
|
\s = "\s"
|
||||||
\\ = "\\"
|
\\ = "\\"
|
||||||
|
|
||||||
|
#@endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue