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