~arges/ubuntu/quantal/rsyslog/fix-lp1059592

« back to all changes in this revision

Viewing changes to var.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2009-02-15 21:56:23 UTC
  • mto: (3.2.4 squeeze) (1.1.9 upstream)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20090215215623-xsycf628eo3kguc0
Tags: upstream-3.20.4
ImportĀ upstreamĀ versionĀ 3.20.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* var.c - a typeless variable class
2
 
 *
3
 
 * This class is used to represent variable values, which may have any type.
4
 
 * Among others, it will be used inside rsyslog's expression system, but
5
 
 * also internally at any place where a typeless variable is needed.
6
 
 *
7
 
 * Module begun 2008-02-20 by Rainer Gerhards, with some code taken
8
 
 * from the obj.c/.h files.
9
 
 *
10
 
 * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
11
 
 *
12
 
 * This file is part of the rsyslog runtime library.
13
 
 *
14
 
 * The rsyslog runtime library is free software: you can redistribute it and/or modify
15
 
 * it under the terms of the GNU Lesser 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
 
 * The rsyslog runtime library 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 Lesser General Public License for more details.
23
 
 *
24
 
 * You should have received a copy of the GNU Lesser General Public License
25
 
 * along with the rsyslog runtime library.  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.
28
 
 * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
29
 
 */
30
 
 
31
 
#include "config.h"
32
 
#include <stdlib.h>
33
 
#include <assert.h>
34
 
 
35
 
#include "rsyslog.h"
36
 
#include "obj.h"
37
 
#include "srUtils.h"
38
 
#include "var.h"
39
 
 
40
 
/* static data */
41
 
DEFobjStaticHelpers
42
 
 
43
 
 
44
 
/* Standard-Constructor
45
 
 */
46
 
BEGINobjConstruct(var) /* be sure to specify the object type also in END macro! */
47
 
ENDobjConstruct(var)
48
 
 
49
 
 
50
 
/* ConstructionFinalizer
51
 
 * rgerhards, 2008-01-09
52
 
 */
53
 
rsRetVal varConstructFinalize(var_t __attribute__((unused)) *pThis)
54
 
{
55
 
        DEFiRet;
56
 
 
57
 
        ISOBJ_TYPE_assert(pThis, var);
58
 
 
59
 
        RETiRet;
60
 
}
61
 
 
62
 
 
63
 
/* destructor for the var object */
64
 
BEGINobjDestruct(var) /* be sure to specify the object type also in END and CODESTART macros! */
65
 
CODESTARTobjDestruct(var)
66
 
        if(pThis->pcsName != NULL)
67
 
                rsCStrDestruct(&pThis->pcsName);
68
 
        if(pThis->varType == VARTYPE_STR) {
69
 
                if(pThis->val.pStr != NULL)
70
 
                        rsCStrDestruct(&pThis->val.pStr);
71
 
        }
72
 
ENDobjDestruct(var)
73
 
 
74
 
 
75
 
/* DebugPrint support for the var object */
76
 
BEGINobjDebugPrint(var) /* be sure to specify the object type also in END and CODESTART macros! */
77
 
CODESTARTobjDebugPrint(var)
78
 
        switch(pThis->varType) {
79
 
                case VARTYPE_STR:
80
 
                        dbgoprint((obj_t*) pThis, "type: cstr, val '%s'\n", rsCStrGetSzStr(pThis->val.pStr));
81
 
                        break;
82
 
                case VARTYPE_NUMBER:
83
 
                        dbgoprint((obj_t*) pThis, "type: number, val %lld\n", pThis->val.num);
84
 
                        break;
85
 
                default:
86
 
                        dbgoprint((obj_t*) pThis, "type %d currently not suppored in debug output\n", pThis->varType);
87
 
                        break;
88
 
        }
89
 
ENDobjDebugPrint(var)
90
 
 
91
 
 
92
 
/* duplicates a var instance
93
 
 * rgerhards, 2008-02-25
94
 
 */
95
 
static rsRetVal
96
 
Duplicate(var_t *pThis, var_t **ppNew)
97
 
