gwenhywfar 4.0.3

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   GWEN_DB_NODE *og;
00368 
00369   og=n;
00370   assert(n);
00371   if (n->typ!=GWEN_DB_NodeType_Group) {
00372     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00373     return NULL;
00374   }
00375   n=GWEN_DB_Node_List_Next(n);
00376   while(n) {
00377     if (n->typ==GWEN_DB_NodeType_Group)
00378       break;
00379     n=GWEN_DB_Node_List_Next(n);
00380   } /* while node */
00381   return n;
00382 }
00383 
00384 
00385 
00386 GWEN_DB_NODE *GWEN_DB_GetFirstVar(GWEN_DB_NODE *n){
00387   GWEN_DB_NODE *nn;
00388 
00389   assert(n);
00390   if (n->typ!=GWEN_DB_NodeType_Group) {
00391     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00392     return NULL;
00393   }
00394   assert(n->children);
00395   nn=GWEN_DB_Node_List_First(n->children);
00396   while(nn) {
00397     if (nn->typ==GWEN_DB_NodeType_Var)
00398       break;
00399     nn=GWEN_DB_Node_List_Next(nn);
00400   } /* while node */
00401   return nn;
00402 }
00403 
00404 
00405 
00406 GWEN_DB_NODE *GWEN_DB_GetNextVar(GWEN_DB_NODE *n){
00407   GWEN_DB_NODE *og;
00408 
00409   og=n;
00410   assert(n);
00411   if (n->typ!=GWEN_DB_NodeType_Var) {
00412     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
00413     return NULL;
00414   }
00415   n=GWEN_DB_Node_List_Next(n);
00416   while(n) {
00417     if (n->typ==GWEN_DB_NodeType_Var)
00418       break;
00419     n=GWEN_DB_Node_List_Next(n);
00420   } /* while node */
00421   return n;
00422 }
00423 
00424 
00425 
00426 GWEN_DB_NODE *GWEN_DB_GetFirstValue(GWEN_DB_NODE *n){
00427   GWEN_DB_NODE *nn;
00428 
00429   assert(n);
00430   if (n->typ!=GWEN_DB_NodeType_Var) {
00431     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
00432     return NULL;
00433   }
00434   assert(n->children);
00435   nn=GWEN_DB_Node_List_First(n->children);
00436   while(nn) {
00437     if (nn->typ>=GWEN_DB_NodeType_ValueChar &&
00438         nn->typ<GWEN_DB_NodeType_ValueLast) {
00439       break;
00440     }
00441     nn=GWEN_DB_Node_List_Next(nn);
00442   } /* while node */
00443   return nn;
00444 }
00445 
00446 
00447 
00448 GWEN_DB_NODE *GWEN_DB_GetNextValue(GWEN_DB_NODE *n){
00449   assert(n);
00450   if (n->typ<GWEN_DB_NodeType_ValueChar ||
00451       n->typ>=GWEN_DB_NodeType_ValueLast) {
00452     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a value");
00453     return NULL;
00454   }
00455 
00456   n=GWEN_DB_Node_List_Next(n);
00457   while(n) {
00458     if (n->typ>=GWEN_DB_NodeType_ValueChar &&
00459         n->typ<GWEN_DB_NodeType_ValueLast) {
00460       break;
00461     }
00462     n=GWEN_DB_Node_List_Next(n);
00463   } /* while node */
00464   return n;
00465 }
00466 
00467 
00468 
00469 GWEN_DB_NODE_TYPE GWEN_DB_GetValueType(GWEN_DB_NODE *n){
00470   assert(n);
00471   if (n->typ>=GWEN_DB_NodeType_ValueChar &&
00472       n->typ<GWEN_DB_NodeType_ValueLast) {
00473     return n->typ;
00474   }
00475   else {
00476     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a value");
00477     return GWEN_DB_NodeType_Unknown;
00478   }
00479 }
00480 
00481 
00482 
00483 const char *GWEN_DB_GetCharValueFromNode(const GWEN_DB_NODE *n){
00484   assert(n);
00485   if (n->typ!=GWEN_DB_NodeType_ValueChar) {
00486     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a char value");
00487     return NULL;
00488   }
00489   return n->data.dataChar;
00490 }
00491 
00492 
00493 
00494 int GWEN_DB_SetCharValueInNode(GWEN_DB_NODE *n, const char *s) {
00495   assert(n);
00496   assert(s);
00497 
00498   if (n->typ!=GWEN_DB_NodeType_ValueChar) {
00499     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a char value");
00500     return GWEN_ERROR_INVALID;
00501   }
00502 
00503   GWEN_Memory_dealloc(n->data.dataChar);
00504   n->data.dataChar=GWEN_Memory_strdup(s);
00505   return 0;
00506 }
00507 
00508 
00509 
00510 int GWEN_DB_GetIntValueFromNode(const GWEN_DB_NODE *n){
00511   const char *p;
00512   int res;
00513 
00514   assert(n);
00515 
00516   switch(n->typ) {
00517   case GWEN_DB_NodeType_ValueInt:
00518     return n->data.dataInt;
00519   case GWEN_DB_NodeType_ValueChar:
00520     p=n->data.dataChar;
00521     assert(p);
00522     if (sscanf(p, "%d", &res)!=1) {
00523       DBG_ERROR(GWEN_LOGDOMAIN, "String in node is not an int value");
00524       return 0;
00525     }
00526     return res;
00527 
00528   default:
00529     DBG_ERROR(GWEN_LOGDOMAIN, "Node is neither char nor int value");
00530     return 0;
00531   }
00532 }
00533 
00534 
00535 
00536 const void *GWEN_DB_GetBinValueFromNode(const GWEN_DB_NODE *n,
00537                                         unsigned int *size){
00538   assert(n);
00539 
00540   if (n->typ!=GWEN_DB_NodeType_ValueBin) {
00541     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a binary value");
00542     return NULL;
00543   }
00544 
00545   *size=n->dataSize;
00546   return n->data.dataBin;
00547 }
00548 
00549 
00550 
00551 GWEN_DB_NODE *GWEN_DB_FindGroup(GWEN_DB_NODE *n,
00552                                 const char *name,
00553                                 int idx) {
00554   GWEN_DB_NODE *nn;
00555 
00556   assert(n);
00557   assert(name);
00558 
00559   if (n->typ!=GWEN_DB_NodeType_Group) {
00560     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00561     return NULL;
00562   }
00563 
00564   /* find existing node */
00565   assert(n->children);
00566   nn=GWEN_DB_Node_List_First(n->children);
00567   while(nn) {
00568     if (nn->typ==GWEN_DB_NodeType_Group) {
00569       if (strcasecmp(nn->data.dataName, name)==0) {
00570         if (!idx)
00571           /* ok, group found, return it */
00572           return nn;
00573         idx--;
00574       } /* if entry found */
00575     }
00576     nn=GWEN_DB_Node_List_Next(nn);
00577   } /* while node */
00578 
00579   return NULL;
00580 }
00581 
00582 
00583 
00584 GWEN_DB_NODE *GWEN_DB_FindVar(GWEN_DB_NODE *n,
00585                               const char *name,
00586                               int idx) {
00587   GWEN_DB_NODE *nn;
00588 
00589   assert(n);
00590   assert(name);
00591 
00592   if (n->typ!=GWEN_DB_NodeType_Group) {
00593     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
00594     return NULL;
00595   }
00596 
00597   /* find existing node */
00598   assert(n->children);
00599   nn=GWEN_DB_Node_List_First(n->children);
00600   while(nn) {
00601     if (nn->typ==GWEN_DB_NodeType_Var) {
00602       if (strcasecmp(nn->data.dataName, name)==0) {
00603         if (!idx)
00604           /* ok, group found, return it */
00605           return nn;
00606         idx--;
00607       } /* if entry found */
00608     }
00609     nn=GWEN_DB_Node_List_Next(nn);
00610   } /* while node */
00611 
00612   return NULL;
00613 }
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 void* GWEN_DB_HandlePath(const char *entry,
00622                          void *data,
00623                          int idx,
00624                          uint32_t flags) {
00625   GWEN_DB_NODE *n;
00626   GWEN_DB_NODE *nn;
00627 
00628   n=(GWEN_DB_NODE*)data;
00629 
00630   /* check whether we are allowed to simply create the node */
00631   if (
00632       ((flags & GWEN_PATH_FLAGS_LAST) &&
00633        (((flags & GWEN_PATH_FLAGS_VARIABLE) &&
00634          (flags & GWEN_PATH_FLAGS_CREATE_VAR)) ||
00635         (!(flags & GWEN_PATH_FLAGS_VARIABLE) &&
00636          (flags & GWEN_PATH_FLAGS_CREATE_GROUP)))
00637       ) ||
00638       (
00639        !(flags & GWEN_PATH_FLAGS_LAST) &&
00640        (flags & GWEN_PATH_FLAGS_PATHCREATE))
00641      ) {
00642     /* simply create the new variable/group */
00643     if (idx!=0) {
00644       DBG_INFO(GWEN_LOGDOMAIN, "Index is not 0, not creating %s[%d]",
00645                entry, idx);
00646       return 0;
00647     }
00648     if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00649       DBG_VERBOUS(GWEN_LOGDOMAIN,
00650                   "Unconditionally creating variable \"%s\"", entry);
00651       nn=GWEN_DB_Var_new(entry);
00652       if (flags & GWEN_DB_FLAGS_INSERT)
00653         GWEN_DB_Node_Insert(n, nn);
00654       else
00655         GWEN_DB_Node_Append(n, nn);
00656       return nn;
00657     }
00658     else {
00659       DBG_VERBOUS(GWEN_LOGDOMAIN,
00660                   "Unconditionally creating group \"%s\"", entry);
00661       nn=GWEN_DB_Group_new(entry);
00662       if (flags & GWEN_DB_FLAGS_INSERT)
00663         GWEN_DB_Node_Insert(n, nn);
00664       else
00665         GWEN_DB_Node_Append(n, nn);
00666       return nn;
00667     }
00668   }
00669 
00670   /* find the node */
00671   if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00672     nn=GWEN_DB_FindVar(n, entry, idx);
00673   }
00674   else {
00675     nn=GWEN_DB_FindGroup(n, entry, idx);
00676   }
00677 
00678   if (!nn) {
00679     /* node not found, check, if we are allowed to create it */
00680     if (
00681         (!(flags & GWEN_PATH_FLAGS_LAST) &&
00682          (flags & GWEN_PATH_FLAGS_PATHMUSTEXIST)) ||
00683         (flags & GWEN_PATH_FLAGS_NAMEMUSTEXIST)
00684        ) {
00685       if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00686         DBG_VERBOUS(GWEN_LOGDOMAIN,
00687                     "Variable \"%s\" does not exist", entry);
00688       }
00689       else {
00690         DBG_VERBOUS(GWEN_LOGDOMAIN,
00691                     "Group \"%s\" does not exist", entry);
00692       }
00693       return 0;
00694     }
00695     /* create the new variable/group */
00696     if (idx!=0) {
00697       DBG_INFO(GWEN_LOGDOMAIN, "Index is not 0, not creating %s[%d]",
00698                entry, idx);
00699       return 0;
00700     }
00701     if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00702       DBG_VERBOUS(GWEN_LOGDOMAIN,
00703                   "Variable \"%s\" not found, creating", entry);
00704       nn=GWEN_DB_Var_new(entry);
00705       if (flags & GWEN_DB_FLAGS_INSERT)
00706         GWEN_DB_Node_Insert(n, nn);
00707       else
00708         GWEN_DB_Node_Append(n, nn);
00709     }
00710     else {
00711       DBG_VERBOUS(GWEN_LOGDOMAIN,
00712                   "Group \"%s\" not found, creating", entry);
00713       nn=GWEN_DB_Group_new(entry);
00714       if (flags & GWEN_DB_FLAGS_INSERT)
00715         GWEN_DB_Node_Insert(n, nn);
00716       else
00717         GWEN_DB_Node_Append(n, nn);
00718     }
00719   } /* if node not found */
00720   else {
00721     /* node does exist, check whether this is ok */
00722     if (
00723         ((flags & GWEN_PATH_FLAGS_LAST) &&
00724          (flags & GWEN_PATH_FLAGS_NAMEMUSTNOTEXIST)) ||
00725         (!(flags & GWEN_PATH_FLAGS_LAST) &&
00726          (flags & GWEN_PATH_FLAGS_PATHMUSTNOTEXIST))
00727        ) {
00728       DBG_VERBOUS(GWEN_LOGDOMAIN, "Entry \"%s\" already exists", entry);
00729       return 0;
00730     }
00731   }
00732 
00733   return nn;
00734 }
00735 
00736 
00737 
00738 GWEN_DB_NODE *GWEN_DB_GetNode(GWEN_DB_NODE *n,
00739                               const char *path,
00740                               uint32_t flags){
00741   return (GWEN_DB_NODE*)GWEN_Path_HandleWithIdx(path,
00742                                                 n,
00743                                                 flags,
00744                                                 GWEN_DB_HandlePath);
00745 }
00746 
00747 
00748 
00749 void GWEN_DB_ClearNode(GWEN_DB_NODE *n) {
00750   assert(n);
00751   if (n->children)
00752     GWEN_DB_Node_List_Clear(n->children);
00753 }
00754 
00755 
00756 
00757 GWEN_DB_NODE *GWEN_DB_GetValue(GWEN_DB_NODE *n,
00758                                const char *path,
00759                                int idx) {
00760   GWEN_DB_NODE *nn;
00761 
00762   /* find corresponding node */
00763   nn=GWEN_DB_GetNode(n,
00764                      path,
00765                      GWEN_PATH_FLAGS_PATHMUSTEXIST |
00766                      GWEN_PATH_FLAGS_NAMEMUSTEXIST |
00767                      GWEN_PATH_FLAGS_VARIABLE);
00768   if (!nn) {
00769     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
00770               path);
00771     return 0;
00772   }
00773 
00774   /* find value */
00775   assert(nn->children);
00776   nn=GWEN_DB_Node_List_First(nn->children);
00777   while(nn) {
00778     if (nn->typ>=GWEN_DB_NodeType_ValueChar &&
00779         nn->typ<GWEN_DB_NodeType_ValueLast) {
00780       if (!idx)
00781         return nn;
00782       idx--;
00783     }
00784     nn=GWEN_DB_Node_List_Next(nn);
00785   }
00786 
00787   DBG_VERBOUS(GWEN_LOGDOMAIN, "No value[%d] for path \"%s\"",
00788               idx, path);
00789   return NULL;
00790 }
00791 
00792 
00793 
00794 int GWEN_DB_DeleteVar(GWEN_DB_NODE *n,
00795                       const char *path) {
00796   GWEN_DB_NODE *nn;
00797 
00798   /* find corresponding node */
00799   nn=GWEN_DB_GetNode(n,
00800                      path,
00801                      GWEN_PATH_FLAGS_PATHMUSTEXIST |
00802                      GWEN_PATH_FLAGS_NAMEMUSTEXIST |
00803                      GWEN_PATH_FLAGS_VARIABLE);
00804   if (!nn) {
00805     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
00806               path);
00807     return 1;
00808   }
00809   GWEN_DB_Node_Unlink(nn);
00810   GWEN_DB_Node_free(nn);
00811   return 0;
00812 }
00813 
00814 
00815 
00816 int GWEN_DB_DeleteGroup(GWEN_DB_NODE *n,
00817                         const char *path) {
00818   GWEN_DB_NODE *nn;
00819 
00820   /* find corresponding node */
00821   nn=GWEN_DB_GetNode(n,
00822                      path,
00823                      GWEN_PATH_FLAGS_PATHMUSTEXIST |
00824                      GWEN_PATH_FLAGS_NAMEMUSTEXIST);
00825   if (!nn) {
00826     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
00827               path);
00828     return 1;
00829   }
00830   GWEN_DB_Node_Unlink(nn);
00831   GWEN_DB_Node_free(nn);
00832   return 0;
00833 }
00834 
00835 
00836 
00837 int GWEN_DB_ClearGroup(GWEN_DB_NODE *n,
00838                        const char *path){
00839   assert(n);
00840   if (path) {
00841     GWEN_DB_NODE *nn;
00842 
00843     /* find corresponding node */
00844     nn=GWEN_DB_GetNode(n,
00845                        path,
00846                        GWEN_PATH_FLAGS_PATHMUSTEXIST |
00847                        GWEN_PATH_FLAGS_NAMEMUSTEXIST);
00848     if (!nn) {
00849       DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found",
00850                 path);
00851       return 1;
00852     }
00853     GWEN_DB_ClearNode(nn);
00854   }
00855   else {
00856     GWEN_DB_ClearNode(n);
00857   }
00858   return 0;
00859 }
00860 
00861 
00862 
00863 const char *GWEN_DB_GetCharValue(GWEN_DB_NODE *n,
00864                                  const char *path,
00865                                  int idx,
00866                                  const char *defVal){
00867   GWEN_DB_NODE *nn;
00868 
00869   nn=GWEN_DB_GetValue(n, path, idx);
00870   if (!nn){
00871     DBG_VERBOUS(GWEN_LOGDOMAIN,
00872                 "Value for \"%s\" not found, returning default value",
00873                 path);
00874     return defVal;
00875   }
00876   if (nn->typ!=GWEN_DB_NodeType_ValueChar) {
00877     /* bad type */
00878     DBG_VERBOUS(GWEN_LOGDOMAIN,
00879                 "Bad type for path \"%s\", returning default value",
00880                 path);
00881     return defVal;
00882   }
00883   return nn->data.dataChar;
00884 }
00885 
00886 
00887 
00888 int GWEN_DB_SetCharValue(GWEN_DB_NODE *n,
00889                          uint32_t flags,
00890                          const char *path,
00891                          const char *val){
00892   GWEN_DB_NODE *nn;
00893   GWEN_DB_NODE *nv;
00894 
00895   /* select/create node */
00896   nn=GWEN_DB_GetNode(n,
00897                      path,
00898                      flags | GWEN_PATH_FLAGS_VARIABLE);
00899   if (!nn) {
00900     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
00901               path);
00902     return 1;
00903   }
00904 
00905   nv=GWEN_DB_ValueChar_new(val);
00906 
00907   /* delete contents of this variable if wanted */
00908   if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
00909     DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
00910     GWEN_DB_ClearNode(nn);
00911   }
00912 
00913   /* add previously created value */
00914   if (flags & GWEN_DB_FLAGS_INSERT)
00915     GWEN_DB_Node_Insert(nn, nv);
00916   else
00917     GWEN_DB_Node_Append(nn, nv);
00918   DBG_VERBOUS(GWEN_LOGDOMAIN,
00919               "Added char value \"%s\" to variable \"%s\"", val, path);
00920 
00921   return 0;
00922 }
00923 
00924 
00925 
00926 int GWEN_DB_AddCharValue(GWEN_DB_NODE *n,
00927                          const char *path,
00928                          const char *val,
00929                          int senseCase,
00930                          int check){
00931   GWEN_DB_NODE *nn;
00932   GWEN_DB_NODE *nv;
00933 
00934   /* select/create node */
00935   nn=GWEN_DB_GetNode(n,
00936                      path,
00937                      GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_VARIABLE);
00938   if (!nn) {
00939     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
00940                 path);
00941     return -1;
00942   }
00943 
00944   if (check) {
00945     nv=GWEN_DB_GetFirstValue(n);
00946     if (nv && nv->typ==GWEN_DB_NodeType_ValueChar) {
00947       int res;
00948 
00949       assert(nv->data.dataChar);
00950       if (senseCase)
00951         res=strcasecmp(nv->data.dataChar, val)==0;
00952       else
00953         res=strcmp(nv->data.dataChar, val)==0;
00954       if (res) {
00955         DBG_DEBUG(GWEN_LOGDOMAIN,
00956                   "Value \"%s\" of var \"%s\" already exists",
00957                   val, path);
00958         return 1;
00959       }
00960     }
00961   } /* if check */
00962 
00963   nv=GWEN_DB_ValueChar_new(val);
00964   GWEN_DB_Node_Append(nn, nv);
00965   DBG_VERBOUS(GWEN_LOGDOMAIN,
00966               "Added char value \"%s\" to variable \"%s\"", val, path);
00967 
00968   return 0;
00969 }
00970 
00971 
00972 
00973 int GWEN_DB_RemoveCharValue(GWEN_DB_NODE *n,
00974                             const char *path,
00975                             const char *val,
00976                             int senseCase){
00977   GWEN_DB_NODE *nn;
00978   GWEN_DB_NODE *nv;
00979 
00980   /* select/create node */
00981   nn=GWEN_DB_GetNode(n,
00982                      path,
00983                      GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_VARIABLE);
00984   if (!nn) {
00985     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
00986                 path);
00987     return -1;
00988   }
00989 
00990   nv=GWEN_DB_GetFirstValue(n);
00991   if (nv && nv->typ==GWEN_DB_NodeType_ValueChar) {
00992     int res;
00993 
00994     assert(nv->data.dataChar);
00995     if (senseCase)
00996       res=strcasecmp(nv->data.dataChar, val)==0;
00997     else
00998       res=strcmp(nv->data.dataChar, val)==0;
00999     if (res) {
01000       DBG_DEBUG(GWEN_LOGDOMAIN,
01001                 "Value \"%s\" of var \"%s\" already exists",
01002                 val, path);
01003       GWEN_DB_Node_Unlink(nv);
01004       GWEN_DB_Node_free(nv);
01005       return 0;
01006     }
01007   }
01008 
01009   return 1;
01010 }
01011 
01012 
01013 
01014 int GWEN_DB_GetIntValue(GWEN_DB_NODE *n,
01015                         const char *path,
01016                         int idx,
01017                         int defVal){
01018   GWEN_DB_NODE *nn;
01019   const char *p;
01020   int res;
01021 
01022   assert(n);
01023   nn=GWEN_DB_GetValue(n, path, idx);
01024   if (!nn){
01025     DBG_VERBOUS(GWEN_LOGDOMAIN,
01026                 "Value[%d] for \"%s\" not found, returning default value",
01027                 idx, path);
01028     return defVal;
01029   }
01030 
01031   switch(nn->typ) {
01032   case GWEN_DB_NodeType_ValueInt:
01033     return nn->data.dataInt;
01034   case GWEN_DB_NodeType_ValueChar:
01035     p=nn->data.dataChar;
01036     assert(p);
01037     if (sscanf(p, "%d", &res)!=1) {
01038       DBG_INFO(GWEN_LOGDOMAIN,
01039                "String [%s] in node is not an int value", p);
01040       return defVal;
01041     }
01042     return res;
01043 
01044   default:
01045     DBG_ERROR(GWEN_LOGDOMAIN, "Node is neither char nor int value");
01046     return defVal;
01047   }
01048 }
01049 
01050 
01051 
01052 int GWEN_DB_SetIntValue(GWEN_DB_NODE *n,
01053                         uint32_t flags,
01054                         const char *path,
01055                         int val){
01056   GWEN_DB_NODE *nn;
01057   GWEN_DB_NODE *nv;
01058 
01059   /* select/create node */
01060   nn=GWEN_DB_GetNode(n,
01061                      path,
01062                      flags | GWEN_PATH_FLAGS_VARIABLE);
01063   if (!nn) {
01064     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
01065               path);
01066     return 1;
01067   }
01068 
01069   /* delete contents of this variable if wanted */
01070   if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
01071     DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
01072     GWEN_DB_ClearNode(nn);
01073   }
01074 
01075   nv=GWEN_DB_ValueInt_new(val);
01076   if (flags & GWEN_DB_FLAGS_INSERT)
01077     GWEN_DB_Node_Insert(nn, nv);
01078   else
01079     GWEN_DB_Node_Append(nn, nv);
01080   DBG_VERBOUS(GWEN_LOGDOMAIN, "Added int value \"%d\" to variable \"%s\"", val, path);
01081   return 0;
01082 }
01083 
01084 
01085 
01086 const void *GWEN_DB_GetBinValue(GWEN_DB_NODE *n,
01087                                 const char *path,
01088                                 int idx,
01089                                 const void *defVal,
01090                                 unsigned int defValSize,
01091                                 unsigned int *returnValueSize){
01092   GWEN_DB_NODE *nn;
01093 
01094   assert(returnValueSize);
01095   nn=GWEN_DB_GetValue(n, path, idx);
01096   if (!nn){
01097     DBG_VERBOUS(GWEN_LOGDOMAIN,
01098                 "Value for \"%s\" not found, returning default value",
01099                 path);
01100     *returnValueSize=defValSize;
01101     return defVal;
01102   }
01103   if (nn->typ!=GWEN_DB_NodeType_ValueBin) {
01104     /* bad type */
01105     DBG_VERBOUS(GWEN_LOGDOMAIN,
01106                 "Bad type for path \"%s\", returning default value",
01107                 path);
01108     *returnValueSize=defValSize;
01109     return defVal;
01110   }
01111   *returnValueSize=nn->dataSize;
01112   return nn->data.dataBin;
01113 }
01114 
01115 
01116 
01117 int GWEN_DB_SetBinValue(GWEN_DB_NODE *n,
01118                         uint32_t flags,
01119                         const char *path,
01120                         const void *val,
01121                         unsigned int valSize){
01122   GWEN_DB_NODE *nn;
01123   GWEN_DB_NODE *nv;
01124 
01125   assert(val);
01126   /* select/create node */
01127   nn=GWEN_DB_GetNode(n,
01128                      path,
01129                      flags | GWEN_PATH_FLAGS_VARIABLE);
01130   if (!nn) {
01131     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
01132                 path);
01133     return 1;
01134   }
01135 
01136   /* delete contents of this variable if wanted */
01137   if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
01138     DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
01139     GWEN_DB_ClearNode(nn);
01140   }
01141 
01142   nv=GWEN_DB_ValueBin_new(val, valSize);
01143   if (flags & GWEN_DB_FLAGS_INSERT)
01144     GWEN_DB_Node_Insert(nn, nv);
01145   else
01146     GWEN_DB_Node_Append(nn, nv);
01147   DBG_VERBOUS(GWEN_LOGDOMAIN, "Added bin value to variable \"%s\"", path);
01148   return 0;
01149 }
01150 
01151 
01152 
01153 void *GWEN_DB_GetPtrValue(GWEN_DB_NODE *n,
01154                           const char *path,
01155                           int idx,
01156                           void *defVal){
01157   GWEN_DB_NODE *nn;
01158 
01159   nn=GWEN_DB_GetValue(n, path, idx);
01160   if (!nn){
01161     DBG_VERBOUS(GWEN_LOGDOMAIN,
01162                 "Value for \"%s\" not found, returning default value",
01163                 path);
01164     return defVal;
01165   }
01166   if (nn->typ!=GWEN_DB_NodeType_ValuePtr) {
01167     /* bad type */
01168     DBG_VERBOUS(GWEN_LOGDOMAIN,
01169                 "Bad type for path \"%s\", returning default value",
01170                 path);
01171     return defVal;
01172   }
01173   return nn->data.dataPtr;
01174 }
01175 
01176 
01177 
01178 int GWEN_DB_SetPtrValue(GWEN_DB_NODE *n,
01179                         uint32_t flags,
01180                         const char *path,
01181                         void *val){
01182   GWEN_DB_NODE *nn;
01183   GWEN_DB_NODE *nv;
01184 
01185   /* select/create node */
01186   nn=GWEN_DB_GetNode(n,
01187                      path,
01188                      flags | GWEN_PATH_FLAGS_VARIABLE);
01189   if (!nn) {
01190     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
01191               path);
01192     return 1;
01193   }
01194 
01195   /* delete contents of this variable if wanted */
01196   if (flags & GWEN_DB_FLAGS_OVERWRITE_VARS) {
01197     DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing variable \"%s\"", path);
01198     GWEN_DB_ClearNode(nn);
01199   }
01200 
01201   nv=GWEN_DB_ValuePtr_new(val);
01202   if (flags & GWEN_DB_FLAGS_INSERT)
01203     GWEN_DB_Node_Insert(nn, nv);
01204   else
01205     GWEN_DB_Node_Append(nn, nv);
01206   DBG_VERBOUS(GWEN_LOGDOMAIN, "Added ptr value to variable \"%s\"", path);
01207 
01208   return 0;
01209 }
01210 
01211 
01212 
01213 
01214 
01215 
01216 
01217 
01218 
01219 
01220 
01221 
01222 
01223 
01224 
01225 
01226 GWEN_DB_NODE *GWEN_DB_GetGroup(GWEN_DB_NODE *n,
01227                                uint32_t flags,
01228                                const char *path) {
01229   GWEN_DB_NODE *nn;
01230 
01231   /* select/create node */
01232   nn=GWEN_DB_GetNode(n,
01233                      path,
01234                      flags & ~GWEN_PATH_FLAGS_VARIABLE);
01235   if (!nn) {
01236     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not available",
01237               path);
01238     return NULL;
01239   }
01240 
01241   /* delete contents of this variable if wanted */
01242   if (flags & GWEN_DB_FLAGS_OVERWRITE_GROUPS) {
01243     DBG_VERBOUS(GWEN_LOGDOMAIN, "Clearing group \"%s\"", path);
01244     GWEN_DB_ClearNode(nn);
01245   }
01246 
01247   return nn;
01248 }
01249 
01250 
01251 
01252 const char *GWEN_DB_GroupName(GWEN_DB_NODE *n){
01253   assert(n);
01254   if (n->typ!=GWEN_DB_NodeType_Group) {
01255     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01256     return NULL;
01257   }
01258   return n->data.dataName;
01259 }
01260 
01261 
01262 
01263 void GWEN_DB_Dump(GWEN_DB_NODE *n, int insert){
01264   if (n) {
01265     int i;
01266 
01267     for (i=0; i<insert; i++)
01268       fprintf(stderr, " ");
01269 
01270     /* dump dynamic (allocated) data */
01271     switch(n->typ) {
01272     case GWEN_DB_NodeType_Group:
01273       fprintf(stderr, "Group : \"%s\"\n", n->data.dataName);
01274       break;
01275     case GWEN_DB_NodeType_Var:
01276       fprintf(stderr, "Var   : \"%s\"\n", n->data.dataName);
01277       break;
01278     case GWEN_DB_NodeType_ValueChar:
01279       fprintf(stderr, "Value : \"%s\" (char)\n", n->data.dataChar);
01280       break;
01281     case GWEN_DB_NodeType_ValueInt:
01282       fprintf(stderr, "Value : %d (int)\n", n->data.dataInt);
01283       break;
01284     case GWEN_DB_NodeType_ValueBin: {
01285       char *buffer;
01286 
01287       buffer=(char*)GWEN_Memory_malloc((n->dataSize*2)+1);
01288       assert(buffer);
01289       if (GWEN_Text_ToHex(n->data.dataBin, n->dataSize,
01290                           buffer, (n->dataSize*2)+1)==0) {
01291         fprintf(stderr, "Value : %d bytes (bin)\n", n->dataSize);
01292       }
01293       else {
01294         fprintf(stderr, "Value : %s (bin)\n", buffer);
01295       }
01296       GWEN_Memory_dealloc(buffer);
01297       break;
01298     }
01299     case GWEN_DB_NodeType_ValuePtr:
01300       fprintf(stderr, "Value : %p (ptr)\n", n->data.dataPtr);
01301       break;
01302     default:
01303       fprintf(stderr, "[unknown node type %d]\n", n->typ);
01304     }
01305 
01306     /* dump children */
01307     if (n->children) {
01308       GWEN_DB_NODE *cn;
01309 
01310       cn=GWEN_DB_Node_List_First(n->children);
01311       while(cn) {
01312         GWEN_DB_Dump(cn, insert+4);
01313         cn=GWEN_DB_Node_List_Next(cn);
01314       }
01315     }
01316   }
01317   else {
01318     fprintf(stderr, "[no node]\n");
01319   }
01320 }
01321 
01322 
01323 
01324 int GWEN_DB_AddGroup(GWEN_DB_NODE *n, GWEN_DB_NODE *nn){
01325   assert(n);
01326   assert(nn);
01327 
01328   if (n->typ!=GWEN_DB_NodeType_Group) {
01329     DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
01330     return 0;
01331   }
01332 
01333   if (nn->typ!=GWEN_DB_NodeType_Group) {
01334     DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
01335     return 0;
01336   }
01337 
01338   GWEN_DB_Node_Append(n, nn);
01339   return 0;
01340 }
01341 
01342 
01343 
01344 int GWEN_DB_InsertGroup(GWEN_DB_NODE *n, GWEN_DB_NODE *nn){
01345   assert(n);
01346   assert(nn);
01347 
01348   if (n->typ!=GWEN_DB_NodeType_Group) {
01349     DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
01350     return 0;
01351   }
01352 
01353   if (nn->typ!=GWEN_DB_NodeType_Group) {
01354     DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
01355     return 0;
01356   }
01357 
01358   GWEN_DB_Node_Insert(n, nn);
01359   return 0;
01360 }
01361 
01362 
01363 
01364 int GWEN_DB_AddGroupChildren(GWEN_DB_NODE *n, GWEN_DB_NODE *nn){
01365   GWEN_DB_NODE *cpn;
01366 
01367   assert(n);
01368   assert(nn);
01369 
01370   if (n->typ!=GWEN_DB_NodeType_Group) {
01371     DBG_ERROR(GWEN_LOGDOMAIN, "Target node is not a group");
01372     return -1;
01373   }
01374 
01375   if (nn->typ!=GWEN_DB_NodeType_Group) {
01376     DBG_ERROR(GWEN_LOGDOMAIN, "Source node is not a group");
01377     GWEN_DB_Dump(nn, 1);
01378     return -1;
01379   }
01380 
01381   nn=GWEN_DB_Node_List_First(nn->children);
01382   while (nn) {
01383     DBG_VERBOUS(GWEN_LOGDOMAIN, "Duplicating node");
01384     cpn=GWEN_DB_Node_dup(nn);
01385     GWEN_DB_Node_Append(n, cpn);
01386     nn=GWEN_DB_Node_List_Next(nn);
01387   } /* while */
01388   return 0;
01389 }
01390 
01391 
01392 
01393 void GWEN_DB_UnlinkGroup(GWEN_DB_NODE *n){
01394   assert(n);
01395   if (n->typ!=GWEN_DB_NodeType_Group) {
01396     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01397     return;
01398   }
01399   GWEN_DB_Node_Unlink(n);
01400 }
01401 
01402 
01403 int GWEN_DB_VariableExists(GWEN_DB_NODE *n, const char *path){
01404   GWEN_DB_NODE *nn;
01405 
01406   /* find corresponding node */
01407   assert(n);
01408   nn=GWEN_DB_GetNode(n,
01409                      path,
01410                      GWEN_PATH_FLAGS_PATHMUSTEXIST |
01411                      GWEN_PATH_FLAGS_NAMEMUSTEXIST |
01412                      GWEN_PATH_FLAGS_VARIABLE);
01413   if (!nn) {
01414     DBG_VERBOUS(GWEN_LOGDOMAIN, "Path \"%s\" not found", path);
01415     return 0;
01416   }
01417 
01418   return 1;
01419 }
01420 
01421 
01422 
01423 int GWEN_DB_ValueExists(GWEN_DB_NODE *n,
01424                         const char *path,
01425                         unsigned int i){
01426   return (GWEN_DB_GetValue(n, path, i)!=0);
01427 }
01428 
01429 
01430 
01431 GWEN_DB_NODE_TYPE GWEN_DB_GetVariableType(GWEN_DB_NODE *n,
01432                                           const char *p){
01433   GWEN_DB_NODE *nn;
01434 
01435   nn=GWEN_DB_FindVar(n, p, 0);
01436   if (!nn)
01437     return GWEN_DB_NodeType_Unknown;
01438 
01439   nn=GWEN_DB_GetFirstValue(nn);
01440   if (!nn)
01441     return GWEN_DB_NodeType_Unknown;
01442   return GWEN_DB_GetValueType(nn);
01443 }
01444 
01445 
01446 
01447 GWEN_DB_NODE_TYPE GWEN_DB_GetValueTypeByPath(GWEN_DB_NODE *n,
01448                                              const char *path,
01449                                              unsigned int i){
01450   GWEN_DB_NODE *nn;
01451 
01452   nn=GWEN_DB_GetValue(n, path, i);
01453   if (!nn)
01454     return GWEN_DB_NodeType_Unknown;
01455   return GWEN_DB_GetValueType(nn);
01456 }
01457 
01458 
01459 void GWEN_DB_GroupRename(GWEN_DB_NODE *n, const char *newname){
01460   assert(n);
01461   assert(newname);
01462   assert(n->typ==GWEN_DB_NodeType_Group);
01463   GWEN_Memory_dealloc(n->data.dataName);
01464   n->data.dataName=GWEN_Memory_strdup(newname);
01465 }
01466 
01467 
01468 
01469 
01470 
01471 
01472 
01473 int GWEN_DB_IsGroup(const GWEN_DB_NODE *n){
01474   assert(n);
01475   return n->typ==GWEN_DB_NodeType_Group;
01476 }
01477 
01478 
01479 
01480 int GWEN_DB_IsVariable(const GWEN_DB_NODE *n){
01481   assert(n);
01482   return n->typ==GWEN_DB_NodeType_Var;
01483 }
01484 
01485 
01486 
01487 int GWEN_DB_IsValue(const GWEN_DB_NODE *n){
01488   assert(n);
01489   return (n->typ>=GWEN_DB_NodeType_ValueChar &&
01490           n->typ>=GWEN_DB_NodeType_ValueLast);
01491 }
01492 
01493 
01494 
01495 void *GWEN_DB_Groups_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func,
01496                              void *user_data){
01497   GWEN_DB_NODE *iter;
01498   void *res;
01499 
01500   assert(node);
01501   assert(func);
01502 
01503   iter=GWEN_DB_GetFirstGroup(node);
01504   res=NULL;
01505   while(iter){
01506     res=(*func)(iter, user_data);
01507     if (res) {
01508       break;
01509     }
01510     iter=GWEN_DB_GetNextGroup(iter);
01511   }
01512   return res;
01513 }
01514 
01515 
01516 
01517 void *GWEN_DB_count_cb(GWEN_UNUSED GWEN_DB_NODE *node, void *user_data){
01518   unsigned int *a = user_data;
01519   ++(*a);
01520   return NULL;
01521 }
01522 
01523 
01524 
01525 unsigned int GWEN_DB_Groups_Count(const GWEN_DB_NODE *node){
01526   unsigned int res = 0;
01527   GWEN_DB_Groups_Foreach((GWEN_DB_NODE *)node, GWEN_DB_count_cb, &res);
01528   return res;
01529 }
01530 
01531 
01532 
01533 void *GWEN_DB_Variables_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func,
01534                                 void *user_data){
01535   GWEN_DB_NODE *iter;
01536   void *res;
01537 
01538   assert(node);
01539   assert(func);
01540 
01541   iter=GWEN_DB_GetFirstVar(node);
01542   res=NULL;
01543   while(iter){
01544     res=(*func)(iter, user_data);
01545     if (res) {
01546       break;
01547     }
01548     iter=GWEN_DB_GetNextVar(iter);
01549   }
01550   return res;
01551 }
01552 
01553 
01554 
01555 unsigned int GWEN_DB_Variables_Count(const GWEN_DB_NODE *node){
01556   unsigned int res = 0;
01557   GWEN_DB_Variables_Foreach((GWEN_DB_NODE *)node, GWEN_DB_count_cb, &res);
01558   return res;
01559 }
01560 
01561 
01562 
01563 void *GWEN_DB_Values_Foreach(GWEN_DB_NODE *node, GWEN_DB_NODES_CB func,
01564                              void *user_data){
01565   GWEN_DB_NODE *iter;
01566   void *res;
01567 
01568   assert(node);
01569   assert(func);
01570 
01571   iter=GWEN_DB_GetFirstValue(node);
01572   res=NULL;
01573   while(iter){
01574     res=(*func)(iter, user_data);
01575     if (res) {
01576       break;
01577     }
01578     iter=GWEN_DB_GetNextValue(iter);
01579   }
01580   return res;
01581 }
01582 
01583 
01584 
01585 unsigned int GWEN_DB_Values_Count(const GWEN_DB_NODE *node){
01586   unsigned int res = 0;
01587   GWEN_DB_Values_Foreach((GWEN_DB_NODE *)node, GWEN_DB_count_cb, &res);
01588   return res;
01589 }
01590 
01591 
01592 
01593 uint32_t GWEN_DB_GetNodeFlags(const GWEN_DB_NODE *n){
01594   assert(n);
01595   return n->nodeFlags;
01596 }
01597 
01598 
01599 
01600 void GWEN_DB_SetNodeFlags(GWEN_DB_NODE *n,
01601                           uint32_t flags){
01602   assert(n);
01603   n->nodeFlags=flags;
01604 }
01605 
01606 
01607 
01608 void GWEN_DB_ModifyBranchFlagsUp(GWEN_DB_NODE *n,
01609                                  uint32_t newflags,
01610                                  uint32_t mask){
01611   uint32_t flags;
01612 
01613   assert(n);
01614 
01615   while(n) {
01616     flags=n->nodeFlags;
01617     flags=((flags^newflags)&(mask))^flags;
01618     n->nodeFlags=flags;
01619     n=n->parent;
01620   } /* while */
01621 }
01622 
01623 
01624 
01625 void GWEN_DB_ModifyBranchFlagsDown(GWEN_DB_NODE *n,
01626                                    uint32_t newflags,
01627                                    uint32_t mask){
01628   uint32_t flags;
01629   GWEN_DB_NODE *cn;
01630 
01631   assert(n);
01632 
01633   flags=n->nodeFlags;
01634   flags=((flags^newflags)&(mask))^flags;
01635   n->nodeFlags=flags;
01636 
01637   cn=GWEN_DB_Node_List_First(n->children);
01638   while(cn) {
01639     GWEN_DB_ModifyBranchFlagsDown(cn, newflags, mask);
01640     cn=GWEN_DB_Node_List_Next(cn);
01641   } /* while cn */
01642 }
01643 
01644 
01645 
01646 GWEN_DB_NODE *GWEN_DB_FindFirstGroup(GWEN_DB_NODE *n, const char *name){
01647   GWEN_DB_NODE *nn;
01648 
01649   assert(n);
01650   if (n->typ!=GWEN_DB_NodeType_Group) {
01651     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01652     return NULL;
01653   }
01654   nn=GWEN_DB_Node_List_First(n->children);
01655   while(nn) {
01656     if ((nn->typ==GWEN_DB_NodeType_Group) &&
01657         (-1!=GWEN_Text_ComparePattern(nn->data.dataName, name, 0)))
01658       break;
01659     nn=GWEN_DB_Node_List_Next(nn);
01660   } /* while node */
01661   return nn;
01662 }
01663 
01664 
01665 
01666 GWEN_DB_NODE *GWEN_DB_FindNextGroup(GWEN_DB_NODE *n, const char *name){
01667   GWEN_DB_NODE *og;
01668 
01669   og=n;
01670   assert(n);
01671   if (n->typ!=GWEN_DB_NodeType_Group) {
01672     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01673     return NULL;
01674   }
01675   n=GWEN_DB_GetNextGroup(n);
01676   while(n) {
01677     if (-1!=GWEN_Text_ComparePattern(n->data.dataName, name, 0))
01678       break;
01679     n=GWEN_DB_GetNextGroup(n);
01680   } /* while node */
01681   assert(n!=og);
01682   return n;
01683 }
01684 
01685 
01686 
01687 GWEN_DB_NODE *GWEN_DB_FindFirstVar(GWEN_DB_NODE *n, const char *name) {
01688   GWEN_DB_NODE *nn;
01689 
01690   assert(n);
01691   if (n->typ!=GWEN_DB_NodeType_Group) {
01692     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a group");
01693     return NULL;
01694   }
01695 
01696   nn=GWEN_DB_Node_List_First(n->children);
01697   while(nn) {
01698     if ((nn->typ==GWEN_DB_NodeType_Var) &&
01699         (-1!=GWEN_Text_ComparePattern(nn->data.dataName, name, 0)))
01700       break;
01701     nn=GWEN_DB_Node_List_Next(nn);
01702   } /* while node */
01703 
01704   return nn;
01705 }
01706 
01707 
01708 
01709 GWEN_DB_NODE *GWEN_DB_FindNextVar(GWEN_DB_NODE *n, const char *name) {
01710   GWEN_DB_NODE *og;
01711 
01712   og=n;
01713   assert(n);
01714   if (n->typ!=GWEN_DB_NodeType_Var) {
01715     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
01716     return NULL;
01717   }
01718   n=GWEN_DB_GetNextVar(n);
01719   while(n) {
01720     if (-1!=GWEN_Text_ComparePattern(n->data.dataName, name, 0))
01721       break;
01722     n=GWEN_DB_GetNextVar(n);
01723   } /* while node */
01724   assert(n!=og);
01725   return n;
01726 }
01727 
01728 
01729 
01730 const char *GWEN_DB_VariableName(GWEN_DB_NODE *n){
01731   assert(n);
01732   if (n->typ!=GWEN_DB_NodeType_Var) {
01733     DBG_ERROR(GWEN_LOGDOMAIN, "Node is not a variable");
01734     return NULL;
01735   }
01736   return n->data.dataName;
01737 }
01738 
01739 
01740 
01741 void GWEN_DB_VariableRename(GWEN_DB_NODE *n, const char *newname){
01742   assert(n);
01743   assert(newname);
01744   assert(n->typ==GWEN_DB_NodeType_Var);
01745   GWEN_Memory_dealloc(n->data.dataName);
01746   n->data.dataName=GWEN_Memory_strdup(newname);
01747 }
01748 
01749 
01750 
01751 
01752 
01753 
01754 #include "dbrw.c"
01755 
01756 
01757 
01758 
01759 
01760 
01761 
01762 
01763