ini_file_reader support #@set directive

pull/37/head
Yu Qing 2017-01-31 21:33:57 +08:00
parent f76f3f6206
commit 5c7ba700b6
6 changed files with 349 additions and 40 deletions

View File

@ -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

View File

@ -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;
}
} }

View File

@ -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

View File

@ -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');
}

View File

@ -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

View File

@ -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