~ubuntu-branches/ubuntu/karmic/rsyslog/karmic-200908151517

« back to all changes in this revision

Viewing changes to stringbuf.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2008-04-23 16:46:39 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080423164639-5acmt8a4vpxjgnxw
Tags: 3.14.2-3
* debian/rsyslog-doc.install
  - Fix a typo in the install path of the dia files. Closes: #477489
    Thanks to Justin B Rye for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 * requires strings to be able to handle embedded \0 characters.
6
6
 * Please see syslogd.c for license information.
7
7
 * All functions in this "class" start with rsCStr (rsyslog Counted String).
8
 
 * This code is placed under the GPL.
9
8
 * begun 2005-09-07 rgerhards
 
9
 *
 
10
 * Copyright (C) 2007 by Rainer Gerhards and Adiscon GmbH
 
11
 *
 
12
 * This file is part of rsyslog.
 
13
 *
 
14
 * Rsyslog is free software: you can redistribute it and/or modify
 
15
 * it under the terms of the GNU General Public License as published by
 
16
 * the Free Software Foundation, either version 3 of the License, or
 
17
 * (at your option) any later version.
 
18
 *
 
19
 * Rsyslog is distributed in the hope that it will be useful,
 
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 * GNU General Public License for more details.
 
23
 *
 
24
 * You should have received a copy of the GNU General Public License
 
25
 * along with Rsyslog.  If not, see <http://www.gnu.org/licenses/>.
 
26
 *
 
27
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
10
28
 */
11
29
#include "config.h"
12
30
 
15
33
#include <string.h>
16
34
#include <ctype.h>
17
35
#include <sys/types.h>
18
 
#include <regex.h>
19
36
#include "rsyslog.h"
20
37
#include "stringbuf.h"
21
38
#include "srUtils.h"
 
39
#include "regexp.h"
 
40
#include "obj.h"
22
41
 
23
42
 
24
43
/* ################################################################# *
25
44
 * private members                                                   *
26
45
 * ################################################################# */
27
46
 
28
 
 
 
47
/* static data */
 
48
DEFobjCurrIf(obj)
 
49
DEFobjCurrIf(regexp)
29
50
 
30
51
/* ################################################################# *
31
52
 * public members                                                    *
32
53
 * ################################################################# */
33
54
 
34
55
 
35
 
rsCStrObj *rsCStrConstruct(void)
 
56
rsRetVal rsCStrConstruct(cstr_t **ppThis)
36
57
{
37
 
        rsCStrObj *pThis;
38
 
 
39
 
        if((pThis = (rsCStrObj*) calloc(1, sizeof(rsCStrObj))) == NULL)
40
 
                return NULL;
 
58
        DEFiRet;
 
59
        cstr_t *pThis;
 
60
 
 
61
        ASSERT(ppThis != NULL);
 
62
 
 
63
        if((pThis = (cstr_t*) calloc(1, sizeof(cstr_t))) == NULL)
 
64
                ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
41
65
 
42
66
        rsSETOBJTYPE(pThis, OIDrsCStr);
43
67
        pThis->pBuf = NULL;
45
69
        pThis->iBufSize = 0;
46
70
        pThis->iStrLen = 0;
47
71
        pThis->iAllocIncrement = RS_STRINGBUF_ALLOC_INCREMENT;
 
72
        *ppThis = pThis;
48
73
 
49
 
        return pThis;
 
74
finalize_it:
 
75
        RETiRet;
50
76
}
51
77
 
 
78
 
52
79
/* construct from sz string
53
80
 * rgerhards 2005-09-15
54
81
 */
55
 
rsRetVal rsCStrConstructFromszStr(rsCStrObj **ppThis, uchar *sz)
 
82
rsRetVal rsCStrConstructFromszStr(cstr_t **ppThis, uchar *sz)
56
83
{
57
 
        rsCStrObj *pThis;
 
84
        DEFiRet;
 
85
        cstr_t *pThis;
58
86
 
59
87
        assert(ppThis != NULL);
60
88
 
61
 
        if((pThis = rsCStrConstruct()) == NULL)
62
 
                return RS_RET_OUT_OF_MEMORY;
 
89
        CHKiRet(rsCStrConstruct(&pThis));
63
90
 
64
91
        pThis->iBufSize = pThis->iStrLen = strlen((char*)(char *) sz);
65
92
        if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) {
66
93
                RSFREEOBJ(pThis);
67
 
                return RS_RET_OUT_OF_MEMORY;
 
94
                ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
68
95
        }
69
96
 
70
97
        /* we do NOT need to copy the \0! */
