• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2001-2004 Brandon Long
3  * All Rights Reserved.
4  *
5  * ClearSilver Templating System
6  *
7  * This code is made available under the terms of the ClearSilver License.
8  * http://www.clearsilver.net/license.hdf
9  *
10  */
11 
12 #ifndef __NEO_HDF_H_
13 #define __NEO_HDF_H_ 1
14 
15 __BEGIN_DECLS
16 
17 #include <stdio.h>
18 #include "util/neo_err.h"
19 #include "util/neo_hash.h"
20 
21 #define FORCE_HASH_AT 10
22 
23 typedef struct _hdf HDF;
24 
25 /* HDFFILELOAD is a callback function to intercept file load requests and
26  * provide templates via another mechanism.  This way you can load templates
27  * that you compiled-into your binary, from in-memory caches, or from a
28  * zip file, etc.  The HDF is provided so you can choose to use the
29  * hdf_search_path function to find the file.  contents should return
30  * a full malloc copy of the contents of the file, which the parser will
31  * own and free.  Use hdf_register_fileload to set this function for
32  * your top level HDF node.
33  * NOTE: Technically, we shouldn't need a separate copy for each parse, but
34  * using the separate copy makes this equivalent to the CSFILELOAD function.  We
35  * can change this if we really want to save that copy at the expense of
36  * slightly more complicated code. */
37 typedef NEOERR* (*HDFFILELOAD)(void *ctx, HDF *hdf, const char *filename,
38                               char **contents);
39 
40 typedef struct _attr
41 {
42   char *key;
43   char *value;
44   struct _attr *next;
45 } HDF_ATTR;
46 
47 struct _hdf
48 {
49   int link;
50   int alloc_value;
51   char *name;
52   int name_len;
53   char *value;
54   struct _attr *attr;
55   struct _hdf *top;
56   struct _hdf *next;
57   struct _hdf *child;
58 
59   /* the following fields are used to implement a cache */
60   struct _hdf *last_hp;
61   struct _hdf *last_hs;
62 
63   /* the following HASH is used when we reach more than FORCE_HASH_AT
64    * elements */
65   NE_HASH *hash;
66   /* When using the HASH, we need to know where to append new children */
67   struct _hdf *last_child;
68 
69   /* Should only be set on the head node, used to override the default file
70    * load method */
71   void *fileload_ctx;
72   HDFFILELOAD fileload;
73 };
74 
75 /*
76  * Function: hdf_init - Initialize an HDF data set
77  * Description: hdf_init initializes an HDF data set and returns the
78  *              pointer to the top node in the data set.
79  * Input: hdf - pointer to an HDF pointer
80  * Output: hdf - allocated hdf node
81  * Returns: NERR_NOMEM - unable to allocate memory for dataset
82  */
83 NEOERR* hdf_init (HDF **hdf);
84 
85 /*
86  * Function: hdf_destroy - deallocate an HDF data set
87  * Description: hdf_destroy is used to deallocate all memory associated
88  *              with an hdf data set.  Although you can pass an HDF node
89  *              as an argument to this function, you are likely to cause
90  *              a segfault if you continue to access the data set.  In
91  *              the future, we may restrict hdf_destroy so it only works
92  *              on the top level node.
93  * Input: hdf - pointer to an HDF data set allocated with hdf_init
94  * Output: None
95  * Returns: None
96  */
97 void hdf_destroy (HDF **hdf);
98 
99 /*
100  * Function: hdf_get_int_value - Return the integer value of a point in
101  *           the data set
102  * Description: hdf_get_int_value walks the HDF data set pointed to by
103  *              hdf to name, and returns the value of that node
104  *              converted to an integer.  If that node does not exist,
105  *              or it does not contain a number, the defval is returned.
106  * Input: hdf -> a node in an HDF data set
107  *        name -> the name of a node to walk to in the data set
108  *        defval -> value to return in case of error or if the node
109  *                  doesn't exist
110  * Output: None
111  * Returns: The integer value of the node, or the defval
112  */
113 int hdf_get_int_value (HDF *hdf, const char *name, int defval);
114 
115 /*
116  * Function: hdf_get_value - Return the value of a node in the data set
117  * Description: hdf_get_value walks the data set pointed to by hdf via
118  *              name and returns the string value located there, or
119  *              defval if the node doesn't exist
120  * Input: hdf -> the dataset node to start from
121  *        name -> the name to walk the data set to
122  *        defval -> the default value to return if the node doesn't
123  *                  exist
124  * Output: None
125  * Returns: A pointer to the string stored in the data set, or defval.
126  *          The data set maintains ownership of the string, if you want
127  *          a copy you either have to call strdup yourself, or use
128  *          hdf_get_copy
129  */
130 char *hdf_get_value (HDF *hdf, const char *name, const char *defval);
131 
132 /*
133  * Function: hdf_get_valuevf - Return the value of a node in the data set
134  * Description: hdf_get_valuevf walks the data set pointed to by hdf via
135  *              namefmt printf expanded with varargs ap, and returns the
136  *              string value located there, or NULL if it doesn't exist.
137  *              This differs from hdf_get_value in that there is no
138  *              default value possible.
139  * Input: hdf -> the dataset node to start from
140  *        namefmt -> the format string
141  *        ap -> va_list of varargs
142  * Output: None
143  * Returns: A pointer to the string stored in the data set, or NULL.
144  *          The data set maintains ownership of the string, if you want
145  *          a copy you either have to call strdup yourself.
146  */
147 char* hdf_get_valuevf (HDF *hdf, const char *namefmt, va_list ap);
148 
149 /*
150  * Function: hdf_get_valuef - Return the value of a node in the data set
151  * Description: hdf_get_valuef walks the data set pointed to by hdf via
152  *              namefmt printf expanded with varargs, and returns the
153  *              string value located there, or NULL if it doesn't exist.
154  *              This differs from hdf_get_value in that there is no
155  *              default value possible.
156  * Input: hdf -> the dataset node to start from
157  *        namefmt -> the printf-style format string
158  *        ... -> arguments to fill out namefmt
159  * Output: None
160  * Returns: A pointer to the string stored in the data set, or NULL.
161  *          The data set maintains ownership of the string, if you want
162  *          a copy you either have to call strdup yourself.
163  */
164 char* hdf_get_valuef (HDF *hdf, const char *namefmt, ...)
165                       ATTRIBUTE_PRINTF(2,3);
166 
167 /*
168  * Function: hdf_get_copy - Returns a copy of a string in the HDF data set
169  * Description: hdf_get_copy is similar to hdf_get_value, except that it
170  *              returns an malloc'd copy of the string.
171  * Input: hdf -> the dataset node to start from
172  *        name -> the name to walk the data set to
173  *        defval -> the default value to return if the node doesn't
174  *                  exist
175  * Output: value -> the allocated string (if defval = NULL, then value
176  *                  will be NULL if defval is used)
177  * Returns: NERR_NOMEM if unable to allocate the new copy
178  */
179 NEOERR* hdf_get_copy (HDF *hdf, const char *name, char **value,
180                       const char *defval);
181 
182 /*
183  * Function: hdf_get_obj - return the HDF data set node at a named location
184  * Description: hdf_get_obj walks the dataset given by hdf to the node
185  *              named name, and then returns the pointer to that node
186  * Input: hdf -> the dataset node to start from
187  *        name -> the name to walk to
188  * Output: None
189  * Returns: the pointer to the named node, or NULL if it doesn't exist
190  */
191 HDF* hdf_get_obj (HDF *hdf, const char *name);
192 
193 /*
194  * Function: hdf_get_node - Similar to hdf_get_obj except all the nodes
195  *           are created if the don't exist.
196  * Description: hdf_get_node is similar to hdf_get_obj, except instead
197  *              of stopping if it can't find a node in the tree, it will
198  *              create all of the nodes necessary to hand you back the
199  *              node you ask for.  Nodes are created with no value.
200  * Input: hdf -> the dataset node to start from
201  *        name -> the name to walk to
202  * Output: ret -> the dataset node you asked for
203  * Returns: NERR_NOMEM - unable to allocate new nodes
204  */
205 NEOERR * hdf_get_node (HDF *hdf, const char *name, HDF **ret);
206 
207 /*
208  * Function: hdf_get_child - return the first child of the named node
209  * Description: hdf_get_child will walk the dataset starting at hdf to
210  *              name, and return the first child of that node
211  * Input: hdf -> the dataset node to start from
212  *        name -> the name to walk to
213  * Output: None
214  * Returns: The first child of the named dataset node or NULL if the
215  *          node is not found (or it has no children)
216  */
217 HDF* hdf_get_child (HDF *hdf, const char *name);
218 
219 /*
220  * Function: hdf_get_attr -
221  * Description:
222  * Input:
223  * Output:
224  * Returns:
225  */
226 HDF_ATTR* hdf_get_attr (HDF *hdf, const char *name);
227 
228 /*
229  * Function: hdf_set_attr -
230  * Description:
231  * Input:
232  * Output:
233  * Returns:
234  */
235 NEOERR* hdf_set_attr (HDF *hdf, const char *name, const char *key,
236                       const char *value);
237 
238 /*
239  * Function: hdf_obj_child - Return the first child of a dataset node
240  * Description: hdf_obj_child and the other hdf_obj_ functions are
241  *              accessors to the HDF dataset.  Although we do not
242  *              currently "hide" the HDF struct implementation, we
243  *              recommend you use the accessor functions instead of
244  *              accessing the values directly.
245  * Input: hdf -> the hdf dataset node
246  * Output: None
247  * Returns: The pointer to the first child, or NULL if there is none
248  */
249 HDF* hdf_obj_child (HDF *hdf);
250 
251 /*
252  * Function: hdf_obj_next - Return the next node of a dataset level
253  * Description: hdf_obj_next is an accessor function for the HDF struct
254  * Input: hdf -> the hdf dataset node
255  * Output: None
256  * Returns: The pointer to the next node, or NULL if there is none
257  */
258 HDF* hdf_obj_next (HDF *hdf);
259 
260 /*
261  * Function: hdf_obj_top - Return the pointer to the top dataset node
262  * Description: hdf_obj_top is an accessor function which returns a
263  *              pointer to the top of the dataset, the node which was
264  *              returned by hdf_init.  This is most useful for
265  *              implementations of language wrappers where individual
266  *              nodes are tied garbage colletion wise to the top node of
267  *              the data set
268  * Input: hdf -> the hdf dataset node
269  * Output: None
270  * Returns: The pointer to the top node
271  */
272 HDF* hdf_obj_top (HDF *hdf);
273 
274 /*
275  * Function: hdf_obj_attr - Return the HDF Attributes for a node
276  * Description:
277  * Input:
278  * Output:
279  * Returns:
280  */
281 HDF_ATTR* hdf_obj_attr (HDF *hdf);
282 
283 /*
284  * Function: hdf_obj_name - Return the name of a node
285  * Description: hdf_obj_name is an accessor function for a datset node
286  *              which returns the name of the node.  This is just the
287  *              local name, and not the full path.
288  * Input: hdf -> the hdf dataset node
289  * Output: None
290  * Returns: The name of the node.  If this is the top node, the name is
291  * NULL.
292  */
293 char* hdf_obj_name (HDF *hdf);
294 
295 /*
296  * Function: hdf_obj_value - Return the value of a node
297  * Description: hdf_obj_value is an accessor function for a dataset node
298  *              which returns the value of the node, or NULL if the node
299  *              has no value.  This is not a copy of the value, so the
300  *              node retains ownership of the value
301  * Input: hdf -> the hdf dataset node
302  * Output: None
303  * Returns: The value of the node, or NULL if it has no value
304  */
305 char* hdf_obj_value (HDF *hdf);
306 
307 /*
308  * Function: hdf_set_value - Set the value of a named node
309  * Description: hdf_set_value will set the value of a named node.  All
310  *              of the interstitial nodes which don't exist will be
311  *              created with a value of NULL.  Existing nodes are not
312  *              modified.  New nodes are created at the end of the list.
313  *              If a list of nodes exceeds FORCE_HASH_AT, then a HASH
314  *              will be created at that level and all of the nodes will
315  *              be added to the hash for faster lookup times.
316  *              The copy of the value will be made which the dataset
317  *              will own.
318  * Input: hdf -> the pointer to the hdf dataset
319  *        name -> the named node to walk to
320  *        value -> the value to set the node to
321  * Output: None
322  * Returns: NERR_NOMEM
323  */
324 NEOERR* hdf_set_value (HDF *hdf, const char *name, const char *value);
325 
326 /*
327  * Function: hdf_set_valuef - Set the value of a named node
328  * Description: hdf_set_valuef is a convenience function that wraps
329  *              hdf_set_value.  Due to limitations of C, the fmt is in
330  *              the format "name=value", where we will first format the
331  *              entire string, and then break it at the first (from the
332  *              left) equal sign (=) and use the left portion as the
333  *              name and the right portion as the value.  This function
334  *              is somewhat inefficient in that it first allocates the
335  *              full name=value, and then the call to hdf_set_value
336  *              duplicates the value portion, and then we free the
337  *              name=value.
338  *              Currently, we don't strip whitespace from the key or
339  *              value.  In the future, this function might work more
340  *              like reading a single line of an HDF string or file,
341  *              allowing for attributes and symlinks to be specified...
342  *              maybe.
343  * Input: hdf -> the pointer to the hdf dataset
344  *        fmt -> the name=value printf(3) format string
345  * Output: None
346  * Returns: NERR_NOMEM
347  */
348 NEOERR* hdf_set_valuef (HDF *hdf, const char *fmt, ...)
349                         ATTRIBUTE_PRINTF(2,3);
350 NEOERR* hdf_set_valuevf (HDF *hdf, const char *fmt, va_list ap);
351 
352 /*
353  * Function: hdf_set_int_value - Set the value of a named node to a number
354  * Description: hdf_set_int_value is a helper function that maps an
355  *              integer to a string, and then calls hdf_set_value with
356  *              that string
357  * Input: hdf -> the pointer to the hdf dataset
358  *        name -> the named node to walk to
359  *        value -> the value to set the node to
360  * Output: None
361  * Returns: NERR_NOMEM
362  */
363 NEOERR* hdf_set_int_value (HDF *hdf, const char *name, int value);
364 
365 /*
366  * Function: hdf_set_copy -> Copy a value from one location in the
367  *           dataset to another
368  * Description: hdf_set_copy first walks the hdf dataset to the named src
369  *              node, and then copies that value to the named dest node.
370  *              If the src node is not found, an error is raised.
371  * Input: hdf -> the pointer to the dataset node
372  *        dest -> the name of the destination node
373  *        src -> the name of the source node
374  * Output: None
375  * Returns: NERR_NOMEM, NERR_NOT_FOUND
376  */
377 NEOERR* hdf_set_copy (HDF *hdf, const char *dest, const char *src);
378 
379 /*
380  * Function: hdf_set_buf - Set the value of a node without duplicating
381  *           the value
382  * Description: hdf_set_buf is similar to hdf_set_value, except the
383  *              dataset takes ownership of the value instead of making a
384  *              copy of it.  The dataset assumes that value was
385  *              malloc'd, since it will attempt to free it when
386  *              hdf_destroy is called
387  * Input: hdf -> the hdf dataset node
388  *        name -> the name to walk to
389  *        value -> the malloc'd value
390  * Output: None
391  * Returns: NERR_NOMEM - unable to allocate a node
392  */
393 
394 NEOERR* hdf_set_buf (HDF *hdf, const char *name, char *value);
395 
396 /*
397  * Function: hdf_set_symlink - Set part of the tree to link to another
398  * Description: hdf_set_symlink creates a link between two sections of
399  *              an HDF dataset.  The link is "by name" hence the term
400  *              "symlink".  This means that the destination node does
401  *              not need to exist.  Any attempt to access the source
402  *              node will cause the function to walk to the dest node,
403  *              and then continue walking from there.  Using symlinks
404  *              can "hide" values in the dataset since you won't be able
405  *              to access any children of the linked node directly,
406  *              though dumps and other things which access the data
407  *              structure directly will bypass the symlink.  Use this
408  *              feature sparingly as its likely to surprise you.
409  * Input: hdf -> the dataset node
410  *        src -> the source node name
411  *        dest -> the destination node name (from the top of the
412  *        dataset, not relative names)
413  * Output: None
414  * Returns: NERR_NOMEM
415  */
416 NEOERR *hdf_set_symlink (HDF *hdf, const char *src, const char *dest);
417 
418 /*
419  * Function: hdf_sort_obj - sort the children of an HDF node
420  * Description: hdf_sort_obj will sort the children of an HDF node,
421  *              based on the given comparison function.
422  *              This function works by creating an array of the pointers
423  *              for each child object of h, using qsort to sort that
424  *              array, and then re-ordering the linked list of children
425  *              to the new order.  The qsort compare function uses a
426  *              pointer to the value in the array, which in our case is
427  *              a pointer to an HDF struct, so your comparison function
428  *              should work on HDF ** pointers.
429  * Input: h - HDF node
430  *        compareFunc - function which returns 1,0,-1 depending on some
431  *                      criteria.  The arguments to this sort function
432  *                      are pointers to pointers to HDF elements.  For
433  *                      example:
434  *                      int sortByName(const void *a, const void *b) {
435  *                        HDF **ha = (HDF **)a;
436  *                        HDF **hb = (HDF **)b;
437  *
438  *                      return strcasecmp(hdf_obj_name(*ha), hdf_obj_name(*hb));
439  *                      }
440  *
441  * Output: None (h children will be sorted)
442  * Return: NERR_NOMEM
443  */
444 NEOERR *hdf_sort_obj(HDF *h, int (*compareFunc)(const void *, const void *));
445 
446 /*
447  * Function: hdf_read_file - read an HDF data file
448  * Description:
449  * Input:
450  * Output:
451  * Returns: NERR_IO, NERR_NOMEM, NERR_PARSE
452  */
453 NEOERR* hdf_read_file (HDF *hdf, const char *path);
454 
455 /*
456  * Function: hdf_write_file - write an HDF data file
457  * Description:
458  * Input:
459  * Output:
460  * Returns: NERR_IO
461  */
462 NEOERR* hdf_write_file (HDF *hdf, const char *path);
463 
464 /*
465  * Function: hdf_write_file_atomic - write an HDF data file atomically
466  * Description: hdf_write_file_atomic is similar to hdf_write_file,
467  *              except the new file is created with a unique name and
468  *              then rename(2) is used to atomically replace the old
469  *              file with the new file
470  * Input:
471  * Output:
472  * Returns: NERR_IO
473  */
474 NEOERR* hdf_write_file_atomic (HDF *hdf, const char *path);
475 
476 /*
477  * Function: hdf_read_string - read an HDF string
478  * Description:
479  * Input:
480  * Output:
481  * Returns: NERR_NOMEM, NERR_PARSE
482  */
483 NEOERR* hdf_read_string (HDF *hdf, const char *s);
484 
485 /*
486  * Function: hdf_read_string_ignore - Read an HDF string and ignore errors
487  * Description:
488  * Input:
489  * Output:
490  * Returns: NERR_NOMEM
491  */
492 NEOERR* hdf_read_string_ignore (HDF *hdf, const char *s, int ignore);
493 
494 /*
495  * Function: hdf_write_string - serialize an HDF dataset to a string
496  * Description:
497  * Input:
498  * Output:
499  * Returns: NERR_NOMEM
500  */
501 NEOERR* hdf_write_string (HDF *hdf, char **s);
502 
503 /*
504  * Function: hdf_dump - dump an HDF dataset to stdout
505  * Description:
506  * Input:
507  * Output:
508  * Returns:
509  */
510 NEOERR* hdf_dump (HDF *hdf, const char *prefix);
511 
512 /*
513  * Function: hdf_dump_format - dump an HDF dataset to FILE *fp
514  * Description:
515  * Input:
516  * Output:
517  * Returns:
518  */
519 NEOERR* hdf_dump_format (HDF *hdf, int lvl, FILE *fp);
520 
521 /*
522  * Function: hdf_dump_str - dump an HDF dataset to STRING
523  * Description:
524  * Input:
525  * Output:
526  * Returns:
527  */
528 NEOERR* hdf_dump_str(HDF *hdf, const char *prefix, int compact, STRING *str);
529 
530 /*
531  * Function: hdf_remove_tree - delete a subtree of an HDF dataset
532  * Description:
533  * Input:
534  * Output:
535  * Returns:
536  */
537 NEOERR* hdf_remove_tree (HDF *hdf, const char *name);
538 
539 /*
540  * Function: hdf_copy - copy part of an HDF dataset to another
541  * Description: hdf_copy is a deep copy of an HDF tree pointed to by
542  *              src to the named node of dest.  dest and src need not be
543  *              part of the same data set
544  * Input: dest_hdf -> the destination dataset
545  *        name -> the name of the destination node
546  *        src -> the hdf dataset to copy to the destination
547  * Output: None
548  * Returns: NERR_NOMEM, NERR_NOT_FOUND
549  */
550 NEOERR* hdf_copy (HDF *dest_hdf, const char *name, HDF *src);
551 
552 /*
553  * Function: hdf_search_path - Find a file given a search path in HDF
554  * Description: hdf_search_path is a convenience/utility function that
555  *              searches for relative filenames in a search path.  The
556  *              search path is the list given by the children of
557  *              hdf.loadpaths.
558  * Input: hdf -> the hdf dataset to use
559  *        path -> the relative path
560  *        full -> a pointer to a _POSIX_PATH_MAX buffer
561  * Output: full -> the full path of the file
562  * Returns: NERR_NOT_FOUND if the file wasn't found in the search path
563  */
564 NEOERR* hdf_search_path (HDF *hdf, const char *path, char *full);
565 
566 /*
567  * Function: hdf_register_fileload - register a fileload function
568  * Description: hdf_register_fileload registers a fileload function that
569  *              overrides the built-in function.  The built-in function
570  *              uses hdf_search_path and ne_file_load (based on stat/open/read)
571  *              to find and load the file on every hdf_read_file (including
572  *              #include).  You can override this function if you wish to provide
573  *              other file search functions, or load the hdf file
574  *              from an in-memory cache, etc.
575  * Input: hdf - pointer to a head HDF node
576  *        ctx - pointer that is passed to the HDFFILELOAD function when called
577  *        fileload - a HDFFILELOAD function
578  * Output: None
579  * Return: None
580  *
581  */
582 
583 void hdf_register_fileload(HDF *hdf, void *ctx, HDFFILELOAD fileload);
584 
585 __END_DECLS
586 
587 #endif /* __NEO_HDF_H_ */
588