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, "&", &lt);
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, "&", &lt);
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