datanode.c

Go to the documentation of this file.
00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00038 #include "fastlib/fx/datanode.h"
00039 /*#include "datanode.h"*/
00040 
00041 #ifndef LINE_MAX
00042 #define LINE_MAX 2048
00043 #endif
00044 
00045 static void datanode__reset(struct datanode *node)
00046 {
00047   node->mod_type = 0;
00048   node->val_type = 0;
00049   node->meta = NULL;
00050 
00051   node->key = NULL;
00052   node->val = NULL;
00053 
00054   node->first_child = NULL;
00055   node->last_child = NULL;
00056   node->next = NULL;
00057   node->parent = NULL;
00058 }
00059 
00060 void datanode_init(struct datanode *node, const char *key)
00061 {
00062   datanode__reset(node);
00063   node->key = strdup(key);
00064 }
00065 
00066 void datanode_destroy(struct datanode *node)
00067 {
00068   struct datanode *child = node->first_child;
00069 
00070   while (child) {
00071     struct datanode *next = child->next;
00072 
00073     datanode_destroy(child);
00074     free(child);
00075 
00076     child = next;
00077   }
00078 
00079   free(node->key);
00080   free(node->val);
00081 
00082   datanode__reset(node);
00083 }
00084 
00085 
00086 
00087 struct datanode *datanode_lookup_expert(struct datanode *node, char *path,
00088                                         int create)
00089 {
00090   char *end = path + strlen(path);
00091   *end = '/'; /* Note: not null-terminated! */
00092 
00093   while (path < end) {
00094     char *slash = strchr(path, '/');
00095     *slash = '\0'; /* Demark end of current query */
00096 
00097     /* Match special paths: "", ".", ".." */
00098     if (unlikely(*path == '\0' || strcmp(path, ".") == 0)) {
00099       path = slash + 1;
00100       continue;
00101     } else if (unlikely(strcmp(path, "..") == 0)) {
00102       if (node->parent) {
00103         node = node->parent;
00104       }
00105       path = slash + 1;
00106       continue;
00107     }
00108 
00109     /* Seek query in node's children, moving it to the end
00110      * - moving things to end gets them out of the way
00111      * - but check end first for fast repeat lookups
00112      */   
00113     if (!node->last_child
00114         || likely(strcmp(path, node->last_child->key) != 0)) {
00115       struct datanode *child;
00116       struct datanode **prev;
00117 
00118       /* Note: last child can't match, already checked it
00119        * - important because use of node->last_child would fail
00120        */
00121       for (prev = &node->first_child, child = node->first_child; child;
00122            prev = &child->next, child = child->next) {
00123         if (unlikely(strcmp(path, child->key) == 0)) {
00124           *prev = child->next;
00125           child->next = NULL;
00126           node->last_child->next = child;
00127           node->last_child = child;
00128           break;
00129         }
00130       }
00131 
00132       /* Create query if not found */
00133       if (unlikely(!child)) {
00134         if (!create) {
00135           return NULL;
00136         }
00137 
00138         child = malloc(sizeof(struct datanode));
00139         datanode__reset(child);
00140 
00141         child->key = malloc((slash - path + 1) * sizeof(char));
00142         strcpy(child->key, path);
00143         child->parent = node;
00144         *prev = child; /* Note: handles empty lists, too */
00145         node->last_child = child;
00146       }
00147     }
00148 
00149     node = node->last_child;
00150     path = slash + 1;
00151   }
00152 
00153   return node;
00154 }
00155 
00156 struct datanode *datanode_lookup(struct datanode *node, const char *path,
00157                                  int create)
00158 {
00159   struct datanode *retval;
00160   char *buf = strdup(path);
00161 
00162   retval = datanode_lookup_expert(node, buf, create);
00163 
00164   free(buf);
00165   return retval;
00166 }
00167 
00168 static int datanode__exists_impl(struct datanode *node)
00169 {
00170   struct datanode *child;
00171 
00172   if (node->val) {
00173     return 1;
00174   }
00175 
00176   for (child = node->first_child; child; child = child->next) {
00177     if (datanode__exists_impl(child)) {
00178       return 1;
00179     }
00180   }
00181 
00182   return 0;
00183 }
00184 
00185 int datanode_exists(struct datanode *node, const char *path)
00186 {
00187   node = datanode_lookup(node, path, 0);
00188 
00189   return node && datanode__exists_impl(node);
00190 }
00191 
00192 void datanode_copy(struct datanode *dest, struct datanode *src,
00193                    int overwrite)
00194 {
00195   struct datanode *child;
00196 
00197   if (!dest->val || overwrite) {
00198     dest->mod_type = src->mod_type;
00199     dest->val_type = src->val_type;
00200     dest->meta = src->meta;
00201 
00202     /* TODO: consider clearing val if val_type < 0 */
00203     if (src->val && src->val_type >= 0) {
00204       free(dest->val);
00205       dest->val = strdup(src->val);
00206     }
00207   }
00208 
00209   for (child = src->first_child; child; child = child->next) {
00210     datanode_copy(datanode_lookup_expert(dest, child->key, 1), child,
00211                   overwrite);
00212   }
00213 }
00214 
00215 
00216 
00217 static void datanode__write_path(struct datanode *node, FILE *stream)
00218 {
00219   if (node->parent) {
00220     datanode__write_path(node->parent, stream);
00221     putc('/', stream);
00222   }
00223   hex_to_stream(stream, node->key, "_.-+");
00224 }
00225 
00226 void datanode_write(struct datanode *node, FILE *stream,
00227                     const char *type_char)
00228 {
00229   struct datanode *child;
00230 
00231   if (node->val && node->val_type >= 0) {
00232     datanode__write_path(node, stream);
00233     if (type_char) {
00234       fprintf(stream, ":%c", type_char[node->mod_type]);
00235     }
00236     putc(' ', stream);
00237     hex_to_stream(stream, node->val, "_.-+");
00238     putc('\n', stream);
00239   }
00240 
00241   for (child = node->first_child; child; child = child->next) {
00242     datanode_write(child, stream, type_char);
00243   }
00244 }
00245 
00246 void datanode_read(struct datanode *node, FILE *stream,
00247                    const char *type_char, int overwrite)
00248 {
00249   char buf[LINE_MAX];
00250 
00251   while (fgets(buf, sizeof(buf), stream) != NULL) {
00252     struct datanode *entry;
00253     char *key;
00254     char *val;
00255     int type;
00256     int len;
00257 
00258     /* Strip whitespace, skipping blanks and comments */
00259     for (key = buf; isspace(*key); ++key) {}
00260     if (*key == '\0' || *key == '#') {
00261       continue;
00262     }
00263     for (len = strlen(key); isspace(key[len-1]); --len) {}
00264     key[len] = '\n'; /* Note: not null-terminated! */
00265 
00266     /* Demark the end of key and beginning of value */
00267     for (val = key; !isspace(*val); ++val) {}
00268     key[len] = '\0'; /* Restore null-termination */
00269     if (val - key == len) {
00270       val = "";
00271     } else {
00272       len = val - key;
00273       *val = '\0';
00274       while (isspace(*++val)) {}
00275     }
00276 
00277     /* Identify the node type, if provided */
00278     type = 0;
00279     if (len > 2 && key[len-2] == ':') {
00280       if (type_char) {
00281         type = strchr(type_char, key[len-1]) - type_char;
00282       }
00283       key[len-2] = '\0';
00284     } else if (key[len-1] == ':') {
00285       key[len-1] = '\0';
00286     }
00287 
00288     unhex_in_place(key);
00289     unhex_in_place(val);
00290 
00291     entry = datanode_lookup_expert(node, key, 1);
00292     if (!entry->val || overwrite) {
00293       if (type_char) {
00294         entry->mod_type = type;
00295       }
00296       free(entry->val);
00297       entry->val = strdup(val);
00298     }
00299   }
00300 }
Generated on Mon Jan 24 12:04:37 2011 for FASTlib by  doxygen 1.6.3