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