71
98
        memcpy(pThis->pBuf, sz, pThis->iStrLen);
72
99
 
73
100
        *ppThis = pThis;
74
 
        return RS_RET_OK;
 
101
 
 
102
finalize_it:
 
103
        RETiRet;
75
104
}
76
105
 
77
106
/* construct from CStr object. only the counted string is
78
107
 * copied, not the szString.
79
108
 * rgerhards 2005-10-18
80
109
 */
81
 
rsRetVal rsCStrConstructFromCStr(rsCStrObj **ppThis, rsCStrObj *pFrom)
 
110
rsRetVal rsCStrConstructFromCStr(cstr_t **ppThis, cstr_t *pFrom)
82
111
{
83
 
        rsCStrObj *pThis;
 
112
        DEFiRet;
 
113
        cstr_t *pThis;
84
114
 
85
115
        assert(ppThis != NULL);
86
116
        rsCHECKVALIDOBJECT(pFrom, OIDrsCStr);
87
117
 
88
 
        if((pThis = rsCStrConstruct()) == NULL)
89
 
                return RS_RET_OUT_OF_MEMORY;
 
118
        CHKiRet(rsCStrConstruct(&pThis));
90
119
 
91
120
        pThis->iBufSize = pThis->iStrLen = pFrom->iStrLen;
92
121
        if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) {
93
122
                RSFREEOBJ(pThis);
94
 
                return RS_RET_OUT_OF_MEMORY;
 
123
                ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
95
124
        }
96
125
 
97
126
        /* copy properties */
98
127
        memcpy(pThis->pBuf, pFrom->pBuf, pThis->iStrLen);
99
128
 
100
129
        *ppThis = pThis;
101
 
        return RS_RET_OK;
 
130
finalize_it:
 
131
        RETiRet;
102
132
}
103
133
 
104
134
 
105
 
void rsCStrDestruct(rsCStrObj *pThis)
 
135
void rsCStrDestruct(cstr_t **ppThis)
106
136
{
 
137
        cstr_t *pThis = *ppThis;
 
138
 
107
139
        /* rgerhards 2005-10-19: The free of pBuf was contained in conditional compilation.
108
140
         * The code was only compiled if STRINGBUF_TRIM_ALLOCSIZE was set to 1. I honestly
109
141
         * do not know why it was so, I think it was an artifact. Anyhow, I have changed this
110
142
         * now. Should there any issue occur, this comment hopefully will shed some light 
111
143
         * on what happened. I re-verified, and this function has never before been called
112
144
         * by anyone. So changing it can have no impact for obvious reasons...
 
145
         *
 
146
         * rgerhards, 2008-02-20: I changed the interface to the new calling conventions, where
 
147
         * the destructor receives a pointer to the object, so that it can set it to NULL.
113
148
         */
114
149
        if(pThis->pBuf != NULL) {
115
150
                free(pThis->pBuf);
120
155
        }
121
156
 
122
157
        RSFREEOBJ(pThis);
123
 
}
124
 
 
125
 
 
126
 
rsRetVal rsCStrAppendStrWithLen(rsCStrObj *pThis, uchar* psz, size_t iStrLen)
127
 
{
128
 
        rsRetVal iRet;
129
 
        int iOldAllocInc;
 
158
        *ppThis = NULL;
 
159
}
 
160
 
 
161
 
 
162
/* extend the string buffer if its size is insufficient.
 
163
 * Param iMinNeeded is the minumum free space needed. If it is larger
 
164
 * than the default alloc increment, space for at least this amount is
 
165
 * allocated. In practice, a bit more is allocated because we envision that
 
166
 * some more characters may be added after these.
 
167
 * rgerhards, 2008-01-07
 
168
 */
 
169
static rsRetVal rsCStrExtendBuf(cstr_t *pThis, size_t iMinNeeded)
 
