00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #define DISABLE_DEBUGLOG
00031
00032 #include "db_p.h"
00033 #include <gwenhywfar/misc.h>
00034 #include <gwenhywfar/debug.h>
00035 #include <gwenhywfar/path.h>
00036 #include <gwenhywfar/text.h>
00037 #include <gwenhywfar/dbio.h>
00038 #include <gwenhywfar/fslock.h>
00039 #include <gwenhywfar/fastbuffer.h>
00040 #include <gwenhywfar/syncio_file.h>
00041 #include <gwenhywfar/syncio_memory.h>
00042
00043 #include <stdlib.h>
00044 #include <assert.h>
00045 #include <string.h>
00046 #include <errno.h>
00047 #include <ctype.h>
00048
00049 #include <sys/types.h>
00050 #ifdef HAVE_SYS_STAT_H
00051 # include <sys/stat.h>
00052 #endif
00053 #ifdef HAVE_FCNTL_H
00054 # include <fcntl.h>
00055 #endif
00056 #ifdef HAVE_UNISTD_H
00057 # include <unistd.h>
00058 #endif
00059
00060
00061 #define GWEN_DB_NODE_FLAGS_MASK_INTERNAL 0xf0000000
00062 #define GWEN_DB_NODE_FLAGS_GROUP 0x80000000
00063
00064
00065 GWEN_LIST_FUNCTIONS(GWEN_DB_NODE, GWEN_DB_Node)
00066
00067
00068
00069 GWEN_DB_NODE *GWEN_DB_Node_new(GWEN_DB_NODE_TYPE t){
00070 GWEN_DB_NODE *node;
00071
00072 GWEN_NEW_OBJECT(GWEN_DB_NODE, node);
00073 GWEN_LIST_INIT(GWEN_DB_NODE, node);
00074 node->typ=t;
00075 return (GWEN_DB_NODE*)node;
00076 }
00077
00078
00079
00080
00081 GWEN_DB_NODE *GWEN_DB_ValueBin_new(const void *data,
00082 unsigned int datasize){
00083 GWEN_DB_NODE *n;
00084
00085 n=GWEN_DB_Node_new(GWEN_DB_NodeType_ValueBin);
00086 if (datasize) {
00087 assert(data);
00088 n->dataSize=datasize;
00089 n->data.dataBin=(char*)GWEN_Memory_malloc(datasize);
00090 assert(n->data.dataBin);
00091 memmove(n->data.dataBin, data, datasize);
00092 }
00093 return n;
00094 }
00095
00096
00097
00098 GWEN_DB_NODE *GWEN_DB_ValueInt_new(int data) {
00099 GWEN_DB_NODE *n;
00100
00101 n=GWEN_DB_Node_new(GWEN_DB_NodeType_ValueInt);
00102 n->data.dataInt=data;
00103 return n;
00104 }
00105
00106
00107
00108 GWEN_DB_NODE *GWEN_DB_ValueChar_new(const char *data) {
00109 GWEN_DB_NODE *n;
00110
00111 n=GWEN_DB_Node_new(GWEN_DB_NodeType_ValueChar);
00112 if (data)
00113 n->data.dataChar=GWEN_Memory_strdup(data);
00114 else
00115 n->data.dataChar=GWEN_Memory_strdup("");
00116 return n;
00117 }
00118
00119
00120
00121 GWEN_DB_NODE *GWEN_DB_ValuePtr_new(void *data) {
00122 GWEN_DB_NODE *n;
00123
00124 n=GWEN_DB_Node_new(GWEN_DB_NodeType_ValuePtr);
00125 n->data.dataPtr=data;
00126 return n;
00127 }
00128
00129
00130
00131 GWEN_DB_NODE *GWEN_DB_Group_new(const char *name){
00132 GWEN_DB_NODE *n;
00133
00134 assert(name);
00135 n=GWEN_DB_Node_new(GWEN_DB_NodeType_Group);
00136 if (name)
00137 n->data.dataName=GWEN_Memory_strdup(name);
00138 else
00139 n->data.dataName=GWEN_Memory_strdup("");
00140 n->children=GWEN_DB_Node_List_new();
00141 return n;
00142 }
00143
00144
00145
00146 GWEN_DB_NODE *GWEN_DB_Var_new(const char *name){
00147 GWEN_DB_NODE *n;
00148
00149 assert(name);
00150 n=GWEN_DB_Node_new(GWEN_DB_NodeType_Var);
00151 if (name)
00152 n->data.dataName=GWEN_Memory_strdup(name);
00153 else
00154 n->data.dataName=GWEN_Memory_strdup("");
00155 n->children=GWEN_DB_Node_List_new();
00156 return n;
00157 }
00158
00159
00160
00161 void GWEN_DB_Node_Append_UnDirty(GWEN_DB_NODE *parent,
00162 GWEN_DB_NODE *n){
00163 assert(parent);
00164 assert(n);
00165 assert(parent!=n);
00166
00167 assert(parent->children!=NULL);
00168 GWEN_DB_Node_List_Add(n, parent->children);
00169
00170 n->parent=parent;
00171 }
00172
00173
00174
00175 void GWEN_DB_Node_Append(GWEN_DB_NODE *parent,
00176 GWEN_DB_NODE *n){
00177 GWEN_DB_Node_Append_UnDirty(parent, n);
00178 GWEN_DB_ModifyBranchFlagsUp(parent,
00179 GWEN_DB_NODE_FLAGS_DIRTY,
00180 GWEN_DB_NODE_FLAGS_DIRTY);
00181 }
00182
00183
00184
00185 void GWEN_DB_Node_InsertUnDirty(GWEN_DB_NODE *parent,
00186 GWEN_DB_NODE *n){
00187 assert(parent);
00188 assert(n);
00189 assert(parent!=n);
00190
00191 assert(parent->children!=NULL);
00192 GWEN_DB_Node_List_Insert(n, parent->children);
00193
00194 n->parent=parent;
00195 }
00196
00197
00198
00199 void GWEN_DB_Node_Insert(GWEN_DB_NODE *parent,
00200 GWEN_DB_NODE *n){
00201 GWEN_DB_Node_InsertUnDirty(parent, n);
00202 GWEN_DB_ModifyBranchFlagsUp(parent,
00203 GWEN_DB_NODE_FLAGS_DIRTY,
00204 GWEN_DB_NODE_FLAGS_DIRTY);
00205 }
00206
00207
00208
00209 void GWEN_DB_Node_Unlink_UnDirty(GWEN_DB_NODE *n) {
00210 GWEN_DB_NODE *parent;
00211
00212 assert(n);
00213 parent=n->parent;
00214 if (!parent) {
00215 DBG_WARN(GWEN_LOGDOMAIN, "Node is not linked, nothing to do");
00216 return;
00217 }
00218
00219 GWEN_DB_Node_List_Del(n);
00220 n->parent=NULL;
00221 }
00222
00223
00224
00225 void GWEN_DB_Node_Unlink(GWEN_DB_NODE *n) {
00226 GWEN_DB_NODE *parent;
00227
00228 assert(n);
00229 parent=n->parent;
00230 assert(parent);
00231
00232 GWEN_DB_Node_Unlink_UnDirty(n);
00233 GWEN_DB_ModifyBranchFlagsUp(parent,
00234 GWEN_DB_NODE_FLAGS_DIRTY,
00235 GWEN_DB_NODE_FLAGS_DIRTY);
00236 }
00237
00238
00239
00240 void GWEN_DB_Node_free(GWEN_DB_NODE *n){
00241 if (n) {
00242 GWEN_LIST_FINI(GWEN_DB_NODE, n);
00243
00244
00245 if (n->children)
00246 GWEN_DB_Node_List_free(n->children);
00247
00248
00249 switch(n->typ) {
00250 case GWEN_DB_NodeType_Group:
00251 case GWEN_DB_NodeType_Var:
00252 GWEN_Memory_dealloc(n->data.dataName);
00253 break;
00254
00255 case GWEN_DB_NodeType_ValueChar:
00256 GWEN_Memory_dealloc(n->data.dataChar);
00257 break;
00258 case GWEN_DB_NodeType_ValueBin:
00259 GWEN_Memory_dealloc(n->data.dataBin);
00260 break;
00261 case GWEN_DB_NodeType_ValuePtr:
00262 case GWEN_DB_NodeType_ValueInt:
00263 break;
00264 default:
00265 DBG_WARN(GWEN_LOGDOMAIN, "Unknown node type (%d)", n->typ);
00266 }
00267 DBG_VERBOUS(GWEN_LOGDOMAIN, "Freeing node itself");
00268 GWEN_FREE_OBJECT(n);
00269 }
00270 }
00271
00272
00273
00274 GWEN_DB_NODE *GWEN_DB_Node_dup(const GWEN_DB_NODE *n){
00275 GWEN_DB_NODE *nn;
00276
00277 switch(n->typ) {
00278 case GWEN_DB_NodeType_Group:
00279 DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating group \"%s\"",
00280 n->data.dataName);
00281 nn=GWEN_DB_Group_new(n->data.dataName);
00282 break;
00283 case GWEN_DB_NodeType_Var:
00284 DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating variable \"%s\"",
00285 n->data.dataName);
00286 nn=GWEN_DB_Var_new(n->data.dataName);
00287 break;
00288 case GWEN_DB_NodeType_ValueChar:
00289 nn=GWEN_DB_ValueChar_new(n->data.dataChar);
00290 break;
00291 case GWEN_DB_NodeType_ValueBin:
00292 nn=GWEN_DB_ValueBin_new(n->data.dataBin, n->dataSize);
00293 break;
00294 case GWEN_DB_NodeType_ValuePtr:
00295 nn=GWEN_DB_ValuePtr_new(n->data.dataPtr);
00296 break;
00297 case GWEN_DB_NodeType_ValueInt:
00298 nn=GWEN_DB_ValueInt_new(n->data.dataInt);
00299 break;
00300 default:
00301 DBG_WARN(GWEN_LOGDOMAIN, "Unknown node type (%d)", n->typ);
00302 nn=0;
00303 }
00304
00305
00306 if (nn) {
00307 const GWEN_DB_NODE *cn;
00308
00309 cn=GWEN_DB_Node_List_First(n->children);
00310 while(cn) {
00311 GWEN_DB_NODE *ncn;
00312
00313
00314 ncn=GWEN_DB_Node_dup(cn);
00315 if (!ncn) {
00316 GWEN_DB_Node_free(nn);
00317 return NULL;
00318 }
00319 GWEN_DB_Node_Append_UnDirty(nn, ncn);
00320 cn=GWEN_DB_Node_List_Next(cn);
00321 }
00322 }
00323
00324 return nn;
00325 }
00326
00327
00328
00329 void GWEN_DB_Group_free(GWEN_DB_NODE *n){
00330 GWEN_DB_Node_free(n);
00331 }
00332
00333
00334
00335 GWEN_DB_NODE *GWEN_DB_Group_dup(const GWEN_DB_NODE *n){
00336 assert(n);
00337 if (n->typ!=GWEN_DB_NodeType_Group) {
00338 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00339 return NULL;
00340 }
00341 return GWEN_DB_Node_dup(n);
00342 }
00343
00344
00345
00346 GWEN_DB_NODE *GWEN_DB_GetFirstGroup(GWEN_DB_NODE *n){
00347 GWEN_DB_NODE *nn;
00348
00349 assert(n);
00350 if (n->typ!=GWEN_DB_NodeType_Group) {
00351 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00352 return NULL;
00353 }
00354 assert(n->children);
00355 nn=GWEN_DB_Node_List_First(n->children);
00356 while(nn) {
00357 if (nn->typ==GWEN_DB_NodeType_Group)
00358 break;
00359 nn=GWEN_DB_Node_List_Next(nn);
00360 }
00361 return nn;
00362 }
00363
00364
00365
00366 GWEN_DB_NODE *GWEN_DB_GetNextGroup(GWEN_DB_NODE *n){
00367 assert(n);
00368 if (n->typ!=GWEN_DB_NodeType_Group) {
00369 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00370 return NULL;
00371 }
00372 n=GWEN_DB_Node_List_Next(n);
00373 while(n) {
00374 if (n->typ==GWEN_DB_NodeType_Group)
00375 break;
00376 n=GWEN_DB_Node_List_Next(n);
00377 }
00378 return n;
00379 }
00380
00381
00382
00383 GWEN_DB_NODE *GWEN_DB_GetFirstVar(GWEN_DB_NODE *n){
00384 GWEN_DB_NODE *nn;
00385
00386 assert(n);
00387 if (n->typ!=GWEN_DB_NodeType_Group) {
00388 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00389 return NULL;
00390 }
00391 assert(n->children);
00392 nn=GWEN_DB_Node_List_First(n->children);
00393 while(nn) {
00394 if (nn->typ==GWEN_DB_NodeType_Var)
00395 break;
00396 nn=GWEN_DB_Node_List_Next(nn);
00397 }
00398 return nn;
00399 }
00400
00401
00402
00403 GWEN_DB_NODE *GWEN_DB_GetNextVar(GWEN_DB_NODE *n){
00404 assert(n);
00405 if (n->typ!=GWEN_DB_NodeType_Var) {
00406 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
00407 return NULL;
00408 }
00409 n=GWEN_DB_Node_List_Next(n);
00410 while(n) {
00411 if (n->typ==GWEN_DB_NodeType_Var)
00412 break;
00413 n=GWEN_DB_Node_List_Next(n);
00414 }
00415 return n;
00416 }
00417
00418
00419
00420 GWEN_DB_NODE *GWEN_DB_GetFirstValue(GWEN_DB_NODE *n){
00421 GWEN_DB_NODE *nn;
00422
00423 assert(n);
00424 if (n->typ!=GWEN_DB_NodeType_Var) {
00425 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
00426 return NULL;
00427 }
00428 assert(n->children);
00429 nn=GWEN_DB_Node_List_First(n->children);
00430 while(nn) {
00431 if (nn->typ>=GWEN_DB_NodeType_ValueChar &&
00432 nn->typ<GWEN_DB_NodeType_ValueLast) {
00433 break;
00434 }
00435 nn=GWEN_DB_Node_List_Next(nn);
00436 }
00437 return nn;
00438 }
00439
00440
00441
00442 GWEN_DB_NODE *GWEN_DB_GetNextValue(GWEN_DB_NODE *n){
00443 assert(n);
00444 if (n->typ<GWEN_DB_NodeType_ValueChar ||
00445 n->typ>=GWEN_DB_NodeType_ValueLast) {
00446 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a value");
00447 return NULL;
00448 }
00449
00450 n=GWEN_DB_Node_List_Next(n);
00451 while(n) {
00452 if (n->typ>=GWEN_DB_NodeType_ValueChar &&
00453 n->typ<GWEN_DB_NodeType_ValueLast) {
00454 break;
00455 }
00456 n=GWEN_DB_Node_List_Next(n);
00457 }
00458 return n;
00459 }
00460
00461
00462
00463 GWEN_DB_NODE_TYPE GWEN_DB_GetValueType(GWEN_DB_NODE *n){
00464 assert(n);
00465 if (n->typ>=GWEN_DB_NodeType_ValueChar &&
00466 n->typ<GWEN_DB_NodeType_ValueLast) {
00467 return n->typ;
00468 }
00469 else {
00470 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a value");
00471 return GWEN_DB_NodeType_Unknown;
00472 }
00473 }
00474
00475
00476
00477 const char *GWEN_DB_GetCharValueFromNode(const GWEN_DB_NODE *n){
00478 assert(n);
00479 if (n->typ!=GWEN_DB_NodeType_ValueChar) {
00480 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a char value");
00481 return NULL;
00482 }
00483 return n->data.dataChar;
00484 }
00485
00486
00487
00488 int GWEN_DB_SetCharValueInNode(GWEN_DB_NODE *n, const char *s) {
00489 assert(n);
00490 assert(s);
00491
00492 if (n->typ!=GWEN_DB_NodeType_ValueChar) {
00493 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a char value");
00494 return GWEN_ERROR_INVALID;
00495 }
00496
00497 GWEN_Memory_dealloc(n->data.dataChar);
00498 n->data.dataChar=GWEN_Memory_strdup(s);
00499 return 0;
00500 }
00501
00502
00503
00504 int GWEN_DB_GetIntValueFromNode(const GWEN_DB_NODE *n){
00505 const char *p;
00506 int res;
00507
00508 assert(n);
00509
00510 switch(n->typ) {
00511 case GWEN_DB_NodeType_ValueInt:
00512 return n->data.dataInt;
00513 case GWEN_DB_NodeType_ValueChar:
00514 p=n->data.dataChar;
00515 assert(p);
00516 if (sscanf(p, "%d", &res)!=1) {
00517 DBG_ERROR(GWEN_LOGDOMAIN, "String in node is not an int value");
00518 return 0;
00519 }
00520 return res;
00521
00522 default:
00523 DBG_ERROR(GWEN_LOGDOMAIN, "Node is neither char nor int value");
00524 return 0;
00525 }
00526 }
00527
00528
00529
00530 const void *GWEN_DB_GetBinValueFromNode(const GWEN_DB_NODE *n,
00531 unsigned int *size){
00532 assert(n);
00533
00534 if (n->typ!=GWEN_DB_NodeType_ValueBin) {
00535 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a binary value");
00536 return NULL;
00537 }
00538
00539 *size=n->dataSize;
00540 return n->data.dataBin;
00541 }
00542
00543
00544
00545 GWEN_DB_NODE *GWEN_DB_FindGroup(GWEN_DB_NODE *n,
00546 const char *name,
00547 int idx) {
00548 GWEN_DB_NODE *nn;
00549
00550 assert(n);
00551 assert(name);
00552
00553 if (n->typ!=GWEN_DB_NodeType_Group) {
00554 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00555 return NULL;
00556 }
00557
00558
00559 assert(n->children);
00560 nn=GWEN_DB_Node_List_First(n->children);
00561 while(nn) {
00562 if (nn->typ==GWEN_DB_NodeType_Group) {
00563 if (strcasecmp(nn->data.dataName, name)==0) {
00564 if (!idx)
00565
00566 return nn;
00567 idx--;
00568 }
00569 }
00570 nn=GWEN_DB_Node_List_Next(nn);
00571 }
00572
00573 return NULL;
00574 }
00575
00576
00577
00578 GWEN_DB_NODE *GWEN_DB_FindVar(GWEN_DB_NODE *n,
00579 const char *name,
00580 int idx) {
00581 GWEN_DB_NODE *nn;
00582
00583 assert(n);
00584 assert(name);
00585
00586 if (n->typ!=GWEN_DB_NodeType_Group) {
00587 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00588 return NULL;
00589 }
00590
00591
00592 assert(n->children);
00593 nn=GWEN_DB_Node_List_First(n->children);
00594 while(nn) {
00595 if (nn->typ==GWEN_DB_NodeType_Var) {
00596 if (strcasecmp(nn->data.dataName, name)==0) {
00597 if (!idx)
00598
00599 return nn;
00600 idx--;
00601 }
00602 }
00603 nn=GWEN_DB_Node_List_Next(nn);
00604 }
00605
00606 return NULL;
00607 }
00608
00609
00610
00611
00612
00613
00614
00615 void* GWEN_DB_HandlePath(const char *entry,
00616 void *data,
00617 int idx,
00618 uint32_t flags) {
00619 GWEN_DB_NODE *n;
00620 GWEN_DB_NODE *nn;
00621
00622 n=(GWEN_DB_NODE*)data;
00623
00624
00625 if (
00626 ((flags & GWEN_PATH_FLAGS_LAST) &&
00627 (((flags & GWEN_PATH_FLAGS_VARIABLE) &&
00628 (flags & GWEN_PATH_FLAGS_CREATE_VAR)) ||
00629 (!(flags & GWEN_PATH_FLAGS_VARIABLE) &&
00630 (flags & GWEN_PATH_FLAGS_CREATE_GROUP)))
00631 ) ||
00632 (
00633 !(flags & GWEN_PATH_FLAGS_LAST) &&
00634 (flags & GWEN_PATH_FLAGS_PATHCREATE))
00635 ) {
00636
00637 if (idx!=0) {
00638 DBG_INFO(GWEN_LOGDOMAIN, "Index is not 0, not creating %s[%d]",
00639 entry, idx);
00640 return 0;
00641 }
00642 if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00643 DBG_VERBOUS(GWEN_LOGDOMAIN,
00644 "Unconditionally creating variable \"%s\"", entry);
00645 nn=GWEN_DB_Var_new(entry);
00646 if (flags & GWEN_DB_FLAGS_INSERT)
00647 GWEN_DB_Node_Insert(n, nn);
00648 else
00649 GWEN_DB_Node_Append(n, nn);
00650 return nn;
00651 }
00652 else {
00653 DBG_VERBOUS(GWEN_LOGDOMAIN,
00654 "Unconditionally creating group \"%s\"", entry);
00655 nn=GWEN_DB_Group_new(entry);
00656 if (flags & GWEN_DB_FLAGS_INSERT)
00657 GWEN_DB_Node_Insert(n, nn);
00658 else
00659 GWEN_DB_Node_Append(n, nn);
00660 return nn;
00661 }
00662 }
00663
00664
00665 if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00666 nn=GWEN_DB_FindVar(n, entry, idx);
00667 }
00668 else {
00669 nn=GWEN_DB_FindGroup(n, entry, idx);
00670 }
00671
00672 if (!nn) {
00673
00674 if (
00675 (!(flags & GWEN_PATH_FLAGS_LAST) &&
00676 (flags & GWEN_PATH_FLAGS_PATHMUSTEXIST)) ||
00677 (flags & GWEN_PATH_FLAGS_NAMEMUSTEXIST)
00678 ) {
00679 if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00680 DBG_VERBOUS(GWEN_LOGDOMAIN,
00681 "Variable \"%s\" does not exist", entry);
00682 }
00683 else {
00684 DBG_VERBOUS(GWEN_LOGDOMAIN,
00685 "Group \"%s\" does not exist", entry);
00686 }
00687 return 0;
00688 }
00689
00690 if (idx!=0) {
00691 DBG_INFO(GWEN_LOGDOMAIN, "Index is not 0, not creating %s[%d]",
00692 entry, idx);
00693 return 0;
00694 }
00695 if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00696 DBG_VERBOUS(GWEN_LOGDOMAIN,
00697 "Variable \"%s\" not found, creating", entry);
00698 nn=GWEN_DB_Var_new(entry);
00699 if (flags & GWEN_DB_FLAGS_INSERT)
00700 GWEN_DB_Node_Insert(n, nn);
00701 else
00702 GWEN_DB_Node_Append(n, nn);
00703 }
00704 else {
00705 DBG_VERBOUS(GWEN_LOGDOMAIN,
00706 "Group \"%s\" not found, creating", entry);
00707 nn=GWEN_DB_Group_new(entry);
00708 if (flags & GWEN_DB_FLAGS_INSERT)
00709 GWEN_DB_Node_Insert(n, nn);
00710 else
00711 GWEN_DB_Node_Append(n, nn);
00712 }
00713 }
00714 else {
00715
00716 if (
00717 ((flags & GWEN_PATH_FLAGS_LAST) &&
00718 (flags & GWEN_PATH_FLAGS_NAMEMUSTNOTEXIST)) ||
00719 (!(flags & GWEN_PATH_FLAGS_LAST) &&
00720 (flags & GWEN_PATH_FLAGS_PATHMUSTNOTEXIST))
00721 ) {
00722 DBG_VERBOUS(GWEN_LOGDOMAIN, "Entry \"%s\" already exists", entry);
00723 return 0;
00724 }
00725 }
00726
00727 return nn;
00728 }
00729
00730
00731
00732 GWEN_DB_NODE *GWEN_DB_GetNode(GWEN_DB_NODE *n,
00733 const char *path,
00734 uint32_t flags){
00735 return (GWEN_DB_NODE*)GWEN_Path_HandleWithIdx(path,
00736 n,
00737 flags,
00738 GWEN_DB_HandlePath);
00739 }
00740
00741
00742
00743 void GWEN_DB_ClearNode(GWEN_DB_NODE *n) {
00744 assert(n);
00745 if (n->children)
00746 GWEN_DB_Node_List_Clear(n->children);
00747 }
00748
00749
00750
00751 GWEN_DB_NODE *GWEN_DB_GetValue(GWEN_DB_NODE *n,
00752 const char *path,
00753 int idx) {
00754 GWEN_DB_NODE *nn;
00755
00756
00757 nn=GWEN_DB_GetNode(n,
00758 path,
00759 GWEN_PATH_FLAGS_PATHMUSTEXIST |
00760 GWEN_PATH_FLAGS_NAMEMUSTEXIST |
00761 GWEN_PATH_FLAGS_VARIABLE);
00762 if (!nn) {
00763 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
00764 path);
00765 return 0;
00766 }
00767
00768
00769 assert(nn->children);
00770 nn=GWEN_DB_Node_List_First(nn->children);
00771 while(nn) {
00772 if (nn->typ>=GWEN_DB_NodeType_ValueChar &&
00773 nn->typ<GWEN_DB_NodeType_ValueLast) {
00774 if (!idx)
00775 return nn;
00776 idx--;
00777 }
00778 nn=GWEN_DB_Node_List_Next(nn);
00779 }
00780
00781 DBG_VERBOUS(GWEN_LOGDOMAIN, "No value[%d] for path \"%s\"",
00782 idx, path);
00783 return NULL;
00784 }
00785
00786
00787
00788 int GWEN_DB_DeleteVar(GWEN_DB_NODE *n,
00789 const char *path) {
00790 GWEN_DB_NODE *nn;
00791
00792
00793 nn=GWEN_DB_GetNode(n,
00794 path,
00795 GWEN_PATH_FLAGS_PATHMUSTEXIST |
00796 GWEN_PATH_FLAGS_NAMEMUSTEXIST |
00797 GWEN_PATH_FLAGS_VARIABLE);
00798 if (!nn) {
00799 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
00800 path);
00801 return 1;
00802 }
00803 GWEN_DB_Node_Unlink(nn);
00804 GWEN_DB_Node_free(nn);
00805 return 0;
00806 }
00807
00808
00809
00810 int GWEN_DB_DeleteGroup(GWEN_DB_NODE *n,
00811 const char *path) {
00812 GWEN_DB_NODE *nn;
00813
00814
00815 nn=GWEN_DB_GetNode(n,
00816 path,
00817 GWEN_PATH_FLAGS_PATHMUSTEXIST |
00818 GWEN_PATH_FLAGS_NAMEMUSTEXIST);
00819 if (!nn) {
00820 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
00821 path);
00822 return 1;
00823 }
00824 GWEN_DB_Node_Unlink(nn);
00825 GWEN_DB_Node_free(nn);
00826 return 0;
00827 }
00828
00829
00830
00831 int GWEN_DB_ClearGroup(GWEN_DB_NODE *n,
00832 const char *path){
00833 assert(n);
00834 if (path) {
00835 GWEN_DB_NODE *nn;
00836
00837
00838 nn=GWEN_DB_GetNode(n,
00839 path,
00840 GWEN_PATH_FLAGS_PATHMUSTEXIST |
00841 GWEN_PATH_FLAGS_NAMEMUSTEXIST);
00842 if (!nn) {
00843 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
00844 path);
00845 return 1;
00846 }
00847 GWEN_DB_ClearNode(nn);
00848 }
00849 else {
00850 GWEN_DB_ClearNode(n);
00851 }
00852 return 0;
00853 }
00854
00855
00856
00857 const char *GWEN_DB_GetCharValue(GWEN_DB_NODE *n,
00858 const char *path,
00859 int idx,
00860 const char *defVal){
00861 GWEN_DB_NODE *nn;
00862
00863 nn=GWEN_DB_GetValue(n, path, idx);
00864 if (!nn){
00865 DBG_VERBOUS(GWEN_LOGDOMAIN,
00866 "Value for \"%s\" not found, returning default value",
00867 path);
00868 return defVal;
00869 }
00870 if (nn->typ!=GWEN_DB_NodeType_ValueChar) {
00871
00872 DBG_VERBOUS(GWEN_LOGDOMAIN,
00873 "Bad type for path \"%s\", returning default value",
00874 path);
00875 return defVal;
00876 }
00877 return nn->data.dataChar;
00878 }
00879
00880
00881
00882 int GWEN_DB_SetCharValue(GWEN_DB_NODE *n,
00883 uint32_t flags,
00884 const char *path,
00885 const char *val){
00886 GWEN_DB_NODE *nn;
00887 GWEN_DB_NODE *nv;
00888
00889
00890 nn=GWEN_DB_GetNode(n,
00891 path,
00892 flags | GWEN_PATH_FLAGS_VARIABLE);
00893 if (!nn) {
00894 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
00895 path);
00896 return 1;
00897 }
00898
00899 nv=GWEN_DB_ValueChar_new(val);
00900
00901
00902 if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
00903 DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
00904 GWEN_DB_ClearNode(nn);
00905 }
00906
00907
00908 if (flags & GWEN_DB_FLAGS_INSERT)
00909 GWEN_DB_Node_Insert(nn, nv);
00910 else
00911 GWEN_DB_Node_Append(nn, nv);
00912 DBG_VERBOUS(GWEN_LOGDOMAIN,
00913 "Added char value \"%s\" to variable \"%s\"", val, path);
00914
00915 return 0;
00916 }
00917
00918
00919
00920 int GWEN_DB_AddCharValue(GWEN_DB_NODE *n,
00921 const char *path,
00922 const char *val,
00923 int senseCase,
00924 int check){
00925 GWEN_DB_NODE *nn;
00926 GWEN_DB_NODE *nv;
00927
00928
00929 nn=GWEN_DB_GetNode(n,
00930 path,
00931 GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_VARIABLE);
00932 if (!nn) {
00933 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
00934 path);
00935 return -1;
00936 }
00937
00938 if (check) {
00939 nv=GWEN_DB_GetFirstValue(n);
00940 if (nv && nv->typ==GWEN_DB_NodeType_ValueChar) {
00941 int res;
00942
00943 assert(nv->data.dataChar);
00944 if (senseCase)
00945 res=strcasecmp(nv->data.dataChar, val)==0;
00946 else
00947 res=strcmp(nv->data.dataChar, val)==0;
00948 if (res) {
00949 DBG_DEBUG(GWEN_LOGDOMAIN,
00950 "Value \"%s\" of var \"%s\" already exists",
00951 val, path);
00952 return 1;
00953 }
00954 }
00955 }
00956
00957 nv=GWEN_DB_ValueChar_new(val);
00958 GWEN_DB_Node_Append(nn, nv);
00959 DBG_VERBOUS(GWEN_LOGDOMAIN,
00960 "Added char value \"%s\" to variable \"%s\"", val, path);
00961
00962 return 0;
00963 }
00964
00965
00966
00967 int GWEN_DB_RemoveCharValue(GWEN_DB_NODE *n,
00968 const char *path,
00969 const char *val,
00970 int senseCase){
00971 GWEN_DB_NODE *nn;
00972 GWEN_DB_NODE *nv;
00973
00974
00975 nn=GWEN_DB_GetNode(n,
00976 path,
00977 GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_VARIABLE);
00978 if (!nn) {
00979 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
00980 path);
00981 return -1;
00982 }
00983
00984 nv=GWEN_DB_GetFirstValue(n);
00985 if (nv && nv->typ==GWEN_DB_NodeType_ValueChar) {
00986 int res;
00987
00988 assert(nv->data.dataChar);
00989 if (senseCase)
00990 res=strcasecmp(nv->data.dataChar, val)==0;
00991 else
00992 res=strcmp(nv->data.dataChar, val)==0;
00993 if (res) {
00994 DBG_DEBUG(GWEN_LOGDOMAIN,
00995 "Value \"%s\" of var \"%s\" already exists",
00996 val, path);
00997 GWEN_DB_Node_Unlink(nv);
00998 GWEN_DB_Node_free(nv);
00999 return 0;
01000 }
01001 }
01002
01003 return 1;
01004 }
01005
01006
01007
01008 int GWEN_DB_GetIntValue(GWEN_DB_NODE *n,
01009 const char *path,
01010 int idx,
01011 int defVal){
01012 GWEN_DB_NODE *nn;
01013 const char *p;
01014 int res;
01015
01016 assert(n);
01017 nn=GWEN_DB_GetValue(n, path, idx);
01018 if (!nn){
01019 DBG_VERBOUS(GWEN_LOGDOMAIN,
01020 "Value[%d] for \"%s\" not found, returning default value",
01021 idx, path);
01022 return defVal;
01023 }
01024
01025 switch(nn->typ) {
01026 case GWEN_DB_NodeType_ValueInt:
01027 return nn->data.dataInt;
01028 case GWEN_DB_NodeType_ValueChar:
01029 p=nn->data.dataChar;
01030 assert(p);
01031 if (sscanf(p, "%d", &res)!=1) {
01032 DBG_INFO(GWEN_LOGDOMAIN,
01033 "String [%s] in node is not an int value", p);
01034 return defVal;
01035 }
01036 return res;
01037
01038 default:
01039 DBG_ERROR(GWEN_LOGDOMAIN, "Node is neither char nor int value");
01040 return defVal;
01041 }
01042 }
01043
01044
01045
01046 int GWEN_DB_SetIntValue(GWEN_DB_NODE *n,
01047 uint32_t flags,
01048 const char *path,
01049 int val){
01050 GWEN_DB_NODE *nn;
01051 GWEN_DB_NODE *nv;
01052
01053
01054 nn=GWEN_DB_GetNode(n,
01055 path,
01056 flags | GWEN_PATH_FLAGS_VARIABLE);
01057 if (!nn) {
01058 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
01059 path);
01060 return 1;
01061 }
01062
01063
01064 if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
01065 DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
01066 GWEN_DB_ClearNode(nn);
01067 }
01068
01069 nv=GWEN_DB_ValueInt_new(val);
01070 if (flags & GWEN_DB_FLAGS_INSERT)
01071 GWEN_DB_Node_Insert(nn, nv);
01072 else
01073 GWEN_DB_Node_Append(nn, nv);
01074 DBG_VERBOUS(GWEN_LOGDOMAIN, "Added int value \"%d\" to variable \"%s\"", val, path);
01075 return 0;
01076 }
01077
01078
01079
01080 const void *GWEN_DB_GetBinValue(GWEN_DB_NODE *n,
01081 const char *path,
01082 int idx,
01083 const void *defVal,
01084 unsigned int defValSize,
01085 unsigned int *returnValueSize){
01086 GWEN_DB_NODE *nn;
01087
01088 assert(returnValueSize);
01089 nn=GWEN_DB_GetValue(n, path, idx);
01090 if (!nn){
01091 DBG_VERBOUS(GWEN_LOGDOMAIN,
01092 "Value for \"%s\" not found, returning default value",
01093 path);
01094 *returnValueSize=defValSize;
01095 return defVal;
01096 }
01097 if (nn->typ!=GWEN_DB_NodeType_ValueBin) {
01098
01099 DBG_VERBOUS(GWEN_LOGDOMAIN,
01100 "Bad type for path \"%s\", returning default value",
01101 path);
01102 *returnValueSize=defValSize;
01103 return defVal;
01104 }
01105 *returnValueSize=nn->dataSize;
01106 return nn->data.dataBin;
01107 }
01108
01109
01110
01111 int GWEN_DB_SetBinValue(GWEN_DB_NODE *n,
01112 uint32_t flags,
01113 const char *path,
01114 const void *val,
01115 unsigned int valSize){
01116 GWEN_DB_NODE *nn;
01117 GWEN_DB_NODE *nv;
01118
01119 assert(val);
01120
01121 nn=GWEN_DB_GetNode(n,
01122 path,
01123 flags | GWEN_PATH_FLAGS_VARIABLE);
01124 if (!nn) {
01125 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
01126 path);
01127 return 1;
01128 }
01129
01130
01131 if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
01132 DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
01133 GWEN_DB_ClearNode(nn);
01134 }
01135
01136 nv=GWEN_DB_ValueBin_new(val, valSize);
01137 if (flags & GWEN_DB_FLAGS_INSERT)
01138 GWEN_DB_Node_Insert(nn, nv);
01139 else
01140 GWEN_DB_Node_Append(nn, nv);
01141 DBG_VERBOUS(GWEN_LOGDOMAIN, "Added bin value to variable \"%s\"", path);
01142 return 0;
01143 }
01144
01145
01146
01147 void *GWEN_DB_GetPtrValue(GWEN_DB_NODE *n,
01148 const char *path,
01149 int idx,
01150 void *defVal){
01151 GWEN_DB_NODE *nn;
01152
01153 nn=GWEN_DB_GetValue(n, path, idx);
01154 if (!nn){
01155 DBG_VERBOUS(GWEN_LOGDOMAIN,
01156 "Value for \"%s\" not found, returning default value",
01157 path);
01158 return defVal;
01159 }
01160 if (nn->typ!=GWEN_DB_NodeType_ValuePtr) {
01161
01162 DBG_VERBOUS(GWEN_LOGDOMAIN,
01163 "Bad type for path \"%s\", returning default value",
01164 path);
01165 return defVal;
01166 }
01167 return nn->data.dataPtr;
01168 }
01169
01170
01171
01172 int GWEN_DB_SetPtrValue(GWEN_DB_NODE *n,
01173 uint32_t flags,
01174 const char *path,
01175 void *val){
01176 GWEN_DB_NODE *nn;
01177 GWEN_DB_NODE *nv;
01178
01179
01180 nn=GWEN_DB_GetNode(n,
01181 path,
01182 flags | GWEN_PATH_FLAGS_VARIABLE);
01183 if (!nn) {
01184 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
01185 path);
01186 return 1;
01187 }
01188
01189
01190 if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
01191 DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
01192 GWEN_DB_ClearNode(nn);
01193 }
01194
01195 nv=GWEN_DB_ValuePtr_new(val);
01196 if (flags & GWEN_DB_FLAGS_INSERT)
01197 GWEN_DB_Node_Insert(nn, nv);
01198 else
01199 GWEN_DB_Node_Append(nn, nv);
01200 DBG_VERBOUS(GWEN_LOGDOMAIN, "Added ptr value to variable \"%s\"", path);
01201
01202 return 0;
01203 }
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220 GWEN_DB_NODE *GWEN_DB_GetGroup(GWEN_DB_NODE *n,
01221 uint32_t flags,
01222 const char *path) {
01223 GWEN_DB_NODE *nn;
01224
01225
01226 nn=GWEN_DB_GetNode(n,
01227 path,
01228 flags & ~GWEN_PATH_FLAGS_VARIABLE);
01229 if (!nn) {
01230 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
01231 path);
01232 return NULL;
01233 }
01234
01235
01236 if (flags & GWEN_DB_FLAGS_OVERWRITE_GROUPS) {
01237 DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing group \"%s\"", path);
01238 GWEN_DB_ClearNode(nn);
01239 }
01240
01241 return nn;
01242 }
01243
01244
01245
01246 const char *GWEN_DB_GroupName(GWEN_DB_NODE *n){
01247 assert(n);
01248 if (n->typ!=GWEN_DB_NodeType_Group) {
01249 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01250 return NULL;
01251 }
01252 return n->data.dataName;
01253 }
01254
01255
01256
01257 void GWEN_DB_Dump(GWEN_DB_NODE *n, int insert){
01258 if (n) {
01259 int i;
01260
01261 for (i=0; i<insert; i++)
01262 fprintf(stderr, " ");
01263
01264
01265 switch(n->typ) {
01266 case GWEN_DB_NodeType_Group:
01267 fprintf(stderr, "Group : \"%s\"\n", n->data.dataName);
01268 break;
01269 case GWEN_DB_NodeType_Var:
01270 fprintf(stderr, "Var : \"%s\"\n", n->data.dataName);
01271 break;
01272 case GWEN_DB_NodeType_ValueChar:
01273 fprintf(stderr, "Value : \"%s\" (char)\n", n->data.dataChar);
01274 break;
01275 case GWEN_DB_NodeType_ValueInt:
01276 fprintf(stderr, "Value : %d (int)\n", n->data.dataInt);
01277 break;
01278 case GWEN_DB_NodeType_ValueBin: {
01279 char *buffer;
01280
01281 buffer=(char*)GWEN_Memory_malloc((n->dataSize*2)+1);
01282 assert(buffer);
01283 if (GWEN_Text_ToHex(n->data.dataBin, n->dataSize,
01284 buffer, (n->dataSize*2)+1)==0) {
01285 fprintf(stderr, "Value : %d bytes (bin)\n", n->dataSize);
01286 }
01287 else {
01288 fprintf(stderr, "Value : %s (bin)\n", buffer);
01289 }
01290 GWEN_Memory_dealloc(buffer);
01291 break;
01292 }
01293 case GWEN_DB_NodeType_ValuePtr:
01294 fprintf(stderr, "Value : %p (ptr)\n", n->data.dataPtr);
01295 break;
01296 default:
01297 fprintf(stderr, "[unknown node type %d]\n", n->typ);
01298 }
01299
01300
01301 if (n->children) {
01302 GWEN_DB_NODE *cn;
01303
01304 cn=GWEN_DB_Node_List_First(n->children);
01305 while(cn) {
01306 GWEN_DB_Dump(cn, insert+4);
01307 cn=GWEN_DB_Node_List_Next(cn);
01308 }
01309 }
01310 }
01311 else {
01312 fprintf(stderr, "[no node]\n");
01313 }
01314 }
01315
01316
01317
01318 int GWEN_DB_AddGroup(GWEN_DB_NODE *n, GWEN_DB_NODE *nn){
01319 assert(n);
01320 assert(nn);
01321
01322 if (n->typ!=GWEN_DB_NodeType_Group) {
01323 DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
01324 return 0;
01325 }
01326
01327 if (nn->typ!=GWEN_DB_NodeType_Group) {
01328 DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
01329 return 0;
01330 }
01331
01332 GWEN_DB_Node_Append(n, nn);
01333 return 0;
01334 }
01335
01336
01337
01338 int GWEN_DB_InsertGroup(GWEN_DB_NODE *n, GWEN_DB_NODE *nn){
01339 assert(n);
01340 assert(nn);
01341
01342 if (n->typ!=GWEN_DB_NodeType_Group) {
01343 DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
01344 return 0;
01345 }
01346
01347 if (nn->typ!=GWEN_DB_NodeType_Group) {
01348 DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
01349 return 0;
01350 }
01351
01352 GWEN_DB_Node_Insert(n, nn);
01353 return 0;
01354 }
01355
01356
01357
01358 int GWEN_DB_AddGroupChildren(GWEN_DB_NODE *n, GWEN_DB_NODE *nn){
01359 GWEN_DB_NODE *cpn;
01360
01361 assert(n);
01362 assert(nn);
01363
01364 if (n->typ!=GWEN_DB_NodeType_Group) {
01365 DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
01366 return -1;
01367 }
01368
01369 if (nn->typ!=GWEN_DB_NodeType_Group) {
01370 DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
01371 GWEN_DB_Dump(nn, 1);
01372 return -1;
01373 }
01374
01375 nn=GWEN_DB_Node_List_First(nn->children);
01376 while (nn) {
01377 DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating node");
01378 cpn=GWEN_DB_Node_dup(nn);
01379 GWEN_DB_Node_Append(n, cpn);
01380 nn=GWEN_DB_Node_List_Next(nn);
01381 }
01382 return 0;
01383 }
01384
01385
01386
01387 void GWEN_DB_UnlinkGroup(GWEN_DB_NODE *n){
01388 assert(n);
01389 if (n->typ!=GWEN_DB_NodeType_Group) {
01390 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01391 return;
01392 }
01393 GWEN_DB_Node_Unlink(n);
01394 }
01395
01396
01397 int GWEN_DB_VariableExists(GWEN_DB_NODE *n, const char *path){
01398 GWEN_DB_NODE *nn;
01399
01400
01401 assert(n);
01402 nn=GWEN_DB_GetNode(n,
01403 path,
01404 GWEN_PATH_FLAGS_PATHMUSTEXIST |
01405 GWEN_PATH_FLAGS_NAMEMUSTEXIST |
01406 GWEN_PATH_FLAGS_VARIABLE);
01407 if (!nn) {
01408 DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found", path);
01409 return 0;
01410 }
01411
01412 return 1;
01413 }
01414
01415
01416
01417 int GWEN_DB_ValueExists(GWEN_DB_NODE *n,
01418 const char *path,
01419 unsigned int i){
01420 return (GWEN_DB_GetValue(n, path, i)!=0);
01421 }
01422
01423
01424
01425 GWEN_DB_NODE_TYPE GWEN_DB_GetVariableType(GWEN_DB_NODE *n,
01426 const char *p){
01427 GWEN_DB_NODE *nn;
01428
01429 nn=GWEN_DB_FindVar(n, p, 0);
01430 if (!nn)
01431 return GWEN_DB_NodeType_Unknown;
01432
01433 nn=GWEN_DB_GetFirstValue(nn);
01434 if (!nn)
01435 return GWEN_DB_NodeType_Unknown;
01436 return GWEN_DB_GetValueType(nn);
01437 }
01438
01439
01440
01441 GWEN_DB_NODE_TYPE GWEN_DB_GetValueTypeByPath(GWEN_DB_NODE *n,
01442 const char *path,
01443 unsigned int i){
01444 GWEN_DB_NODE *nn;
01445
01446 nn=GWEN_DB_GetValue(n, path, i);
01447 if (!nn)
01448 return GWEN_DB_NodeType_Unknown;
01449 return GWEN_DB_GetValueType(nn);
01450 }
01451
01452
01453 void GWEN_DB_GroupRename(GWEN_DB_NODE *n, const char *newname){
01454 assert(n);
01455 assert(newname);
01456 assert(n->typ==GWEN_DB_NodeType_Group);
01457 GWEN_Memory_dealloc(n->data.dataName);
01458 n->data.dataName=GWEN_Memory_strdup(newname);
01459 }
01460
01461
01462
01463
01464
01465
01466
01467 int GWEN_DB_IsGroup(const GWEN_DB_NODE *n){
01468 assert(n);
01469 return n->typ==GWEN_DB_NodeType_Group;
01470 }
01471
01472
01473
01474 int GWEN_DB_IsVariable(const GWEN_DB_NODE *n){
01475 assert(n);
01476 return n->typ==GWEN_DB_NodeType_Var;
01477 }
01478
01479
01480
01481 int GWEN_DB_IsValue(const GWEN_DB_NODE *n){
01482 assert(n);
01483 return (n->typ>=GWEN_DB_NodeType_ValueChar &&
01484 n->typ>=GWEN_DB_NodeType_ValueLast);
01485 }
01486
01487
01488
01489 void *GWEN_DB_Groups_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func,
01490 void *user_data){
01491 GWEN_DB_NODE *iter;
01492 void *res;
01493
01494 assert(node);
01495 assert(func);
01496
01497 iter=GWEN_DB_GetFirstGroup(node);
01498 res=NULL;
01499 while(iter){
01500 res=(*func)(iter, user_data);
01501 if (res) {
01502 break;
01503 }
01504 iter=GWEN_DB_GetNextGroup(iter);
01505 }
01506 return res;
01507 }
01508
01509
01510
01511 void *GWEN_DB_count_cb(GWEN_UNUSED GWEN_DB_NODE *node, void *user_data){
01512 unsigned int *a = user_data;
01513 ++(*a);
01514 return NULL;
01515 }
01516
01517
01518
01519 unsigned int GWEN_DB_Groups_Count(const GWEN_DB_NODE *node){
01520 unsigned int res = 0;
01521 GWEN_DB_Groups_Foreach((GWEN_DB_NODE *)node, GWEN_DB_count_cb, &res);
01522 return res;
01523 }
01524
01525
01526
01527 void *GWEN_DB_Variables_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func,
01528 void *user_data){
01529 GWEN_DB_NODE *iter;
01530 void *res;
01531
01532 assert(node);
01533 assert(func);
01534
01535 iter=GWEN_DB_GetFirstVar(node);
01536 res=NULL;
01537 while(iter){
01538 res=(*func)(iter, user_data);
01539 if (res) {
01540 break;
01541 }
01542 iter=GWEN_DB_GetNextVar(iter);
01543 }
01544 return res;
01545 }
01546
01547
01548
01549 unsigned int GWEN_DB_Variables_Count(const GWEN_DB_NODE *node){
01550 unsigned int res = 0;
01551 GWEN_DB_Variables_Foreach((GWEN_DB_NODE *)node, GWEN_DB_count_cb, &res);
01552 return res;
01553 }
01554
01555
01556
01557 void *GWEN_DB_Values_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func,
01558 void *user_data){
01559 GWEN_DB_NODE *iter;
01560 void *res;
01561
01562 assert(node);
01563 assert(func);
01564
01565 iter=GWEN_DB_GetFirstValue(node);
01566 res=NULL;
01567 while(iter){
01568 res=(*func)(iter, user_data);
01569 if (res) {
01570 break;
01571 }
01572 iter=GWEN_DB_GetNextValue(iter);
01573 }
01574 return res;
01575 }
01576
01577
01578
01579 unsigned int GWEN_DB_Values_Count(const GWEN_DB_NODE *node){
01580 unsigned int res = 0;
01581 GWEN_DB_Values_Foreach((GWEN_DB_NODE *)node, GWEN_DB_count_cb, &res);
01582 return res;
01583 }
01584
01585
01586
01587 uint32_t GWEN_DB_GetNodeFlags(const GWEN_DB_NODE *n){
01588 assert(n);
01589 return n->nodeFlags;
01590 }
01591
01592
01593
01594 void GWEN_DB_SetNodeFlags(GWEN_DB_NODE *n,
01595 uint32_t flags){
01596 assert(n);
01597 n->nodeFlags=flags;
01598 }
01599
01600
01601
01602 void GWEN_DB_ModifyBranchFlagsUp(GWEN_DB_NODE *n,
01603 uint32_t newflags,
01604 uint32_t mask){
01605 uint32_t flags;
01606
01607 assert(n);
01608
01609 while(n) {
01610 flags=n->nodeFlags;
01611 flags=((flags^newflags)&(mask))^flags;
01612 n->nodeFlags=flags;
01613 n=n->parent;
01614 }
01615 }
01616
01617
01618
01619 void GWEN_DB_ModifyBranchFlagsDown(GWEN_DB_NODE *n,
01620 uint32_t newflags,
01621 uint32_t mask){
01622 uint32_t flags;
01623 GWEN_DB_NODE *cn;
01624
01625 assert(n);
01626
01627 flags=n->nodeFlags;
01628 flags=((flags^newflags)&(mask))^flags;
01629 n->nodeFlags=flags;
01630
01631 cn=GWEN_DB_Node_List_First(n->children);
01632 while(cn) {
01633 GWEN_DB_ModifyBranchFlagsDown(cn, newflags, mask);
01634 cn=GWEN_DB_Node_List_Next(cn);
01635 }
01636 }
01637
01638
01639
01640 GWEN_DB_NODE *GWEN_DB_GetParentGroup(GWEN_DB_NODE *n) {
01641 GWEN_DB_NODE *nn;
01642
01643 assert(n);
01644 nn=n->parent;
01645 while(nn && nn->typ!=GWEN_DB_NodeType_Group)
01646 nn=nn->parent;
01647 return nn;
01648 }
01649
01650
01651
01652 GWEN_DB_NODE *GWEN_DB_FindFirstGroup(GWEN_DB_NODE *n, const char *name){
01653 GWEN_DB_NODE *nn;
01654
01655 assert(n);
01656 if (n->typ!=GWEN_DB_NodeType_Group) {
01657 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01658 return NULL;
01659 }
01660 nn=GWEN_DB_Node_List_First(n->children);
01661 while(nn) {
01662 if ((nn->typ==GWEN_DB_NodeType_Group) &&
01663 (-1!=GWEN_Text_ComparePattern(nn->data.dataName, name, 0)))
01664 break;
01665 nn=GWEN_DB_Node_List_Next(nn);
01666 }
01667 return nn;
01668 }
01669
01670
01671
01672 GWEN_DB_NODE *GWEN_DB_FindNextGroup(GWEN_DB_NODE *n, const char *name){
01673 GWEN_DB_NODE *og;
01674
01675 og=n;
01676 assert(n);
01677 if (n->typ!=GWEN_DB_NodeType_Group) {
01678 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01679 return NULL;
01680 }
01681 n=GWEN_DB_GetNextGroup(n);
01682 while(n) {
01683 if (-1!=GWEN_Text_ComparePattern(n->data.dataName, name, 0))
01684 break;
01685 n=GWEN_DB_GetNextGroup(n);
01686 }
01687 assert(n!=og);
01688 return n;
01689 }
01690
01691
01692
01693 GWEN_DB_NODE *GWEN_DB_FindFirstVar(GWEN_DB_NODE *n, const char *name) {
01694 GWEN_DB_NODE *nn;
01695
01696 assert(n);
01697 if (n->typ!=GWEN_DB_NodeType_Group) {
01698 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01699 return NULL;
01700 }
01701
01702 nn=GWEN_DB_Node_List_First(n->children);
01703 while(nn) {
01704 if ((nn->typ==GWEN_DB_NodeType_Var) &&
01705 (-1!=GWEN_Text_ComparePattern(nn->data.dataName, name, 0)))
01706 break;
01707 nn=GWEN_DB_Node_List_Next(nn);
01708 }
01709
01710 return nn;
01711 }
01712
01713
01714
01715 GWEN_DB_NODE *GWEN_DB_FindNextVar(GWEN_DB_NODE *n, const char *name) {
01716 GWEN_DB_NODE *og;
01717
01718 og=n;
01719 assert(n);
01720 if (n->typ!=GWEN_DB_NodeType_Var) {
01721 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
01722 return NULL;
01723 }
01724 n=GWEN_DB_GetNextVar(n);
01725 while(n) {
01726 if (-1!=GWEN_Text_ComparePattern(n->data.dataName, name, 0))
01727 break;
01728 n=GWEN_DB_GetNextVar(n);
01729 }
01730 assert(n!=og);
01731 return n;
01732 }
01733
01734
01735
01736 const char *GWEN_DB_VariableName(GWEN_DB_NODE *n){
01737 assert(n);
01738 if (n->typ!=GWEN_DB_NodeType_Var) {
01739 DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
01740 return NULL;
01741 }
01742 return n->data.dataName;
01743 }
01744
01745
01746
01747 void GWEN_DB_VariableRename(GWEN_DB_NODE *n, const char *newname){
01748 assert(n);
01749 assert(newname);
01750 assert(n->typ==GWEN_DB_NodeType_Var);
01751 GWEN_Memory_dealloc(n->data.dataName);
01752 n->data.dataName=GWEN_Memory_strdup(newname);
01753 }
01754
01755
01756
01757
01758
01759
01760 #include "dbrw.c"
01761
01762
01763
01764
01765
01766
01767
01768
01769