diff options
Diffstat (limited to 'stringbuf.c')
-rw-r--r--[-rwxr-xr-x] | stringbuf.c | 507 |
1 files changed, 416 insertions, 91 deletions
diff --git a/stringbuf.c b/stringbuf.c index 01467f4d..4254d5bd 100755..100644 --- a/stringbuf.c +++ b/stringbuf.c @@ -5,8 +5,26 @@ * requires strings to be able to handle embedded \0 characters. * Please see syslogd.c for license information. * All functions in this "class" start with rsCStr (rsyslog Counted String). - * This code is placed under the GPL. * begun 2005-09-07 rgerhards + * + * Copyright (C) 2007 by Rainer Gerhards and Adiscon GmbH + * + * This file is part of rsyslog. + * + * Rsyslog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" @@ -15,29 +33,35 @@ #include <string.h> #include <ctype.h> #include <sys/types.h> -#include <regex.h> #include "rsyslog.h" #include "stringbuf.h" #include "srUtils.h" +#include "regexp.h" +#include "obj.h" /* ################################################################# * * private members * * ################################################################# */ - +/* static data */ +DEFobjCurrIf(obj) +DEFobjCurrIf(regexp) /* ################################################################# * * public members * * ################################################################# */ -rsCStrObj *rsCStrConstruct(void) +rsRetVal rsCStrConstruct(cstr_t **ppThis) { - rsCStrObj *pThis; + DEFiRet; + cstr_t *pThis; + + ASSERT(ppThis != NULL); - if((pThis = (rsCStrObj*) calloc(1, sizeof(rsCStrObj))) == NULL) - return NULL; + if((pThis = (cstr_t*) calloc(1, sizeof(cstr_t))) == NULL) + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); rsSETOBJTYPE(pThis, OIDrsCStr); pThis->pBuf = NULL; @@ -45,71 +69,82 @@ rsCStrObj *rsCStrConstruct(void) pThis->iBufSize = 0; pThis->iStrLen = 0; pThis->iAllocIncrement = RS_STRINGBUF_ALLOC_INCREMENT; + *ppThis = pThis; - return pThis; +finalize_it: + RETiRet; } + /* construct from sz string * rgerhards 2005-09-15 */ -rsRetVal rsCStrConstructFromszStr(rsCStrObj **ppThis, uchar *sz) +rsRetVal rsCStrConstructFromszStr(cstr_t **ppThis, uchar *sz) { - rsCStrObj *pThis; + DEFiRet; + cstr_t *pThis; assert(ppThis != NULL); - if((pThis = rsCStrConstruct()) == NULL) - return RS_RET_OUT_OF_MEMORY; + CHKiRet(rsCStrConstruct(&pThis)); pThis->iBufSize = pThis->iStrLen = strlen((char*)(char *) sz); if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) { RSFREEOBJ(pThis); - return RS_RET_OUT_OF_MEMORY; + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* we do NOT need to copy the \0! */ memcpy(pThis->pBuf, sz, pThis->iStrLen); *ppThis = pThis; - return RS_RET_OK; + +finalize_it: + RETiRet; } /* construct from CStr object. only the counted string is * copied, not the szString. * rgerhards 2005-10-18 */ -rsRetVal rsCStrConstructFromCStr(rsCStrObj **ppThis, rsCStrObj *pFrom) +rsRetVal rsCStrConstructFromCStr(cstr_t **ppThis, cstr_t *pFrom) { - rsCStrObj *pThis; + DEFiRet; + cstr_t *pThis; assert(ppThis != NULL); rsCHECKVALIDOBJECT(pFrom, OIDrsCStr); - if((pThis = rsCStrConstruct()) == NULL) - return RS_RET_OUT_OF_MEMORY; + CHKiRet(rsCStrConstruct(&pThis)); pThis->iBufSize = pThis->iStrLen = pFrom->iStrLen; if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) { RSFREEOBJ(pThis); - return RS_RET_OUT_OF_MEMORY; + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* copy properties */ memcpy(pThis->pBuf, pFrom->pBuf, pThis->iStrLen); *ppThis = pThis; - return RS_RET_OK; +finalize_it: + RETiRet; } -void rsCStrDestruct(rsCStrObj *pThis) +void rsCStrDestruct(cstr_t **ppThis) { + cstr_t *pThis = *ppThis; + /* rgerhards 2005-10-19: The free of pBuf was contained in conditional compilation. * The code was only compiled if STRINGBUF_TRIM_ALLOCSIZE was set to 1. I honestly * do not know why it was so, I think it was an artifact. Anyhow, I have changed this * now. Should there any issue occur, this comment hopefully will shed some light * on what happened. I re-verified, and this function has never before been called * by anyone. So changing it can have no impact for obvious reasons... + * + * rgerhards, 2008-02-20: I changed the interface to the new calling conventions, where + * the destructor receives a pointer to the object, so that it can set it to NULL. */ if(pThis->pBuf != NULL) { free(pThis->pBuf); @@ -120,39 +155,76 @@ void rsCStrDestruct(rsCStrObj *pThis) } RSFREEOBJ(pThis); + *ppThis = NULL; +} + + +/* extend the string buffer if its size is insufficient. + * Param iMinNeeded is the minumum free space needed. If it is larger + * than the default alloc increment, space for at least this amount is + * allocated. In practice, a bit more is allocated because we envision that + * some more characters may be added after these. + * rgerhards, 2008-01-07 + */ +static rsRetVal rsCStrExtendBuf(cstr_t *pThis, size_t iMinNeeded) +{ + DEFiRet; + uchar *pNewBuf; + size_t iNewSize; + + /* first compute the new size needed */ + if(iMinNeeded > pThis->iAllocIncrement) { + /* we allocate "n" iAllocIncrements. Usually, that should + * leave some room after the absolutely needed one. It also + * reduces memory fragmentation. Note that all of this are + * integer operations (very important to understand what is + * going on)! Parenthesis are for better readibility. + */ + iNewSize = ((iMinNeeded / pThis->iAllocIncrement) + 1) * pThis->iAllocIncrement; + } else { + iNewSize = pThis->iBufSize + pThis->iAllocIncrement; + } + iNewSize += pThis->iBufSize; /* add current size */ + + /* and then allocate and copy over */ + /* DEV debugging only: dbgprintf("extending string buffer, old %d, new %d\n", pThis->iBufSize, iNewSize); */ + if((pNewBuf = (uchar*) malloc(iNewSize * sizeof(uchar))) == NULL) + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); + memcpy(pNewBuf, pThis->pBuf, pThis->iBufSize); + pThis->iBufSize = iNewSize; + if(pThis->pBuf != NULL) { + free(pThis->pBuf); + } + pThis->pBuf = pNewBuf; + +finalize_it: + RETiRet; } -rsRetVal rsCStrAppendStrWithLen(rsCStrObj *pThis, uchar* psz, size_t iStrLen) +/* append a string of known length. In this case, we make sure we do at most + * one additional memory allocation. + * I optimized this function to use memcpy(), among others. Consider it a + * rewrite (which may be good to know in case of bugs) -- rgerhards, 2008-01-07 + */ +rsRetVal rsCStrAppendStrWithLen(cstr_t *pThis, uchar* psz, size_t iStrLen) { - rsRetVal iRet; - int iOldAllocInc; + DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); assert(psz != NULL); - /* we first check if the to-be-added string is larger than the - * alloc increment. If so, we temporarily increase the alloc - * increment to the length of the string. This will ensure that - * one string copy will be needed at most. As this is a very - * costly operation, it outweights the cost of the strlen((char*)) and - * related stuff - at least I think so. - * rgerhards 2005-09-22 - */ - /* We save the current alloc increment in any case, so we can just - * overwrite it below, this is faster than any if-construct. - */ - iOldAllocInc = pThis->iAllocIncrement; - if(iStrLen > pThis->iAllocIncrement) { - pThis->iAllocIncrement = iStrLen; + /* does the string fit? */ + if(pThis->iStrLen + iStrLen > pThis->iBufSize) { + CHKiRet(rsCStrExtendBuf(pThis, iStrLen)); /* need more memory! */ } - while(*psz) - if((iRet = rsCStrAppendChar(pThis, *psz++)) != RS_RET_OK) - return iRet; + /* ok, now we always have sufficient continues memory to do a memcpy() */ + memcpy(pThis->pBuf + pThis->iStrLen, psz, iStrLen); + pThis->iStrLen += iStrLen; - pThis->iAllocIncrement = iOldAllocInc; /* restore */ - return RS_RET_OK; +finalize_it: + RETiRet; } @@ -161,42 +233,44 @@ rsRetVal rsCStrAppendStrWithLen(rsCStrObj *pThis, uchar* psz, size_t iStrLen) * need to change existing code. * rgerhards, 2007-07-03 */ -rsRetVal rsCStrAppendStr(rsCStrObj *pThis, uchar* psz) +rsRetVal rsCStrAppendStr(cstr_t *pThis, uchar* psz) { - return rsCStrAppendStrWithLen(pThis, psz, strlen((char*)(char*) psz)); + return rsCStrAppendStrWithLen(pThis, psz, strlen((char*) psz)); } -rsRetVal rsCStrAppendInt(rsCStrObj *pThis, int i) +/* append the contents of one cstr_t object to another + * rgerhards, 2008-02-25 + */ +rsRetVal rsCStrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend) { - rsRetVal iRet; + return rsCStrAppendStrWithLen(pThis, pstrAppend->pBuf, pstrAppend->iStrLen); +} + + +rsRetVal rsCStrAppendInt(cstr_t *pThis, long i) +{ + DEFiRet; uchar szBuf[32]; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - if((iRet = srUtilItoA((char*) szBuf, sizeof(szBuf), i)) != RS_RET_OK) - return iRet; + CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), i)); - return rsCStrAppendStr(pThis, szBuf); + iRet = rsCStrAppendStr(pThis, szBuf); +finalize_it: + RETiRet; } -rsRetVal rsCStrAppendChar(rsCStrObj *pThis, uchar c) +rsRetVal rsCStrAppendChar(cstr_t *pThis, uchar c) { - uchar* pNewBuf; + DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - if(pThis->iStrLen >= pThis->iBufSize) - { /* need more memory! */ - if((pNewBuf = (uchar*) malloc((pThis->iBufSize + pThis->iAllocIncrement) * sizeof(uchar))) == NULL) - return RS_RET_OUT_OF_MEMORY; - memcpy(pNewBuf, pThis->pBuf, pThis->iBufSize); - pThis->iBufSize += pThis->iAllocIncrement; - if(pThis->pBuf != NULL) { - free(pThis->pBuf); - } - pThis->pBuf = pNewBuf; + if(pThis->iStrLen >= pThis->iBufSize) { + CHKiRet(rsCStrExtendBuf(pThis, 1)); /* need more memory! */ } /* ok, when we reach this, we have sufficient memory */ @@ -208,7 +282,8 @@ rsRetVal rsCStrAppendChar(rsCStrObj *pThis, uchar c) pThis->pszBuf = NULL; } - return RS_RET_OK; +finalize_it: + RETiRet; } @@ -219,7 +294,7 @@ rsRetVal rsCStrAppendChar(rsCStrObj *pThis, uchar c) * not modified by this function. * rgerhards, 2005-10-18 */ -rsRetVal rsCStrSetSzStr(rsCStrObj *pThis, uchar *pszNew) +rsRetVal rsCStrSetSzStr(cstr_t *pThis, uchar *pszNew) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); @@ -260,7 +335,7 @@ rsRetVal rsCStrSetSzStr(rsCStrObj *pThis, uchar *pszNew) * WARNING: The returned pointer MUST NOT be freed, as it may be * obtained from that constant memory pool (in case of NULL!) */ -uchar* rsCStrGetSzStrNoNULL(rsCStrObj *pThis) +uchar* rsCStrGetSzStrNoNULL(cstr_t *pThis) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); if(pThis->pBuf == NULL) @@ -278,7 +353,7 @@ uchar* rsCStrGetSzStrNoNULL(rsCStrObj *pThis) * rsCStrGetSzStrNoNULL() instead. * rgerhards, 2005-09-15 */ -uchar* rsCStrGetSzStr(rsCStrObj *pThis) +uchar* rsCStrGetSzStr(cstr_t *pThis) { size_t i; @@ -342,7 +417,7 @@ uchar* rsCStrGetSzStr(rsCStrObj *pThis) * PLEASE NOTE: the caller must free the memory returned in ppSz in any case * (except, of course, if it is NULL). */ -rsRetVal rsCStrConvSzStrAndDestruct(rsCStrObj *pThis, uchar **ppSz, int bRetNULL) +rsRetVal rsCStrConvSzStrAndDestruct(cstr_t *pThis, uchar **ppSz, int bRetNULL) { DEFiRet; uchar* pRetBuf; @@ -373,17 +448,52 @@ finalize_it: free(pThis->pBuf); RSFREEOBJ(pThis); - return(iRet); + RETiRet; } -rsRetVal rsCStrFinish(rsCStrObj __attribute__((unused)) *pThis) +#if STRINGBUF_TRIM_ALLOCSIZE == 1 + /* Only in this mode, we need to trim the string. To do + * so, we must allocate a new buffer of the exact + * string size, and then copy the old one over. + */ + /* WARNING + * STRINGBUF_TRIM_ALLOCSIZE can, in theory, be used to trim + * memory buffers. This part of the code was inherited from + * liblogging (where it is used in a different context) but + * never put to use in rsyslog. The reason is that it is hardly + * imaginable where the extra performance cost is worth the save + * in memory alloc. Then Anders Blomdel rightfully pointed out that + * the code does not work at all - and nobody even know that it + * probably shouldn't. Rather than removing, I deciced to somewhat + * fix the code, so that this feature may be enabled if somebody + * really has a need for it. Be warned, however, that I NEVER + * tested the fix. So if you intend to use this feature, you must + * do full testing before you rely on it. -- rgerhards, 2008-02-12 + */ +rsRetVal rsCStrFinish(cstr_t __attribute__((unused)) *pThis) { + DEFiRet; + uchar* pBuf; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - return RS_RET_OK; + + if((pBuf = malloc((pThis->iStrLen) * sizeof(uchar))) == NULL) + { /* OK, in this case we use the previous buffer. At least + * we have it ;) + */ + } + else + { /* got the new buffer, so let's use it */ + memcpy(pBuf, pThis->pBuf, pThis->iStrLen); + pThis->pBuf = pBuf; + } + + RETiRet; } +#endif /* #if STRINGBUF_TRIM_ALLOCSIZE == 1 */ + -void rsCStrSetAllocIncrement(rsCStrObj *pThis, int iNewIncrement) +void rsCStrSetAllocIncrement(cstr_t *pThis, int iNewIncrement) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); assert(iNewIncrement > 0); @@ -399,7 +509,7 @@ void rsCStrSetAllocIncrement(rsCStrObj *pThis, int iNewIncrement) * This is due to performance reasons. */ #ifndef NDEBUG -int rsCStrLen(rsCStrObj *pThis) +int rsCStrLen(cstr_t *pThis) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); return(pThis->iStrLen); @@ -409,7 +519,7 @@ int rsCStrLen(rsCStrObj *pThis) /* Truncate characters from the end of the string. * rgerhards 2005-09-15 */ -rsRetVal rsCStrTruncate(rsCStrObj *pThis, size_t nTrunc) +rsRetVal rsCStrTruncate(cstr_t *pThis, size_t nTrunc) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); @@ -432,7 +542,7 @@ rsRetVal rsCStrTruncate(rsCStrObj *pThis, size_t nTrunc) /* Trim trailing whitespace from a given string */ -rsRetVal rsCStrTrimTrailingWhiteSpace(rsCStrObj *pThis) +rsRetVal rsCStrTrimTrailingWhiteSpace(cstr_t *pThis) { register int i; register uchar *pC; @@ -459,7 +569,7 @@ rsRetVal rsCStrTrimTrailingWhiteSpace(rsCStrObj *pThis) * in equal-size strings. * rgerhards, 2005-09-26 */ -int rsCStrCStrCmp(rsCStrObj *pCS1, rsCStrObj *pCS2) +int rsCStrCStrCmp(cstr_t *pCS1, cstr_t *pCS2) { rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); rsCHECKVALIDOBJECT(pCS2, OIDrsCStr); @@ -483,12 +593,15 @@ int rsCStrCStrCmp(rsCStrObj *pCS1, rsCStrObj *pCS2) } -/* check if a sz-type string start with a CStr object. This function +/* check if a sz-type string starts with a CStr object. This function * is initially written to support the "startswith" property-filter * comparison operation. Maybe it also has other needs. + * This functions is modelled after the strcmp() series, thus a + * return value of 0 indicates that the string starts with the + * sequence while -1 indicates it does not! * rgerhards 2005-10-19 */ -int rsCStrSzStrStartsWithCStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz) +int rsCStrSzStrStartsWithCStr(cstr_t *pCS1, uchar *psz, size_t iLenSz) { register int i; int iMax; @@ -518,9 +631,12 @@ int rsCStrSzStrStartsWithCStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz) /* check if a CStr object starts with a sz-type string. + * This functions is modelled after the strcmp() series, thus a + * return value of 0 indicates that the string starts with the + * sequence while -1 indicates it does not! * rgerhards 2005-09-26 */ -int rsCStrStartsWithSzStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz) +int rsCStrStartsWithSzStr(cstr_t *pCS1, uchar *psz, size_t iLenSz) { register size_t i; @@ -546,22 +662,66 @@ int rsCStrStartsWithSzStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz) return -1; /* pCS1 is less then psz */ } + +/* The same as rsCStrStartsWithSzStr(), but does a case-insensitive + * comparison. TODO: consolidate the two. + * rgerhards 2008-02-28 + */ +int rsCStrCaseInsensitveStartsWithSzStr(cstr_t *pCS1, uchar *psz, size_t iLenSz) +{ + register size_t i; + + rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); + assert(psz != NULL); + assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */ + if(pCS1->iStrLen >= iLenSz) { + /* we are using iLenSz below, because we need to check + * iLenSz characters at maximum (start with!) + */ + if(iLenSz == 0) + return 0; /* yes, it starts with a zero-sized string ;) */ + else { /* we now have something to compare, so let's do it... */ + for(i = 0 ; i < iLenSz ; ++i) { + if(tolower(pCS1->pBuf[i]) != tolower(psz[i])) + return tolower(pCS1->pBuf[i]) - tolower(psz[i]); + } + /* if we arrive here, the string actually starts with psz */ + return 0; + } + } + else + return -1; /* pCS1 is less then psz */ +} + /* check if a CStr object matches a regex. * msamia@redhat.com 2007-07-12 * @return returns 0 if matched * bug: doesn't work for CStr containing \0 * rgerhards, 2007-07-16: bug is no real bug, because rsyslogd ensures there * never is a \0 *inside* a property string. + * Note that the function returns -1 if regexp functionality is not available. + * TODO: change calling interface! -- rgerhards, 2008-03-07 */ -int rsCStrSzStrMatchRegex(rsCStrObj *pCS1, uchar *psz) +int rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz) { - regex_t preq; - regcomp(&preq, (char*) rsCStrGetSzStr(pCS1), 0); - int iRet = regexec(&preq, (char*) psz, 0, NULL, 0); - regfree(&preq); - return iRet; + regex_t preq; + int ret; + + BEGINfunc + + if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) { + regexp.regcomp(&preq, (char*) rsCStrGetSzStr(pCS1), 0); + ret = regexp.regexec(&preq, (char*) psz, 0, NULL, 0); + regexp.regfree(&preq); + } else { + ret = 1; /* simulate "not found" */ + } + + ENDfunc + return ret; } + /* compare a rsCStr object with a classical sz string. This function * is almost identical to rsCStrZsStrCmp(), but it also takes an offset * to the CStr object from where the comparison is to start. @@ -583,8 +743,9 @@ int rsCStrSzStrMatchRegex(rsCStrObj *pCS1, uchar *psz) * program bug and will lead to unpredictable results and program aborts). * rgerhards 2005-09-26 */ -int rsCStrOffsetSzStrCmp(rsCStrObj *pCS1, size_t iOffset, uchar *psz, size_t iLenSz) +int rsCStrOffsetSzStrCmp(cstr_t *pCS1, size_t iOffset, uchar *psz, size_t iLenSz) { + BEGINfunc rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); assert(iOffset < pCS1->iStrLen); assert(psz != NULL); @@ -593,9 +754,10 @@ int rsCStrOffsetSzStrCmp(rsCStrObj *pCS1, size_t iOffset, uchar *psz, size_t iLe /* we are using iLenSz below, because the lengths * are equal and iLenSz is faster to access */ - if(iLenSz == 0) + if(iLenSz == 0) { return 0; /* zero-sized strings are equal ;) */ - else { /* we now have two non-empty strings of equal + ENDfunc + } else { /* we now have two non-empty strings of equal * length, so we need to actually check if they * are equal. */ @@ -606,10 +768,110 @@ int rsCStrOffsetSzStrCmp(rsCStrObj *pCS1, size_t iOffset, uchar *psz, size_t iLe } /* if we arrive here, the strings are equal */ return 0; + ENDfunc } } - else + else { return pCS1->iStrLen - iOffset - iLenSz; + ENDfunc + } +} + + +/* Converts a string to a number. If the string dos not contain a number, + * RS_RET_NOT_A_NUMBER is returned and the contents of pNumber is undefined. + * If all goes well, pNumber contains the number that the string was converted + * to. + */ +rsRetVal +rsCStrConvertToNumber(cstr_t *pStr, number_t *pNumber) +{ + DEFiRet; + number_t n; + int bIsNegative; + size_t i; + + ASSERT(pStr != NULL); + ASSERT(pNumber != NULL); + + if(pStr->iStrLen == 0) { + /* can be converted to 0! (by convention) */ + pNumber = 0; + FINALIZE; + } + + /* first skip whitespace (if present) */ + for(i = 0 ; i < pStr->iStrLen && isspace(pStr->pBuf[i]) ; ++i) { + /*DO NOTHING*/ + } + + /* we have a string, so let's check its syntax */ + if(pStr->pBuf[i] == '+') { + ++i; /* skip that char */ + bIsNegative = 0; + } else if(pStr->pBuf[0] == '-') { + ++i; /* skip that char */ + bIsNegative = 1; + } else { + bIsNegative = 0; + } + + /* TODO: octal? hex? */ + n = 0; + while(i < pStr->iStrLen && isdigit(pStr->pBuf[i])) { + n = n * 10 + pStr->pBuf[i] * 10; + ++i; + } + + if(i < pStr->iStrLen) /* non-digits before end of string? */ + ABORT_FINALIZE(RS_RET_NOT_A_NUMBER); + + if(bIsNegative) + n *= -1; + + /* we got it, so return the number */ + *pNumber = n; + +finalize_it: + RETiRet; +} + + +/* Converts a string to a boolen. First tries to convert to a number. If + * that succeeds, we are done (number is then used as boolean value). If + * that fails, we look if the string is "yes" or "true". If so, a value + * of 1 is returned. In all other cases, a value of 0 is returned. Please + * note that we do not have a specific boolean type, so we return a number. + * so, these are + * RS_RET_NOT_A_NUMBER is returned and the contents of pNumber is undefined. + * If all goes well, pNumber contains the number that the string was converted + * to. + */ +rsRetVal +rsCStrConvertToBool(cstr_t *pStr, number_t *pBool) +{ + DEFiRet; + + ASSERT(pStr != NULL); + ASSERT(pBool != NULL); + + iRet = rsCStrConvertToNumber(pStr, pBool); + + if(iRet != RS_RET_NOT_A_NUMBER) { + FINALIZE; /* in any case, we have nothing left to do */ + } + + /* TODO: maybe we can do better than strcasecmp ;) -- overhead! */ + if(!strcasecmp((char*)rsCStrGetSzStr(pStr), "true")) { + *pBool = 1; + } else if(!strcasecmp((char*)rsCStrGetSzStr(pStr), "yes")) { + *pBool = 1; + } else { + *pBool = 0; + } + +finalize_it: + RETiRet; } @@ -626,7 +888,7 @@ int rsCStrOffsetSzStrCmp(rsCStrObj *pCS1, size_t iOffset, uchar *psz, size_t iLe * The to sz string pointer must not be NULL! * rgerhards 2005-09-26 */ -int rsCStrSzStrCmp(rsCStrObj *pCS1, uchar *psz, size_t iLenSz) +int rsCStrSzStrCmp(cstr_t *pCS1, uchar *psz, size_t iLenSz) { rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); assert(psz != NULL); @@ -659,7 +921,7 @@ int rsCStrSzStrCmp(rsCStrObj *pCS1, uchar *psz, size_t iLenSz) * returned. Both parameters MUST be given (NULL is not allowed). * rgerhards 2005-09-19 */ -int rsCStrLocateInSzStr(rsCStrObj *pThis, uchar *sz) +int rsCStrLocateInSzStr(cstr_t *pThis, uchar *sz) { int i; int iMax; @@ -694,6 +956,46 @@ int rsCStrLocateInSzStr(rsCStrObj *pThis, uchar *sz) } +/* This is the same as rsCStrLocateInSzStr(), but does a case-insensitve + * comparison. + * TODO: over time, consolidate the two. + * rgerhards, 2008-02-28 + */ +int rsCStrCaseInsensitiveLocateInSzStr(cstr_t *pThis, uchar *sz) +{ + int i; + int iMax; + int bFound; + rsCHECKVALIDOBJECT(pThis, OIDrsCStr); + assert(sz != NULL); + + if(pThis->iStrLen == 0) + return 0; + + /* compute the largest index where a match could occur - after all, + * the to-be-located string must be able to be present in the + * searched string (it needs its size ;)). + */ + iMax = strlen((char*)sz) - pThis->iStrLen; + + bFound = 0; + i = 0; + while(i <= iMax && !bFound) { + size_t iCheck; + uchar *pComp = sz + i; + for(iCheck = 0 ; iCheck < pThis->iStrLen ; ++iCheck) + if(tolower(*(pComp + iCheck)) != tolower(*(pThis->pBuf + iCheck))) + break; + if(iCheck == pThis->iStrLen) + bFound = 1; /* found! - else it wouldn't be equal */ + else + ++i; /* on to the next try */ + } + + return(bFound ? i : -1); +} + + #if 0 /* read comment below why this is commented out. In short: for future use! */ /* locate the first occurence of a standard sz string inside a rsCStr object. * Returns the offset (0-bound) of this first occurrence. If not found, -1 is @@ -704,7 +1006,7 @@ int rsCStrLocateInSzStr(rsCStrObj *pThis, uchar *sz) * some time later. However, it is not fully tested, so start with testing * it before you put it to first use). */ -int rsCStrLocateSzStr(rsCStrObj *pThis, uchar *sz) +int rsCStrLocateSzStr(cstr_t *pThis, uchar *sz) { int iLenSz; int i; @@ -744,6 +1046,29 @@ int rsCStrLocateSzStr(rsCStrObj *pThis, uchar *sz) #endif /* end comment out */ +/* our exit function. TODO: remove once converted to a class + * rgerhards, 2008-03-11 + */ +rsRetVal strExit() +{ + DEFiRet; + objRelease(regexp, LM_REGEXP_FILENAME); + RETiRet; +} + + +/* our init function. TODO: remove once converted to a class + */ +rsRetVal strInit() +{ + DEFiRet; + CHKiRet(objGetObjInterface(&obj)); + +finalize_it: + RETiRet; +} + + /* * Local variables: * c-indent-level: 8 |