170
{
 
171
        DEFiRet;
 
172
        uchar *pNewBuf;
 
173
        size_t iNewSize;
 
174
 
 
175
        /* first compute the new size needed */
 
176
        if(iMinNeeded > pThis->iAllocIncrement) {
 
177
                /* we allocate "n" iAllocIncrements. Usually, that should
 
178
                 * leave some room after the absolutely needed one. It also
 
179
                 * reduces memory fragmentation. Note that all of this are
 
180
                 * integer operations (very important to understand what is
 
181
                 * going on)! Parenthesis are for better readibility.
 
182
                 */
 
183
                iNewSize = ((iMinNeeded / pThis->iAllocIncrement) + 1) * pThis->iAllocIncrement;
 
184
        } else {
 
185
                iNewSize = pThis->iBufSize + pThis->iAllocIncrement;
 
186
        }
 
187
        iNewSize += pThis->iBufSize; /* add current size */
 
188
 
 
189
        /* and then allocate and copy over */
 
190
        /* DEV debugging only: dbgprintf("extending string buffer, old %d, new %d\n", pThis->iBufSize, iNewSize); */
 
191
        if((pNewBuf = (uchar*) malloc(iNewSize * sizeof(uchar))) == NULL)
 
192
                ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
 
193
        memcpy(pNewBuf, pThis->pBuf, pThis->iBufSize);
 
194
        pThis->iBufSize = iNewSize;
 
195
        if(pThis->pBuf != NULL) {
 
196
                free(pThis->pBuf);
 
197
        }
 
198
        pThis->pBuf = pNewBuf;
 
199
 
 
200
finalize_it:
 
201
        RETiRet;
 
202
}
 
203
 
 
204
 
 
205
/* append a string of known length. In this case, we make sure we do at most
 
206
 * one additional memory allocation.
 
207
 * I optimized this function to use memcpy(), among others. Consider it a
 
208
 * rewrite (which may be good to know in case of bugs) -- rgerhards, 2008-01-07
 
209
 */
 
210
rsRetVal rsCStrAppendStrWithLen(cstr_t *pThis, uchar* psz, size_t iStrLen)
 
211
{
 
212
        DEFiRet;
130
213
 
131
214
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
132
215
        assert(psz != NULL);
133
216
 
134
 
        /* we first check if the to-be-added string is larger than the
135
 
         * alloc increment. If so, we temporarily increase the alloc
136
 
         * increment to the length of the string. This will ensure that
137
 
         * one string copy will be needed at most. As this is a very
138
 
         * costly operation, it outweights the cost of the strlen((char*)) and
139
 
         * related stuff - at least I think so.
140
 
         * rgerhards 2005-09-22
141
 
         */
142
 
        /* We save the current alloc increment in any case, so we can just
143
 
         * overwrite it below, this is faster than any if-construct.
144
 
         */
145
 
        iOldAllocInc = pThis->iAllocIncrement;
146
 
        if(iStrLen > pThis->iAllocIncrement) {
147
 
                pThis->iAllocIncrement = iStrLen;
 
217
        /* does the string fit? */
 
218
        if(pThis->iStrLen + iStrLen > pThis->iBufSize) {  
 
219
                CHKiRet(rsCStrExtendBuf(pThis, iStrLen)); /* need more memory! */
148
220
        }
149
221
 
150
 
        while(*psz)
151
 
                if((iRet = rsCStrAppendChar(pThis, *psz++)) != RS_RET_OK)
152
 
                        return iRet;
 
222
        /* ok, now we always have sufficient continues memory to do a memcpy() */
 
223
        memcpy(pThis->pBuf + pThis->iStrLen, psz, iStrLen);
 
224
        pThis->iStrLen += iStrLen;
153
225
 
154
 
        pThis->iAllocIncrement = iOldAllocInc; /* restore */
155
 
        return RS_RET_OK;
 
226
finalize_it:
 
227
        RETiRet;
156
228
}
157
229
 
158
230
 
161
233
 * need to change existing code.
162
234
 * rgerhards, 2007-07-03
163
235
 */
164
 
rsRetVal rsCStrAppendStr(rsCStrObj *pThis, uchar* psz)
165
 
{
166
 
        return rsCStrAppendStrWithLen(pThis, psz, strlen((char*)(char*) psz));
167
 
}
168
 
 
169
 
 
170
 
rsRetVal rsCStrAppendInt(rsCStrObj *pThis, int i)
171
 
{
172
 
        rsRetVal iRet;
 
236
rsRetVal rsCStrAppendStr(cstr_t *pThis, uchar* psz)
 
237
{
 
238
        return rsCStrAppendStrWithLen(pThis, psz, strlen((char*) psz));
 
239
}
 
240
 
 
241
 
 
242
/* append the contents of one cstr_t object to another
 
243
 * rgerhards, 2008-02-25
 
244
 */
 
245
rsRetVal rsCStrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend)
 
246
{
 
247
        return rsCStrAppendStrWithLen(pThis, pstrAppend->pBuf, pstrAppend->iStrLen);
 
248
}
 
249
 
 
250
 
 
251
rsRetVal rsCStrAppendInt(cstr_t *pThis, long i)
 
252
{
 
253
        DEFiRet;
173
254
        uchar szBuf[32];
174
255
 
175
256
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
176
257
 
177
 
        if((iRet = srUtilItoA((char*) szBuf, sizeof(szBuf), i)) != RS_RET_OK)
178
 
                return iRet;
 
258
        CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), i));