{
98
 
        DEFiRet;
99
 
        var_t *pNew = NULL;
100
 
        cstr_t *pstr;
101
 
 
102
 
        ISOBJ_TYPE_assert(pThis, var);
103
 
        assert(ppNew != NULL);
104
 
 
105
 
        CHKiRet(varConstruct(&pNew));
106
 
        CHKiRet(varConstructFinalize(pNew));
107
 
 
108
 
        /* we have the object, now copy value */
109
 
        pNew->varType = pThis->varType;
110
 
        if(pThis->varType == VARTYPE_NUMBER) {
111
 
                pNew->val.num = pThis->val.num;
112
 
        } else if(pThis->varType == VARTYPE_STR) {
113
 
                CHKiRet(rsCStrConstructFromCStr(&pstr, pThis->val.pStr));
114
 
                pNew->val.pStr = pstr;
115
 
        }
116
 
 
117
 
        *ppNew = pNew;
118
 
 
119
 
finalize_it:
120
 
        if(iRet != RS_RET_OK && pNew != NULL)
121
 
                varDestruct(&pNew);
122
 
 
123
 
        RETiRet;
124
 
}
125
 
 
126
 
 
127
 
/* free the current values (destructs objects if necessary)
128
 
 */
129
 
static rsRetVal
130
 
varUnsetValues(var_t *pThis)
131
 
{
132
 
        DEFiRet;
133
 
 
134
 
        ISOBJ_TYPE_assert(pThis, var);
135
 
        if(pThis->varType == VARTYPE_STR)
136
 
                rsCStrDestruct(&pThis->val.pStr);
137
 
 
138
 
        pThis->varType = VARTYPE_NONE;
139
 
 
140
 
        RETiRet;
141
 
}
142
 
 
143
 
 
144
 
/* set a string value 
145
 
 * The caller hands over the string and must n longer use it after this method
146
 
 * has been called.
147
 
 */
148
 
static rsRetVal
149
 
varSetString(var_t *pThis, cstr_t *pStr)
150
 
{
151
 
        DEFiRet;
152
 
 
153
 
        ISOBJ_TYPE_assert(pThis, var);
154
 
 
155
 
        CHKiRet(varUnsetValues(pThis));
156
 
        pThis->varType = VARTYPE_STR;
157
 
        pThis->val.pStr = pStr;
158
 
 
159
 
finalize_it:
160
 
        RETiRet;
161
 
}
162
 
 
163
 
 
164
 
/* set an int64 value */
165
 
static rsRetVal
166
 
varSetNumber(var_t *pThis, number_t iVal)
167
 
{
168
 
        DEFiRet;
169
 
 
170
 
        ISOBJ_TYPE_assert(pThis, var);
171
 
 
172
 
        CHKiRet(varUnsetValues(pThis));
173
 
        pThis->varType = VARTYPE_NUMBER;
174
 
        pThis->val.num = iVal;
175
 
 
176
 
finalize_it:
177
 
        RETiRet;
178
 
}
179
 
 
180
 
 
181
 
/* Change the provided object to be of type number.
182
 
 * rgerhards, 2008-02-22
183
 
 */
184
 
rsRetVal
185
 
ConvToNumber(var_t *pThis)
186
 
{
187
 
        DEFiRet;
188
 
        number_t n;
189
 
 
190
 
        if(pThis->varType == VARTYPE_NUMBER) {
191
 
                FINALIZE;
192
 
        } else if(pThis->varType == VARTYPE_STR) {
193
 
                iRet = rsCStrConvertToNumber(pThis->val.pStr, &n);
194
 
                if(iRet == RS_RET_NOT_A_NUMBER) {
195
 
                        n = 0;
196
 
                        iRet = RS_RET_OK; /* we accept this as part of the language definition */
197
 
                } else if (iRet != RS_RET_OK) {
198
 
                        FINALIZE;
199
 
                }
200
 
 
201
 
                /* we need to destruct the string first, because string and number are
202
 
                 * inside a union and share the memory area! -- rgerhards, 2008-04-03
203
 
                 */
204
 
                rsCStrDestruct(&pThis->val.pStr);
205
 
        
206
 
                pThis->val.num = n;
207
 
                pThis->varType = VARTYPE_NUMBER;
208
 
        }
209
 
 
210
 
finalize_it:
211
 
        RETiRet;
212
 
}
213
 
 
214
 
 
215
 
/* convert the provided var to type string. This is always possible
216
 
 * (except, of course, for things like out of memory...)
217
 
 * TODO: finish implementation!!!!!!!!!
218
 
 * rgerhards, 2008-02-24
219
 
 */
220
 
rsRetVal
221
 
