db.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  begin       : Tue Sep 09 2003
00003  copyright   : (C) 2003-2010 by Martin Preuss
00004  email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *                                                                         *
00008  *   This library is free software; you can redistribute it and/or         *
00009  *   modify it under the terms of the GNU Lesser General Public            *
00010  *   License as published by the Free Software Foundation; either          *
00011  *   version 2.1 of the License, or (at your option) any later version.    *
00012  *                                                                         *
00013  *   This library is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00016  *   Lesser General Public License for more details.                       *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU Lesser General Public      *
00019  *   License along with this library; if not, write to the Free Software   *
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00021  *   MA  02111-1307  USA                                                   *
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     /* free children */
00245     if (n->children)
00246       GWEN_DB_Node_List_free(n->children);
00247 
00248     /* free dynamic (allocated) data */
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   /* duplicate all children and add them to the new node */
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       /* duplicate child and add it */
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     } /* while cn */
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   } /* while node */
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   } /* while node */
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   } /* while node */
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   } /* while node */
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   } /* while node */
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   } /* while node */
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   /* find existing node */
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           /* ok, group found, return it */
00566           return nn;
00567         idx--;
00568       } /* if entry found */
00569     }
00570     nn=GWEN_DB_Node_List_Next(nn);
00571   } /* while node */
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   /* find existing node */
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           /* ok, group found, return it */
00599           return nn;
00600         idx--;
00601       } /* if entry found */
00602     }
00603     nn=GWEN_DB_Node_List_Next(nn);
00604   } /* while node */
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   /* check whether we are allowed to simply create the node */
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     /* simply create the new variable/group */
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   /* find the node */
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     /* node not found, check, if we are allowed to create it */
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     /* create the new variable/group */
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   } /* if node not found */
00714   else {
00715     /* node does exist, check whether this is ok */
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   /* find corresponding node */
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   /* find value */
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   /* find corresponding node */
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   /* find corresponding node */
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     /* find corresponding node */
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     /* bad type */
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   /* select/create node */
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   /* delete contents of this variable if wanted */
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   /* add previously created value */
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   /* select/create node */
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   } /* if check */
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   /* select/create node */
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   /* select/create node */
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   /* delete contents of this variable if wanted */
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     /* bad type */
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   /* select/create node */
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   /* delete contents of this variable if wanted */
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     /* bad type */
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   /* select/create node */
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   /* delete contents of this variable if wanted */
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   /* select/create node */
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   /* delete contents of this variable if wanted */
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     /* dump dynamic (allocated) data */
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     /* dump children */
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   } /* while */
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   /* find corresponding node */
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   } /* while */
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   } /* while cn */
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   } /* while node */
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   } /* while node */
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   } /* while node */
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   } /* while node */
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