From 79ca6100e64b3fff6f52444f121ee1f7642a7b04 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 22 Feb 2008 18:13:01 +0000 Subject: worked a bit on var_t data type conversion --- stringbuf.c | 31 ++++++++++++++++++++++++++++++ stringbuf.h | 1 + var.c | 63 ++++++++++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 78 insertions(+), 17 deletions(-) diff --git a/stringbuf.c b/stringbuf.c index a54fe1bd..d1e69abf 100755 --- a/stringbuf.c +++ b/stringbuf.c @@ -718,6 +718,37 @@ int rsCStrOffsetSzStrCmp(cstr_t *pCS1, size_t iOffset, uchar *psz, size_t iLenSz } +/* check if the string can be converted to a number. Returns 1 if that's possible + * and 0 otherwise. + */ +int rsCStrCanConvertToNumber(cstr_t *pStr) +{ + int i; + int ret = 1; + + if(pStr->iStrLen == 0) { + /* can be converted to 0! (by convention) */ + goto finalize_it; + } + + /* we have a string, so let's check its syntax */ + if(pStr->pBuf[0] == '+' || pStr->pBuf[0] == '-') { + i = 1; /* skip that char */ + } else { + i = 0; /* start from the beginning */ + } + + while(i < pStr->iStrLen && isdigit(pStr->pBuf[i])) + ++i; + + if(i < pStr->iStrLen) /* non-digits before end of string? */ + ret = 0; /* than we can not convert */ + +finalize_it: + return ret; +} + + /* compare a rsCStr object with a classical sz string. * Just like rsCStrCStrCmp, just for a different data type. * There must not only the sz string but also its length be diff --git a/stringbuf.h b/stringbuf.h index 1c4ff04b..02720c2a 100755 --- a/stringbuf.h +++ b/stringbuf.h @@ -138,6 +138,7 @@ int rsCStrLocateInSzStr(cstr_t *pThis, uchar *sz); int rsCStrStartsWithSzStr(cstr_t *pCS1, uchar *psz, size_t iLenSz); int rsCStrSzStrStartsWithCStr(cstr_t *pCS1, uchar *psz, size_t iLenSz); int rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz); +int rsCStrCanConvertToNumber(cstr_t *pStr); /* now come inline-like functions */ #ifdef NDEBUG diff --git a/var.c b/var.c index d383a1a8..1f4ed1cb 100644 --- a/var.c +++ b/var.c @@ -142,6 +142,29 @@ finalize_it: } +/* check if the provided object can be converted to a number. Uses + * non-standard calling conventions because it makes an awful lot of sense. + * Returns 1 if conversion is possibe and 0 if not. If 1 is returned, a + * conversion request on the unchanged object is guaranteed to succeed. + * rgerhards, 2008-02-22 + */ +int canConvToNumber(var_t *pThis) +{ + int ret = 0; + + BEGINfunc + + if(pThis->varType == VARTYPE_NUMBER) { + ret = 1; + } else if(pThis->varType == VARTYPE_STR) { + ret = rsCStrCanConvertToNumber(pThis->val.pStr); // TODO: implement the same method in str_t object, then call that */ + } + + ENDfunc + return ret; +} + + /* This function is used to prepare two var_t objects for a common operation, * e.g before they are added, multiplied or compared. The function looks at * the data types of both operands and finds the best data type suitable for @@ -184,42 +207,48 @@ ConvForOperation(var_t *pThis, var_t *pOther) if(pThis->varType == VARTYPE_NONE || pOther->varType == VARTYPE_NONE) ABORT_FINALIZE(RS_RET_INVALID_VAR); -#if 0 switch(pThis->varType) { case VARTYPE_NONE: ABORT_FINALIZE(RS_RET_INVALID_VAR); break; - // TODO: remove VARTYPE_PSZ? - // TODO: check need for SHORT/INT/LONG... - case VARTYPE_PSZ: - case VARTYPE_CSTR: - switch(pThis->varType) { + case VARTYPE_STR: + switch(pOther->varType) { case VARTYPE_NONE: ABORT_FINALIZE(RS_RET_INVALID_VAR); break; - case VARTYPE_PSZ: - case VARTYPE_CSTR: + case VARTYPE_STR: + commonType = VARTYPE_STR; break; - case VARTYPE_SHORT: - case VARTYPE_INT: - case VARTYPE_LONG: - case VARTYPE_INT64: + case VARTYPE_NUMBER: + /* check if we can convert pThis to a number, if so use number format. */ + commonType = canConvToNumber(pThis) ? VARTYPE_NUMBER : VARTYPE_STR; break; case VARTYPE_SYSLOGTIME: ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED); break; } break; - case VARTYPE_SHORT: - case VARTYPE_INT: - case VARTYPE_LONG: - case VARTYPE_INT64: + case VARTYPE_NUMBER: + switch(pOther->varType) { + case VARTYPE_NONE: + ABORT_FINALIZE(RS_RET_INVALID_VAR); + break; + case VARTYPE_STR: + /* check if we can convert pOther to a number, if so use number format. */ + commonType = canConvToNumber(pOther) ? VARTYPE_NUMBER : VARTYPE_STR; + break; + case VARTYPE_NUMBER: + commonType = VARTYPE_NUMBER; + break; + case VARTYPE_SYSLOGTIME: + ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED); + break; + } break; case VARTYPE_SYSLOGTIME: ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED); break; } -#endif finalize_it: RETiRet; -- cgit