1 /* Copyright (C) 2000-2015 Lavtech.com corp. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18 #include "udm_config.h"
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <errno.h>
25
26 #define UDM_VAR_H_PRIVATE
27
28 #include "udm_common.h"
29 #include "udm_utils.h"
30 #include "udm_wild.h"
31 #include "udm_vars.h"
32 #include "udm_http.h"
33 #include "udm_sgml.h"
34
35 void
UdmSectionParamInit(UDM_SECTION_PARAM * Param,udm_secno_t secno)36 UdmSectionParamInit(UDM_SECTION_PARAM *Param, udm_secno_t secno)
37 {
38 Param->flags= UDM_VARFLAG_NONE;
39 Param->secno= secno;
40 }
41
42
43 void
UdmSectionParamInitFromVar(UDM_SECTION_PARAM * Param,const UDM_VAR * Var)44 UdmSectionParamInitFromVar(UDM_SECTION_PARAM *Param, const UDM_VAR *Var)
45 {
46 if (Var && UdmVarValueHandlerType(Var) == UDM_VALUE_HANDLER_TYPE_STR)
47 {
48 const UDM_SECTION *Sec= (const UDM_SECTION *) UdmVarConstDataPtr(Var);
49 *Param= Sec->Param;
50 }
51 else
52 {
53 bzero((void*) Param, sizeof(*Param));
54 }
55 }
56
57
58 int udm_l1tolower[256]=
59 {
60 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
61 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
62 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
63 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
64 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
65 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x5B,0x5C,0x5D,0x5E,0x5F,
66 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
67 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
68 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
69 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
70 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
71 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
72 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
73 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xD7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xDF,
74 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
75 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
76 };
77
78
79 static int
varcmpci(UDM_VAR ** uv1,UDM_VAR ** uv2)80 varcmpci(UDM_VAR **uv1, UDM_VAR **uv2)
81 {
82 const char *us1= uv1[0]->header.name;
83 const char *us2= uv2[0]->header.name;
84 while (udm_l1tolower[(unsigned char)*us1] == udm_l1tolower[(unsigned char)*us2++])
85 if (*us1++ == '\0')
86 return 0;
87 return udm_l1tolower[(unsigned char)*us1] -
88 udm_l1tolower[(unsigned char)*--us2];
89 }
90
91
92 static int
varcmpcs(UDM_VAR ** uv1,UDM_VAR ** uv2)93 varcmpcs(UDM_VAR **uv1, UDM_VAR **uv2)
94 {
95 return strcmp(uv1[0]->header.name, uv2[0]->header.name);
96 }
97
98
99 static udm_qsort_cmp
UdmVarListCmpFunc(const UDM_VARLIST * Vars)100 UdmVarListCmpFunc(const UDM_VARLIST *Vars)
101 {
102 return (Vars->flags & UDM_VARLIST_FLAG_CS) ?
103 (udm_qsort_cmp)varcmpcs :
104 (udm_qsort_cmp) varcmpci;
105 }
106
107
108 static int
varcmp2(UDM_VARLIST * Vars,UDM_VAR ** uv1,UDM_VAR ** uv2)109 varcmp2(UDM_VARLIST *Vars, UDM_VAR **uv1, UDM_VAR **uv2)
110 {
111 return UdmVarListCmpFunc(Vars)(uv1, uv2);
112 }
113
114
115 udm_value_handler_type_t
UdmVarValueHandlerType(const UDM_VAR * v)116 UdmVarValueHandlerType(const UDM_VAR *v)
117 {
118 return v->Value.handler->type;
119 }
120
121
122 udm_value_data_type_t
UdmVarValueDataType(const UDM_VAR * v)123 UdmVarValueDataType(const UDM_VAR *v)
124 {
125 return v->Value.handler->datatype;
126 }
127
128
UdmVarGetConstStr(const UDM_VAR * v,UDM_CONST_STR * str)129 UDM_CONST_STR *UdmVarGetConstStr(const UDM_VAR *v, UDM_CONST_STR *str)
130 {
131 v->Value.handler->GetConstStr(UdmVarConstDataPtr(v), str);
132 return str;
133 }
134
135
136 const char *
UdmValueStr(const UDM_VALUE * v)137 UdmValueStr(const UDM_VALUE *v)
138 {
139 UDM_CONST_STR str;
140 v->handler->GetConstStr(UdmValueConstDataPtr(v), &str);
141 return str.str;
142 }
143
144
145 const char *
UdmVarStr(const UDM_VAR * v)146 UdmVarStr(const UDM_VAR *v)
147 {
148 UDM_CONST_STR str;
149 v->Value.handler->GetConstStr(UdmVarConstDataPtr(v), &str);
150 return str.str;
151 }
152
153
154 size_t
UdmVarLength(const UDM_VAR * v)155 UdmVarLength(const UDM_VAR *v)
156 {
157 UDM_CONST_STR str;
158 v->Value.handler->GetConstStr(UdmVarConstDataPtr(v), &str);
159 return str.length;
160 }
161
162
163 udm_secno_t
UdmVarSecno(const UDM_VAR * Var)164 UdmVarSecno(const UDM_VAR *Var)
165 {
166 return Var->Value.handler->Secno(UdmVarConstDataPtr(Var));
167 }
168
169
170 udm_var_flag_t
UdmVarFlags(const UDM_VAR * Var)171 UdmVarFlags(const UDM_VAR *Var)
172 {
173 return Var->Value.handler->Flags(UdmVarConstDataPtr(Var));
174 }
175
176
177 udm_bool_t
UdmVarIsReadOnly(const UDM_VAR * Var)178 UdmVarIsReadOnly(const UDM_VAR *Var)
179 {
180 return UDM_TEST(UdmVarFlags(Var) & UDM_VARFLAG_READONLY);
181 }
182
183
184 int
UdmVarIntVal(const UDM_VAR * Var)185 UdmVarIntVal(const UDM_VAR *Var)
186 {
187 int res;
188 Var->Value.handler->GetInt(UdmVarConstDataPtr(Var), &res);
189 return res;
190 }
191
192
193 int
UdmVarListFindInt(const UDM_VARLIST * vars,const char * name,int defval)194 UdmVarListFindInt(const UDM_VARLIST *vars, const char *name, int defval)
195 {
196 const UDM_VAR *Var;
197 if ((Var= UdmVarListFind(vars, name)) != NULL)
198 {
199 return UdmVarIntVal(Var);
200 }
201 else
202 return defval;
203 }
204
205
206 unsigned
UdmVarListFindUnsigned(const UDM_VARLIST * Vars,const char * name,unsigned defval)207 UdmVarListFindUnsigned(const UDM_VARLIST *Vars,
208 const char *name, unsigned defval)
209 {
210 const UDM_VAR *Var;
211 if ((Var= UdmVarListFind(Vars, name)) != NULL)
212 {
213 unsigned int res;
214 Var->Value.handler->GetUInt(UdmVarConstDataPtr(Var), &res);
215 return res;
216 }
217 else
218 return defval;
219 }
220
221
222 udm_bool_t
UdmVarListFindBool(const UDM_VARLIST * Vars,const char * name,udm_bool_t defval)223 UdmVarListFindBool(const UDM_VARLIST *Vars,
224 const char *name, udm_bool_t defval)
225 {
226 const UDM_VAR *Var;
227 if ((Var= UdmVarListFind(Vars, name)) != NULL)
228 {
229 udm_bool_t res;
230 Var->Value.handler->GetBool(UdmVarConstDataPtr(Var), &res);
231 return res;
232 }
233 else
234 return defval;
235 }
236
237
238 double
UdmVarListFindDouble(const UDM_VARLIST * Vars,const char * name,double defval)239 UdmVarListFindDouble(const UDM_VARLIST *Vars,
240 const char *name, double defval)
241 {
242 const UDM_VAR *Var;
243 if ((Var= UdmVarListFind(Vars, name)) != NULL)
244 {
245 double res;
246 Var->Value.handler->GetDouble(UdmVarConstDataPtr(Var), &res);
247 return res;
248 }
249 else
250 return(defval);
251 }
252
253
254 udm_rc_t
UdmVarListConvert(UDM_VARLIST * Vars,UDM_CONV * conv,int flags)255 UdmVarListConvert(UDM_VARLIST *Vars, UDM_CONV *conv, int flags)
256 {
257 size_t i;
258 for (i= 0; i < Vars->nvars; i++)
259 {
260 UDM_VAR *Var= UdmVarListFindByIndex(Vars, i);
261 udm_rc_t rc= Var->Value.handler->ConvertCharset(UdmVarDataPtr(Var), conv, flags);
262 switch (rc)
263 {
264 case UDM_ERROR:
265 return rc;
266 case UDM_TERMINATED:
267 UDM_ASSERT(0);
268 case UDM_NOTARGET:
269 case UDM_OK:
270 break;
271 }
272 }
273 return UDM_OK;
274 }
275
276
277 udm_rc_t
UdmVarSetStrn(UDM_VAR * Var,const char * str,size_t length)278 UdmVarSetStrn(UDM_VAR *Var, const char *str, size_t length)
279 {
280 udm_rc_t rc= Var->Value.handler->SetStrn(UdmVarDataPtr(Var), str, length);
281 switch (rc)
282 {
283 case UDM_ERROR:
284 return rc;
285 case UDM_TERMINATED:
286 UDM_ASSERT(0);
287 case UDM_NOTARGET:
288 case UDM_OK:
289 break;
290 }
291 return UDM_OK;
292 }
293
294
295 udm_rc_t
UdmVarSetConv(UDM_VAR * Var,UDM_CONV * conv,int cnvflags,const char * str,size_t length)296 UdmVarSetConv(UDM_VAR *Var, UDM_CONV *conv, int cnvflags,
297 const char *str, size_t length)
298 {
299 udm_rc_t rc= Var->Value.handler->SetConv(UdmVarDataPtr(Var), conv, cnvflags,
300 str, length);
301 switch (rc)
302 {
303 case UDM_ERROR:
304 return rc;
305 case UDM_TERMINATED:
306 UDM_ASSERT(0);
307 case UDM_NOTARGET:
308 case UDM_OK:
309 break;
310 }
311 return UDM_OK;
312 }
313
314
315 udm_rc_t
UdmVarAppendStrn(UDM_VAR * Var,const char * str,size_t length)316 UdmVarAppendStrn(UDM_VAR *Var, const char *str, size_t length)
317 {
318 switch (Var->Value.handler->AppendStrn(UdmVarDataPtr(Var), str, length))
319 {
320 case UDM_ERROR:
321 return UDM_ERROR;
322 case UDM_TERMINATED:
323 UDM_ASSERT(0);
324 case UDM_NOTARGET:
325 case UDM_OK:
326 break;
327 }
328 return UDM_OK;
329 }
330
331
332 udm_rc_t
UdmVarAppendConv(UDM_VAR * Var,size_t maxlen,UDM_CONV * cnv,int cnvflags,const char * str,size_t length)333 UdmVarAppendConv(UDM_VAR *Var, size_t maxlen,
334 UDM_CONV *cnv, int cnvflags,
335 const char *str, size_t length)
336 {
337 udm_rc_t rc= Var->Value.handler->AppendConv(UdmVarDataPtr(Var), maxlen,
338 cnv, cnvflags,
339 str, length);
340 switch (rc)
341 {
342 case UDM_ERROR:
343 return rc;
344 case UDM_TERMINATED:
345 UDM_ASSERT(0);
346 case UDM_NOTARGET:
347 case UDM_OK:
348 break;
349 }
350 return UDM_OK;
351 }
352
353
354 size_t
UdmVarListUsedMemory(const UDM_VARLIST * Vars)355 UdmVarListUsedMemory(const UDM_VARLIST *Vars)
356 {
357 size_t i, mem= Vars->mvars * sizeof(UDM_VAR*);
358 for (i= 0; i < Vars->nvars; i++)
359 {
360 const UDM_VAR *Var= UdmVarListFindConstByIndex(Vars, i);
361 mem+= Var->Value.handler->MemUsed(UdmVarConstDataPtr(Var));
362 }
363 return mem;
364 }
365
366
367 /************************************************************/
368
369 static udm_rc_t
UdmVarCopyName(UDM_VAR * D,const char * prefix,const char * name)370 UdmVarCopyName(UDM_VAR *D, const char *prefix, const char *name)
371 {
372 if (prefix)
373 {
374 size_t len= strlen(prefix) + strlen(name) + 3;
375 if (!(D->header.name= (char*) UdmMalloc(len)))
376 return UDM_ERROR;
377 udm_snprintf(D->header.name, len, "%s.%s", prefix, name);
378 }
379 else
380 {
381 if (!(D->header.name= (char*) UdmStrdup(name)))
382 return UDM_ERROR;
383 }
384 return UDM_OK;
385 }
386
387
388 static udm_rc_t
UdmVarCopyWithoutName(UDM_VAR * D,const UDM_VAR * S)389 UdmVarCopyWithoutName(UDM_VAR *D, const UDM_VAR *S)
390 {
391 const UDM_VALUE_HANDLER *handler= S->Value.handler;
392 D->Value.handler= S->Value.handler;
393 handler->Copy(UdmVarDataPtr(D), UdmVarConstDataPtr(S));
394 return UDM_OK;
395 }
396
397
398 static udm_rc_t
UdmVarCopyNameAndValue(UDM_VAR * D,const char * prefix,const UDM_VAR * S)399 UdmVarCopyNameAndValue(UDM_VAR *D, const char *prefix, const UDM_VAR *S)
400 {
401 UDM_ASSERT(prefix || S->header.name);
402 #ifdef DEBUG_VARS
403 fprintf(stderr, "Copy: '%s:%s'\n", prefix, S->name);
404 #endif
405 UdmVarCopyName(D, prefix, S->header.name);
406 return UdmVarCopyWithoutName(D, S);
407 }
408
409
410 /**
411 Find a sorted position of a new variable "Var" in the list "Vars".
412 @param suffix - ignore the trailing "suffix" elements.
413 */
414 static size_t
UdmVarListFindSortedPosition(UDM_VARLIST * Vars,UDM_VAR ** Var,size_t suffix)415 UdmVarListFindSortedPosition(UDM_VARLIST *Vars, UDM_VAR **Var, size_t suffix)
416 {
417 UDM_VAR **Left= &Vars->Var[0];
418 UDM_VAR **Right= &Vars->Var[Vars->nvars - suffix]; /* The next after the last */
419 for ( ; Left < Right ; )
420 {
421 UDM_VAR **Middle= Left + (Right - Left)/2;
422 if (varcmp2(Vars, Middle, Var) <= 0) /* We are looking for the last, see above */
423 Left= Middle + 1;
424 else
425 Right= Middle;
426 }
427 return Right - Vars->Var;
428 }
429
430
431 /*
432 This function is called after UdmVarListAppendNull().
433 Move the last added variable to its sorted place.
434
435 If there are variables with the same name, the
436 new variable is inserted after them.
437 */
438 static void
UdmVarListMoveLast(UDM_VARLIST * Vars)439 UdmVarListMoveLast(UDM_VARLIST *Vars)
440 {
441 size_t movevars, pos;
442 UDM_VAR **Last= &Vars->Var[Vars->nvars-1];
443
444 if (Vars->nvars < 2)
445 return;
446
447 pos= UdmVarListFindSortedPosition(Vars, Last, 1 /*ignore last*/);
448
449 if ((movevars= Vars->nvars - pos - 1))
450 {
451 UDM_VAR *Tmp= *Last;
452 UDM_VAR **Pos= &Vars->Var[pos];
453 memmove(Pos + 1, Pos, movevars * sizeof(Vars->Var[0]));
454 *Pos= Tmp;
455 }
456 }
457
458
459 static void
UdmVarListSort(UDM_VARLIST * Vars)460 UdmVarListSort(UDM_VARLIST *Vars)
461 {
462 #ifdef DEBUG_VARS
463 fprintf(stderr, "VarListSort: %d\n", Vars->nvars);
464 #endif
465
466 if (Vars->nvars < 2)
467 return;
468
469 UdmSort(Vars->Var, Vars->nvars, sizeof(Vars->Var[0]),
470 UdmVarListCmpFunc(Vars));
471 }
472
473
474 static udm_rc_t
UdmVarListReserve(UDM_VARLIST * Lst,size_t add)475 UdmVarListReserve(UDM_VARLIST *Lst, size_t add)
476 {
477 if (Lst->nvars + add >= Lst->mvars)
478 {
479 Lst->mvars+= add + 256;
480 Lst->Var= (UDM_VAR**) UdmRealloc(Lst->Var, Lst->mvars * sizeof(Lst->Var[0]));
481 if (!Lst->Var)
482 return UDM_ERROR;
483 }
484 return UDM_OK;
485 }
486
487
488 static void
UdmVarListDelAtOffset(UDM_VARLIST * Vars,size_t offset)489 UdmVarListDelAtOffset(UDM_VARLIST *Vars, size_t offset)
490 {
491 size_t nvars= Vars->nvars - offset - 1; /* Number of vars after "offset" */
492 UDM_VAR **Var= &Vars->Var[offset];
493 UDM_ASSERT(offset < Vars->nvars);
494 UdmVarDelete(Var[0]);
495 if (nvars > 0)
496 memmove(Var, Var + 1, nvars * sizeof(Var[0]));
497 Vars->nvars--;
498 }
499
500
501 static void
UdmVarListDelAtPosition(UDM_VARLIST * Vars,const UDM_VAR * const * Var)502 UdmVarListDelAtPosition(UDM_VARLIST *Vars, const UDM_VAR * const *Var)
503 {
504 size_t offset= Var - ((const UDM_VAR * const *) (Vars->Var));
505 UdmVarListDelAtOffset(Vars, offset);
506 }
507
508
509 static udm_rc_t
UdmVarCreateGeneric(UDM_VAR ** dst,size_t size,const char * prefix,const char * name)510 UdmVarCreateGeneric(UDM_VAR **dst,
511 size_t size, const char *prefix, const char *name)
512 {
513 if (!(dst[0]= (UDM_VAR*) UdmMalloc(size)))
514 return UDM_ERROR;
515 if (UDM_OK != UdmVarCopyName(dst[0], prefix, name))
516 {
517 UdmFree(dst[0]);
518 return UDM_ERROR;
519 }
520 return UDM_OK;
521 }
522
523
524 static udm_rc_t
UdmVarCreateWithPrefix(const UDM_VALUE_HANDLER * ha,UDM_VAR ** Var,const char * prefix,const char * name,const UDM_VALUE ** args,size_t nargs)525 UdmVarCreateWithPrefix(const UDM_VALUE_HANDLER *ha, UDM_VAR **Var,
526 const char *prefix, const char *name,
527 const UDM_VALUE **args, size_t nargs)
528 {
529 udm_rc_t rc;
530 if (UDM_OK != (rc= UdmVarCreateGeneric(Var, ha->VarSize(), prefix, name)))
531 return rc;
532 Var[0]->Value.handler= ha;
533 if (UDM_OK != (rc= ha->Constructor(UdmVarDataPtr(Var[0]), args, nargs)))
534 {
535 UdmVarFreeGeneric(Var[0]);
536 return rc;
537 }
538 return UDM_OK;
539 }
540
541
542 udm_rc_t
UdmVarCreate(const UDM_VALUE_HANDLER * ha,UDM_VAR ** Var,const char * name,const UDM_VALUE ** args,size_t nargs)543 UdmVarCreate(const UDM_VALUE_HANDLER *ha, UDM_VAR **Var,
544 const char *name,
545 const UDM_VALUE **args, size_t nargs)
546 {
547 return UdmVarCreateWithPrefix(ha, Var, NULL, name, args, nargs);
548 }
549
550
551 static UDM_VAR *
UdmVarNew(const UDM_VALUE_HANDLER * handler,const char * prefix,const char * name)552 UdmVarNew(const UDM_VALUE_HANDLER *handler,
553 const char *prefix, const char *name)
554 {
555 UDM_VAR *Var;
556 if (UDM_OK != UdmVarCreateWithPrefix(handler, &Var, prefix, name, NULL, 0))
557 return NULL;
558 return Var;
559 }
560
561
562 static UDM_VAR *
UdmVarListAppendNull(UDM_VARLIST * Lst,const UDM_VALUE_HANDLER * handler,const char * prefix,const char * name)563 UdmVarListAppendNull(UDM_VARLIST *Lst, const UDM_VALUE_HANDLER *handler,
564 const char *prefix, const char *name)
565 {
566 UDM_VAR *New;
567 if (UDM_OK != UdmVarListReserve(Lst, 1) ||
568 !(New= UdmVarNew(handler, prefix, name)))
569 return NULL;
570 Lst->Var[Lst->nvars++]= New;
571 return New;
572 }
573
574
575 static udm_rc_t
UdmVarListAddNamedNoSort(UDM_VARLIST * Lst,const char * prefix,const UDM_VAR * S)576 UdmVarListAddNamedNoSort(UDM_VARLIST *Lst, const char *prefix, const UDM_VAR *S)
577 {
578 UDM_VAR *v;
579 if (!(v= UdmVarListAppendNull(Lst, S->Value.handler, prefix, S->header.name)))
580 return UDM_ERROR;
581 UdmVarCopyWithoutName(v, S);
582 return UDM_OK;
583 }
584
585
586 /********************************************************/
587
588 static udm_rc_t
UdmVarListAddVar(UDM_VARLIST * Vars,UDM_VAR * Var)589 UdmVarListAddVar(UDM_VARLIST *Vars, UDM_VAR *Var)
590 {
591 udm_rc_t rc;
592 if (UDM_OK != (rc= UdmVarListReserve(Vars, 1)))
593 return rc;
594 Vars->Var[Vars->nvars++]= Var;
595 UdmVarListMoveLast(Vars);
596 return UDM_OK;
597 }
598
599
600 udm_rc_t
UdmVarListReplaceVar(UDM_VARLIST * Vars,UDM_VAR * Var)601 UdmVarListReplaceVar(UDM_VARLIST *Vars, UDM_VAR *Var)
602 {
603 udm_rc_t rc;
604 UdmVarListDel(Vars, Var->header.name);
605 if (UDM_OK != (rc= UdmVarListReserve(Vars, 1)))
606 return rc;
607 Vars->Var[Vars->nvars++]= Var;
608 UdmVarListMoveLast(Vars);
609 return UDM_OK;
610 }
611
612
UdmVarFreeGeneric(UDM_VAR * S)613 void UdmVarFreeGeneric(UDM_VAR *S)
614 {
615 UDM_FREE(S->header.name);
616 }
617
618
UdmVarFree(UDM_VAR * S)619 void UdmVarFree(UDM_VAR *S)
620 {
621 S->Value.handler->Destructor(UdmVarDataPtr(S));
622 UDM_FREE(S->header.name);
623 }
624
625
UdmVarDelete(UDM_VAR * S)626 void UdmVarDelete(UDM_VAR *S)
627 {
628 UdmVarFree(S);
629 UdmFree(S);
630 }
631
632
633 #ifdef HAVE_GCC_PRAGMA_PUSH
634 #pragma GCC diagnostic push
635 #pragma GCC diagnostic ignored "-Wcast-qual"
636 #endif /* __GNUC__ */
637
638
UdmVarListFindByIndex(const UDM_VARLIST * Vars,size_t i)639 UDM_VAR *UdmVarListFindByIndex(const UDM_VARLIST *Vars, size_t i)
640 {
641 UDM_ASSERT(i < Vars->nvars);
642 return &Vars->Var[i][0];
643 }
644
645
UdmVarListFindConstByIndex(const UDM_VARLIST * Vars,size_t i)646 const UDM_VAR *UdmVarListFindConstByIndex(const UDM_VARLIST *Vars, size_t i)
647 {
648 UDM_ASSERT(i < Vars->nvars);
649 return &Vars->Var[i][0];
650 }
651
652
653 static UDM_VAR **
UdmVarListFindPtr(const UDM_VARLIST * vars,const char * name)654 UdmVarListFindPtr(const UDM_VARLIST *vars,const char * name)
655 {
656 UDM_VAR key, *key2= &key;
657 UDM_VAR **res;
658 #ifdef DEBUG_VARS
659 fprintf(stderr, "Find: '%s'\n", name);
660 #endif
661 if (!vars->nvars) return NULL;
662
663 key.header.name= (char*)name;
664 res= (UDM_VAR**) UdmBSearch(&key2, vars->Var, vars->nvars,
665 sizeof(vars->Var[0]),
666 UdmVarListCmpFunc(vars));
667 return res;
668 }
669
670
671 UDM_VAR *
UdmVarListFindVar(const UDM_VARLIST * vars,const char * name)672 UdmVarListFindVar(const UDM_VARLIST *vars,const char * name)
673 {
674 UDM_VAR **ptr= UdmVarListFindPtr(vars, name);
675 return ptr ? ptr[0] : NULL;
676 }
677
678
679 #ifdef HAVE_GCC_PRAGMA_PUSH
680 #pragma GCC diagnostic pop
681 #endif /* __GNUC__ */
682
683
684 const UDM_VAR *
UdmVarListFind(const UDM_VARLIST * vars,const char * name)685 UdmVarListFind(const UDM_VARLIST *vars, const char *name)
686 {
687 return UdmVarListFindVar(vars, name);
688 }
689
690
691 const UDM_VALUE *
UdmVarListFindConstValue(const UDM_VARLIST * Vars,const char * name)692 UdmVarListFindConstValue(const UDM_VARLIST *Vars, const char *name)
693 {
694 const UDM_VAR *Var= UdmVarListFindVar(Vars, name);
695 return Var ? &Var->Value : NULL;
696 }
697
698
699 UDM_VALUE *
UdmVarListFindValue(const UDM_VARLIST * Vars,const char * name)700 UdmVarListFindValue(const UDM_VARLIST *Vars, const char *name)
701 {
702 UDM_VAR *Var= UdmVarListFindVar(Vars, name);
703 return Var ? &Var->Value : NULL;
704 }
705
706
707 UDM_VAR *
UdmVarListFindOrCreateStr(UDM_VARLIST * Vars,const char * name)708 UdmVarListFindOrCreateStr(UDM_VARLIST *Vars, const char *name)
709 {
710 UDM_VAR *v= UdmVarListFindVar(Vars, name);
711 if (v)
712 return v;
713 UdmVarListAddStr(Vars, name, "");
714 return UdmVarListFindVar(Vars, name);
715 }
716
717
718 const UDM_VAR *
UdmVarListFindBySecno(const UDM_VARLIST * vars,int secno)719 UdmVarListFindBySecno(const UDM_VARLIST *vars, int secno)
720 {
721 size_t i;
722 for (i= 0; i < vars->nvars; i++)
723 {
724 UDM_VAR *v= UdmVarListFindByIndex(vars, i);
725 if (UdmVarSecno(v) == secno)
726 return v;
727 }
728 return NULL;
729 }
730
731
732 udm_rc_t
UdmVarListDelBySection(UDM_VARLIST * Vars,int sec)733 UdmVarListDelBySection(UDM_VARLIST *Vars, int sec)
734 {
735 size_t i;
736 for (i= 0; i < Vars->nvars; )
737 {
738 const UDM_VAR *Var= UdmVarListFindConstByIndex(Vars, i);
739 if (UdmVarSecno(Var) == sec)
740 UdmVarListDelAtOffset(Vars, i);
741 else
742 i++;
743 }
744 return UDM_OK;
745 }
746
747
748 udm_rc_t
UdmVarListDelByName(UDM_VARLIST * Vars,const char * name)749 UdmVarListDelByName(UDM_VARLIST *Vars, const char *name)
750 {
751 size_t i;
752 for (i= 0; i < Vars->nvars; )
753 {
754 const UDM_VAR *Var= UdmVarListFindConstByIndex(Vars, i);
755 if (!UdmWildCaseCmp(Var->header.name, name))
756 UdmVarListDelAtOffset(Vars, i);
757 else
758 i++;
759 }
760 return UDM_OK;
761 }
762
763
764 udm_rc_t
UdmVarListDel(UDM_VARLIST * Vars,const char * name)765 UdmVarListDel(UDM_VARLIST *Vars, const char *name)
766 {
767 UDM_VAR **v= UdmVarListFindPtr(Vars, name);
768 if (v)
769 {
770 size_t offset= v - Vars->Var;
771 UdmVarListDelAtOffset(Vars, offset);
772 }
773 return UDM_OK;
774 }
775
776
777 static udm_rc_t
UdmVarListReplaceNamed(UDM_VARLIST * Lst,const char * prefix,UDM_VAR * S)778 UdmVarListReplaceNamed(UDM_VARLIST *Lst, const char *prefix, UDM_VAR *S)
779 {
780 udm_rc_t rc;
781 UDM_VAR *v;
782 char fullname[64];
783 if (prefix)
784 udm_snprintf(fullname, sizeof(fullname), "%s.%s", prefix, S->header.name);
785 else
786 udm_snprintf(fullname, sizeof(fullname), "%s", S->header.name);
787
788 if ((v= UdmVarListFindVar(Lst, fullname)))
789 {
790 const UDM_VALUE_HANDLER *ha= v->Value.handler;
791 UDM_ASSERT(ha == &UdmValueHandlerSimple);
792 UDM_ASSERT(S->Value.handler == &UdmValueHandlerSimple);
793 UdmVarFree(v);
794 if (UDM_OK != (rc= ha->Constructor(UdmVarDataPtr(v), NULL, 0)))
795 return rc;
796 rc=UdmVarCopyNameAndValue(v, prefix, S); /* Note, add with a different name */
797 }
798 else
799 {
800 if (UDM_OK == (rc= UdmVarListAddNamedNoSort(Lst, prefix, S)))
801 UdmVarListMoveLast(Lst);
802 }
803 return rc;
804 }
805
806
807 UDM_API(const char *)
UdmVarListFindStr(const UDM_VARLIST * vars,const char * name,const char * defval)808 UdmVarListFindStr(const UDM_VARLIST *vars, const char *name, const char *defval)
809 {
810 const UDM_VAR * var;
811 if ((var= UdmVarListFind(vars,name)) != NULL)
812 {
813 UDM_CONST_STR buf, *value= UdmVarGetConstStr(var, &buf);
814 return value->str != NULL ? value->str : defval;
815 }
816 else
817 return defval;
818 }
819
820
821 const char *
UdmVarListFindStrNonEmpty(const UDM_VARLIST * vars,const char * name,const char * defval)822 UdmVarListFindStrNonEmpty(const UDM_VARLIST *vars, const char *name, const char *defval)
823 {
824 const UDM_VAR * var;
825 if ((var= UdmVarListFind(vars,name)) != NULL)
826 {
827 UDM_CONST_STR buf, *value= UdmVarGetConstStr(var, &buf);
828 return value->str != NULL && value->length != 0 ? value->str : defval;
829 }
830 else
831 return defval;
832 }
833
834
835 udm_bool_t
UdmVarListFindConstStr(UDM_CONST_STR * buf,const UDM_VARLIST * vars,const char * name,const UDM_CONST_STR * defval)836 UdmVarListFindConstStr(UDM_CONST_STR *buf,
837 const UDM_VARLIST *vars,
838 const char *name,
839 const UDM_CONST_STR *defval)
840 {
841 const UDM_VAR *var= UdmVarListFind(vars, name);
842 UDM_CONST_STR *tmp;
843 if (!var || !(tmp= UdmVarGetConstStr(var, buf))->str)
844 {
845 *buf= *defval;
846 return UDM_TRUE;
847 }
848 if (tmp != buf)
849 *buf= *tmp;
850 return UDM_FALSE;
851 }
852
853
UdmVarListInit(UDM_VARLIST * l)854 void UdmVarListInit(UDM_VARLIST *l)
855 {
856 bzero((void*)l,sizeof(*l));
857 }
858
859
UdmVarListFree(UDM_VARLIST * vars)860 void UdmVarListFree(UDM_VARLIST * vars)
861 {
862 size_t i;
863 for(i=0;i<vars->nvars;i++)
864 UdmVarDelete(vars->Var[i]);
865 UDM_FREE(vars->Var);
866 vars->nvars= 0;
867 vars->mvars= 0;
868 }
869
870
871 static udm_rc_t
UdmVarListAddStrnWithParamInternal(UDM_VARLIST * Vars,const UDM_SECTION_PARAM * Param,const char * name,const char * str,size_t length,udm_bool_t sort_flag)872 UdmVarListAddStrnWithParamInternal(UDM_VARLIST *Vars,
873 const UDM_SECTION_PARAM *Param,
874 const char *name,
875 const char *str, size_t length,
876 udm_bool_t sort_flag)
877 {
878 UDM_SECTION *Sec;
879 UDM_VAR *Var;
880 UDM_VALUE_HANDLER *ha= &UdmValueHandlerSimple;
881 if (!(Var= UdmVarNew(ha, NULL, name)))
882 return UDM_ERROR;
883 Sec= (UDM_SECTION *) UdmVarDataPtr(Var);
884 Sec->Param= *Param;
885 UdmVarSetStrn(Var, str, length);
886 if (UDM_OK != UdmVarListAddVar(Vars, Var))
887 {
888 UdmFree(Var);
889 return UDM_ERROR;
890 }
891 if (sort_flag)
892 UdmVarListSort(Vars);
893 return UDM_OK;
894 }
895
896
897 udm_rc_t
UdmVarListAddStrn(UDM_VARLIST * vars,const char * name,const char * val,size_t vallen)898 UdmVarListAddStrn(UDM_VARLIST *vars, const char *name,
899 const char *val, size_t vallen)
900 {
901 UDM_SECTION_PARAM Param;
902 UdmSectionParamInit(&Param, 0);
903 return UdmVarListAddStrnWithParamInternal(vars, &Param, name,
904 val, vallen, UDM_TRUE);
905 }
906
907
908 udm_rc_t
UdmVarListAddStrnWithParam(UDM_VARLIST * vars,const UDM_SECTION_PARAM * Param,const char * name,const char * val,size_t vallen)909 UdmVarListAddStrnWithParam(UDM_VARLIST *vars,
910 const UDM_SECTION_PARAM *Param,
911 const char *name,
912 const char *val, size_t vallen)
913 {
914 return UdmVarListAddStrnWithParamInternal(vars, Param, name,
915 val, vallen, UDM_TRUE);
916 }
917
918
919 udm_rc_t
UdmVarListAddStr(UDM_VARLIST * vars,const char * name,const char * val)920 UdmVarListAddStr(UDM_VARLIST *vars, const char *name, const char *val)
921 {
922 return UdmVarListAddStrn(vars, name, val, val ? strlen(val) : 0);
923 }
924
925
926 udm_rc_t
UdmVarListAddQueryStr(UDM_VARLIST * vars,const char * name,const char * val,size_t vallen)927 UdmVarListAddQueryStr(UDM_VARLIST *vars, const char *name,
928 const char *val, size_t vallen)
929 {
930 UDM_SECTION_PARAM Param;
931 UdmSectionParamInit(&Param, UDM_VARSRC_QSTRING);
932 return UdmVarListAddStrnWithParamInternal(vars, &Param, name,
933 val, vallen, UDM_TRUE);
934 }
935
936
937 udm_rc_t
UdmVarListAddInt(UDM_VARLIST * vars,const char * name,int val)938 UdmVarListAddInt(UDM_VARLIST * vars,const char * name, int val)
939 {
940 char num[64];
941 udm_snprintf(num, 64, "%d", val);
942 return UdmVarListAddStr(vars,name,num);
943 }
944
945
946 udm_rc_t
UdmVarListAddUnsigned(UDM_VARLIST * vars,const char * name,uint4 val)947 UdmVarListAddUnsigned(UDM_VARLIST * vars,const char * name, uint4 val)
948 {
949 char num[64];
950 udm_snprintf(num, 64, "%u", val);
951 return UdmVarListAddStr(vars, name, num);
952 }
953
954
955 udm_rc_t
UdmVarListAddULongLong(UDM_VARLIST * vars,const char * name,unsigned long long val)956 UdmVarListAddULongLong(UDM_VARLIST *vars,
957 const char * name, unsigned long long val)
958 {
959 char num[64];
960 udm_snprintf(num, 64, "%llu", val);
961 return UdmVarListAddStr(vars,name,num);
962 }
963
964
965 udm_rc_t
UdmVarListAddDouble(UDM_VARLIST * vars,const char * name,double val)966 UdmVarListAddDouble(UDM_VARLIST * vars,const char * name, double val)
967 {
968 char num[128];
969 udm_snprintf(num, 128, "%f", val);
970 return UdmVarListAddStr(vars, name, num);
971 }
972
973
974 udm_rc_t
UdmVarListInsStr(UDM_VARLIST * vars,const char * name,const char * val)975 UdmVarListInsStr(UDM_VARLIST * vars,const char * name,const char * val)
976 {
977 return UdmVarListFind(vars,name) ? UDM_OK : UdmVarListAddStr(vars,name,val);
978 }
979
980
981 udm_rc_t
UdmVarListInsInt(UDM_VARLIST * vars,const char * name,int val)982 UdmVarListInsInt(UDM_VARLIST * vars,const char * name,int val)
983 {
984 return UdmVarListFind(vars,name) ? UDM_OK : UdmVarListAddInt(vars,name,val);
985 }
986
987
988 udm_rc_t
UdmVarListReplaceStrn(UDM_VARLIST * vars,const char * name,const char * val,size_t len)989 UdmVarListReplaceStrn(UDM_VARLIST *vars,
990 const char *name,
991 const char *val, size_t len)
992 {
993 udm_rc_t rc;
994 char *v= udm_strndup(val, len);
995 rc= UdmVarListReplaceStr(vars, name, v);
996 UdmFree(v);
997 return rc;
998 }
999
1000
1001 udm_rc_t
UdmVarListReplaceOrAppendStrn(UDM_VARLIST * Vars,const char * name,const char * val,size_t len,int hl)1002 UdmVarListReplaceOrAppendStrn(UDM_VARLIST *Vars, const char *name,
1003 const char *val, size_t len, int hl)
1004 {
1005 UDM_VAR *Var= UdmVarListFindVar(Vars, name);
1006
1007 if (!Var)
1008 {
1009 UdmVarListReplaceStr(Vars, name, "");
1010 Var= UdmVarListFindVar(Vars, name);
1011 if (!Var)
1012 return UDM_ERROR;
1013 }
1014
1015 /* Append new piece */
1016 if (hl && UdmVarValueHandlerType(Var) == UDM_VALUE_HANDLER_TYPE_STR)
1017 {
1018 UDM_SECTION *Sec= (UDM_SECTION *) UdmVarDataPtr(Var);
1019 Sec->Param.flags= (udm_var_flag_t) (Sec->Param.flags | UDM_VARFLAG_HL);
1020 UdmVarAppendStrn(Var, "\2", 1);
1021 }
1022 UdmVarAppendStrn(Var, val, len);
1023 if (hl)
1024 UdmVarAppendStrn(Var, "\3", 1);
1025 return UDM_OK;
1026 }
1027
1028
1029 /**
1030 Replace a variable with the given name to a new string and parameter.
1031 If the variable exists and it is not SimpleVar, then it is deleted.
1032 */
1033 udm_rc_t
UdmVarListReplaceStrnWithParam(UDM_VARLIST * Vars,const UDM_SECTION_PARAM * Param,const char * name,const char * val,size_t length)1034 UdmVarListReplaceStrnWithParam(UDM_VARLIST *Vars,
1035 const UDM_SECTION_PARAM *Param,
1036 const char *name,
1037 const char *val, size_t length)
1038 {
1039 UDM_VAR **ptr;
1040
1041 if ((ptr= UdmVarListFindPtr(Vars, name)) != NULL)
1042 {
1043 UDM_VAR *Var= ptr[0];
1044 if (UdmVarValueHandlerType(Var) == UDM_VALUE_HANDLER_TYPE_STR)
1045 {
1046 UDM_SECTION *Sec= (UDM_SECTION *) UdmVarDataPtr(Var);
1047 Sec->Param= *Param;
1048 return Var->Value.handler->SetStrn(UdmVarDataPtr(Var), val, length);
1049 }
1050 UdmVarListDelAtPosition(Vars, (const UDM_VAR * const *) ptr);
1051 }
1052 return UdmVarListAddStrnWithParamInternal(Vars, Param, name,
1053 val, length, UDM_TRUE);
1054 }
1055
1056
1057 /**
1058 Replace a variable with the given name to a new string value.
1059 If the variable exists and it is not SimpleVar, then it is deleted.
1060 If the variable exists and it is SimpleVar, then the other members
1061 (e.g. Param) remain unchanged.
1062 */
1063 UDM_API(udm_rc_t)
UdmVarListReplaceStr(UDM_VARLIST * vars,const char * name,const char * val)1064 UdmVarListReplaceStr(UDM_VARLIST *vars, const char *name, const char *val)
1065 {
1066 UDM_VAR **ptr;
1067
1068 if ((ptr= UdmVarListFindPtr(vars, name)) != NULL)
1069 {
1070 UDM_VAR *var= ptr[0];
1071 if (var->Value.handler == &UdmValueHandlerSimple)
1072 return var->Value.handler->SetStrn(UdmVarDataPtr(var),
1073 val, val ? strlen(val) : 0);
1074 UdmVarListDelAtPosition(vars, (const UDM_VAR * const *) ptr);
1075 }
1076 return UdmVarListAddStr(vars, name, val);
1077 }
1078
1079
1080 UDM_API(udm_rc_t)
UdmVarListReplaceInt(UDM_VARLIST * vars,const char * name,int val)1081 UdmVarListReplaceInt(UDM_VARLIST * vars, const char * name,int val)
1082 {
1083 if (UdmVarListFind(vars,name) != NULL)
1084 {
1085 char num[64];
1086 udm_snprintf(num, 64, "%d", val);
1087 return UdmVarListReplaceStr(vars, name, num);
1088 }
1089 return UdmVarListAddInt(vars,name,val);
1090 }
1091
1092
1093 udm_rc_t
UdmVarListReplaceUnsigned(UDM_VARLIST * vars,const char * name,uint4 val)1094 UdmVarListReplaceUnsigned(UDM_VARLIST * vars, const char * name, uint4 val)
1095 {
1096 if (UdmVarListFind(vars, name) != NULL)
1097 {
1098 char num[64];
1099 udm_snprintf(num, 64, "%u", val);
1100 return UdmVarListReplaceStr(vars, name, num);
1101 }
1102 return UdmVarListAddUnsigned(vars, name, val);
1103 }
1104
1105
1106 udm_rc_t
UdmVarListReplaceULongLong(UDM_VARLIST * vars,const char * name,unsigned long long val)1107 UdmVarListReplaceULongLong(UDM_VARLIST *vars,
1108 const char *name, unsigned long long val)
1109 {
1110 if (UdmVarListFind(vars, name) != NULL)
1111 {
1112 char num[64];
1113 udm_snprintf(num, 64, "%llu", val);
1114 return UdmVarListReplaceStr(vars, name, num);
1115 }
1116 return UdmVarListAddUnsigned(vars, name, val);
1117 }
1118
1119
1120 udm_rc_t
UdmVarListReplaceDouble(UDM_VARLIST * vars,const char * name,double val)1121 UdmVarListReplaceDouble(UDM_VARLIST * vars, const char * name, double val)
1122 {
1123 if (UdmVarListFind(vars, name) != NULL)
1124 {
1125 char num[128];
1126 udm_snprintf(num, 128, "%f", val);
1127 return UdmVarListReplaceStr(vars, name, num);
1128 }
1129 return UdmVarListAddDouble(vars, name, val);
1130 }
1131
1132
1133 const UDM_VAR *
UdmVarListFindWithValue(const UDM_VARLIST * vars,const char * name,const char * val,size_t vallen)1134 UdmVarListFindWithValue(const UDM_VARLIST * vars,
1135 const char *name, const char *val, size_t vallen)
1136 {
1137 size_t i;
1138 UDM_ASSERT((vars->flags & UDM_VARLIST_FLAG_CS) == 0);
1139 for (i= 0; i < vars->nvars; i++)
1140 {
1141 const UDM_VAR *Var= UdmVarListFindConstByIndex(vars, i);
1142 if (!strcasecmp(name, Var->header.name))
1143 {
1144 UDM_CONST_STR strbuf, *str= UdmVarGetConstStr(Var, &strbuf);
1145 if (str->length == vallen && !strncasecmp(val, str->str, vallen))
1146 return Var;
1147 }
1148 }
1149 return NULL;
1150 }
1151
1152
1153 udm_rc_t
UdmVarListReplaceLst(UDM_VARLIST * D,const UDM_VARLIST * S,const char * prefix,const char * mask)1154 UdmVarListReplaceLst(UDM_VARLIST *D, const UDM_VARLIST *S,
1155 const char *prefix, const char *mask)
1156 {
1157 size_t i;
1158
1159 UDM_ASSERT(D != S);
1160 for (i= 0; i < S->nvars; i++)
1161 {
1162 UDM_VAR *v= UdmVarListFindByIndex(S, i);
1163 /* TODO34: UDM_VALUE_HANDLER::CloneVar */
1164 if (v->Value.handler == &UdmValueHandlerSimple &&
1165 !UdmWildCaseCmp(v->header.name, mask))
1166 UdmVarListReplaceNamed(D, prefix, v);
1167 }
1168 return UDM_OK;
1169 }
1170
1171
1172 udm_rc_t
UdmVarListAddLst(UDM_VARLIST * D,const UDM_VARLIST * S,const char * prefix,const char * mask)1173 UdmVarListAddLst(UDM_VARLIST *D, const UDM_VARLIST *S,
1174 const char *prefix, const char *mask)
1175 {
1176 size_t i;
1177 for (i= 0; i < S->nvars; i++)
1178 {
1179 UDM_VAR *v= UdmVarListFindByIndex(S, i);
1180 /* TODO34: UDM_VALUE_HANDLER::CloneVar */
1181 if (v->Value.handler == &UdmValueHandlerSimple &&
1182 !UdmWildCaseCmp(v->header.name, mask))
1183 {
1184 if (UDM_OK != UdmVarListAddNamedNoSort(D, prefix, v))
1185 return UDM_ERROR;
1186 }
1187 }
1188 UdmVarListSort(D);
1189 return UDM_OK;
1190 }
1191
1192
1193 static udm_rc_t
UdmVarListMergeAdd(UDM_VARLIST * Lst,UDM_VAR * Src)1194 UdmVarListMergeAdd(UDM_VARLIST *Lst, UDM_VAR *Src)
1195 {
1196 UDM_VAR *Var;
1197 const UDM_VALUE_HANDLER *ha;
1198 UDM_ASSERT(Lst->nvars < Lst->mvars);
1199 /* TODO34: UDM_VALUE_HANDLER::CloneVar */
1200 if ((ha= Src->Value.handler) != &UdmValueHandlerSimple)
1201 return UDM_OK;
1202 if (!(Var= (UDM_VAR *) UdmMalloc(Src->Value.handler->VarSize())))
1203 return UDM_ERROR;
1204 Var->Value.handler= ha;
1205 if (UDM_OK != ha->Constructor(UdmVarDataPtr(Var), NULL, 0))
1206 return UDM_ERROR;
1207 if (UDM_OK != UdmVarCopyNameAndValue(Var, NULL, Src))
1208 return UDM_ERROR;
1209 Lst->Var[Lst->nvars]= Var;
1210 Lst->nvars++;
1211 return UDM_OK;
1212 }
1213
1214
1215 /*
1216 Merge two varlists with single sorting
1217 */
1218 udm_rc_t
UdmVarListMerge(UDM_VARLIST * Lst,UDM_VARLIST * Src1,UDM_VARLIST * Src2)1219 UdmVarListMerge(UDM_VARLIST * Lst,UDM_VARLIST *Src1, UDM_VARLIST *Src2)
1220 {
1221 size_t i;
1222 size_t nvars= Src1->nvars + Src2->nvars;
1223 if (UdmVarListReserve(Lst, nvars))
1224 return UDM_ERROR;
1225 for (i= 0; i < Src1->nvars; i++)
1226 {
1227 if (UDM_OK != UdmVarListMergeAdd(Lst, UdmVarListFindByIndex(Src1, i)))
1228 return UDM_ERROR;
1229 }
1230 for (i= 0; i < Src2->nvars; i++)
1231 {
1232 if (UDM_OK != UdmVarListMergeAdd(Lst, UdmVarListFindByIndex(Src2, i)))
1233 return UDM_ERROR;
1234 }
1235 if (Lst->nvars)
1236 UdmVarListSort(Lst);
1237 return UDM_OK;
1238 }
1239
1240
1241 /*
1242 Add environment variables
1243 into a varlist
1244 */
1245 #ifdef HAVE_GCC_PRAGMA_PUSH
1246 #pragma GCC diagnostic push
1247 #pragma GCC diagnostic ignored "-Wredundant-decls"
1248 #endif /* HAVE_GCC_PRAGMA_PUSH */
1249 extern char **environ;
1250 #ifdef HAVE_GCC_PRAGMA_PUSH
1251 #pragma GCC diagnostic pop
1252 #endif /* HAVE_GCC_PRAGMA_PUSH */
1253
1254
1255 udm_rc_t
UdmVarListAddEnviron(UDM_VARLIST * Vars,const char * name)1256 UdmVarListAddEnviron(UDM_VARLIST *Vars, const char *name)
1257 {
1258 UDM_SECTION_PARAM Param;
1259 #ifdef WIN32
1260 /*
1261 GetEnvironmentStrings() returns all environment variables in this format:
1262
1263 Name1=Val1\0
1264 Name2=Val2\0
1265 ...
1266 NameN=ValN\0\0
1267 */
1268 const char *env= GetEnvironmentStrings();
1269 UdmSectionParamInit(&Param, UDM_VARSRC_ENV);
1270 while (env && *env)
1271 {
1272 char buf[1024], *val;
1273 const char *end= env + strlen(env);
1274 udm_snprintf(buf, sizeof(buf), "%s%s%s",
1275 name ? name : "", name ? "." : "", env);
1276 if ((val= strchr(buf, '=')) && val > buf)
1277 {
1278 *val++= '\0';
1279 UdmVarListAddStrnWithParamInternal(Vars, &Param, buf,
1280 val, strlen(val), UDM_FALSE);
1281 }
1282 env= end + 1; /* The next character after '\0' - start of the next name */
1283 }
1284 #else
1285 char **e, *val, *str;
1286 size_t lenstr = 1024;
1287
1288 UdmSectionParamInit(&Param, UDM_VARSRC_ENV);
1289
1290 if ((str = (char*)UdmMalloc(1024)) == NULL)
1291 return UDM_ERROR;
1292
1293 for ( e=environ; e[0] ; e++)
1294 {
1295 size_t len = strlen(e[0]);
1296 if (len > lenstr)
1297 {
1298 if ((str = (char*)UdmRealloc(str, lenstr = len + 64)) == NULL)
1299 return UDM_ERROR;
1300 }
1301 len = udm_snprintf(str, lenstr - 1, "%s%s%s",
1302 name ? name : "", name ? "." : "", e[0]);
1303 str[len]='\0';
1304
1305 if((val=strchr(str,'=')))
1306 {
1307 *val++='\0';
1308 UdmVarListAddStrnWithParamInternal(Vars, &Param, str,
1309 val, strlen(val), UDM_FALSE);
1310 }
1311 }
1312 UDM_FREE(str);
1313 #endif /* WIN32 */
1314 UdmVarListSort(Vars);
1315 return UDM_OK;
1316 }
1317
1318
1319 UDM_CHARSET *
UdmVarListFindCharset(const UDM_VARLIST * Lst,const char * name,UDM_CHARSET * def)1320 UdmVarListFindCharset(const UDM_VARLIST *Lst, const char *name, UDM_CHARSET *def)
1321 {
1322 UDM_CHARSET *res;
1323 if ((name= UdmVarListFindStr(Lst, name, NULL)) && (res= UdmGetCharSet(name)))
1324 return res;
1325 return def;
1326 }
1327
1328
1329 udm_content_type_t
UdmVarListFindContentType(const UDM_VARLIST * Lst,const char * name,udm_content_type_t def)1330 UdmVarListFindContentType(const UDM_VARLIST *Lst, const char *name, udm_content_type_t def)
1331 {
1332 udm_content_type_t res;
1333 if ((name= UdmVarListFindStr(Lst, name, NULL)) && (res= UdmContentTypeByName(name)))
1334 return res;
1335 return def;
1336 }
1337
1338
1339 const UDM_VAR *
UdmVarListFindByPrefix(const UDM_VARLIST * Vars,const char * prefix,size_t prefix_length)1340 UdmVarListFindByPrefix(const UDM_VARLIST *Vars,
1341 const char *prefix, size_t prefix_length)
1342 {
1343 size_t i;
1344 UDM_ASSERT((Vars->flags & UDM_VARLIST_FLAG_CS) == 0);
1345 for (i= 0; i < Vars->nvars; i++)
1346 {
1347 const UDM_VAR *V= UdmVarListFindConstByIndex(Vars, i);
1348 if (!strncasecmp(V->header.name, prefix, prefix_length))
1349 return V;
1350 }
1351 return NULL;
1352 }
1353
1354
1355 /*
1356 Print for --dumpconf.
1357 */
1358 void
UdmVarListPrint(const UDM_VARLIST * L,FILE * f)1359 UdmVarListPrint(const UDM_VARLIST *L, FILE *f)
1360 {
1361 size_t i;
1362 char str[128];
1363 for (i= 0; i < L->nvars; i++)
1364 {
1365 const UDM_VAR *V= UdmVarListFindConstByIndex(L, i);
1366 UDM_CONST_STR valbuf, *val;
1367 if (!strcasecmp(V->header.name, "DBAddr") ||
1368 !strcasecmp(V->header.name, "ConfDir") || /* TODO */
1369 !strcasecmp(V->header.name, "ShareDir") || /* TODO */
1370 !strcasecmp(V->header.name, "TmpDir") || /* TODO */
1371 !strcasecmp(V->header.name, "Request.User-Agent")) /* TODO */
1372 continue;
1373 val= UdmVarGetConstStr(V, &valbuf);
1374 udm_snprintf(str, sizeof(str),
1375 "%s \"%.*s\"", V->header.name, (int) val->length, val->str);
1376 fprintf(f, "%s\n", str);
1377 }
1378 }
1379
1380
1381 static void
UdmDSTRAppendWild(UDM_DSTR * d,const UDM_VARLIST * L,const char * pattern)1382 UdmDSTRAppendWild(UDM_DSTR *d, const UDM_VARLIST *L, const char *pattern)
1383 {
1384 size_t i;
1385 for (i= 0; i < L->nvars; i++)
1386 {
1387 UDM_VAR *V= UdmVarListFindByIndex(L, i);
1388 if (V->header.name && !UdmWildCmp(V->header.name, pattern))
1389 {
1390 UDM_CONST_STR valbuf, *val= UdmVarGetConstStr(V, &valbuf);
1391 if (val->str)
1392 UdmDSTRAppend(d, val->str, val->length);
1393 }
1394 }
1395 }
1396
1397
1398 size_t
UdmDSTRParse(UDM_DSTR * d,const char * fmt,const UDM_VARLIST * L)1399 UdmDSTRParse(UDM_DSTR *d, const char *fmt, const UDM_VARLIST *L)
1400 {
1401 UdmDSTRReset(d);
1402 for ( ; fmt[0]; fmt++)
1403 {
1404 const char *end;
1405 if (fmt[0] == '$' && fmt[1] == '{' && (end= strchr(fmt,'}')))
1406 {
1407 char name[128];
1408 size_t namelen;
1409 fmt+=2;
1410 namelen= end - fmt;
1411 if (namelen < sizeof(name) - 1)
1412 {
1413 const char *val;
1414 memcpy(name, fmt, namelen);
1415 name[namelen]= '\0';
1416 if (strchr(name, '*'))
1417 {
1418 /* Append all variables whose name prefix matchs */
1419 UdmDSTRAppendWild(d, L, name);
1420 }
1421 else if ((val= UdmVarListFindStr(L, name, NULL)))
1422 UdmDSTRAppendSTR(d, val);
1423 }
1424 fmt= end;
1425 }
1426 else
1427 UdmDSTRAppend(d, fmt, 1);
1428 }
1429 return UdmDSTRLength(d);
1430 }
1431
1432
1433 udm_rc_t
UdmSectionListPrint(const UDM_VARLIST * L,FILE * f)1434 UdmSectionListPrint(const UDM_VARLIST *L, FILE *f)
1435 {
1436 size_t i;
1437 for (i= 0; i < L->nvars; i++)
1438 {
1439 const UDM_VAR *V= UdmVarListFindConstByIndex(L, i);
1440 V->Value.handler->Dump(UdmVarConstDataPtr(V), V->header.name, f);
1441 }
1442 return UDM_OK;
1443 }
1444
1445
1446 UDM_SECTION *
UdmVarToSection(UDM_VAR * Var)1447 UdmVarToSection(UDM_VAR *Var)
1448 {
1449 UDM_SECTION *Sec;
1450 if (UdmVarValueHandlerType(Var) != UDM_VALUE_HANDLER_TYPE_STR)
1451 return NULL;
1452 Sec= (UDM_SECTION *) UdmVarDataPtr(Var);
1453 return Sec;
1454 }
1455
1456
1457 /**** VarListList *********/
UdmVarListListInit(UDM_VARLISTLIST * List)1458 void UdmVarListListInit(UDM_VARLISTLIST *List)
1459 {
1460 UDM_BZERO(List, sizeof(*List));
1461 }
1462
1463
UdmVarListListFree(UDM_VARLISTLIST * List)1464 void UdmVarListListFree(UDM_VARLISTLIST *List)
1465 {
1466 size_t i;
1467 for (i= 0; i < List->nitems; i++)
1468 UdmVarListFree(&List->Item[i]);
1469 UdmFree(List->Item);
1470 }
1471
1472
1473 udm_rc_t
UdmVarListListAddWithFlags(UDM_VARLISTLIST * List,udm_varlist_flag_t flags)1474 UdmVarListListAddWithFlags(UDM_VARLISTLIST *List, udm_varlist_flag_t flags)
1475 {
1476 if (List->nitems >= List->mitems)
1477 {
1478 size_t mitems= List->mitems + 16;
1479 UDM_VARLIST *Item;
1480 if (!(Item= (UDM_VARLIST *) UdmRealloc(List->Item,
1481 mitems * sizeof(List->Item[0]))))
1482 return UDM_ERROR;
1483 List->Item= Item;
1484 List->mitems= mitems;
1485 }
1486 UdmVarListInit(&List->Item[List->nitems++]);
1487 List->Item[List->nitems-1].flags= flags;
1488 return UDM_OK;
1489 }
1490
1491 udm_rc_t
UdmVarListListAdd(UDM_VARLISTLIST * List)1492 UdmVarListListAdd(UDM_VARLISTLIST *List)
1493 {
1494 return UdmVarListListAddWithFlags(List, UDM_VARLIST_FLAG_NONE);
1495 }
1496
1497
UdmVarListListLastDelete(UDM_VARLISTLIST * List)1498 void UdmVarListListLastDelete(UDM_VARLISTLIST *List)
1499 {
1500 UDM_ASSERT(List->nitems > 0);
1501 List->nitems--;
1502 UdmVarListFree(&List->Item[List->nitems]);
1503 }
1504
1505
1506 UDM_VALUE *
UdmValueNew(const UDM_VALUE_HANDLER * ha)1507 UdmValueNew(const UDM_VALUE_HANDLER *ha)
1508 {
1509 UDM_VALUE *Value= UdmMalloc(ha->ValueSize());
1510 if (!Value)
1511 return NULL;
1512 Value->handler= ha;
1513 if (UDM_OK == ha->Constructor(UdmValueDataPtr(Value), NULL, 0))
1514 return Value;
1515 UdmFree(Value);
1516 return NULL;
1517 }
1518
1519
1520 void
UdmValueDelete(UDM_VALUE * Value)1521 UdmValueDelete(UDM_VALUE *Value)
1522 {
1523 Value->handler->Destructor(UdmValueDataPtr(Value));
1524 UdmFree(Value);
1525 }
1526
1527
UdmValueDataPtr(UDM_VALUE * Value)1528 char *UdmValueDataPtr(UDM_VALUE *Value)
1529 {
1530 return ((char *) Value) + Value->handler->DataOffset();
1531 }
1532
1533
UdmValueConstDataPtr(const UDM_VALUE * Value)1534 const char *UdmValueConstDataPtr(const UDM_VALUE *Value)
1535 {
1536 return ((const char *) Value) + Value->handler->DataOffset();
1537 }
1538
1539
UdmVarDataPtr(UDM_VAR * Var)1540 char *UdmVarDataPtr(UDM_VAR *Var)
1541 {
1542 return UdmValueDataPtr(&Var->Value);
1543 }
1544
1545
UdmVarConstDataPtr(const UDM_VAR * Var)1546 const char *UdmVarConstDataPtr(const UDM_VAR *Var)
1547 {
1548 return UdmValueConstDataPtr(&Var->Value);
1549 }
1550
1551
1552 udm_rc_t
UdmVarListAddQueryStringStrn(UDM_VARLIST * vars,const char * name_prefix,const char * query_string,size_t length)1553 UdmVarListAddQueryStringStrn(UDM_VARLIST *vars, const char *name_prefix,
1554 const char *query_string, size_t length)
1555 {
1556 char * tok, *lt;
1557 char *str= (char *) UdmMalloc(length + 7);
1558 char *qs= (char*) udm_strndup(query_string, length);
1559 char qname[256];
1560
1561 if ((str == NULL) || qs == NULL)
1562 {
1563 UDM_FREE(str);
1564 UDM_FREE(qs);
1565 return UDM_ERROR;
1566 }
1567
1568 UdmSGMLUnescape(qs);
1569
1570 tok= udm_strtok_r(qs, "&", <);
1571 while(tok)
1572 {
1573 char empty[]="";
1574 char * val;
1575 size_t unescaped_length;
1576
1577 if((val=strchr(tok,'=')))
1578 {
1579 *val='\0';
1580 val++;
1581 }
1582 else
1583 {
1584 val=empty;
1585 }
1586 unescaped_length= UdmUnescapeCGIQuery(str,val);
1587 UdmVarListAddQueryStr(vars, tok, str, unescaped_length);
1588 udm_snprintf(qname, sizeof(qname), "%s%s", name_prefix, tok);
1589 UdmVarListAddQueryStr(vars, qname, str, unescaped_length);
1590
1591 tok= udm_strtok_r(NULL, "&", <);
1592 }
1593 UDM_FREE(str);
1594 UDM_FREE(qs);
1595 return UDM_OK;
1596 }
1597
1598
1599 UDM_API(udm_rc_t)
UdmVarListAddQueryString(UDM_VARLIST * vars,const char * name_prefix,const char * query_string)1600 UdmVarListAddQueryString(UDM_VARLIST *vars,
1601 const char *name_prefix,
1602 const char *query_string)
1603 {
1604 return UdmVarListAddQueryStringStrn(vars, name_prefix,
1605 query_string, strlen(query_string));
1606 }
1607
1608
UdmVarNameVar(UDM_VAR * Var)1609 char *UdmVarNameVar(UDM_VAR *Var)
1610 {
1611 return Var->header.name;
1612 }
1613
1614
UdmVarName(const UDM_VAR * Var)1615 const char *UdmVarName(const UDM_VAR *Var)
1616 {
1617 return Var->header.name;
1618 }
1619
1620
UdmVarNameLength(const UDM_VAR * Var)1621 size_t UdmVarNameLength(const UDM_VAR *Var)
1622 {
1623 return strlen(Var->header.name);
1624 }
1625