diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2008-04-16 10:26:54 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2008-04-16 10:26:54 +0200 |
commit | 8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc (patch) | |
tree | 8bd92ca19ae3cccd5b160c717960db88bb095e73 /stringbuf.c | |
parent | 3af28bbd2dc4c79b242aad3b9e3f45cffe0f19d0 (diff) | |
download | rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.tar.gz rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.tar.xz rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.zip |
moved files to the runtime
there are still some files left which could go into the
runtime, but I think we will delete most of them once we
are done with the full modularization.
Diffstat (limited to 'stringbuf.c')
-rw-r--r-- | stringbuf.c | 1079 |
1 files changed, 0 insertions, 1079 deletions
diff --git a/stringbuf.c b/stringbuf.c deleted file mode 100644 index 4254d5bd..00000000 --- a/stringbuf.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* This is the byte-counted string class for rsyslog. It is a replacement - * for classical \0 terminated string functions. We introduce it in - * the hope it will make the program more secure, obtain some performance - * and, most importantly, lay they foundation for syslog-protocol, which - * 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). - * 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" - -#include <stdlib.h> -#include <assert.h> -#include <string.h> -#include <ctype.h> -#include <sys/types.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 * - * ################################################################# */ - - -rsRetVal rsCStrConstruct(cstr_t **ppThis) -{ - DEFiRet; - cstr_t *pThis; - - ASSERT(ppThis != NULL); - - if((pThis = (cstr_t*) calloc(1, sizeof(cstr_t))) == NULL) - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - - rsSETOBJTYPE(pThis, OIDrsCStr); - pThis->pBuf = NULL; - pThis->pszBuf = NULL; - pThis->iBufSize = 0; - pThis->iStrLen = 0; - pThis->iAllocIncrement = RS_STRINGBUF_ALLOC_INCREMENT; - *ppThis = pThis; - -finalize_it: - RETiRet; -} - - -/* construct from sz string - * rgerhards 2005-09-15 - */ -rsRetVal rsCStrConstructFromszStr(cstr_t **ppThis, uchar *sz) -{ - DEFiRet; - cstr_t *pThis; - - assert(ppThis != NULL); - - CHKiRet(rsCStrConstruct(&pThis)); - - pThis->iBufSize = pThis->iStrLen = strlen((char*)(char *) sz); - if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) { - RSFREEOBJ(pThis); - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - } - - /* we do NOT need to copy the \0! */ - memcpy(pThis->pBuf, sz, pThis->iStrLen); - - *ppThis = pThis; - -finalize_it: - RETiRet; -} - -/* construct from CStr object. only the counted string is - * copied, not the szString. - * rgerhards 2005-10-18 - */ -rsRetVal rsCStrConstructFromCStr(cstr_t **ppThis, cstr_t *pFrom) -{ - DEFiRet; - cstr_t *pThis; - - assert(ppThis != NULL); - rsCHECKVALIDOBJECT(pFrom, OIDrsCStr); - - CHKiRet(rsCStrConstruct(&pThis)); - - pThis->iBufSize = pThis->iStrLen = pFrom->iStrLen; - if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) { - RSFREEOBJ(pThis); - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - } - - /* copy properties */ - memcpy(pThis->pBuf, pFrom->pBuf, pThis->iStrLen); - - *ppThis = pThis; -finalize_it: - RETiRet; -} - - -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); - } - - if(pThis->pszBuf != NULL) { - free(pThis->pszBuf); - } - - 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; -} - - -/* 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) -{ - DEFiRet; - - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - assert(psz != NULL); - - /* does the string fit? */ - if(pThis->iStrLen + iStrLen > pThis->iBufSize) { - CHKiRet(rsCStrExtendBuf(pThis, iStrLen)); /* need more memory! */ - } - - /* ok, now we always have sufficient continues memory to do a memcpy() */ - memcpy(pThis->pBuf + pThis->iStrLen, psz, iStrLen); - pThis->iStrLen += iStrLen; - -finalize_it: - RETiRet; -} - - -/* changed to be a wrapper to rsCStrAppendStrWithLen() so that - * we can save some time when we have the length but do not - * need to change existing code. - * rgerhards, 2007-07-03 - */ -rsRetVal rsCStrAppendStr(cstr_t *pThis, uchar* psz) -{ - return rsCStrAppendStrWithLen(pThis, psz, strlen((char*) psz)); -} - - -/* append the contents of one cstr_t object to another - * rgerhards, 2008-02-25 - */ -rsRetVal rsCStrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend) -{ - return rsCStrAppendStrWithLen(pThis, pstrAppend->pBuf, pstrAppend->iStrLen); -} - - -rsRetVal rsCStrAppendInt(cstr_t *pThis, long i) -{ - DEFiRet; - uchar szBuf[32]; - - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - - CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), i)); - - iRet = rsCStrAppendStr(pThis, szBuf); -finalize_it: - RETiRet; -} - - -rsRetVal rsCStrAppendChar(cstr_t *pThis, uchar c) -{ - DEFiRet; - - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - - if(pThis->iStrLen >= pThis->iBufSize) { - CHKiRet(rsCStrExtendBuf(pThis, 1)); /* need more memory! */ - } - - /* ok, when we reach this, we have sufficient memory */ - *(pThis->pBuf + pThis->iStrLen++) = c; - - /* check if we need to invalidate an sz representation! */ - if(pThis->pszBuf != NULL) { - free(pThis->pszBuf); - pThis->pszBuf = NULL; - } - -finalize_it: - RETiRet; -} - - -/* Sets the string object to the classigal sz-string provided. - * Any previously stored vlaue is discarded. If a NULL pointer - * the the new value (pszNew) is provided, an empty string is - * created (this is NOT an error!). Property iAllocIncrement is - * not modified by this function. - * rgerhards, 2005-10-18 - */ -rsRetVal rsCStrSetSzStr(cstr_t *pThis, uchar *pszNew) -{ - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - - if(pThis->pBuf != NULL) - free(pThis->pBuf); - if(pThis->pszBuf != NULL) - free(pThis->pszBuf); - if(pszNew == NULL) { - pThis->iStrLen = 0; - pThis->iBufSize = 0; - pThis->pBuf = NULL; - pThis->pszBuf = NULL; - } else { - pThis->iStrLen = strlen((char*)pszNew); - pThis->iBufSize = pThis->iStrLen; - pThis->pszBuf = NULL; - /* iAllocIncrement is NOT modified! */ - - /* now save the new value */ - if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) { - RSFREEOBJ(pThis); - return RS_RET_OUT_OF_MEMORY; - } - - /* we do NOT need to copy the \0! */ - memcpy(pThis->pBuf, pszNew, pThis->iStrLen); - } - - return RS_RET_OK; -} - -/* Converts the CStr object to a classical sz string and returns that. - * Same restrictions as in rsCStrGetSzStr() applies (see there!). This - * function here guarantees that a valid string is returned, even if - * the CStr object currently holds a NULL pointer string buffer. If so, - * "" is returned. - * rgerhards 2005-10-19 - * WARNING: The returned pointer MUST NOT be freed, as it may be - * obtained from that constant memory pool (in case of NULL!) - */ -uchar* rsCStrGetSzStrNoNULL(cstr_t *pThis) -{ - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - if(pThis->pBuf == NULL) - return (uchar*) ""; - else - return rsCStrGetSzStr(pThis); -} - - -/* Converts the CStr object to a classical zero-terminated C string - * and returns that string. The caller must not free it and must not - * destroy the CStr object as long as the ascii string is used. - * This function may return NULL, if the string is currently NULL. This - * is a feature, not a bug. If you need non-NULL in any case, use - * rsCStrGetSzStrNoNULL() instead. - * rgerhards, 2005-09-15 - */ -uchar* rsCStrGetSzStr(cstr_t *pThis) -{ - size_t i; - - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - - if(pThis->pBuf != NULL) - if(pThis->pszBuf == NULL) { - /* we do not yet have a usable sz version - so create it... */ - if((pThis->pszBuf = malloc((pThis->iStrLen + 1) * sizeof(uchar))) == NULL) { - /* TODO: think about what to do - so far, I have no bright - * idea... rgerhards 2005-09-07 - */ - } - else { /* we can create the sz String */ - /* now copy it while doing a sanity check. The string might contain a - * \0 byte. There is no way how a sz string can handle this. For - * the time being, we simply replace it with space - something that - * could definitely be improved (TODO). - * 2005-09-15 rgerhards - */ - for(i = 0 ; i < pThis->iStrLen ; ++i) { - if(pThis->pBuf[i] == '\0') - pThis->pszBuf[i] = ' '; - else - pThis->pszBuf[i] = pThis->pBuf[i]; - } - /* write terminator... */ - pThis->pszBuf[i] = '\0'; - } - } - - return(pThis->pszBuf); -} - - -/* Converts the CStr object to a classical zero-terminated C string, - * returns that string and destroys the CStr object. The returned string - * MUST be freed by the caller. The function might return NULL if - * no memory can be allocated. - * - * TODO: - * This function should at some time become special. The base idea is to - * add one extra byte to the end of the regular buffer, so that we can - * convert it to an szString without the need to copy. The extra memory - * footprint is not hefty, but the performance gain is potentially large. - * To get it done now, I am not doing the optimiziation right now. - * rgerhards, 2005-09-07 - * - * rgerhards, 2007-09-04: I have changed the interface of this function. It now - * returns an rsRetVal, so that we can communicate back if we have an error. - * Using the standard method is much better than returning NULL. Secondly, NULL - * was not actually an error - it was in indication if the string was empty. - * This was needed in some parts of the code, in others not. I have now added - * a second parameter to specify what the caller needs. I hope these changes - * will make it less likely that the function is called incorrectly, what - * previously happend quite often and was the cause of a number of program - * aborts. So the parameters are now: - * pointer to the object, pointer to string-pointer to receive string and - * bRetNULL: 0 - must not return NULL on empty string, return "" in that - * case, 1 - return NULL instead of an empty string. - * PLEASE NOTE: the caller must free the memory returned in ppSz in any case - * (except, of course, if it is NULL). - */ -rsRetVal rsCStrConvSzStrAndDestruct(cstr_t *pThis, uchar **ppSz, int bRetNULL) -{ - DEFiRet; - uchar* pRetBuf; - - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - assert(ppSz != NULL); - assert(bRetNULL == 0 || bRetNULL == 1); - - if(pThis->pBuf == NULL) { - if(bRetNULL == 0) { - if((pRetBuf = malloc(sizeof(uchar))) == NULL) - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - *pRetBuf = '\0'; - } else { - pRetBuf = NULL; - } - } else - pRetBuf = rsCStrGetSzStr(pThis); - - *ppSz = pRetBuf; - -finalize_it: - /* We got it, now free the object ourselfs. Please note - * that we can NOT use the rsCStrDestruct function as it would - * also free the sz String buffer, which we pass on to the user. - */ - if(pThis->pBuf != NULL) - free(pThis->pBuf); - RSFREEOBJ(pThis); - - RETiRet; -} - - -#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); - - 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(cstr_t *pThis, int iNewIncrement) -{ - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - assert(iNewIncrement > 0); - - pThis->iAllocIncrement = iNewIncrement; -} - - -/* return the length of the current string - * 2005-09-09 rgerhards - * Please note: this is only a function in a debug build. - * For release builds, it is a macro defined in stringbuf.h. - * This is due to performance reasons. - */ -#ifndef NDEBUG -int rsCStrLen(cstr_t *pThis) -{ - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - return(pThis->iStrLen); -} -#endif - -/* Truncate characters from the end of the string. - * rgerhards 2005-09-15 - */ -rsRetVal rsCStrTruncate(cstr_t *pThis, size_t nTrunc) -{ - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - - if(pThis->iStrLen < nTrunc) - return RS_TRUNCAT_TOO_LARGE; - - pThis->iStrLen -= nTrunc; - - if(pThis->pszBuf != NULL) { - /* in this case, we adjust the psz representation - * by writing a new \0 terminator - this is by far - * the fastest way and outweights the additional memory - * required. 2005-9-19 rgerhards. - */ - pThis->pszBuf[pThis->iStrLen] = '\0'; - } - - return RS_RET_OK; -} - -/* Trim trailing whitespace from a given string - */ -rsRetVal rsCStrTrimTrailingWhiteSpace(cstr_t *pThis) -{ - register int i; - register uchar *pC; - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - - i = pThis->iStrLen; - pC = pThis->pBuf + i - 1; - while(i > 0 && isspace((int)*pC)) { - --pC; - --i; - } - /* i now is the new string length! */ - pThis->iStrLen = i; - - return RS_RET_OK; -} - -/* compare two string objects - works like strcmp(), but operates - * on CStr objects. Please note that this version here is - * faster in the majority of cases, simply because it can - * rely on StrLen. - * rgerhards 2005-09-19 - * fixed bug, in which only the last byte was actually compared - * in equal-size strings. - * rgerhards, 2005-09-26 - */ -int rsCStrCStrCmp(cstr_t *pCS1, cstr_t *pCS2) -{ - rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); - rsCHECKVALIDOBJECT(pCS2, OIDrsCStr); - if(pCS1->iStrLen == pCS2->iStrLen) - if(pCS1->iStrLen == 0) - return 0; /* zero-sized string are equal ;) */ - else { /* we now have two non-empty strings of equal - * length, so we need to actually check if they - * are equal. - */ - register size_t i; - for(i = 0 ; i < pCS1->iStrLen ; ++i) { - if(pCS1->pBuf[i] != pCS2->pBuf[i]) - return pCS1->pBuf[i] - pCS2->pBuf[i]; - } - /* if we arrive here, the strings are equal */ - return 0; - } - else - return pCS1->iStrLen - pCS2->iStrLen; -} - - -/* 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(cstr_t *pCS1, uchar *psz, size_t iLenSz) -{ - register int i; - int iMax; - - rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); - assert(psz != NULL); - assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */ - if(iLenSz >= pCS1->iStrLen) { - /* we need to checkusing pCS1->iStrLen charactes at maximum, thus - * we move it to iMax. - */ - iMax = pCS1->iStrLen; - if(iMax == 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 < iMax ; ++i) { - if(psz[i] != pCS1->pBuf[i]) - return psz[i] - pCS1->pBuf[i]; - } - /* if we arrive here, the string actually starts with pCS1 */ - return 0; - } - } - else - return -1; /* pCS1 is less then psz */ -} - - -/* 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(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(pCS1->pBuf[i] != psz[i]) - return pCS1->pBuf[i] - psz[i]; - } - /* if we arrive here, the string actually starts with psz */ - return 0; - } - } - else - 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(cstr_t *pCS1, uchar *psz) -{ - 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. - * I have thought quite a while if it really makes sense to more or - * less duplicate the code. After all, if you call it with an offset of - * zero, the functionality is exactly the same. So it looks natural to - * just have a single function. However, supporting the offset requires - * some (few) additional integer operations. While they are few, they - * happen at places in the code that is run very frequently. All in all, - * I have opted for performance and thus duplicated the code. I hope - * this is a good, or at least acceptable, compromise. - * rgerhards, 2005-09-26 - * This function also has an offset-pointer which allows to - * specify *where* the compare operation should begin in - * the CStr. If everything is to be compared, it must be set - * to 0. If some leading bytes are to be skipped, it must be set - * to the first index that is to be compared. It must not be - * set higher than the string length (this is considered a - * program bug and will lead to unpredictable results and program aborts). - * rgerhards 2005-09-26 - */ -int rsCStrOffsetSzStrCmp(cstr_t *pCS1, size_t iOffset, uchar *psz, size_t iLenSz) -{ - BEGINfunc - rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); - assert(iOffset < pCS1->iStrLen); - assert(psz != NULL); - assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */ - if((pCS1->iStrLen - iOffset) == iLenSz) { - /* we are using iLenSz below, because the lengths - * are equal and iLenSz is faster to access - */ - if(iLenSz == 0) { - return 0; /* zero-sized strings are equal ;) */ - ENDfunc - } else { /* we now have two non-empty strings of equal - * length, so we need to actually check if they - * are equal. - */ - register size_t i; - for(i = 0 ; i < iLenSz ; ++i) { - if(pCS1->pBuf[i+iOffset] != psz[i]) - return pCS1->pBuf[i+iOffset] - psz[i]; - } - /* if we arrive here, the strings are equal */ - return 0; - ENDfunc - } - } - 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; -} - - -/* 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 - * provided. If the caller does not know the length he can - * call with - * rsCstrSzStrCmp(pCS, psz, strlen((char*)psz)); - * we are not doing the strlen((char*)) ourselfs as the caller might - * already know the length and in such cases we can save the - * overhead of doing it one more time (strelen() is costly!). - * The bottom line is that the provided length MUST be correct! - * The to sz string pointer must not be NULL! - * rgerhards 2005-09-26 - */ -int rsCStrSzStrCmp(cstr_t *pCS1, uchar *psz, size_t iLenSz) -{ - 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 the lengths - * are equal and iLenSz is faster to access - */ - if(iLenSz == 0) - return 0; /* zero-sized strings are equal ;) */ - else { /* we now have two non-empty strings of equal - * length, so we need to actually check if they - * are equal. - */ - register size_t i; - for(i = 0 ; i < iLenSz ; ++i) { - if(pCS1->pBuf[i] != psz[i]) - return pCS1->pBuf[i] - psz[i]; - } - /* if we arrive here, the strings are equal */ - return 0; - } - else - return pCS1->iStrLen - iLenSz; -} - - -/* Locate the first occurence of this rsCStr object inside a standard sz string. - * Returns the offset (0-bound) of this first occurrence. If not found, -1 is - * returned. Both parameters MUST be given (NULL is not allowed). - * rgerhards 2005-09-19 - */ -int rsCStrLocateInSzStr(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(*(pComp + iCheck) != *(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); -} - - -/* 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 - * returned. - * rgerhards 2005-09-19 - * WARNING: I accidently created this function (I later noticed I didn't relly - * need it... I will not remove the function, as it probably is useful - * some time later. However, it is not fully tested, so start with testing - * it before you put it to first use). - */ -int rsCStrLocateSzStr(cstr_t *pThis, uchar *sz) -{ - int iLenSz; - int i; - int iMax; - int bFound; - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - - if(sz == NULL) - return 0; - - iLenSz = strlen((char*)sz); - if(iLenSz == 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 = pThis->iStrLen - iLenSz; - - bFound = 0; - i = 0; - while(i < iMax && !bFound) { - int iCheck; - uchar *pComp = pThis->pBuf + i; - for(iCheck = 0 ; iCheck < iLenSz ; ++iCheck) - if(*(pComp + iCheck) != *(sz + iCheck)) - break; - if(iCheck == iLenSz) - bFound = 1; /* found! - else it wouldn't be equal */ - else - ++i; /* on to the next try */ - } - - return(bFound ? i : -1); -} -#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 - * c-basic-offset: 8 - * tab-width: 8 - * End: - * vi:set ai: - */ |