gwenhywfar  4.3.3
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 GWEN_LIST_FUNCTIONS(GWEN_DB_NODE, GWEN_DB_Node)
66 
67 
68 
70  GWEN_DB_NODE *node;
71 
74  node->typ=t;
75  return (GWEN_DB_NODE*)node;
76 }
77 
78 
79 
80 
82  unsigned int datasize){
83  GWEN_DB_NODE *n;
84 
86  if (datasize) {
87  assert(data);
88  n->dataSize=datasize;
89  n->data.dataBin=(char*)GWEN_Memory_malloc(datasize);
90  assert(n->data.dataBin);
91  memmove(n->data.dataBin, data, datasize);
92  }
93  return n;
94 }
95 
96 
97 
99  GWEN_DB_NODE *n;
100 
102  n->data.dataInt=data;
103  return n;
104 }
105 
106 
107 
109  GWEN_DB_NODE *n;
110 
112  if (data)
113  n->data.dataChar=GWEN_Memory_strdup(data);
114  else
115  n->data.dataChar=GWEN_Memory_strdup("");
116  return n;
117 }
118 
119 
120 
122  GWEN_DB_NODE *n;
123 
125  n->data.dataPtr=data;
126  return n;
127 }
128 
129 
130 
131 GWEN_DB_NODE *GWEN_DB_Group_new(const char *name){
132  GWEN_DB_NODE *n;
133 
134  assert(name);
136  if (name)
137  n->data.dataName=GWEN_Memory_strdup(name);
138  else
139  n->data.dataName=GWEN_Memory_strdup("");
140  n->children=GWEN_DB_Node_List_new();
141  return n;
142 }
143 
144 
145 
146 GWEN_DB_NODE *GWEN_DB_Var_new(const char *name){
147  GWEN_DB_NODE *n;
148 
149  assert(name);
151  if (name)
152  n->data.dataName=GWEN_Memory_strdup(name);
153  else
154  n->data.dataName=GWEN_Memory_strdup("");
155  n->children=GWEN_DB_Node_List_new();
156  return n;
157 }
158 
159 
160 
162  GWEN_DB_NODE *n){
163  assert(parent);
164  assert(n);
165  assert(parent!=n);
166 
167  assert(parent->children!=NULL);
168  GWEN_DB_Node_List_Add(n, parent->children);
169 
170  n->parent=parent;
171 }
172 
173 
174 
176  GWEN_DB_NODE *n){
177  GWEN_DB_Node_Append_UnDirty(parent, n);
181 }
182 
183 
184 
186  GWEN_DB_NODE *n){
187  assert(parent);
188  assert(n);
189  assert(parent!=n);
190 
191  assert(parent->children!=NULL);
192  GWEN_DB_Node_List_Insert(n, parent->children);
193 
194  n->parent=parent;
195 }
196 
197 
198 
200  GWEN_DB_NODE *n){
201  GWEN_DB_Node_InsertUnDirty(parent, n);
205 }
206 
207 
208 
210  GWEN_DB_NODE *parent;
211 
212  assert(n);
213  parent=n->parent;
214  if (!parent) {
215  DBG_WARN(GWEN_LOGDOMAIN, "Node is not linked, nothing to do");
216  return;
217  }
218 
219  GWEN_DB_Node_List_Del(n);
220  n->parent=NULL;
221 }
222 
223 
224 
226  GWEN_DB_NODE *parent;
227 
228  assert(n);
229  parent=n->parent;
230  assert(parent);
231 
236 }
237 
238 
239 
241  if (n) {
243 
244  /* free children */
245  if (n->children)
246  GWEN_DB_Node_List_free(n->children);
247 
248  /* free dynamic (allocated) data */
249  switch(n->typ) {
252  GWEN_Memory_dealloc(n->data.dataName);
253  break;
254 
256  GWEN_Memory_dealloc(n->data.dataChar);
257  break;
259  GWEN_Memory_dealloc(n->data.dataBin);
260  break;
263  break;
264  default:
265  DBG_WARN(GWEN_LOGDOMAIN, "Unknown node type (%d)", n->typ);
266  }
267  DBG_VERBOUS(GWEN_LOGDOMAIN, "Freeing node itself");
268  GWEN_FREE_OBJECT(n);
269  }
270 }
271 
272 
273 
275  GWEN_DB_NODE *nn;
276 
277  switch(n->typ) {
279  DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating group \"%s\"",
280  n->data.dataName);
281  nn=GWEN_DB_Group_new(n->data.dataName);
282  break;
284  DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating variable \"%s\"",
285  n->data.dataName);
286  nn=GWEN_DB_Var_new(n->data.dataName);
287  break;
289  nn=GWEN_DB_ValueChar_new(n->data.dataChar);
290  break;
292  nn=GWEN_DB_ValueBin_new(n->data.dataBin, n->dataSize);
293  break;
295  nn=GWEN_DB_ValuePtr_new(n->data.dataPtr);
296  break;
298  nn=GWEN_DB_ValueInt_new(n->data.dataInt);
299  break;
300  default:
301  DBG_WARN(GWEN_LOGDOMAIN, "Unknown node type (%d)", n->typ);
302  nn=0;
303  }
304 
305  /* duplicate all children and add them to the new node */
306  if (nn) {
307  const GWEN_DB_NODE *cn;
308 
309  cn=GWEN_DB_Node_List_First(n->children);
310  while(cn) {
311  GWEN_DB_NODE *ncn;
312 
313  /* duplicate child and add it */
314  ncn=GWEN_DB_Node_dup(cn);
315  if (!ncn) {
316  GWEN_DB_Node_free(nn);
317  return NULL;
318  }
320  cn=GWEN_DB_Node_List_Next(cn);
321  } /* while cn */
322  }
323 
324  return nn;
325 }
326 
327 
328 
331 }
332 
333 
334 
336  assert(n);
337  if (n->typ!=GWEN_DB_NodeType_Group) {
338  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
339  return NULL;
340  }
341  return GWEN_DB_Node_dup(n);
342 }
343 
344 
345 
347  GWEN_DB_NODE *nn;
348 
349  assert(n);
350  if (n->typ!=GWEN_DB_NodeType_Group) {
351  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
352  return NULL;
353  }
354  assert(n->children);
355  nn=GWEN_DB_Node_List_First(n->children);
356  while(nn) {
357  if (nn->typ==GWEN_DB_NodeType_Group)
358  break;
359  nn=GWEN_DB_Node_List_Next(nn);
360  } /* while node */
361  return nn;
362 }
363 
364 
365 
367  assert(n);
368  if (n->typ!=GWEN_DB_NodeType_Group) {
369  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
370  return NULL;
371  }
372  n=GWEN_DB_Node_List_Next(n);
373  while(n) {
374  if (n->typ==GWEN_DB_NodeType_Group)
375  break;
376  n=GWEN_DB_Node_List_Next(n);
377  } /* while node */
378  return n;
379 }
380 
381 
382 
384  GWEN_DB_NODE *nn;
385 
386  assert(n);
387  if (n->typ!=GWEN_DB_NodeType_Group) {
388  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
389  return NULL;
390  }
391  assert(n->children);
392  nn=GWEN_DB_Node_List_First(n->children);
393  while(nn) {
394  if (nn->typ==GWEN_DB_NodeType_Var)
395  break;
396  nn=GWEN_DB_Node_List_Next(nn);
397  } /* while node */
398  return nn;
399 }
400 
401 
402 
404  assert(n);
405  if (n->typ!=GWEN_DB_NodeType_Var) {
406  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
407  return NULL;
408  }
409  n=GWEN_DB_Node_List_Next(n);
410  while(n) {
411  if (n->typ==GWEN_DB_NodeType_Var)
412  break;
413  n=GWEN_DB_Node_List_Next(n);
414  } /* while node */
415  return n;
416 }
417 
418 
419 
421  GWEN_DB_NODE *nn;
422 
423  assert(n);
424  if (n->typ!=GWEN_DB_NodeType_Var) {
425  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
426  return NULL;
427  }
428  assert(n->children);
429  nn=GWEN_DB_Node_List_First(n->children);
430  while(nn) {
431  if (nn->typ>=GWEN_DB_NodeType_ValueChar &&
432  nn->typ<GWEN_DB_NodeType_ValueLast) {
433  break;
434  }
435  nn=GWEN_DB_Node_List_Next(nn);
436  } /* while node */
437  return nn;
438 }
439 
440 
441 
443  assert(n);
444  if (n->typ<GWEN_DB_NodeType_ValueChar ||
445  n->typ>=GWEN_DB_NodeType_ValueLast) {
446  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a value");
447  return NULL;
448  }
449 
450  n=GWEN_DB_Node_List_Next(n);
451  while(n) {
452  if (n->typ>=GWEN_DB_NodeType_ValueChar &&
454  break;
455  }
456  n=GWEN_DB_Node_List_Next(n);
457  } /* while node */
458  return n;
459 }
460 
461 
462 
464  assert(n);
465  if (n->typ>=GWEN_DB_NodeType_ValueChar &&
467  return n->typ;
468  }
469  else {
470  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a value");
472  }
473 }
474 
475 
476 
478  assert(n);
479  if (n->typ!=GWEN_DB_NodeType_ValueChar) {
480  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a char value");
481  return NULL;
482  }
483  return n->data.dataChar;
484 }
485 
486 
487 
488 int GWEN_DB_SetCharValueInNode(GWEN_DB_NODE *n, const char *s) {
489  assert(n);
490  assert(s);
491 
492  if (n->typ!=GWEN_DB_NodeType_ValueChar) {
493  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a char value");
494  return GWEN_ERROR_INVALID;
495  }
496 
497  GWEN_Memory_dealloc(n->data.dataChar);
498  n->data.dataChar=GWEN_Memory_strdup(s);
499  return 0;
500 }
501 
502 
503 
505  const char *p;
506  int res;
507 
508  assert(n);
509 
510  switch(n->typ) {
512  return n->data.dataInt;
514  p=n->data.dataChar;
515  assert(p);
516  if (sscanf(p, "%d", &res)!=1) {
517  DBG_ERROR(GWEN_LOGDOMAIN, "String in node is not an int value");
518  return 0;
519  }
520  return res;
521 
522  default:
523  DBG_ERROR(GWEN_LOGDOMAIN, "Node is neither char nor int value");
524  return 0;
525  }
526 }
527 
528 
529 
531  unsigned int *size){
532  assert(n);
533 
534  if (n->typ!=GWEN_DB_NodeType_ValueBin) {
535  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a binary value");
536  return NULL;
537  }
538 
539  *size=n->dataSize;
540  return n->data.dataBin;
541 }
542 
543 
544 
546  const char *name,
547  int idx) {
548  GWEN_DB_NODE *nn;
549 
550  assert(n);
551  assert(name);
552 
553  if (n->typ!=GWEN_DB_NodeType_Group) {
554  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
555  return NULL;
556  }
557 
558  /* find existing node */
559  assert(n->children);
560  nn=GWEN_DB_Node_List_First(n->children);
561  while(nn) {
562  if (nn->typ==GWEN_DB_NodeType_Group) {
563  if (strcasecmp(nn->data.dataName, name)==0) {
564  if (!idx)
565  /* ok, group found, return it */
566  return nn;
567  idx--;
568  } /* if entry found */
569  }
570  nn=GWEN_DB_Node_List_Next(nn);
571  } /* while node */
572 
573  return NULL;
574 }
575 
576 
577 
579  const char *name,
580  int idx) {
581  GWEN_DB_NODE *nn;
582 
583  assert(n);
584  assert(name);
585 
586  if (n->typ!=GWEN_DB_NodeType_Group) {
587  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
588  return NULL;
589  }
590 
591  /* find existing node */
592  assert(n->children);
593  nn=GWEN_DB_Node_List_First(n->children);
594  while(nn) {
595  if (nn->typ==GWEN_DB_NodeType_Var) {
596  if (strcasecmp(nn->data.dataName, name)==0) {
597  if (!idx)
598  /* ok, group found, return it */
599  return nn;
600  idx--;
601  } /* if entry found */
602  }
603  nn=GWEN_DB_Node_List_Next(nn);
604  } /* while node */
605 
606  return NULL;
607 }
608 
609 
610 
611 
612 
613 
614 
615 void* GWEN_DB_HandlePath(const char *entry,
616  void *data,
617  int idx,
618  uint32_t flags) {
619  GWEN_DB_NODE *n;
620  GWEN_DB_NODE *nn;
621 
622  n=(GWEN_DB_NODE*)data;
623 
624  /* check whether we are allowed to simply create the node */
625  if (
626  ((flags & GWEN_PATH_FLAGS_LAST) &&
627  (((flags & GWEN_PATH_FLAGS_VARIABLE) &&
628  (flags & GWEN_PATH_FLAGS_CREATE_VAR)) ||
629  (!(flags & GWEN_PATH_FLAGS_VARIABLE) &&
630  (flags & GWEN_PATH_FLAGS_CREATE_GROUP)))
631  ) ||
632  (
633  !(flags & GWEN_PATH_FLAGS_LAST) &&
634  (flags & GWEN_PATH_FLAGS_PATHCREATE))
635  ) {
636  /* simply create the new variable/group */
637  if (idx!=0) {
638  DBG_INFO(GWEN_LOGDOMAIN, "Index is not 0, not creating %s[%d]",
639  entry, idx);
640  return 0;
641  }
642  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
644  "Unconditionally creating variable \"%s\"", entry);
645  nn=GWEN_DB_Var_new(entry);
646  if (flags & GWEN_DB_FLAGS_INSERT)
647  GWEN_DB_Node_Insert(n, nn);
648  else
649  GWEN_DB_Node_Append(n, nn);
650  return nn;
651  }
652  else {
654  "Unconditionally creating group \"%s\"", entry);
655  nn=GWEN_DB_Group_new(entry);
656  if (flags & GWEN_DB_FLAGS_INSERT)
657  GWEN_DB_Node_Insert(n, nn);
658  else
659  GWEN_DB_Node_Append(n, nn);
660  return nn;
661  }
662  }
663 
664  /* find the node */
665  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
666  nn=GWEN_DB_FindVar(n, entry, idx);
667  }
668  else {
669  nn=GWEN_DB_FindGroup(n, entry, idx);
670  }
671 
672  if (!nn) {
673  /* node not found, check, if we are allowed to create it */
674  if (
675  (!(flags & GWEN_PATH_FLAGS_LAST) &&
676  (flags & GWEN_PATH_FLAGS_PATHMUSTEXIST)) ||
678  ) {
679  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
681  "Variable \"%s\" does not exist", entry);
682  }
683  else {
685  "Group \"%s\" does not exist", entry);
686  }
687  return 0;
688  }
689  /* create the new variable/group */
690  if (idx!=0) {
691  DBG_INFO(GWEN_LOGDOMAIN, "Index is not 0, not creating %s[%d]",
692  entry, idx);
693  return 0;
694  }
695  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
697  "Variable \"%s\" not found, creating", entry);
698  nn=GWEN_DB_Var_new(entry);
699  if (flags & GWEN_DB_FLAGS_INSERT)
700  GWEN_DB_Node_Insert(n, nn);
701  else
702  GWEN_DB_Node_Append(n, nn);
703  }
704  else {
706  "Group \"%s\" not found, creating", entry);
707  nn=GWEN_DB_Group_new(entry);
708  if (flags & GWEN_DB_FLAGS_INSERT)
709  GWEN_DB_Node_Insert(n, nn);
710  else
711  GWEN_DB_Node_Append(n, nn);
712  }
713  } /* if node not found */
714  else {
715  /* node does exist, check whether this is ok */
716  if (
717  ((flags & GWEN_PATH_FLAGS_LAST) &&
719  (!(flags & GWEN_PATH_FLAGS_LAST) &&
721  ) {
722  DBG_VERBOUS(GWEN_LOGDOMAIN, "Entry \"%s\" already exists", entry);
723  return 0;
724  }
725  }
726 
727  return nn;
728 }
729 
730 
731 
733  const char *path,
734  uint32_t flags){
736  n,
737  flags,
739 }
740 
741 
742 
744  assert(n);
745  if (n->children)
746  GWEN_DB_Node_List_Clear(n->children);
747 }
748 
749 
750 
752  const char *path,
753  int idx) {
754  GWEN_DB_NODE *nn;
755 
756  /* find corresponding node */
757  nn=GWEN_DB_GetNode(n,
758  path,
762  if (!nn) {
763  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
764  path);
765  return 0;
766  }
767 
768  /* find value */
769  assert(nn->children);
770  nn=GWEN_DB_Node_List_First(nn->children);
771  while(nn) {
772  if (nn->typ>=GWEN_DB_NodeType_ValueChar &&
773  nn->typ<GWEN_DB_NodeType_ValueLast) {
774  if (!idx)
775  return nn;
776  idx--;
777  }
778  nn=GWEN_DB_Node_List_Next(nn);
779  }
780 
781  DBG_VERBOUS(GWEN_LOGDOMAIN, "No value[%d] for path \"%s\"",
782  idx, path);
783  return NULL;
784 }
785 
786 
787 
789  const char *path) {
790  GWEN_DB_NODE *nn;
791 
792  /* find corresponding node */
793  nn=GWEN_DB_GetNode(n,
794  path,
798  if (!nn) {
799  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
800  path);
801  return 1;
802  }
804  GWEN_DB_Node_free(nn);
805  return 0;
806 }
807 
808 
809 
811  const char *path) {
812  GWEN_DB_NODE *nn;
813 
814  /* find corresponding node */
815  nn=GWEN_DB_GetNode(n,
816  path,
819  if (!nn) {
820  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
821  path);
822  return 1;
823  }
825  GWEN_DB_Node_free(nn);
826  return 0;
827 }
828 
829 
830 
832  const char *path){
833  assert(n);
834  if (path) {
835  GWEN_DB_NODE *nn;
836 
837  /* find corresponding node */
838  nn=GWEN_DB_GetNode(n,
839  path,
842  if (!nn) {
843  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
844  path);
845  return 1;
846  }
847  GWEN_DB_ClearNode(nn);
848  }
849  else {
851  }
852  return 0;
853 }
854 
855 
856 
858  const char *path,
859  int idx,
860  const char *defVal){
861  GWEN_DB_NODE *nn;
862 
863  nn=GWEN_DB_GetValue(n, path, idx);
864  if (!nn){
866  "Value for \"%s\" not found, returning default value",
867  path);
868  return defVal;
869  }
870  if (nn->typ!=GWEN_DB_NodeType_ValueChar) {
871  /* bad type */
873  "Bad type for path \"%s\", returning default value",
874  path);
875  return defVal;
876  }
877  return nn->data.dataChar;
878 }
879 
880 
881 
883  uint32_t flags,
884  const char *path,
885  const char *val){
886  GWEN_DB_NODE *nn;
887  GWEN_DB_NODE *nv;
888 
889  /* select/create node */
890  nn=GWEN_DB_GetNode(n,
891  path,
892  flags | GWEN_PATH_FLAGS_VARIABLE);
893  if (!nn) {
894  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
895  path);
896  return 1;
897  }
898 
899  nv=GWEN_DB_ValueChar_new(val);
900 
901  /* delete contents of this variable if wanted */
902  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
903  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
904  GWEN_DB_ClearNode(nn);
905  }
906 
907  /* add previously created value */
908  if (flags & GWEN_DB_FLAGS_INSERT)
909  GWEN_DB_Node_Insert(nn, nv);
910  else
911  GWEN_DB_Node_Append(nn, nv);
913  "Added char value \"%s\" to variable \"%s\"", val, path);
914 
915  return 0;
916 }
917 
918 
919 
921  const char *path,
922  const char *val,
923  int senseCase,
924  int check){
925  GWEN_DB_NODE *nn;
926  GWEN_DB_NODE *nv;
927 
928  /* select/create node */
929  nn=GWEN_DB_GetNode(n,
930  path,
932  if (!nn) {
933  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
934  path);
935  return -1;
936  }
937 
938  if (check) {
939  nv=GWEN_DB_GetFirstValue(n);
940  if (nv && nv->typ==GWEN_DB_NodeType_ValueChar) {
941  int res;
942 
943  assert(nv->data.dataChar);
944  if (senseCase)
945  res=strcasecmp(nv->data.dataChar, val)==0;
946  else
947  res=strcmp(nv->data.dataChar, val)==0;
948  if (res) {
950  "Value \"%s\" of var \"%s\" already exists",
951  val, path);
952  return 1;
953  }
954  }
955  } /* if check */
956 
957  nv=GWEN_DB_ValueChar_new(val);
958  GWEN_DB_Node_Append(nn, nv);
960  "Added char value \"%s\" to variable \"%s\"", val, path);
961 
962  return 0;
963 }
964 
965 
966 
968  const char *path,
969  const char *val,
970  int senseCase){
971  GWEN_DB_NODE *nn;
972  GWEN_DB_NODE *nv;
973 
974  /* select/create node */
975  nn=GWEN_DB_GetNode(n,
976  path,
978  if (!nn) {
979  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
980  path);
981  return -1;
982  }
983 
984  nv=GWEN_DB_GetFirstValue(n);
985  if (nv && nv->typ==GWEN_DB_NodeType_ValueChar) {
986  int res;
987 
988  assert(nv->data.dataChar);
989  if (senseCase)
990  res=strcasecmp(nv->data.dataChar, val)==0;
991  else
992  res=strcmp(nv->data.dataChar, val)==0;
993  if (res) {
995  "Value \"%s\" of var \"%s\" already exists",
996  val, path);
998  GWEN_DB_Node_free(nv);
999  return 0;
1000  }
1001  }
1002 
1003  return 1;
1004 }
1005 
1006 
1007 
1009  const char *path,
1010  int idx,
1011  int defVal){
1012  GWEN_DB_NODE *nn;
1013  const char *p;
1014  int res;
1015 
1016  assert(n);
1017  nn=GWEN_DB_GetValue(n, path, idx);
1018  if (!nn){
1020  "Value[%d] for \"%s\" not found, returning default value",
1021  idx, path);
1022  return defVal;
1023  }
1024 
1025  switch(nn->typ) {
1027  return nn->data.dataInt;
1029  p=nn->data.dataChar;
1030  assert(p);
1031  if (sscanf(p, "%d", &res)!=1) {
1033  "String [%s] in node is not an int value", p);
1034  return defVal;
1035  }
1036  return res;
1037 
1038  default:
1039  DBG_ERROR(GWEN_LOGDOMAIN, "Node is neither char nor int value");
1040  return defVal;
1041  }
1042 }
1043 
1044 
1045 
1047  uint32_t flags,
1048  const char *path,
1049  int val){
1050  GWEN_DB_NODE *nn;
1051  GWEN_DB_NODE *nv;
1052 
1053  /* select/create node */
1054  nn=GWEN_DB_GetNode(n,
1055  path,
1056  flags | GWEN_PATH_FLAGS_VARIABLE);
1057  if (!nn) {
1058  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1059  path);
1060  return 1;
1061  }
1062 
1063  /* delete contents of this variable if wanted */
1064  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
1065  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
1066  GWEN_DB_ClearNode(nn);
1067  }
1068 
1069  nv=GWEN_DB_ValueInt_new(val);
1070  if (flags & GWEN_DB_FLAGS_INSERT)
1071  GWEN_DB_Node_Insert(nn, nv);
1072  else
1073  GWEN_DB_Node_Append(nn, nv);
1074  DBG_VERBOUS(GWEN_LOGDOMAIN, "Added int value \"%d\" to variable \"%s\"", val, path);
1075  return 0;
1076 }
1077 
1078 
1079 
1081  const char *path,
1082  int idx,
1083  const void *defVal,
1084  unsigned int defValSize,
1085  unsigned int *returnValueSize){
1086  GWEN_DB_NODE *nn;
1087 
1088  assert(returnValueSize);
1089  nn=GWEN_DB_GetValue(n, path, idx);
1090  if (!nn){
1092  "Value for \"%s\" not found, returning default value",
1093  path);
1094  *returnValueSize=defValSize;
1095  return defVal;
1096  }
1097  if (nn->typ!=GWEN_DB_NodeType_ValueBin) {
1098  /* bad type */
1100  "Bad type for path \"%s\", returning default value",
1101  path);
1102  *returnValueSize=defValSize;
1103  return defVal;
1104  }
1105  *returnValueSize=nn->dataSize;
1106  return nn->data.dataBin;
1107 }
1108 
1109 
1110 
1112  uint32_t flags,
1113  const char *path,
1114  const void *val,
1115  unsigned int valSize){
1116  GWEN_DB_NODE *nn;
1117  GWEN_DB_NODE *nv;
1118 
1119  assert(val);
1120  /* select/create node */
1121  nn=GWEN_DB_GetNode(n,
1122  path,
1123  flags | GWEN_PATH_FLAGS_VARIABLE);
1124  if (!nn) {
1125  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1126  path);
1127  return 1;
1128  }
1129 
1130  /* delete contents of this variable if wanted */
1131  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
1132  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
1133  GWEN_DB_ClearNode(nn);
1134  }
1135 
1136  nv=GWEN_DB_ValueBin_new(val, valSize);
1137  if (flags & GWEN_DB_FLAGS_INSERT)
1138  GWEN_DB_Node_Insert(nn, nv);
1139  else
1140  GWEN_DB_Node_Append(nn, nv);
1141  DBG_VERBOUS(GWEN_LOGDOMAIN, "Added bin value to variable \"%s\"", path);
1142  return 0;
1143 }
1144 
1145 
1146 
1148  const char *path,
1149  int idx,
1150  void *defVal){
1151  GWEN_DB_NODE *nn;
1152 
1153  nn=GWEN_DB_GetValue(n, path, idx);
1154  if (!nn){
1156  "Value for \"%s\" not found, returning default value",
1157  path);
1158  return defVal;
1159  }
1160  if (nn->typ!=GWEN_DB_NodeType_ValuePtr) {
1161  /* bad type */
1163  "Bad type for path \"%s\", returning default value",
1164  path);
1165  return defVal;
1166  }
1167  return nn->data.dataPtr;
1168 }
1169 
1170 
1171 
1173  uint32_t flags,
1174  const char *path,
1175  void *val){
1176  GWEN_DB_NODE *nn;
1177  GWEN_DB_NODE *nv;
1178 
1179  /* select/create node */
1180  nn=GWEN_DB_GetNode(n,
1181  path,
1182  flags | GWEN_PATH_FLAGS_VARIABLE);
1183  if (!nn) {
1184  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1185  path);
1186  return 1;
1187  }
1188 
1189  /* delete contents of this variable if wanted */
1190  if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
1191  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
1192  GWEN_DB_ClearNode(nn);
1193  }
1194 
1195  nv=GWEN_DB_ValuePtr_new(val);
1196  if (flags & GWEN_DB_FLAGS_INSERT)
1197  GWEN_DB_Node_Insert(nn, nv);
1198  else
1199  GWEN_DB_Node_Append(nn, nv);
1200  DBG_VERBOUS(GWEN_LOGDOMAIN, "Added ptr value to variable \"%s\"", path);
1201 
1202  return 0;
1203 }
1204 
1205 
1206 
1207 
1208 
1209 
1210 
1211 
1212 
1213 
1214 
1215 
1216 
1217 
1218 
1219 
1221  uint32_t flags,
1222  const char *path) {
1223  GWEN_DB_NODE *nn;
1224 
1225  /* select/create node */
1226  nn=GWEN_DB_GetNode(n,
1227  path,
1228  flags & ~GWEN_PATH_FLAGS_VARIABLE);
1229  if (!nn) {
1230  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
1231  path);
1232  return NULL;
1233  }
1234 
1235  /* delete contents of this variable if wanted */
1236  if (flags & GWEN_DB_FLAGS_OVERWRITE_GROUPS) {
1237  DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing group \"%s\"", path);
1238  GWEN_DB_ClearNode(nn);
1239  }
1240 
1241  return nn;
1242 }
1243 
1244 
1245 
1247  assert(n);
1248  if (n->typ!=GWEN_DB_NodeType_Group) {
1249  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1250  return NULL;
1251  }
1252  return n->data.dataName;
1253 }
1254 
1255 
1256 
1257 void GWEN_DB_Dump(GWEN_DB_NODE *n, int insert){
1258  if (n) {
1259  int i;
1260 
1261  for (i=0; i<insert; i++)
1262  fprintf(stderr, " ");
1263 
1264  /* dump dynamic (allocated) data */
1265  switch(n->typ) {
1267  fprintf(stderr, "Group : \"%s\"\n", n->data.dataName);
1268  break;
1269  case GWEN_DB_NodeType_Var:
1270  fprintf(stderr, "Var : \"%s\"\n", n->data.dataName);
1271  break;
1273  fprintf(stderr, "Value : \"%s\" (char)\n", n->data.dataChar);
1274  break;
1276  fprintf(stderr, "Value : %d (int)\n", n->data.dataInt);
1277  break;
1279  char *buffer;
1280 
1281  buffer=(char*)GWEN_Memory_malloc((n->dataSize*2)+1);
1282  assert(buffer);
1283  if (GWEN_Text_ToHex(n->data.dataBin, n->dataSize,
1284  buffer, (n->dataSize*2)+1)==0) {
1285  fprintf(stderr, "Value : %d bytes (bin)\n", n->dataSize);
1286  }
1287  else {
1288  fprintf(stderr, "Value : %s (bin)\n", buffer);
1289  }
1290  GWEN_Memory_dealloc(buffer);
1291  break;
1292  }
1294  fprintf(stderr, "Value : %p (ptr)\n", n->data.dataPtr);
1295  break;
1296  default:
1297  fprintf(stderr, "[unknown node type %d]\n", n->typ);
1298  }
1299 
1300  /* dump children */
1301  if (n->children) {
1302  GWEN_DB_NODE *cn;
1303 
1304  cn=GWEN_DB_Node_List_First(n->children);
1305  while(cn) {
1306  GWEN_DB_Dump(cn, insert+4);
1307  cn=GWEN_DB_Node_List_Next(cn);
1308  }
1309  }
1310  }
1311  else {
1312  fprintf(stderr, "[no node]\n");
1313  }
1314 }
1315 
1316 
1317 
1319  assert(n);
1320  assert(nn);
1321 
1322  if (n->typ!=GWEN_DB_NodeType_Group) {
1323  DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
1324  return 0;
1325  }
1326 
1327  if (nn->typ!=GWEN_DB_NodeType_Group) {
1328  DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
1329  return 0;
1330  }
1331 
1332  GWEN_DB_Node_Append(n, nn);
1333  return 0;
1334 }
1335 
1336 
1337 
1339  assert(n);
1340  assert(nn);
1341 
1342  if (n->typ!=GWEN_DB_NodeType_Group) {
1343  DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
1344  return 0;
1345  }
1346 
1347  if (nn->typ!=GWEN_DB_NodeType_Group) {
1348  DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
1349  return 0;
1350  }
1351 
1352  GWEN_DB_Node_Insert(n, nn);
1353  return 0;
1354 }
1355 
1356 
1357 
1359  GWEN_DB_NODE *cpn;
1360 
1361  assert(n);
1362  assert(nn);
1363 
1364  if (n->typ!=GWEN_DB_NodeType_Group) {
1365  DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
1366  return -1;
1367  }
1368 
1369  if (nn->typ!=GWEN_DB_NodeType_Group) {
1370  DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
1371  GWEN_DB_Dump(nn, 1);
1372  return -1;
1373  }
1374 
1375  nn=GWEN_DB_Node_List_First(nn->children);
1376  while (nn) {
1377  DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating node");
1378  cpn=GWEN_DB_Node_dup(nn);
1379  GWEN_DB_Node_Append(n, cpn);
1380  nn=GWEN_DB_Node_List_Next(nn);
1381  } /* while */
1382  return 0;
1383 }
1384 
1385 
1386 
1388  assert(n);
1389  if (n->typ!=GWEN_DB_NodeType_Group) {
1390  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1391  return;
1392  }
1394 }
1395 
1396 
1397 int GWEN_DB_VariableExists(GWEN_DB_NODE *n, const char *path){
1398  GWEN_DB_NODE *nn;
1399 
1400  /* find corresponding node */
1401  assert(n);
1402  nn=GWEN_DB_GetNode(n,
1403  path,
1407  if (!nn) {
1408  DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found", path);
1409  return 0;
1410  }
1411 
1412  return 1;
1413 }
1414 
1415 
1416 
1418  const char *path,
1419  unsigned int i){
1420  return (GWEN_DB_GetValue(n, path, i)!=0);
1421 }
1422 
1423 
1424 
1426  const char *p){
1427  GWEN_DB_NODE *nn;
1428 
1429  nn=GWEN_DB_FindVar(n, p, 0);
1430  if (!nn)
1431  return GWEN_DB_NodeType_Unknown;
1432 
1433  nn=GWEN_DB_GetFirstValue(nn);
1434  if (!nn)
1435  return GWEN_DB_NodeType_Unknown;
1436  return GWEN_DB_GetValueType(nn);
1437 }
1438 
1439 
1440 
1442  const char *path,
1443  unsigned int i){
1444  GWEN_DB_NODE *nn;
1445 
1446  nn=GWEN_DB_GetValue(n, path, i);
1447  if (!nn)
1448  return GWEN_DB_NodeType_Unknown;
1449  return GWEN_DB_GetValueType(nn);
1450 }
1451 
1452 
1453 void GWEN_DB_GroupRename(GWEN_DB_NODE *n, const char *newname){
1454  assert(n);
1455  assert(newname);
1456  assert(n->typ==GWEN_DB_NodeType_Group);
1457  GWEN_Memory_dealloc(n->data.dataName);
1458  n->data.dataName=GWEN_Memory_strdup(newname);
1459 }
1460 
1461 
1462 
1463 
1464 
1465 
1466 
1468  assert(n);
1469  return n->typ==GWEN_DB_NodeType_Group;
1470 }
1471 
1472 
1473 
1475  assert(n);
1476  return n->typ==GWEN_DB_NodeType_Var;
1477 }
1478 
1479 
1480 
1482  assert(n);
1483  return (n->typ>=GWEN_DB_NodeType_ValueChar &&
1484  n->typ>=GWEN_DB_NodeType_ValueLast);
1485 }
1486 
1487 
1488 
1490  void *user_data){
1491  GWEN_DB_NODE *iter;
1492  void *res;
1493 
1494  assert(node);
1495  assert(func);
1496 
1497  iter=GWEN_DB_GetFirstGroup(node);
1498  res=NULL;
1499  while(iter){
1500  res=(*func)(iter, user_data);
1501  if (res) {
1502  break;
1503  }
1504  iter=GWEN_DB_GetNextGroup(iter);
1505  }
1506  return res;
1507 }
1508 
1509 
1510 
1511 void *GWEN_DB_count_cb(GWEN_UNUSED GWEN_DB_NODE *node, void *user_data){
1512  unsigned int *a = user_data;
1513  ++(*a);
1514  return NULL;
1515 }
1516 
1517 
1518 
1519 unsigned int GWEN_DB_Groups_Count(const GWEN_DB_NODE *node){
1520  unsigned int res = 0;
1522  return res;
1523 }
1524 
1525 
1526 
1528  void *user_data){
1529  GWEN_DB_NODE *iter;
1530  void *res;
1531 
1532  assert(node);
1533  assert(func);
1534 
1535  iter=GWEN_DB_GetFirstVar(node);
1536  res=NULL;
1537  while(iter){
1538  res=(*func)(iter, user_data);
1539  if (res) {
1540  break;
1541  }
1542  iter=GWEN_DB_GetNextVar(iter);
1543  }
1544  return res;
1545 }
1546 
1547 
1548 
1549 unsigned int GWEN_DB_Variables_Count(const GWEN_DB_NODE *node){
1550  unsigned int res = 0;
1552  return res;
1553 }
1554 
1555 
1556 
1558  void *user_data){
1559  GWEN_DB_NODE *iter;
1560  void *res;
1561 
1562  assert(node);
1563  assert(func);
1564 
1565  iter=GWEN_DB_GetFirstValue(node);
1566  res=NULL;
1567  while(iter){
1568  res=(*func)(iter, user_data);
1569  if (res) {
1570  break;
1571  }
1572  iter=GWEN_DB_GetNextValue(iter);
1573  }
1574  return res;
1575 }
1576 
1577 
1578 
1579 unsigned int GWEN_DB_Values_Count(const GWEN_DB_NODE *node){
1580  unsigned int res = 0;
1582  return res;
1583 }
1584 
1585 
1586 
1588  assert(n);
1589  return n->nodeFlags;
1590 }
1591 
1592 
1593 
1595  uint32_t flags){
1596  assert(n);
1597  n->nodeFlags=flags;
1598 }
1599 
1600 
1601 
1603  uint32_t newflags,
1604  uint32_t mask){
1605  uint32_t flags;
1606 
1607  assert(n);
1608 
1609  while(n) {
1610  flags=n->nodeFlags;
1611  flags=((flags^newflags)&(mask))^flags;
1612  n->nodeFlags=flags;
1613  n=n->parent;
1614  } /* while */
1615 }
1616 
1617 
1618 
1620  uint32_t newflags,
1621  uint32_t mask){
1622  uint32_t flags;
1623  GWEN_DB_NODE *cn;
1624 
1625  assert(n);
1626 
1627  flags=n->nodeFlags;
1628  flags=((flags^newflags)&(mask))^flags;
1629  n->nodeFlags=flags;
1630 
1631  cn=GWEN_DB_Node_List_First(n->children);
1632  while(cn) {
1633  GWEN_DB_ModifyBranchFlagsDown(cn, newflags, mask);
1634  cn=GWEN_DB_Node_List_Next(cn);
1635  } /* while cn */
1636 }
1637 
1638 
1639 
1641  GWEN_DB_NODE *nn;
1642 
1643  assert(n);
1644  nn=n->parent;
1645  while(nn && nn->typ!=GWEN_DB_NodeType_Group)
1646  nn=nn->parent;
1647  return nn;
1648 }
1649 
1650 
1651 
1653  GWEN_DB_NODE *nn;
1654 
1655  assert(n);
1656  if (n->typ!=GWEN_DB_NodeType_Group) {
1657  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1658  return NULL;
1659  }
1660  nn=GWEN_DB_Node_List_First(n->children);
1661  while(nn) {
1662  if ((nn->typ==GWEN_DB_NodeType_Group) &&
1663  (-1!=GWEN_Text_ComparePattern(nn->data.dataName, name, 0)))
1664  break;
1665  nn=GWEN_DB_Node_List_Next(nn);
1666  } /* while node */
1667  return nn;
1668 }
1669 
1670 
1671 
1673  GWEN_DB_NODE *og;
1674 
1675  og=n;
1676  assert(n);
1677  if (n->typ!=GWEN_DB_NodeType_Group) {
1678  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1679  return NULL;
1680  }
1681  n=GWEN_DB_GetNextGroup(n);
1682  while(n) {
1683  if (-1!=GWEN_Text_ComparePattern(n->data.dataName, name, 0))
1684  break;
1685  n=GWEN_DB_GetNextGroup(n);
1686  } /* while node */
1687  assert(n!=og);
1688  return n;
1689 }
1690 
1691 
1692 
1694  GWEN_DB_NODE *nn;
1695 
1696  assert(n);
1697  if (n->typ!=GWEN_DB_NodeType_Group) {
1698  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
1699  return NULL;
1700  }
1701 
1702  nn=GWEN_DB_Node_List_First(n->children);
1703  while(nn) {
1704  if ((nn->typ==GWEN_DB_NodeType_Var) &&
1705  (-1!=GWEN_Text_ComparePattern(nn->data.dataName, name, 0)))
1706  break;
1707  nn=GWEN_DB_Node_List_Next(nn);
1708  } /* while node */
1709 
1710  return nn;
1711 }
1712 
1713 
1714 
1716  GWEN_DB_NODE *og;
1717 
1718  og=n;
1719  assert(n);
1720  if (n->typ!=GWEN_DB_NodeType_Var) {
1721  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
1722  return NULL;
1723  }
1724  n=GWEN_DB_GetNextVar(n);
1725  while(n) {
1726  if (-1!=GWEN_Text_ComparePattern(n->data.dataName, name, 0))
1727  break;
1728  n=GWEN_DB_GetNextVar(n);
1729  } /* while node */
1730  assert(n!=og);
1731  return n;
1732 }
1733 
1734 
1735 
1737  assert(n);
1738  if (n->typ!=GWEN_DB_NodeType_Var) {
1739  DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
1740  return NULL;
1741  }
1742  return n->data.dataName;
1743 }
1744 
1745 
1746 
1747 void GWEN_DB_VariableRename(GWEN_DB_NODE *n, const char *newname){
1748  assert(n);
1749  assert(newname);
1750  assert(n->typ==GWEN_DB_NodeType_Var);
1751  GWEN_Memory_dealloc(n->data.dataName);
1752  n->data.dataName=GWEN_Memory_strdup(newname);
1753 }
1754 
1755 
1756 
1757 
1758 
1759 
1760 #include "dbrw.c"
1761 
1762 
1763 
1764 
1765 
1766 
1767 
1768 
1769