ConvToString(var_t *pThis)
222
 
{
223
 
        DEFiRet;
224
 
        uchar szNumBuf[64];
225
 
 
226
 
        if(pThis->varType == VARTYPE_STR) {
227
 
                FINALIZE;
228
 
        } else if(pThis->varType == VARTYPE_NUMBER) {
229
 
                CHKiRet(srUtilItoA((char*)szNumBuf, sizeof(szNumBuf)/sizeof(uchar), pThis->val.num));
230
 
                CHKiRet(rsCStrConstructFromszStr(&pThis->val.pStr, szNumBuf));
231
 
                pThis->varType = VARTYPE_STR;
232
 
        }
233
 
 
234
 
finalize_it:
235
 
        RETiRet;
236
 
}
237
 
 
238
 
 
239
 
/* convert (if necessary) the value to a boolean. In essence, this means the
240
 
 * value must be a number, but in case of a string special logic is used as
241
 
 * some string-values may represent a boolean (e.g. "true").
242
 
 * rgerhards, 2008-02-25
243
 
 */
244
 
rsRetVal
245
 
ConvToBool(var_t *pThis)
246
 
{
247
 
        DEFiRet;
248
 
        number_t n;
249
 
 
250
 
        if(pThis->varType == VARTYPE_NUMBER) {
251
 
                FINALIZE;
252
 
        } else if(pThis->varType == VARTYPE_STR) {
253
 
                iRet = rsCStrConvertToBool(pThis->val.pStr, &n);
254
 
                if(iRet == RS_RET_NOT_A_NUMBER) {
255
 
                        n = 0;
256
 
                        iRet = RS_RET_OK; /* we accept this as part of the language definition */
257
 
                } else if (iRet != RS_RET_OK) {
258
 
                        FINALIZE;
259
 
                }
260
 
 
261
 
                /* we need to destruct the string first, because string and number are
262
 
                 * inside a union and share the memory area! -- rgerhards, 2008-04-03
263
 
                 */
264
 
                rsCStrDestruct(&pThis->val.pStr);
265
 
                pThis->val.num = n;
266
 
                pThis->varType = VARTYPE_NUMBER;
267
 
        }
268
 
 
269
 
finalize_it:
270
 
        RETiRet;
271
 
}
272
 
 
273
 
 
274
 
/* This function is used to prepare two var_t objects for a common operation,
275
 
 * e.g before they are added, compared. The function looks at
276
 
 * the data types of both operands and finds the best data type suitable for
277
 
 * the operation (in respect to current types). Then, it converts those
278
 
 * operands that need conversion. Please note that the passed-in var objects
279
 
 * *are* modified and returned as new type. So do call this function only if
280
 
 * you actually need the conversion.
281
 
 *
282
 
 * This is how the common data type is selected. Note that op1 and op2 are
283
 
 * just the two operands, their order is irrelevant (this would just take up
284
 
 * more table space - so string/number is the same thing as number/string).
285
 
 *
286
 
 * Common Types:
287
 
 * op1          op2     operation data type
288
 
 * string       string  string
289
 
 * string       number  number if op1 can be converted to number, string else
290
 
 * date         string  date if op1 can be converted to date, string else
291
 
 * number       number  number
292
 
 * date         number  string (maybe we can do better?)
293
 
 * date         date    date
294
 
 * none         n/a     error
295
 
 *
296
 
 * If a boolean value is required, we need to have a number inside the
297
 
 * operand. If it is not, conversion rules to number apply. Once we
298
 
 * have a number, things get easy: 0 is false, anything else is true.
299
 
 * Please note that due to this conversion rules, "0" becomes false
300
 
 * while "-4712" becomes true. Using a date as boolen is not a good
301
 
 * idea. Depending on the ultimate conversion rules, it may always
302
 
 * become true or false. As such, using dates as booleans is
303
 
 * prohibited and the result defined to be undefined.
304
 
 *
305
 
 * rgerhards, 2008-02-22
306
 
 */
307
 
static rsRetVal
308
 
ConvForOperation(var_t *pThis, var_t *pOther)
309
 
