gwenhywfar  4.99.15beta
db.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Tue Sep 09 2003
3  copyright : (C) 2003-2010 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #define DISABLE_DEBUGLOG
31 
32 #include "db_p.h"
33 #include <gwenhywfar/misc.h>
34 #include <gwenhywfar/debug.h>
35 #include <gwenhywfar/path.h>
36 #include <gwenhywfar/text.h>
37 #include <gwenhywfar/dbio.h>
38 #include <gwenhywfar/fslock.h>
39 #include <gwenhywfar/fastbuffer.h>
40 #include <gwenhywfar/syncio_file.h>
41 #include <gwenhywfar/syncio_memory.h>
42 
43 #include <stdlib.h>
44 #include <assert.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <ctype.h>
48 
49 #include <sys/types.h>
50 #ifdef HAVE_SYS_STAT_H
51 # include <sys/stat.h>
52 #endif
53 #ifdef HAVE_FCNTL_H
54 # include <fcntl.h>
55 #endif
56 #ifdef HAVE_UNISTD_H
57 # include <unistd.h>
58 #endif
59 
60 
61 #define GWEN_DB_NODE_FLAGS_MASK_INTERNAL 0xf0000000
62 #define GWEN_DB_NODE_FLAGS_GROUP 0x80000000
63 
64 
65 
66 static int _splitVariableNameInNameAndIndex(const char *s, char **pVariableName);
67 
68 
69 
70 
71 GWEN_LIST_FUNCTIONS(GWEN_DB_NODE, GWEN_DB_Node)
72 
73 
74 
76 {
77  GWEN_DB_NODE *node;
78 
81  node->typ=t;
82  return (GWEN_DB_NODE *)node;
83 }
84 
85 
86 
87 
89  unsigned int datasize)
90 {
91  GWEN_DB_NODE *n;
92 
94  if (datasize) {
95  assert(data);
96  n->dataSize=datasize;
97  n->data.dataBin=(char *)GWEN_Memory_malloc(datasize);
98  assert(n->data.dataBin);
99  memmove(n->data.dataBin, data, datasize);
100  }
101  return n;
102 }
103 
104 
105 
107 {
108  GWEN_DB_NODE *n;
109 
111  n->data.dataInt=data;
112  return n;
113 }
114 
115 
116 
118 {
119  GWEN_DB_NODE *n;
120 
122  if (data)
123  n->data.dataChar=GWEN_Memory_strdup(data);
124  else
125  n->data.dataChar=GWEN_Memory_strdup("");
126  return n;
127 }
128 
129 
130 
132 {
133  GWEN_DB_NODE *n;
134  char numbuffer[64];
135  int rv;
136 
137  rv=snprintf(numbuffer, sizeof(numbuffer)-1, "%d", v);
138  if (rv>=sizeof(numbuffer)) {
139  }
140  numbuffer[sizeof(numbuffer)-1]=0;
141 
143  n->data.dataChar=GWEN_Memory_strdup(numbuffer);
144  return n;
145 }
146 
147 
148 
150 {
151  GWEN_DB_NODE *n;
152 
154  n->data.dataPtr=data;
155  return n;
156 }
157 
158 
159 
160 GWEN_DB_NODE *GWEN_DB_Group_new(const char *name)
161 {
162  GWEN_DB_NODE *n;
163 
164  assert(name);
166  if (name)
167  n->data.dataName=GWEN_Memory_strdup(name);
168  else
169  n->data.dataName=GWEN_Memory_strdup("");
170  n->children=GWEN_DB_Node_List_new();
171  return n;
172 }
173 
174 
175 
176 GWEN_DB_NODE *GWEN_DB_Var_new(const char *name)
177 {
178  GWEN_DB_NODE *n;
179 
180  assert(name);
182  if (name)
183  n->data.dataName=GWEN_Memory_strdup(name);
184  else
185  n->data.dataName=GWEN_Memory_strdup("");
186  n->children=GWEN_DB_Node_List_new();
187  return n;
188 }
189 
190 
191 
193  GWEN_DB_NODE *n)
194 {
195  assert(parent);
196  assert(n);
197  assert(parent!=n);
198 
199  assert(parent->children!=NULL);
200  GWEN_DB_Node_List_Add(n, parent->children);
201 
202  n->parent=parent;
203 }
204 
205 
206 
208  GWEN_DB_NODE *n)
209 {
210  GWEN_DB_Node_Append_UnDirty(parent, n);
214 }
215 
216 
217 
219  GWEN_DB_NODE *n)
220 {
221  assert(parent);
222  assert(n);
223  assert(parent!=n);
224 
225  assert(parent->children!=NULL);
226  GWEN_DB_Node_List_Insert(n, parent->children);
227 
228  n->parent=parent;
229 }
230 
231 
232 
234  GWEN_DB_NODE *n)
235 {
236  GWEN_DB_Node_InsertUnDirty(parent, n);
240 }
241 
242 
243 
245 {
246  GWEN_DB_NODE *parent;
247 
248  assert(n);
249  parent=n->parent;
250  if (!parent) {
251  DBG_WARN(GWEN_LOGDOMAIN, "Node is not linked, nothing to do");
252  return;
253  }
254 
255  GWEN_DB_Node_List_Del(n);
256  n->parent=NULL;
257 }
258 
259 
260 
262 {
263  GWEN_DB_NODE *parent;
264 
265  assert(n);
266  parent=n->parent;
267  assert(parent);
268 
273 }
274 
275 
276 
278 {
279  if (n) {
281 
282  /* free children */
283  if (n->children)
284  GWEN_DB_Node_List_free(n->children);
285 
286  if (n->nodeFlags & GWEN_DB_NODE_FLAGS_SAFE) {
287  /* free dynamic (allocated) data safely */
288  switch (n->typ) {
291  if (n->data.dataName) {
292  int l=strlen(n->data.dataName);
293  if (l)
294  memset(n->data.dataName, 0, l);
295  GWEN_Memory_dealloc(n->data.dataName);
296  }
297  break;
298 
300  if (n->data.dataChar) {
301  int l=strlen(n->data.dataChar);
302  if (l)
303  memset(n->data.dataChar, 0, l);
304  GWEN_Memory_dealloc(n->data.dataChar);
305  }
306  break;
308  if (n->data.dataBin && n->dataSize) {
309  memset(n->data.dataBin, 0, n->dataSize);
310  GWEN_Memory_dealloc(n->data.dataBin);
311  }
312  break;
314  n->data.dataPtr=NULL;
315  break;
317  n->data.dataInt=0;
318  break;
319  default:
320  DBG_WARN(GWEN_LOGDOMAIN, "Unknown node type (%d)", n->typ);
321  }
322  }
323  else {
324  /* free dynamic (allocated) data */
325  switch (n->typ) {
328  GWEN_Memory_dealloc(n->data.dataName);
329  break;
330 
332  GWEN_Memory_dealloc(n->data.dataChar);
333  break;
335  GWEN_Memory_dealloc(n->data.dataBin);
336  break;
339  break;
340  default:
341  DBG_WARN(GWEN_LOGDOMAIN, "Unknown node type (%d)", n->typ);
342  }
343  }
344 
345  DBG_VERBOUS(GWEN_LOGDOMAIN, "Freeing node itself");
346  GWEN_FREE_OBJECT(n);
347  }
348 }
349 
350 
351 
353 {
354  GWEN_DB_NODE *nn;
355 
356  switch (n->typ) {
358  DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating group \"%s\"",
359  n->data.dataName);
360  nn=GWEN_DB_Group_new(n->data.dataName);
361  break;
363  DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating variable \"%s\"",
364  n->data.dataName);
365  nn=GWEN_DB_Var_new(n->data.dataName);
366  break;
368  nn=GWEN_DB_ValueChar_new(n->data.dataChar);
369  break;
371  nn=GWEN_DB_ValueBin_new(n->data.dataBin, n->dataSize);
372  break;
374  nn=GWEN_DB_ValuePtr_new(n->data.dataPtr);
375  break;
377  nn=GWEN_DB_ValueInt_new(n->data.dataInt);
378  break;
379  default:
380  DBG_WARN(GWEN_LOGDOMAIN, "Unknown node type (%d)", n->typ);
381  nn=0;
382  }
383 
384  /* duplicate all children and add them to the new node */
385  if (nn) {
386  const GWEN_DB_NODE *cn;
387 
388  cn=GWEN_DB_Node_List_First(n->children);
389  while (cn) {
390  GWEN_DB_NODE *ncn;
391 
392  /* duplicate child and add it */
393  ncn=GWEN_DB_Node_dup(cn);
394  if (!ncn) {
395  GWEN_DB_Node_free(nn);
396  return NULL;
397  }
399  cn=GWEN_DB_Node_List_Next(cn);
400  } /* while cn */
401  }
402 
403  return nn;
404 }
405 
406 
407 
409 {
411 }
412 
413 
414 
416 {
417  assert(n);
418  if (n->typ!=GWEN_DB_NodeType_Group) {
419  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
420  return NULL;
421  }
422  return GWEN_DB_Node_dup(n);
423 }
424 
425 
426 
428 {
429  GWEN_DB_NODE *nn;
430 
431  assert(n);
432  if (n->typ!=GWEN_DB_NodeType_Group) {
433  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
434  return NULL;
435  }
436  assert(n->children);
437  nn=GWEN_DB_Node_List_First(n->children);
438  while (nn) {
439  if (nn->typ==GWEN_DB_NodeType_Group)
440  break;
441  nn=GWEN_DB_Node_List_Next(nn);
442  } /* while node */
443  return nn;
444 }
445 
446 
447 
449 {
450  assert(n);
451  if (n->typ!=GWEN_DB_NodeType_Group) {
452  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
453  return NULL;
454  }
455  n=GWEN_DB_Node_List_Next(n);
456  while (n) {
457  if (n->typ==GWEN_DB_NodeType_Group)
458  break;
459  n=GWEN_DB_Node_List_Next(n);
460  } /* while node */
461  return n;
462 }
463 
464 
465 
467 {
468  GWEN_DB_NODE *nn;
469 
470  assert(n);
471  if (n->typ!=GWEN_DB_NodeType_Group) {
472  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
473  return NULL;
474  }
475  assert(n->children);
476  nn=GWEN_DB_Node_List_First(n->children);
477  while (nn) {
478  if (nn->typ==GWEN_DB_NodeType_Var)
479  break;
480  nn=GWEN_DB_Node_List_Next(nn);
481  } /* while node */
482  return nn;
483 }
484 
485 
486 
488 {
489  assert(n);
490  if (n->typ!=GWEN_DB_NodeType_Var) {
491  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
492  return NULL;
493  }
494  n=GWEN_DB_Node_List_Next(n);
495  while (n) {
496  if (n->typ==GWEN_DB_NodeType_Var)
497  break;
498  n=GWEN_DB_Node_List_Next(n);
499  } /* while node */
500  return n;
501 }
502 
503 
504 
506 {
507  GWEN_DB_NODE *nn;
508 
509  assert(n);
510  if (n->typ!=GWEN_DB_NodeType_Var) {
511  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
512  return NULL;
513  }
514  assert(n->children);
515  nn=GWEN_DB_Node_List_First(n->children);
516  while (nn) {
517  if (nn->typ>=GWEN_DB_NodeType_ValueChar &&
518  nn->typ<GWEN_DB_NodeType_ValueLast) {
519  break;
520  }
521  nn=GWEN_DB_Node_List_Next(nn);
522  } /* while node */
523  return nn;
524 }
525 
526 
527 
529 {
530  assert(n);
531  if (n->typ<GWEN_DB_NodeType_ValueChar ||
532  n->typ>=GWEN_DB_NodeType_ValueLast) {
533  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a value");
534  return NULL;
535  }
536 
537  n=GWEN_DB_Node_List_Next(n);
538  while (n) {
539  if (n->typ>=GWEN_DB_NodeType_ValueChar &&
541  break;
542  }
543  n=GWEN_DB_Node_List_Next(n);
544  } /* while node */
545  return n;
546 }
547 
548 
549 
551 {
552  assert(n);
553  if (n->typ>=GWEN_DB_NodeType_ValueChar &&
555  return n->typ;
556  }
557  else {
558  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a value");
560  }
561 }
562 
563 
564 
566 {
567  assert(n);
568  if (n->typ!=GWEN_DB_NodeType_ValueChar) {
569  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a char value");
570  return NULL;
571  }
572  return n->data.dataChar;
573 }
574 
575 
576 
578 {
579  assert(n);
580  assert(s);
581 
582  if (n->typ!=GWEN_DB_NodeType_ValueChar) {
583  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a char value");
584  return GWEN_ERROR_INVALID;
585  }
586 
587  GWEN_Memory_dealloc(n->data.dataChar);
588  n->data.dataChar=GWEN_Memory_strdup(s);
589  return 0;
590 }
591 
592 
593 
595 {
596  const char *p;
597  int res;
598 
599  assert(n);
600 
601  switch (n->typ) {
603  return n->data.dataInt;
605  p=n->data.dataChar;
606  assert(p);
607  if (sscanf(p, "%d", &res)!=1) {
608  DBG_ERROR(GWEN_LOGDOMAIN, "String in node is not an int value");
609  return 0;
610  }
611  return res;
612 
613  default:
614  DBG_ERROR(GWEN_LOGDOMAIN, "Node is neither char nor int value");
615  return 0;
616  }
617 }
618 
619 
620 
622  unsigned int *size)
623 {
624  assert(n);
625 
626  if (n->typ!=GWEN_DB_NodeType_ValueBin) {
627  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a binary value");
628  return NULL;
629  }
630 
631  *size=n->dataSize;
632  return n->data.dataBin;
633 }
634 
635 
636 
638  const char *name,
639  int idx)
640 {
641  GWEN_DB_NODE *nn;
642 
643  assert(n);
644  assert(name);
645 
646  if (n->typ!=GWEN_DB_NodeType_Group) {
647  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
648  return NULL;
649  }
650 
651  /* find existing node */
652  assert(n->children);
653  nn=GWEN_DB_Node_List_First(n->children);
654  while (nn) {
655  if (nn->typ==GWEN_DB_NodeType_Group) {
656  if (strcasecmp(nn->data.dataName, name)==0) {
657  if (!idx)
658  /* ok, group found, return it */
659  return nn;
660  idx--;
661  } /* if entry found */
662  }
663  nn=GWEN_DB_Node_List_Next(nn);
664  } /* while node */
665 
666  return NULL;
667 }
668 
669 
670 
672  const char *name,
673  int idx)
674 {
675  GWEN_DB_NODE *nn;
676 
677  assert(n);
678  assert(name);
679 
680  if (n->typ!=GWEN_DB_NodeType_Group) {
681  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
682  return NULL;
683  }
684 
685  /* find existing node */
686  assert(n->children);
687  nn=GWEN_DB_Node_List_First(n->children);
688  while (nn) {
689  if (nn->typ==GWEN_DB_NodeType_Var) {
690  if (strcasecmp(nn->data.dataName, name)==0) {
691  if (!idx)
692  /* ok, group found, return it */
693  return nn;
694  idx--;
695  } /* if entry found */
696  }
697  nn=GWEN_DB_Node_List_Next(nn);
698  } /* while node */
699 
700  return NULL;
701 }
702 
703 
704 
705 
706 
707 
708 
709 void *GWEN_DB_HandlePath(const char *entry,
710  void *data,
711  int idx,
712  uint32_t flags)
713 {
714  GWEN_DB_NODE *n;
715  GWEN_DB_NODE *nn;
716 
717  n=(GWEN_DB_NODE *)data;
718 
719  /* check whether we are allowed to simply create the node */
720  if (
721  ((flags & GWEN_PATH_FLAGS_LAST) &&
722  (((flags & GWEN_PATH_FLAGS_VARIABLE) &&
723  (flags & GWEN_PATH_FLAGS_CREATE_VAR)) ||
724  (!(flags & GWEN_PATH_FLAGS_VARIABLE) &&
725  (flags & GWEN_PATH_FLAGS_CREATE_GROUP)))
726  ) ||
727  (
728  !(flags & GWEN_PATH_FLAGS_LAST) &&
729  (flags & GWEN_PATH_FLAGS_PATHCREATE))
730  ) {
731  /* simply create the new variable/group */
732  if (idx!=0) {
733  DBG_INFO(GWEN_LOGDOMAIN, "Index is not 0, not creating %s[%d]",
734  entry, idx);
735  return 0;
736  }
737  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
739  "Unconditionally creating variable \"%s\"", entry);
740  nn=GWEN_DB_Var_new(entry);
741  if (flags & GWEN_DB_FLAGS_INSERT)
742  GWEN_DB_Node_Insert(n, nn);
743  else
744  GWEN_DB_Node_Append(n, nn);
745  return nn;
746  }
747  else {
749  "Unconditionally creating group \"%s\"", entry);
750  nn=GWEN_DB_Group_new(entry);
751  if (flags & GWEN_DB_FLAGS_INSERT)
752  GWEN_DB_Node_Insert(n, nn);
753  else
754  GWEN_DB_Node_Append(n, nn);
755  return nn;
756  }
757  }
758 
759  /* find the node */
760  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
761  nn=GWEN_DB_FindVar(n, entry, idx);
762  }
763  else {
764  nn=GWEN_DB_FindGroup(n, entry, idx);
765  }
766 
767  if (!nn) {
768  /* node not found, check, if we are allowed to create it */
769  if (
770  (!(flags & GWEN_PATH_FLAGS_LAST) &&
771  (flags & GWEN_PATH_FLAGS_PATHMUSTEXIST)) ||
773  ) {
774  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
776  "Variable \"%s\" does not exist", entry);
777  }
778  else {
780  "Group \"%s\" does not exist", entry);
781  }
782  return 0;
783  }
784  /* create the new variable/group */
785  if (idx!=0) {
786  DBG_INFO(GWEN_LOGDOMAIN, "Index is not 0, not creating %s[%d]",
787  entry, idx);
788  return 0;
789  }
790  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
792  "Variable \"%s\" not found, creating", entry);
793  nn=GWEN_DB_Var_new(entry);
794  if (flags & GWEN_DB_FLAGS_INSERT)
795  GWEN_DB_Node_Insert(n, nn);
796  else
797  GWEN_DB_Node_Append(n, nn);
798  }
799  else {
801  "Group \"%s\" not found, creating", entry);
802  nn=GWEN_DB_Group_new(entry);
803  if (flags & GWEN_DB_FLAGS_INSERT)
804  GWEN_DB_Node_Insert(n, nn);
805  else
806  GWEN_DB_Node_Append(n, nn);
807  }
808  } /* if node not found */
809  else {
810  /* node does exist, check whether this is ok */
811  if (
812  ((flags & GWEN_PATH_FLAGS_LAST) &&
814  (!(flags & GWEN_PATH_FLAGS_LAST) &&
816  ) {
817  DBG_VERBOUS(GWEN_LOGDOMAIN, "Entry \"%s\" already exists", entry);
818  return 0;
819  }
820  }
821 
822  return nn;
823 }
824 
825 
826 
828  const char *path,
829  uint32_t flags)
830 {
831  return (GWEN_DB_NODE *)GWEN_Path_HandleWithIdx(path,
832  n,
833  flags,
835 }
836 
837 
838 
840 {
841  assert(n);
842  if (n->children)
843  GWEN_DB_Node_List_Clear(n->children);
844 }
845 
846 
847 
849  const char *path,
850  int idx)
851 {
852  GWEN_DB_NODE *nn;
853 
854  /* find corresponding node */
855  nn=GWEN_DB_GetNode(n,
856  path,
860  if (!nn) {
861  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
862  path);
863  return 0;
864  }
865 
866  /* find value */
867  assert(nn->children);
868  nn=GWEN_DB_Node_List_First(nn->children);
869  while (nn) {
870  if (nn->typ>=GWEN_DB_NodeType_ValueChar &&
871  nn->typ<GWEN_DB_NodeType_ValueLast) {
872  if (!idx)
873  return nn;
874  idx--;
875  }
876  nn=GWEN_DB_Node_List_Next(nn);
877  }
878 
879  DBG_VERBOUS(GWEN_LOGDOMAIN, "No value[%d] for path \"%s\"",
880  idx, path);
881  return NULL;
882 }
883 
884 
885 
887  const char *path)
888 {
889  GWEN_DB_NODE *nn;
890 
891  /* find corresponding node */
892  nn=GWEN_DB_GetNode(n,
893  path,
897  if (!nn) {
898  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
899  path);
900  return 1;
901  }
903  GWEN_DB_Node_free(nn);
904  return 0;
905 }
906 
907 
908 
910  const char *path)
911 {
912  GWEN_DB_NODE *nn;
913 
914  /* find corresponding node */
915  nn=GWEN_DB_GetNode(n,
916  path,
919  if (!nn) {
920  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
921  path);
922  return 1;
923  }
925  GWEN_DB_Node_free(nn);
926  return 0;
927 }
928 
929 
930 
932  const char *path)
933 {
934  assert(n);
935  if (path) {
936  GWEN_DB_NODE *nn;
937 
938  /* find corresponding node */
939  nn=GWEN_DB_GetNode(n,
940  path,
943  if (!nn) {
944  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
945  path);
946  return 1;
947  }
948  GWEN_DB_ClearNode(nn);
949  }
950  else {
952  }
953  return 0;
954 }
955 
956 
957 
959  const char *path,
960  int idx,
961  const char *defVal)
962 {
963  GWEN_DB_NODE *nn;
964 
965  nn=GWEN_DB_GetValue(n, path, idx);
966  if (!nn) {
968  "Value for \"%s\" not found, returning default value",
969  path);
970  return defVal;
971  }
972  if (nn->typ!=GWEN_DB_NodeType_ValueChar) {
973  /* bad type */
975  "Bad type for path \"%s\", returning default value",
976  path);
977  return defVal;
978  }
979  return nn->data.dataChar;
980 }
981 
982 
983 
985  uint32_t flags,
986  const char *path,
987  const char *val)
988 {
989  GWEN_DB_NODE *nn;
990  GWEN_DB_NODE *nv;
991 
992  /* select/create node */
993  nn=GWEN_DB_GetNode(n,
994  path,
995  flags | GWEN_PATH_FLAGS_VARIABLE);
996  if (!nn) {
997  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
998  path);
999  return 1;
1000  }
1001 
1002  nv=GWEN_DB_ValueChar_new(val);
1003 
1004  /* delete contents of this variable if wanted */
1005  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
1006  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
1007  GWEN_DB_ClearNode(nn);
1008  }
1009 
1010  /* add previously created value */
1011  if (flags & GWEN_DB_FLAGS_INSERT)
1012  GWEN_DB_Node_Insert(nn, nv);
1013  else
1014  GWEN_DB_Node_Append(nn, nv);
1016  "Added char value \"%s\" to variable \"%s\"", val, path);
1017 
1018  return 0;
1019 }
1020 
1021 
1022 
1024  uint32_t flags,
1025  const char *path,
1026  int val)
1027 {
1028  GWEN_DB_NODE *nn;
1029  GWEN_DB_NODE *nv;
1030 
1031  /* select/create node */
1032  nn=GWEN_DB_GetNode(n, path, flags | GWEN_PATH_FLAGS_VARIABLE);
1033  if (!nn) {
1034  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1035  path);
1036  return 1;
1037  }
1038 
1040 
1041  /* delete contents of this variable if wanted */
1042  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
1043  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
1044  GWEN_DB_ClearNode(nn);
1045  }
1046 
1047  /* add previously created value */
1048  if (flags & GWEN_DB_FLAGS_INSERT)
1049  GWEN_DB_Node_Insert(nn, nv);
1050  else
1051  GWEN_DB_Node_Append(nn, nv);
1053  "Added char value \"%s\" to variable \"%s\"", val, path);
1054 
1055  return 0;
1056 }
1057 
1058 
1059 
1061  const char *path,
1062  const char *val,
1063  int senseCase,
1064  int check)
1065 {
1066  GWEN_DB_NODE *nn;
1067  GWEN_DB_NODE *nv;
1068 
1069  /* select/create node */
1070  nn=GWEN_DB_GetNode(n,
1071  path,
1073  if (!nn) {
1074  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1075  path);
1076  return -1;
1077  }
1078 
1079  if (check) {
1080  nv=GWEN_DB_GetFirstValue(n);
1081  if (nv && nv->typ==GWEN_DB_NodeType_ValueChar) {
1082  int res;
1083 
1084  assert(nv->data.dataChar);
1085  if (senseCase)
1086  res=strcasecmp(nv->data.dataChar, val)==0;
1087  else
1088  res=strcmp(nv->data.dataChar, val)==0;
1089  if (res) {
1091  "Value \"%s\" of var \"%s\" already exists",
1092  val, path);
1093  return 1;
1094  }
1095  }
1096  } /* if check */
1097 
1098  nv=GWEN_DB_ValueChar_new(val);
1099  GWEN_DB_Node_Append(nn, nv);
1101  "Added char value \"%s\" to variable \"%s\"", val, path);
1102 
1103  return 0;
1104 }
1105 
1106 
1107 
1109  const char *path,
1110  const char *val,
1111  int senseCase)
1112 {
1113  GWEN_DB_NODE *nn;
1114  GWEN_DB_NODE *nv;
1115 
1116  /* select/create node */
1117  nn=GWEN_DB_GetNode(n,
1118  path,
1120  if (!nn) {
1121  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1122  path);
1123  return -1;
1124  }
1125 
1126  nv=GWEN_DB_GetFirstValue(n);
1127  if (nv && nv->typ==GWEN_DB_NodeType_ValueChar) {
1128  int res;
1129 
1130  assert(nv->data.dataChar);
1131  if (senseCase)
1132  res=strcasecmp(nv->data.dataChar, val)==0;
1133  else
1134  res=strcmp(nv->data.dataChar, val)==0;
1135  if (res) {
1137  "Value \"%s\" of var \"%s\" already exists",
1138  val, path);
1139  GWEN_DB_Node_Unlink(nv);
1140  GWEN_DB_Node_free(nv);
1141  return 0;
1142  }
1143  }
1144 
1145  return 1;
1146 }
1147 
1148 
1149 
1151  const char *path,
1152  int idx,
1153  int defVal)
1154 {
1155  GWEN_DB_NODE *nn;
1156  const char *p;
1157  int res;
1158 
1159  assert(n);
1160  nn=GWEN_DB_GetValue(n, path, idx);
1161  if (!nn) {
1163  "Value[%d] for \"%s\" not found, returning default value",
1164  idx, path);
1165  return defVal;
1166  }
1167 
1168  switch (nn->typ) {
1170  return nn->data.dataInt;
1172  p=nn->data.dataChar;
1173  assert(p);
1174  if (sscanf(p, "%d", &res)!=1) {
1176  "String [%s] in node is not an int value", p);
1177  return defVal;
1178  }
1179  return res;
1180 
1181  default:
1182  DBG_ERROR(GWEN_LOGDOMAIN, "Node is neither char nor int value");
1183  return defVal;
1184  }
1185 }
1186 
1187 
1188 
1190  uint32_t flags,
1191  const char *path,
1192  int val)
1193 {
1194  GWEN_DB_NODE *nn;
1195  GWEN_DB_NODE *nv;
1196 
1197  /* select/create node */
1198  nn=GWEN_DB_GetNode(n,
1199  path,
1200  flags | GWEN_PATH_FLAGS_VARIABLE);
1201  if (!nn) {
1202  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1203  path);
1204  return 1;
1205  }
1206 
1207  /* delete contents of this variable if wanted */
1208  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
1209  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
1210  GWEN_DB_ClearNode(nn);
1211  }
1212 
1213  nv=GWEN_DB_ValueInt_new(val);
1214  if (flags & GWEN_DB_FLAGS_INSERT)
1215  GWEN_DB_Node_Insert(nn, nv);
1216  else
1217  GWEN_DB_Node_Append(nn, nv);
1218  DBG_VERBOUS(GWEN_LOGDOMAIN, "Added int value \"%d\" to variable \"%s\"", val, path);
1219  return 0;
1220 }
1221 
1222 
1223 
1225  const char *path,
1226  int idx,
1227  const void *defVal,
1228  unsigned int defValSize,
1229  unsigned int *returnValueSize)
1230 {
1231  GWEN_DB_NODE *nn;
1232 
1233  assert(returnValueSize);
1234  nn=GWEN_DB_GetValue(n, path, idx);
1235  if (!nn) {
1237  "Value for \"%s\" not found, returning default value",
1238  path);
1239  *returnValueSize=defValSize;
1240  return defVal;
1241  }
1242  if (nn->typ!=GWEN_DB_NodeType_ValueBin) {
1243  /* bad type */
1245  "Bad type for path \"%s\", returning default value",
1246  path);
1247  *returnValueSize=defValSize;
1248  return defVal;
1249  }
1250  *returnValueSize=nn->dataSize;
1251  return nn->data.dataBin;
1252 }
1253 
1254 
1255 
1257  uint32_t flags,
1258  const char *path,
1259  const void *val,
1260  unsigned int valSize)
1261 {
1262  GWEN_DB_NODE *nn;
1263  GWEN_DB_NODE *nv;
1264 
1265  assert(val);
1266  /* select/create node */
1267  nn=GWEN_DB_GetNode(n,
1268  path,
1269  flags | GWEN_PATH_FLAGS_VARIABLE);
1270  if (!nn) {
1271  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1272  path);
1273  return 1;
1274  }
1275 
1276  /* delete contents of this variable if wanted */
1277  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
1278  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
1279  GWEN_DB_ClearNode(nn);
1280  }
1281 
1282  nv=GWEN_DB_ValueBin_new(val, valSize);
1283  if (flags & GWEN_DB_FLAGS_INSERT)
1284  GWEN_DB_Node_Insert(nn, nv);
1285  else
1286  GWEN_DB_Node_Append(nn, nv);
1287  DBG_VERBOUS(GWEN_LOGDOMAIN, "Added bin value to variable \"%s\"", path);
1288  return 0;
1289 }
1290 
1291 
1292 
1294  const char *path,
1295  int idx,
1296  void *defVal)
1297 {
1298  GWEN_DB_NODE *nn;
1299 
1300  nn=GWEN_DB_GetValue(n, path, idx);
1301  if (!nn) {
1303  "Value for \"%s\" not found, returning default value",
1304  path);
1305  return defVal;
1306  }
1307  if (nn->typ!=GWEN_DB_NodeType_ValuePtr) {
1308  /* bad type */
1310  "Bad type for path \"%s\", returning default value",
1311  path);
1312  return defVal;
1313  }
1314  return nn->data.dataPtr;
1315 }
1316 
1317 
1318 
1320  uint32_t flags,
1321  const char *path,
1322  void *val)
1323 {
1324  GWEN_DB_NODE *nn;
1325  GWEN_DB_NODE *nv;
1326 
1327  /* select/create node */
1328  nn=GWEN_DB_GetNode(n,
1329  path,
1330  flags | GWEN_PATH_FLAGS_VARIABLE);
1331  if (!nn) {
1332  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1333  path);
1334  return 1;
1335  }
1336 
1337  /* delete contents of this variable if wanted */
1338  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
1339  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
1340  GWEN_DB_ClearNode(nn);
1341  }
1342 
1343  nv=GWEN_DB_ValuePtr_new(val);
1344  if (flags & GWEN_DB_FLAGS_INSERT)
1345  GWEN_DB_Node_Insert(nn, nv);
1346  else
1347  GWEN_DB_Node_Append(nn, nv);
1348  DBG_VERBOUS(GWEN_LOGDOMAIN, "Added ptr value to variable \"%s\"", path);
1349 
1350  return 0;
1351 }
1352 
1353 
1354 
1355 
1356 
1357 
1358 
1359 
1360 
1361 
1362 
1363 
1364 
1365 
1366 
1367 
1369  uint32_t flags,
1370  const char *path)
1371 {
1372  GWEN_DB_NODE *nn;
1373 
1374  /* select/create node */
1375  nn=GWEN_DB_GetNode(n,
1376  path,
1377  flags & ~GWEN_PATH_FLAGS_VARIABLE);
1378  if (!nn) {
1379  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1380  path);
1381  return NULL;
1382  }
1383 
1384  /* delete contents of this variable if wanted */
1385  if (flags & GWEN_DB_FLAGS_OVERWRITE_GROUPS) {
1386  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing group \"%s\"", path);
1387  GWEN_DB_ClearNode(nn);
1388  }
1389 
1390  return nn;
1391 }
1392 
1393 
1394 
1396 {
1397  assert(n);
1398  if (n->typ!=GWEN_DB_NodeType_Group) {
1399  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1400  return NULL;
1401  }
1402  return n->data.dataName;
1403 }
1404 
1405 
1406 
1407 void GWEN_DB_Dump(GWEN_DB_NODE *n, int insert)
1408 {
1409  if (n) {
1410  int i;
1411 
1412  for (i=0; i<insert; i++)
1413  fprintf(stderr, " ");
1414 
1415  /* dump dynamic (allocated) data */
1416  switch (n->typ) {
1418  fprintf(stderr, "Group : \"%s\"\n", n->data.dataName);
1419  break;
1420  case GWEN_DB_NodeType_Var:
1421  fprintf(stderr, "Var : \"%s\"\n", n->data.dataName);
1422  break;
1424  fprintf(stderr, "Value : \"%s\" (char)\n", n->data.dataChar);
1425  break;
1427  fprintf(stderr, "Value : %d (int)\n", n->data.dataInt);
1428  break;
1430  char *buffer;
1431 
1432  buffer=(char *)GWEN_Memory_malloc((n->dataSize*2)+1);
1433  assert(buffer);
1434  if (GWEN_Text_ToHex(n->data.dataBin, n->dataSize,
1435  buffer, (n->dataSize*2)+1)==0) {
1436  fprintf(stderr, "Value : %d bytes (bin)\n", n->dataSize);
1437  }
1438  else {
1439  fprintf(stderr, "Value : %s (bin)\n", buffer);
1440  }
1441  GWEN_Memory_dealloc(buffer);
1442  break;
1443  }
1445  fprintf(stderr, "Value : %p (ptr)\n", n->data.dataPtr);
1446  break;
1447  default:
1448  fprintf(stderr, "[unknown node type %d]\n", n->typ);
1449  }
1450 
1451  /* dump children */
1452  if (n->children) {
1453  GWEN_DB_NODE *cn;
1454 
1455  cn=GWEN_DB_Node_List_First(n->children);
1456  while (cn) {
1457  GWEN_DB_Dump(cn, insert+4);
1458  cn=GWEN_DB_Node_List_Next(cn);
1459  }
1460  }
1461  }
1462  else {
1463  fprintf(stderr, "[no node]\n");
1464  }
1465 }
1466 
1467 
1468 
1470 {
1471  assert(n);
1472  assert(nn);
1473 
1474  if (n->typ!=GWEN_DB_NodeType_Group) {
1475  DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
1476  return 0;
1477  }
1478 
1479  if (nn->typ!=GWEN_DB_NodeType_Group) {
1480  DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
1481  return 0;
1482  }
1483 
1484  GWEN_DB_Node_Append(n, nn);
1485  return 0;
1486 }
1487 
1488 
1489 
1491 {
1492  assert(n);
1493  assert(nn);
1494 
1495  if (n->typ!=GWEN_DB_NodeType_Group) {
1496  DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
1497  return 0;
1498  }
1499 
1500  if (nn->typ!=GWEN_DB_NodeType_Group) {
1501  DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
1502  return 0;
1503  }
1504 
1505  GWEN_DB_Node_Insert(n, nn);
1506  return 0;
1507 }
1508 
1509 
1510 
1512 {
1513  GWEN_DB_NODE *cpn;
1514 
1515  assert(n);
1516  assert(nn);
1517 
1518  if (n->typ!=GWEN_DB_NodeType_Group) {
1519  DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
1520  return -1;
1521  }
1522 
1523  if (nn->typ!=GWEN_DB_NodeType_Group) {
1524  DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
1525  GWEN_DB_Dump(nn, 1);
1526  return -1;
1527  }
1528 
1529  nn=GWEN_DB_Node_List_First(nn->children);
1530  while (nn) {
1531  DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating node");
1532  cpn=GWEN_DB_Node_dup(nn);
1533  GWEN_DB_Node_Append(n, cpn);
1534  nn=GWEN_DB_Node_List_Next(nn);
1535  } /* while */
1536  return 0;
1537 }
1538 
1539 
1540 
1542 {
1543  assert(n);
1544  if (n->typ!=GWEN_DB_NodeType_Group) {
1545  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1546  return;
1547  }
1549 }
1550 
1551 
1552 int GWEN_DB_VariableExists(GWEN_DB_NODE *n, const char *path)
1553 {
1554  GWEN_DB_NODE *nn;
1555 
1556  /* find corresponding node */
1557  assert(n);
1558  nn=GWEN_DB_GetNode(n,
1559  path,
1563  if (!nn) {
1564  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found", path);
1565  return 0;
1566  }
1567 
1568  return 1;
1569 }
1570 
1571 
1572 
1574  const char *path,
1575  unsigned int i)
1576 {
1577  return (GWEN_DB_GetValue(n, path, i)!=0);
1578 }
1579 
1580 
1581 
1583  const char *p)
1584 {
1585  GWEN_DB_NODE *nn;
1586 
1587  nn=GWEN_DB_FindVar(n, p, 0);
1588  if (!nn)
1589  return GWEN_DB_NodeType_Unknown;
1590 
1591  nn=GWEN_DB_GetFirstValue(nn);
1592  if (!nn)
1593  return GWEN_DB_NodeType_Unknown;
1594  return GWEN_DB_GetValueType(nn);
1595 }
1596 
1597 
1598 
1600  const char *path,
1601  unsigned int i)
1602 {
1603  GWEN_DB_NODE *nn;
1604 
1605  nn=GWEN_DB_GetValue(n, path, i);
1606  if (!nn)
1607  return GWEN_DB_NodeType_Unknown;
1608  return GWEN_DB_GetValueType(nn);
1609 }
1610 
1611 
1612 void GWEN_DB_GroupRename(GWEN_DB_NODE *n, const char *newname)
1613 {
1614  assert(n);
1615  assert(newname);
1616  assert(n->typ==GWEN_DB_NodeType_Group);
1617  GWEN_Memory_dealloc(n->data.dataName);
1618  n->data.dataName=GWEN_Memory_strdup(newname);
1619 }
1620 
1621 
1622 
1623 
1624 
1625 
1626 
1628 {
1629  assert(n);
1630  return n->typ==GWEN_DB_NodeType_Group;
1631 }
1632 
1633 
1634 
1636 {
1637  assert(n);
1638  return n->typ==GWEN_DB_NodeType_Var;
1639 }
1640 
1641 
1642 
1644 {
1645  assert(n);
1646  return (n->typ>=GWEN_DB_NodeType_ValueChar &&
1647  n->typ>=GWEN_DB_NodeType_ValueLast);
1648 }
1649 
1650 
1651 
1653  void *user_data)
1654 {
1655  GWEN_DB_NODE *iter;
1656  void *res;
1657 
1658  assert(node);
1659  assert(func);
1660 
1661  iter=GWEN_DB_GetFirstGroup(node);
1662  res=NULL;
1663  while (iter) {
1664  res=(*func)(iter, user_data);
1665  if (res) {
1666  break;
1667  }
1668  iter=GWEN_DB_GetNextGroup(iter);
1669  }
1670  return res;
1671 }
1672 
1673 
1674 
1675 void *GWEN_DB_count_cb(GWEN_UNUSED GWEN_DB_NODE *node, void *user_data)
1676 {
1677  unsigned int *a = user_data;
1678  ++(*a);
1679  return NULL;
1680 }
1681 
1682 
1683 
1684 unsigned int GWEN_DB_Groups_Count(const GWEN_DB_NODE *node)
1685 {
1686  unsigned int res = 0;
1688  return res;
1689 }
1690 
1691 
1692 
1694  void *user_data)
1695 {
1696  GWEN_DB_NODE *iter;
1697  void *res;
1698 
1699  assert(node);
1700  assert(func);
1701 
1702  iter=GWEN_DB_GetFirstVar(node);
1703  res=NULL;
1704  while (iter) {
1705  res=(*func)(iter, user_data);
1706  if (res) {
1707  break;
1708  }
1709  iter=GWEN_DB_GetNextVar(iter);
1710  }
1711  return res;
1712 }
1713 
1714 
1715 
1716 unsigned int GWEN_DB_Variables_Count(const GWEN_DB_NODE *node)
1717 {
1718  unsigned int res = 0;
1720  return res;
1721 }
1722 
1723 
1724 
1726  void *user_data)
1727 {
1728  GWEN_DB_NODE *iter;
1729  void *res;
1730 
1731  assert(node);
1732  assert(func);
1733 
1734  iter=GWEN_DB_GetFirstValue(node);
1735  res=NULL;
1736  while (iter) {
1737  res=(*func)(iter, user_data);
1738  if (res) {
1739  break;
1740  }
1741  iter=GWEN_DB_GetNextValue(iter);
1742  }
1743  return res;
1744 }
1745 
1746 
1747 
1748 unsigned int GWEN_DB_Values_Count(const GWEN_DB_NODE *node)
1749 {
1750  unsigned int res = 0;
1752  return res;
1753 }
1754 
1755 
1756 
1758 {
1759  assert(n);
1760  return n->nodeFlags;
1761 }
1762 
1763 
1764 
1766  uint32_t flags)
1767 {
1768  assert(n);
1769  n->nodeFlags=flags;
1770 }
1771 
1772 
1773 
1775  uint32_t newflags,
1776  uint32_t mask)
1777 {
1778  uint32_t flags;
1779 
1780  assert(n);
1781 
1782  while (n) {
1783  flags=n->nodeFlags;
1784  flags=((flags^newflags)&(mask))^flags;
1785  n->nodeFlags=flags;
1786  n=n->parent;
1787  } /* while */
1788 }
1789 
1790 
1791 
1793  uint32_t newflags,
1794  uint32_t mask)
1795 {
1796  uint32_t flags;
1797  GWEN_DB_NODE *cn;
1798 
1799  assert(n);
1800 
1801  flags=n->nodeFlags;
1802  flags=((flags^newflags)&(mask))^flags;
1803  n->nodeFlags=flags;
1804 
1805  cn=GWEN_DB_Node_List_First(n->children);
1806  while (cn) {
1807  GWEN_DB_ModifyBranchFlagsDown(cn, newflags, mask);
1808  cn=GWEN_DB_Node_List_Next(cn);
1809  } /* while cn */
1810 }
1811 
1812 
1813 
1815 {
1816  GWEN_DB_NODE *nn;
1817 
1818  assert(n);
1819  nn=n->parent;
1820  while (nn && nn->typ!=GWEN_DB_NodeType_Group)
1821  nn=nn->parent;
1822  return nn;
1823 }
1824 
1825 
1826 
1828 {
1829  GWEN_DB_NODE *nn;
1830 
1831  assert(n);
1832  if (n->typ!=GWEN_DB_NodeType_Group) {
1833  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1834  return NULL;
1835  }
1836  nn=GWEN_DB_Node_List_First(n->children);
1837  while (nn) {
1838  if ((nn->typ==GWEN_DB_NodeType_Group) &&
1839  (-1!=GWEN_Text_ComparePattern(nn->data.dataName, name, 0)))
1840  break;
1841  nn=GWEN_DB_Node_List_Next(nn);
1842  } /* while node */
1843  return nn;
1844 }
1845 
1846 
1847 
1849 {
1850  GWEN_DB_NODE *og;
1851 
1852  og=n;
1853  assert(n);
1854  if (n->typ!=GWEN_DB_NodeType_Group) {
1855  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1856  return NULL;
1857  }
1858  n=GWEN_DB_GetNextGroup(n);
1859  while (n) {
1860  if (-1!=GWEN_Text_ComparePattern(n->data.dataName, name, 0))
1861  break;
1862  n=GWEN_DB_GetNextGroup(n);
1863  } /* while node */
1864  assert(n!=og);
1865  return n;
1866 }
1867 
1868 
1869 
1871 {
1872  GWEN_DB_NODE *nn;
1873 
1874  assert(n);
1875  if (n->typ!=GWEN_DB_NodeType_Group) {
1876  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1877  return NULL;
1878  }
1879 
1880  nn=GWEN_DB_Node_List_First(n->children);
1881  while (nn) {
1882  if ((nn->typ==GWEN_DB_NodeType_Var) &&
1883  (-1!=GWEN_Text_ComparePattern(nn->data.dataName, name, 0)))
1884  break;
1885  nn=GWEN_DB_Node_List_Next(nn);
1886  } /* while node */
1887 
1888  return nn;
1889 }
1890 
1891 
1892 
1894 {
1895  GWEN_DB_NODE *og;
1896 
1897  og=n;
1898  assert(n);
1899  if (n->typ!=GWEN_DB_NodeType_Var) {
1900  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
1901  return NULL;
1902  }
1903  n=GWEN_DB_GetNextVar(n);
1904  while (n) {
1905  if (-1!=GWEN_Text_ComparePattern(n->data.dataName, name, 0))
1906  break;
1907  n=GWEN_DB_GetNextVar(n);
1908  } /* while node */
1909  assert(n!=og);
1910  return n;
1911 }
1912 
1913 
1914 
1916 {
1917  assert(n);
1918  if (n->typ!=GWEN_DB_NodeType_Var) {
1919  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
1920  return NULL;
1921  }
1922  return n->data.dataName;
1923 }
1924 
1925 
1926 
1927 void GWEN_DB_VariableRename(GWEN_DB_NODE *n, const char *newname)
1928 {
1929  assert(n);
1930  assert(newname);
1931  assert(n->typ==GWEN_DB_NodeType_Var);
1932  GWEN_Memory_dealloc(n->data.dataName);
1933  n->data.dataName=GWEN_Memory_strdup(newname);
1934 }
1935 
1936 
1937 
1938 int GWEN_DB_ReplaceVars(GWEN_DB_NODE *db, const char *s, GWEN_BUFFER *dbuf)
1939 {
1940  const char *p;
1941 
1942  p=s;
1943  while (*p) {
1944  if (*p=='$') {
1945  p++;
1946  if (*p=='$')
1947  GWEN_Buffer_AppendByte(dbuf, '$');
1948  else if (*p=='(') {
1949  const char *pStart;
1950 
1951  p++;
1952  pStart=p;
1953  while (*p && *p!=')')
1954  p++;
1955  if (*p!=')') {
1956  DBG_ERROR(GWEN_LOGDOMAIN, "Unterminated variable name in code");
1957  return GWEN_ERROR_BAD_DATA;
1958  }
1959  else {
1960  int len;
1961  char *name=NULL;
1962  char index=0;
1963  char *rawName;
1964  const char *valueString;
1965  int valueInt;
1966  char numbuf[32];
1967  int rv;
1968  GWEN_DB_NODE_TYPE valType;
1969 
1970  len=p-pStart;
1971  if (len<1) {
1972  DBG_ERROR(GWEN_LOGDOMAIN, "Empty variable name in code");
1973  return GWEN_ERROR_BAD_DATA;
1974  }
1975  rawName=(char *) malloc(len+1);
1976  assert(rawName);
1977  memmove(rawName, pStart, len);
1978  rawName[len]=0;
1979 
1980  index=_splitVariableNameInNameAndIndex(rawName, &name);
1981  if (index<0) {
1982  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid variable name \"%s\"", rawName);
1983  free(rawName);
1984  return index;
1985  }
1986  free(rawName);
1987 
1988  valType=GWEN_DB_GetVariableType(db, name);
1989 
1990  switch (valType) { /* GWEN_DB_GetVariableType */
1992  valueInt=GWEN_DB_GetIntValue(db, name, index, 0);
1993  rv=GWEN_Text_NumToString(valueInt, numbuf, sizeof(numbuf)-1, 0);
1994  if (rv>=0)
1995  GWEN_Buffer_AppendString(dbuf, numbuf);
1996  break;
1998  valueString=GWEN_DB_GetCharValue(db, name, index, NULL);
1999  if (valueString)
2000  GWEN_Buffer_AppendString(dbuf, valueString);
2001 #if 0 /* just replace with empty value */
2002  else {
2003  GWEN_Buffer_AppendString(dbuf, " [__VALUE OF ");
2004  GWEN_Buffer_AppendString(dbuf, name);
2005  GWEN_Buffer_AppendString(dbuf, " WAS NOT SET__] ");
2006  }
2007 #endif
2008  break;
2009 
2010  default:
2011  break;
2012  }
2013  free(name);
2014  }
2015  }
2016  else {
2017  DBG_ERROR(GWEN_LOGDOMAIN, "Bad variable string in code");
2018  return GWEN_ERROR_BAD_DATA;
2019  }
2020  p++;
2021  }
2022  else {
2023  if (*p=='#') {
2024  /* let # lines begin on a new line */
2025  GWEN_Buffer_AppendByte(dbuf, '\n');
2026  GWEN_Buffer_AppendByte(dbuf, *p);
2027 
2028  /* skip introducing cross and copy all stuff until the next cross
2029  * upon which wa inject a newline (to make the preprocessor happy)
2030  */
2031  p++;
2032  while (*p && *p!='#') {
2033  GWEN_Buffer_AppendByte(dbuf, *p);
2034  p++;
2035  }
2036  if (*p=='#') {
2037  GWEN_Buffer_AppendByte(dbuf, '\n');
2038  p++;
2039  }
2040  }
2041  else if (*p=='\\') {
2042  /* check for recognized control escapes */
2043  if (tolower(p[1])=='n') {
2044  GWEN_Buffer_AppendByte(dbuf, '\n');
2045  p+=2; /* skip introducing backslash and control character */
2046  }
2047  else if (tolower(p[1])=='t') {
2048  GWEN_Buffer_AppendByte(dbuf, '\t');
2049  p+=2; /* skip introducing backslash and control character */
2050  }
2051  else if (tolower(p[1])=='\\') {
2052  GWEN_Buffer_AppendByte(dbuf, '\\');
2053  p+=2; /* skip introducing backslash and control character */
2054  }
2055  else {
2056  /* no known escape character, just add literally */
2057  GWEN_Buffer_AppendByte(dbuf, *p);
2058  p++;
2059  }
2060  }
2061  else {
2062  GWEN_Buffer_AppendByte(dbuf, *p);
2063  p++;
2064  }
2065  }
2066  }
2067 
2068  return 0;
2069 }
2070 
2071 
2072 
2073 int _splitVariableNameInNameAndIndex(const char *s, char **pVariableName)
2074 {
2075  const char *p;
2076  const char *pStart;
2077  int len;
2078  char *name=NULL;
2079  char index=0;
2080 
2081  p=s;
2082  pStart=p;
2083  while (*p && *p!='[')
2084  p++;
2085 
2086  len=p-pStart;
2087  if (len<1) {
2088  DBG_ERROR(GWEN_LOGDOMAIN, "Empty variable name in code");
2089  return GWEN_ERROR_BAD_DATA;
2090  }
2091  name=(char *) malloc(len+1);
2092  assert(name);
2093  memmove(name, pStart, len);
2094  name[len]=0;
2095 
2096  if (*p=='[') {
2097  /* we have an index */
2098  p++;
2099  pStart=p;
2100  while(*p && *p!=']' && isdigit(*p)) {
2101  index*=10;
2102  index+=(*p)-'0';
2103  p++;
2104  }
2105  if (*p!=']') {
2106  DBG_ERROR(GWEN_LOGDOMAIN, "Bad index specification in variable name");
2107  free(name);
2108  return GWEN_ERROR_BAD_DATA;
2109  }
2110  }
2111 
2112  *pVariableName=name;
2113  return index;
2114 }
2115 
2116 
2117 
2118 
2119 
2120 
2121 #include "dbrw.c"
2122 
2123 
2124 
2125 
2126 
2127 
2128 
2129 
2130 
int GWEN_DB_ReplaceVars(GWEN_DB_NODE *db, const char *s, GWEN_BUFFER *dbuf)
Definition: db.c:1938
GWEN_DB_NODE * GWEN_DB_GetValue(GWEN_DB_NODE *n, const char *path, int idx)
Definition: db.c:848
#define GWEN_DB_FLAGS_OVERWRITE_VARS
Definition: db.h:121
void GWEN_DB_ModifyBranchFlagsUp(GWEN_DB_NODE *n, uint32_t newflags, uint32_t mask)
Definition: db.c:1774
void GWEN_DB_Dump(GWEN_DB_NODE *n, int insert)
Definition: db.c:1407
void * GWEN_DB_Groups_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func, void *user_data)
Definition: db.c:1652
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
#define GWEN_DB_FLAGS_INSERT
Definition: db.h:160
void GWEN_DB_Group_free(GWEN_DB_NODE *n)
Definition: db.c:408
#define GWEN_ERROR_INVALID
Definition: error.h:67
void GWEN_DB_ClearNode(GWEN_DB_NODE *n)
Definition: db.c:839
char * GWEN_Memory_strdup(const char *s)
Definition: memory.c:546
GWEN_DB_NODE * GWEN_DB_ValuePtr_new(void *data)
Definition: db.c:149
uint32_t GWEN_DB_GetNodeFlags(const GWEN_DB_NODE *n)
Definition: db.c:1757
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:92
#define NULL
Definition: binreloc.c:297
void GWEN_Memory_dealloc(void *p)
Definition: memory.c:487
#define GWEN_PATH_FLAGS_CREATE_GROUP
Definition: path.h:96
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:216
GWEN_DB_NODE * GWEN_DB_GetNextValue(GWEN_DB_NODE *n)
Definition: db.c:528
void *(* GWEN_DB_NODES_CB)(GWEN_DB_NODE *node, void *user_data)
Definition: db.h:378
void GWEN_DB_GroupRename(GWEN_DB_NODE *n, const char *newname)
Definition: db.c:1612
void GWEN_DB_Node_Append_UnDirty(GWEN_DB_NODE *parent, GWEN_DB_NODE *n)
Definition: db.c:192
unsigned int GWEN_DB_Groups_Count(const GWEN_DB_NODE *node)
Definition: db.c:1684
#define DBG_WARN(dbg_logger, format, args...)
Definition: debug.h:123
#define GWEN_LOGDOMAIN
Definition: logger.h:35
void GWEN_DB_ModifyBranchFlagsDown(GWEN_DB_NODE *n, uint32_t newflags, uint32_t mask)
Definition: db.c:1792
int GWEN_DB_ValueExists(GWEN_DB_NODE *n, const char *path, unsigned int i)
Definition: db.c:1573
int GWEN_DB_SetPtrValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, void *val)
Definition: db.c:1319
int GWEN_DB_SetCharValueFromInt(GWEN_DB_NODE *n, uint32_t flags, const char *path, int val)
Definition: db.c:1023
GWEN_DB_NODE * GWEN_DB_ValueBin_new(const void *data, unsigned int datasize)
Definition: db.c:88
#define GWEN_PATH_FLAGS_LAST
Definition: path.h:166
GWEN_DB_NODE * GWEN_DB_Node_dup(const GWEN_DB_NODE *n)
Definition: db.c:352
int GWEN_DB_InsertGroup(GWEN_DB_NODE *n, GWEN_DB_NODE *nn)
Definition: db.c:1490
GWEN_DB_NODE * GWEN_DB_GetNode(GWEN_DB_NODE *n, const char *path, uint32_t flags)
Definition: db.c:827
#define GWEN_ERROR_BAD_DATA
Definition: error.h:121
int GWEN_DB_AddGroup(GWEN_DB_NODE *n, GWEN_DB_NODE *nn)
Definition: db.c:1469
#define GWEN_PATH_FLAGS_NAMEMUSTNOTEXIST
Definition: path.h:89
GWEN_DB_NODE * GWEN_DB_GetFirstVar(GWEN_DB_NODE *n)
Definition: db.c:466
GWEN_DB_NODE_TYPE GWEN_DB_GetVariableType(GWEN_DB_NODE *n, const char *p)
Definition: db.c:1582
int GWEN_DB_IsVariable(const GWEN_DB_NODE *n)
Definition: db.c:1635
int GWEN_DB_SetBinValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const void *val, unsigned int valSize)
Definition: db.c:1256
void GWEN_DB_Node_free(GWEN_DB_NODE *n)
Definition: db.c:277
void GWEN_DB_VariableRename(GWEN_DB_NODE *n, const char *newname)
Definition: db.c:1927
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:86
void GWEN_DB_Node_Unlink_UnDirty(GWEN_DB_NODE *n)
Definition: db.c:244
static int _splitVariableNameInNameAndIndex(const char *s, char **pVariableName)
Definition: db.c:2073
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:208
const char * GWEN_DB_GroupName(GWEN_DB_NODE *n)
Definition: db.c:1395
GWEN_DB_NODE * GWEN_DB_ValueChar_newFromInt(int v)
Definition: db.c:131
void GWEN_DB_Node_Append(GWEN_DB_NODE *parent, GWEN_DB_NODE *n)
Definition: db.c:207
int GWEN_DB_DeleteGroup(GWEN_DB_NODE *n, const char *path)
Definition: db.c:909
#define GWEN_DB_FLAGS_OVERWRITE_GROUPS
Definition: db.h:123
#define GWEN_PATH_FLAGS_VARIABLE
Definition: path.h:111
#define GWEN_DB_NODE_FLAGS_SAFE
Definition: db.h:214
void * GWEN_Memory_malloc(size_t wsize)
Definition: memory.c:398
const void * GWEN_DB_GetBinValue(GWEN_DB_NODE *n, const char *path, int idx, const void *defVal, unsigned int defValSize, unsigned int *returnValueSize)
Definition: db.c:1224
void GWEN_DB_Node_InsertUnDirty(GWEN_DB_NODE *parent, GWEN_DB_NODE *n)
Definition: db.c:218
GWEN_DB_NODE * GWEN_DB_GetNextGroup(GWEN_DB_NODE *n)
Definition: db.c:448
void * GWEN_DB_GetPtrValue(GWEN_DB_NODE *n, const char *path, int idx, void *defVal)
Definition: db.c:1293
const void * GWEN_DB_GetBinValueFromNode(const GWEN_DB_NODE *n, unsigned int *size)
Definition: db.c:621
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:399
const char * GWEN_DB_GetCharValue(GWEN_DB_NODE *n, const char *path, int idx, const char *defVal)
Definition: db.c:958
GWEN_DB_NODE * GWEN_DB_Group_dup(const GWEN_DB_NODE *n)
Definition: db.c:415
const char * GWEN_DB_VariableName(GWEN_DB_NODE *n)
Definition: db.c:1915
int GWEN_DB_IsValue(const GWEN_DB_NODE *n)
Definition: db.c:1643
int GWEN_DB_VariableExists(GWEN_DB_NODE *n, const char *path)
Definition: db.c:1552
GWEN_DB_NODE * GWEN_DB_FindNextVar(GWEN_DB_NODE *n, const char *name)
Definition: db.c:1893
GWEN_DB_NODE * GWEN_DB_GetGroup(GWEN_DB_NODE *n, uint32_t flags, const char *path)
Definition: db.c:1368
GWEN_DB_NODE * GWEN_DB_ValueChar_new(const char *data)
Definition: db.c:117
GWEN_DB_NODE * GWEN_DB_FindGroup(GWEN_DB_NODE *n, const char *name, int idx)
Definition: db.c:637
int GWEN_DB_DeleteVar(GWEN_DB_NODE *n, const char *path)
Definition: db.c:886
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:41
GWEN_DB_NODE * GWEN_DB_Node_new(GWEN_DB_NODE_TYPE t)
Definition: db.c:75
#define GWEN_DB_NODE_FLAGS_DIRTY
Definition: db.h:207
int GWEN_Text_NumToString(int num, char *buffer, unsigned int bufsize, int fillchar)
Definition: text.c:1216
#define GWEN_PATH_FLAGS_PATHCREATE
Definition: path.h:78
#define GWEN_PATH_FLAGS_CREATE_VAR
Definition: path.h:103
#define GWEN_PATH_FLAGS_PATHMUSTNOTEXIST
Definition: path.h:70
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
void GWEN_DB_Node_Unlink(GWEN_DB_NODE *n)
Definition: db.c:261
GWEN_DB_NODE * GWEN_DB_FindFirstVar(GWEN_DB_NODE *n, const char *name)
Definition: db.c:1870
char * GWEN_Text_ToHex(const char *src, unsigned l, char *buffer, unsigned int maxsize)
Definition: text.c:630
int GWEN_Text_ComparePattern(const char *w, const char *p, int sensecase)
Definition: text.c:1181
int GWEN_DB_SetCharValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const char *val)
Definition: db.c:984
unsigned int GWEN_DB_Variables_Count(const GWEN_DB_NODE *node)
Definition: db.c:1716
void * GWEN_DB_HandlePath(const char *entry, void *data, int idx, uint32_t flags)
Definition: db.c:709
GWEN_DB_NODE * GWEN_DB_GetFirstValue(GWEN_DB_NODE *n)
Definition: db.c:505
#define GWEN_PATH_FLAGS_PATHMUSTEXIST
Definition: path.h:66
GWEN_DB_NODE_TYPE GWEN_DB_GetValueTypeByPath(GWEN_DB_NODE *n, const char *path, unsigned int i)
Definition: db.c:1599
int GWEN_DB_IsGroup(const GWEN_DB_NODE *n)
Definition: db.c:1627
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:177
int GWEN_DB_AddCharValue(GWEN_DB_NODE *n, const char *path, const char *val, int senseCase, int check)
Definition: db.c:1060
GWEN_DB_NODE * GWEN_DB_GetNextVar(GWEN_DB_NODE *n)
Definition: db.c:487
GWEN_DB_NODE * GWEN_DB_FindVar(GWEN_DB_NODE *n, const char *name, int idx)
Definition: db.c:671
void GWEN_DB_UnlinkGroup(GWEN_DB_NODE *n)
Definition: db.c:1541
void * GWEN_DB_count_cb(GWEN_UNUSED GWEN_DB_NODE *node, void *user_data)
Definition: db.c:1675
GWEN_DB_NODE_TYPE
Definition: db.h:233
#define GWEN_LIST_INIT(t, element)
Definition: list1.h:465
int GWEN_DB_GetIntValue(GWEN_DB_NODE *n, const char *path, int idx, int defVal)
Definition: db.c:1150
GWEN_DB_NODE * GWEN_DB_GetParentGroup(GWEN_DB_NODE *n)
Definition: db.c:1814
GWEN_DB_NODE * GWEN_DB_FindFirstGroup(GWEN_DB_NODE *n, const char *name)
Definition: db.c:1827
GWEN_DB_NODE * GWEN_DB_Group_new(const char *name)
Definition: db.c:160
GWEN_DB_NODE * GWEN_DB_GetFirstGroup(GWEN_DB_NODE *n)
Definition: db.c:427
int GWEN_DB_SetIntValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, int val)
Definition: db.c:1189
#define GWEN_LIST_FUNCTIONS(t, pr)
Definition: list1.h:366
void * GWEN_Path_HandleWithIdx(const char *path, void *data, uint32_t flags, GWEN_PATHIDXHANDLERPTR elementFunction)
Definition: path.c:189
int GWEN_DB_GetIntValueFromNode(const GWEN_DB_NODE *n)
Definition: db.c:594
int GWEN_DB_RemoveCharValue(GWEN_DB_NODE *n, const char *path, const char *val, int senseCase)
Definition: db.c:1108
void * GWEN_DB_Variables_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func, void *user_data)
Definition: db.c:1693
int GWEN_DB_ClearGroup(GWEN_DB_NODE *n, const char *path)
Definition: db.c:931
int GWEN_DB_AddGroupChildren(GWEN_DB_NODE *n, GWEN_DB_NODE *nn)
Definition: db.c:1511
#define GWEN_PATH_FLAGS_NAMEMUSTEXIST
Definition: path.h:84
int GWEN_DB_SetCharValueInNode(GWEN_DB_NODE *n, const char *s)
Definition: db.c:577
GWEN_DB_NODE * GWEN_DB_FindNextGroup(GWEN_DB_NODE *n, const char *name)
Definition: db.c:1848
#define GWEN_LIST_FINI(t, element)
Definition: list1.h:474
void * GWEN_DB_Values_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func, void *user_data)
Definition: db.c:1725
#define GWEN_UNUSED
GWEN_DB_NODE * GWEN_DB_ValueInt_new(int data)
Definition: db.c:106
void GWEN_DB_SetNodeFlags(GWEN_DB_NODE *n, uint32_t flags)
Definition: db.c:1765
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1062
#define GWEN_DB_FLAGS_DEFAULT
Definition: db.h:168
void GWEN_DB_Node_Insert(GWEN_DB_NODE *parent, GWEN_DB_NODE *n)
Definition: db.c:233
GWEN_DB_NODE_TYPE GWEN_DB_GetValueType(GWEN_DB_NODE *n)
Definition: db.c:550
GWEN_DB_NODE * GWEN_DB_Var_new(const char *name)
Definition: db.c:176
unsigned int GWEN_DB_Values_Count(const GWEN_DB_NODE *node)
Definition: db.c:1748
const char * GWEN_DB_GetCharValueFromNode(const GWEN_DB_NODE *n)
Definition: db.c:565