179
259
 
180
 
        return rsCStrAppendStr(pThis, szBuf);
 
260
        iRet = rsCStrAppendStr(pThis, szBuf);
 
261
finalize_it:
 
262
        RETiRet;
181
263
}
182
264
 
183
265
 
184
 
rsRetVal rsCStrAppendChar(rsCStrObj *pThis, uchar c)
 
266
rsRetVal rsCStrAppendChar(cstr_t *pThis, uchar c)
185
267
{
186
 
        uchar* pNewBuf;
 
268
        DEFiRet;
187
269
 
188
270
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
189
271
 
190
 
        if(pThis->iStrLen >= pThis->iBufSize)
191
 
        {  /* need more memory! */
192
 
                if((pNewBuf = (uchar*) malloc((pThis->iBufSize + pThis->iAllocIncrement) * sizeof(uchar))) == NULL)
193
 
                        return RS_RET_OUT_OF_MEMORY;
194
 
                memcpy(pNewBuf, pThis->pBuf, pThis->iBufSize);
195
 
                pThis->iBufSize += pThis->iAllocIncrement;
196
 
                if(pThis->pBuf != NULL) {
197
 
                        free(pThis->pBuf);
198
 
                }
199
 
                pThis->pBuf = pNewBuf;
 
272
        if(pThis->iStrLen >= pThis->iBufSize) {  
 
273
                CHKiRet(rsCStrExtendBuf(pThis, 1)); /* need more memory! */
200
274
        }
201
275
 
202
276
        /* ok, when we reach this, we have sufficient memory */
208
282
                pThis->pszBuf = NULL;
209
283
        }
210
284
 
211
 
        return RS_RET_OK;
 
285
finalize_it:
 
286
        RETiRet;
212
287
}
213
288
 
214
289
 
219
294
 * not modified by this function.
220
295
 * rgerhards, 2005-10-18
221
296
 */
222
 
rsRetVal rsCStrSetSzStr(rsCStrObj *pThis, uchar *pszNew)
 
