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