{
310
 
        DEFiRet;
311
 
 
312
 
        if(pThis->varType == VARTYPE_NONE || pOther->varType == VARTYPE_NONE)
313
 
                ABORT_FINALIZE(RS_RET_INVALID_VAR);
314
 
 
315
 
        switch(pThis->varType) {
316
 
                case VARTYPE_NONE:
317
 
                        ABORT_FINALIZE(RS_RET_INVALID_VAR);
318
 
                        break;
319
 
                case VARTYPE_STR:
320
 
                        switch(pOther->varType) {
321
 
                                case VARTYPE_NONE:
322
 
                                        ABORT_FINALIZE(RS_RET_INVALID_VAR);
323
 
                                        break;
324
 
                                case VARTYPE_STR:
325
 
                                        FINALIZE; /* two strings, we are all set */
326
 
                                        break;
327
 
                                case VARTYPE_NUMBER:
328
 
                                        /* check if we can convert pThis to a number, if so use number format. */
329
 
                                        iRet = ConvToNumber(pThis);
330
 
                                        if(iRet != RS_RET_NOT_A_NUMBER) {
331
 
                                                CHKiRet(ConvToString(pOther));
332
 
                                        } else {
333
 
                                                FINALIZE; /* OK or error */
334
 
                                        }
335
 
                                        break;
336
 
                                case VARTYPE_SYSLOGTIME:
337
 
                                        ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED);
338
 
                                        break;
339
 
                        }
340
 
                        break;
341
 
                case VARTYPE_NUMBER:
342
 
                        switch(pOther->varType) {
343
 
                                case VARTYPE_NONE:
344
 
                                        ABORT_FINALIZE(RS_RET_INVALID_VAR);
345
 
                                        break;
346
 
                                case VARTYPE_STR:
347
 
                                        iRet = ConvToNumber(pOther);
348
 
                                        if(iRet != RS_RET_NOT_A_NUMBER) {
349
 
                                                CHKiRet(ConvToString(pThis));
350
 
                                        } else {
351
 
                                                FINALIZE; /* OK or error */
352
 
                                        }
353
 
                                        break;
354
 
                                case VARTYPE_NUMBER:
355
 
                                        FINALIZE; /* two numbers, so we are all set */
356
 
                                        break;
357
 
                                case VARTYPE_SYSLOGTIME:
358
 
                                        ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED);
359
 
                                        break;
360
 
                        }
361
 
                        break;
362
 
                case VARTYPE_SYSLOGTIME:
363
 
                        ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED);
364
 
                        break;
365
 
        }
366
 
 
367
 
finalize_it:
368
 
        RETiRet;
369
 
}
370
 
 
371
 
 
372
 
/* queryInterface function
373
 
 * rgerhards, 2008-02-21
374
 
 */
375
 
BEGINobjQueryInterface(var)
376
 
CODESTARTobjQueryInterface(var)
377
 
        if(pIf->ifVersion != varCURR_IF_VERSION) { /* check for current version, increment on each change */
378
 
                ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
379
 
        }
380
 
 
381
 
        /* ok, we have the right interface, so let's fill it
382
 
         * Please note that we may also do some backwards-compatibility
383
 
         * work here (if we can support an older interface version - that,
384
 
         * of course, also affects the "if" above).
385
 
         */
386
 
        pIf->Construct = varConstruct;
387
 
        pIf->ConstructFinalize = varConstructFinalize;
388
 
        pIf->Destruct = varDestruct;
389
 
        pIf->DebugPrint = varDebugPrint;
390
 
        pIf->SetNumber = varSetNumber;
391
 
        pIf->SetString = varSetString;
392
 
        pIf->ConvForOperation = ConvForOperation;
393
 
        pIf->ConvToNumber = ConvToNumber;
394
 
        pIf->ConvToBool = ConvToBool;
395
 
        pIf->ConvToString = ConvToString;
396
 
        pIf->Duplicate = Duplicate;
397
 
finalize_it:
398
 
ENDobjQueryInterface(var)
399
 
 
400
 
 
401
 
/* Initialize the var class. Must be called as the very first method
402
 
 * before anything else is called inside this class.
403
 
 * rgerhards, 2008-02-19
404
 
 */
405
 
BEGINObjClassInit(var, 1, OBJ_IS_CORE_MODULE) /* class, version */
406
 
        /* request objects we use */
407
 
 
408
 
        /* now set our own handlers */
409
 
        OBJSetMethodHandler(objMethod_DEBUGPRINT, varDebugPrint);
410
 
        OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, varConstructFinalize);
411
 
ENDObjClassInit(var)
412
 
 
413
 
/* vi:set ai:
414
 
 */