297
rsRetVal rsCStrSetSzStr(cstr_t *pThis, uchar *pszNew)
223
298
{
224
299
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
225
300
 
260
335
 * WARNING: The returned pointer MUST NOT be freed, as it may be
261
336
 *          obtained from that constant memory pool (in case of NULL!)
262
337
 */
263
 
uchar*  rsCStrGetSzStrNoNULL(rsCStrObj *pThis)
 
338
uchar*  rsCStrGetSzStrNoNULL(cstr_t *pThis)
264
339
{
265
340
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
266
341
        if(pThis->pBuf == NULL)
278
353
 * rsCStrGetSzStrNoNULL() instead.
279
354
 * rgerhards, 2005-09-15
280
355
 */
281
 
uchar*  rsCStrGetSzStr(rsCStrObj *pThis)
 
356
uchar*  rsCStrGetSzStr(cstr_t *pThis)
282
357
{
283
358
        size_t i;
284
359
 
342
417
 * PLEASE NOTE: the caller must free the memory returned in ppSz in any case
343
418
 * (except, of course, if it is NULL).
344
419
 */
345
 
rsRetVal rsCStrConvSzStrAndDestruct(rsCStrObj *pThis, uchar **ppSz, int bRetNULL)
 
420
rsRetVal rsCStrConvSzStrAndDestruct(cstr_t *pThis, uchar **ppSz, int bRetNULL)
346
421
{
347
422
        DEFiRet;
348
423
        uchar* pRetBuf;
373
448
                free(pThis->pBuf);
374
449
        RSFREEOBJ(pThis);
375
450
        
376
 
        return(iRet);
 
451
        RETiRet;
377
452
}
378
453
 
379
454
 
380
 
rsRetVal  rsCStrFinish(rsCStrObj __attribute__((unused)) *pThis)
381
 
{
382
 
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
383
 
 
384
 
#       if STRINGBUF_TRIM_ALLOCSIZE == 1
385
 
        /* in this mode, we need to trim the string. To do
 
455
#if STRINGBUF_TRIM_ALLOCSIZE == 1
 
456
        /* Only in this mode, we need to trim the string. To do
386
457
         * so, we must allocate a new buffer of the exact 
387
458
         * string size, and then copy the old one over. 
388
 
         * This new buffer is then to be returned.
389
 
         */
390
 
        if((pRetBuf = malloc((pThis->iBufSize) * sizeof(uchar))) == NULL)
 
459
         */
 
460
        /* WARNING
 
461
         * STRINGBUF_TRIM_ALLOCSIZE can, in theory, be used to trim
 
462
         * memory buffers. This part of the code was inherited from
 
463
         * liblogging (where it is used in a different context) but
 
464
         * never put to use in rsyslog. The reason is that it is hardly
 
465
         * imaginable where the extra performance cost is worth the save
 
466
         * in memory alloc. Then Anders Blomdel rightfully pointed out that
 
467
         * the code does not work at all - and nobody even know that it
 
468
         * probably shouldn't. Rather than removing, I deciced to somewhat
 
469
         * fix the code, so that this feature may be enabled if somebody
 
470
         * really has a need for it. Be warned, however, that I NEVER
 
471
         * tested the fix. So if you intend to use this feature, you must
 
472
         * do full testing before you rely on it. -- rgerhards, 2008-02-12
 
473
         */
 
474
rsRetVal  rsCStrFinish(cstr_t __attribute__((unused)) *pThis)
 
475
{
 
476
        DEFiRet;
 
477
        uchar* pBuf;
 
478
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
 
479
 
 
480
        if((pBuf = malloc((pThis->iStrLen) * sizeof(uchar))) == NULL)
391
481
        {       /* OK, in this case we use the previous buffer. At least
392
482
                 * we have it ;)
393
483
                 */
394
484
        }
395
485
        else
396
486
        {       /* got the new buffer, so let's use it */
397
 
                uchar* pBuf;
398
 
                memcpy(pBuf, pThis->pBuf, pThis->iBufPtr + 1);
 
487
                memcpy(pBuf, pThis->pBuf, pThis->iStrLen);
399
488
                pThis->pBuf = pBuf;
400
489
        }
401
 
#       else
402
 
        /* here, we need to do ... nothing ;)
403
 
         */
404
 
#       endif
405
 
        return RS_RET_OK;
 
490
 
 
491
        RETiRet;
406
492
}
407
 
 
408
 
void rsCStrSetAllocIncrement(rsCStrObj *pThis, int iNewIncrement)
 
493
#endif  /* #if STRINGBUF_TRIM_ALLOCSIZE == 1 */
 
494
 
 
495
 
 
496
void rsCStrSetAllocIncrement(cstr_t *pThis, int iNewIncrement)
409
497
{
410
498
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
411
499
        assert(iNewIncrement > 0);
421
509
 * This is due to performance reasons.
422
510
 */
423
511
#ifndef NDEBUG
424
 
int rsCStrLen(rsCStrObj *pThis)
 
512
int rsCStrLen(cstr_t *pThis)
425
513
{
426
514
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
427
515
        return(pThis->iStrLen);
431
519
/* Truncate characters from the end of the string.
432
520
 * rgerhards 2005-09-15
433
521
 */
434
 
rsRetVal rsCStrTruncate(rsCStrObj *pThis, size_t nTrunc)
 
522
rsRetVal rsCStrTruncate(cstr_t *pThis, size_t nTrunc)
435
523
{
436
524
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
437
525
 
454
542
 
455
543
/* Trim trailing whitespace from a given string
456
544
 */
457
 
rsRetVal rsCStrTrimTrailingWhiteSpace(rsCStrObj *pThis)
 
545
rsRetVal rsCStrTrimTrailingWhiteSpace(cstr_t *pThis)
458
546
{
459
547
        register int i;
460
548
        register uchar *pC;
481
569
 * in equal-size strings.
482
570
 * rgerhards, 2005-09-26
483
571
 */
484
 
int rsCStrCStrCmp(rsCStrObj *pCS1, rsCStrObj *pCS2)
 
572
int rsCStrCStrCmp(cstr_t *pCS1, cstr_t *pCS2)
485
573
{
486
574
        rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
487
575
        rsCHECKVALIDOBJECT(pCS2, OIDrsCStr);
505
593
}
506
594
 
507
595
 
508
 
/* check if a sz-type string start with a CStr object. This function
 
596
/* check if a sz-type string starts with a CStr object. This function
509
597
 * is initially written to support the "startswith" property-filter
510
598
 * comparison operation. Maybe it also has other needs.
 
599
 * This functions is modelled after the strcmp() series, thus a
 
600
 * return value of 0 indicates that the string starts with the
 
601
 * sequence while -1 indicates it does not!
511
602
 * rgerhards 2005-10-19
512
603
 */
513
 
int rsCStrSzStrStartsWithCStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz)
 
604
int rsCStrSzStrStartsWithCStr(cstr_t *pCS1, uchar *psz, size_t iLenSz)
514
605
{
515
606
        register int i;
516
607
        int iMax;
540
631
 
541
632
 
542
633
/* check if a CStr object starts with a sz-type string.
 
634
 * This functions is modelled after the strcmp() series, thus a
 
635
 * return value of 0 indicates that the string starts with the
 
636
 * sequence while -1 indicates it does not!
543
637
 * rgerhards 2005-09-26
544
638
 */
545
 
int rsCStrStartsWithSzStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz)
 
639
int rsCStrStartsWithSzStr(cstr_t *pCS1, uchar *psz, size_t iLenSz)
546
640
{
547
641
        register size_t i;
548
642
 
568
662
                return -1; /* pCS1 is less then psz */
569
663
}
570
664
 
 
665
 
 
666
/* The same as rsCStrStartsWithSzStr(), but does a case-insensitive
 
667
 * comparison. TODO: consolidate the two.
 
668
 * rgerhards 2008-02-28
 
669
 */
 
670
int rsCStrCaseInsensitveStartsWithSzStr(cstr_t *pCS1, uchar *psz, size_t iLenSz)
 
671
{
 
672
        register size_t i;
 
673
 
 
674
        rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
 
675
        assert(psz != NULL);
 
676
        assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */
 
677
        if(pCS1->iStrLen >= iLenSz) {
 
678
                /* we are using iLenSz below, because we need to check
 
679
                 * iLenSz characters at maximum (start with!)
 
680
                 */
 
681
                if(iLenSz == 0)
 
682
                        return 0; /* yes, it starts with a zero-sized string ;) */
 
683
                else {  /* we now have something to compare, so let's do it... */
 
684
                        for(i = 0 ; i < iLenSz ; ++i) {
 
685
                                if(tolower(pCS1->pBuf[i]) != tolower(psz[i]))
 
686
                                        return tolower(pCS1->pBuf[i]) - tolower(psz[i]);
 
687
                        }
 
688
                        /* if we arrive here, the string actually starts with psz */
 
689
                        return 0;
 
690
                }
 
691
        }
 
692
        else
 
693
                return -1; /* pCS1 is less then psz */
 
694
}
 
695
 
571
696
/* check if a CStr object matches a regex.
572
697
 * msamia@redhat.com 2007-07-12
573
698
 * @return returns 0 if matched
574
699
 * bug: doesn't work for CStr containing \0
575
700
 * rgerhards, 2007-07-16: bug is no real bug, because rsyslogd ensures there
576
701
 * never is a \0 *inside* a property string.
 
702
 * Note that the function returns -1 if regexp functionality is not available.
 
703
 * TODO: change calling interface! -- rgerhards, 2008-03-07
577
704
 */
578
 
int rsCStrSzStrMatchRegex(rsCStrObj *pCS1, uchar *psz)
 
705
int rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz)
579
706
{
580
 
    regex_t preq;
581
 
    regcomp(&preq, (char*) rsCStrGetSzStr(pCS1), 0);
582
 
    int iRet = regexec(&preq, (char*) psz, 0, NULL, 0);
583
 
    regfree(&preq);
584
 
    return iRet;
 
707
        regex_t preq;
 
708
        int ret;
 
709
 
 
710
        BEGINfunc
 
711
 
 
712
        if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) {
 
713
                regexp.regcomp(&preq, (char*) rsCStrGetSzStr(pCS1), 0);
 
714
                ret = regexp.regexec(&preq, (char*) psz, 0, NULL, 0);
 
715
                regexp.regfree(&preq);
 
716
        } else {
 
717
                ret = 1; /* simulate "not found" */
 
718
        }
 
719
 
 
720
        ENDfunc
 
721
        return ret;
585
722
}
586
723
 
 
724
 
587
725
/* compare a rsCStr object with a classical sz string.  This function
588
726
 * is almost identical to rsCStrZsStrCmp(), but it also takes an offset
589
727
 * to the CStr object from where the comparison is to start.
605
743
 * program bug and will lead to unpredictable results and program aborts).
606
744
 * rgerhards 2005-09-26
607
745
 */
608
 
int rsCStrOffsetSzStrCmp(rsCStrObj *pCS1, size_t iOffset, uchar *psz, size_t iLenSz)
 
746
int rsCStrOffsetSzStrCmp(cstr_t *pCS1, size_t iOffset, uchar *psz, size_t iLenSz)
609
747
{
 
748
        BEGINfunc
610
749
        rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
611
750
        assert(iOffset < pCS1->iStrLen);
612
751
        assert(psz != NULL);
615
754
                /* we are using iLenSz below, because the lengths
616
755
                 * are equal and iLenSz is faster to access
617
756
                 */
618
 
                if(iLenSz == 0)
 
757
                if(iLenSz == 0) {
619
758
                        return 0; /* zero-sized strings are equal ;) */
620
 
                else {  /* we now have two non-empty strings of equal
 
759
                        ENDfunc
 
760
                } else {  /* we now have two non-empty strings of equal
621
761
                         * length, so we need to actually check if they
622
762
                         * are equal.
623
763
                         */
628
768
                        }
629
769
                        /* if we arrive here, the strings are equal */
630
770
                        return 0;
 
771
                        ENDfunc
631
772
                }
632
773
        }
633
 
        else
 
774
        else {
634
775
                return pCS1->iStrLen - iOffset - iLenSz;
 
776
                ENDfunc
 
777
        }
 
778
}
 
779
 
 
780
 
 
781
/* Converts a string to a number. If the string dos not contain a number, 
 
782
 * RS_RET_NOT_A_NUMBER is returned and the contents of pNumber is undefined.
 
783
 * If all goes well, pNumber contains the number that the string was converted
 
784
 * to.
 
785
 */
 
786
rsRetVal
 
787
rsCStrConvertToNumber(cstr_t *pStr, number_t *pNumber)
 
788
{
 
789
        DEFiRet;
 
790
        number_t n;
 
791
        int bIsNegative;
 
792
        size_t i;
 
793
 
 
794
        ASSERT(pStr != NULL);
 
795
        ASSERT(pNumber != NULL);
 
796
 
 
797
        if(pStr->iStrLen == 0) {
 
798
                /* can be converted to 0! (by convention) */
 
799
                pNumber = 0;
 
800
                FINALIZE;
 
801
        }
 
802
 
 
803
        /* first skip whitespace (if present) */
 
804
        for(i = 0 ; i < pStr->iStrLen && isspace(pStr->pBuf[i]) ; ++i) {
 
805
                /*DO NOTHING*/
 
806
        }
 
807
 
 
808
        /* we have a string, so let's check its syntax */
 
809
        if(pStr->pBuf[i] == '+') {
 
810
                ++i; /* skip that char */
 
811
                bIsNegative = 0;
 
812
        } else if(pStr->pBuf[0] == '-') {
 
813
                ++i; /* skip that char */
 
814
                bIsNegative = 1;
 
815
        } else {
 
816
                bIsNegative = 0;
 
817
        }
 
818
 
 
819
        /* TODO: octal? hex? */
 
820
        n = 0;
 
821
        while(i < pStr->iStrLen && isdigit(pStr->pBuf[i])) {
 
822
                n = n * 10 + pStr->pBuf[i] * 10;
 
823
                ++i;
 
824
        }
 
825
        
 
826
        if(i < pStr->iStrLen) /* non-digits before end of string? */
 
827
                ABORT_FINALIZE(RS_RET_NOT_A_NUMBER);
 
828
 
 
829
        if(bIsNegative)
 
830
                n *= -1;
 
831
 
 
832
        /* we got it, so return the number */
 
833
        *pNumber = n;
 
834
 
 
835
finalize_it:
 
836
        RETiRet;
 
837
}
 
838
 
 
839
 
 
840
/* Converts a string to a boolen. First tries to convert to a number. If
 
841
 * that succeeds, we are done (number is then used as boolean value). If
 
842
 * that fails, we look if the string is "yes" or "true". If so, a value
 
843
 * of 1 is returned. In all other cases, a value of 0 is returned. Please
 
844
 * note that we do not have a specific boolean type, so we return a number.
 
845
 * so, these are 
 
846
 * RS_RET_NOT_A_NUMBER is returned and the contents of pNumber is undefined.
 
847
 * If all goes well, pNumber contains the number that the string was converted
 
848
 * to.
 
849
 */
 
850
rsRetVal
 
851
rsCStrConvertToBool(cstr_t *pStr, number_t *pBool)
 
852
{
 
853
        DEFiRet;
 
854
 
 
855
        ASSERT(pStr != NULL);
 
856
        ASSERT(pBool != NULL);
 
857
 
 
858
        iRet = rsCStrConvertToNumber(pStr, pBool);
 
859
 
 
860
        if(iRet != RS_RET_NOT_A_NUMBER) {
 
861
                FINALIZE; /* in any case, we have nothing left to do */
 
862
        }
 
863
 
 
864
        /* TODO: maybe we can do better than strcasecmp ;) -- overhead! */
 
865
        if(!strcasecmp((char*)rsCStrGetSzStr(pStr), "true")) {
 
866
                *pBool = 1;
 
867
        } else if(!strcasecmp((char*)rsCStrGetSzStr(pStr), "yes")) {
 
868
                *pBool = 1;
 
869
        } else {
 
870
                *pBool = 0;
 
871
        }
 
872
 
 
873
finalize_it:
 
874
        RETiRet;
635
875
}
636
876
 
637
877
 
648
888
 * The to sz string pointer must not be NULL!
649
889
 * rgerhards 2005-09-26
650
890
 */
651
 
int rsCStrSzStrCmp(rsCStrObj *pCS1, uchar *psz, size_t iLenSz)
 
891
int rsCStrSzStrCmp(cstr_t *pCS1, uchar *psz, size_t iLenSz)
652
892
{
653
893
        rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
654
894
        assert(psz != NULL);
681
921
 * returned. Both parameters MUST be given (NULL is not allowed).
682
922
 * rgerhards 2005-09-19
683
923
 */
684
 
int rsCStrLocateInSzStr(rsCStrObj *pThis, uchar *sz)
 
924
int rsCStrLocateInSzStr(cstr_t *pThis, uchar *sz)
685
925
{
686
926
        int i;
687
927
        int iMax;
716
956
}
717
957
 
718
958
 
 
959
/* This is the same as rsCStrLocateInSzStr(), but does a case-insensitve
 
960
 * comparison.
 
961
 * TODO: over time, consolidate the two.
 
962
 * rgerhards, 2008-02-28
 
963
 */
 
964
int rsCStrCaseInsensitiveLocateInSzStr(cstr_t *pThis, uchar *sz)
 
965
{
 
966
        int i;
 
967
        int iMax;
 
968
        int bFound;
 
969
        rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
 
970
        assert(sz != NULL);
 
971
        
 
972
        if(pThis->iStrLen == 0)
 
973
                return 0;
 
974
        
 
975
        /* compute the largest index where a match could occur - after all,
 
976
         * the to-be-located string must be able to be present in the 
 
977
         * searched string (it needs its size ;)).
 
978
         */
 
979
        iMax = strlen((char*)sz) - pThis->iStrLen;
 
980
 
 
981
        bFound = 0;
 
982
        i = 0;
 
983
        while(i  <= iMax && !bFound) {
 
984
                size_t iCheck;
 
985
                uchar *pComp = sz + i;
 
986
                for(iCheck = 0 ; iCheck < pThis->iStrLen ; ++iCheck)
 
987
                        if(tolower(*(pComp + iCheck)) != tolower(*(pThis->pBuf + iCheck)))
 
988
                                break;
 
989
                if(iCheck == pThis->iStrLen)
 
990
                        bFound = 1; /* found! - else it wouldn't be equal */
 
991
                else
 
992
                        ++i; /* on to the next try */
 
993
        }
 
994
 
 
995
        return(bFound ? i : -1);
 
996
}
 
997
 
 
998
 
719
999
#if 0    /* read comment below why this is commented out. In short: for future use! */
720
1000
/* locate the first occurence of a standard sz string inside a rsCStr object.
721
1001
 * Returns the offset (0-bound) of this first occurrence. If not found, -1 is
726
1006
 *          some time later. However, it is not fully tested, so start with testing
727
1007
 *          it before you put it to first use).
728
1008
 */
729
 
int rsCStrLocateSzStr(rsCStrObj *pThis, uchar *sz)
 
1009
int rsCStrLocateSzStr(cstr_t *pThis, uchar *sz)
730
1010
{
731
1011
        int iLenSz;
732
1012
        int i;
766
1046
#endif /* end comment out */
767
1047
 
768
1048
 
 
1049
/* our exit function. TODO: remove once converted to a class
 
1050
 * rgerhards, 2008-03-11
 
1051
 */
 
1052
rsRetVal strExit()
 
1053
{
 
1054
        DEFiRet;
 
1055
        objRelease(regexp, LM_REGEXP_FILENAME);
 
1056
        RETiRet;
 
1057
}
 
1058
 
 
1059
 
 
1060
/* our init function. TODO: remove once converted to a class
 
1061
 */
 
1062
rsRetVal strInit()
 
1063
{
 
1064
        DEFiRet;
 
1065
        CHKiRet(objGetObjInterface(&obj));
 
1066
 
 
1067
finalize_it:
 
1068
        RETiRet;
 
1069
}
 
1070
 
 
1071
 
769
1072
/*
770
1073
 * Local variables:
771
1074
 *  c-indent-level: 8