Files
mlpack/fastlib2/fastlib/fx/datanode.h
T
2008-05-18 03:53:22 +00:00

201 lines
7.1 KiB
C

// Copyright 2007 Georgia Institute of Technology. All rights reserved.
/**
* @file datanode.h
*
* File-system-like storage of string data. Useful, for instance, for
* managing parameters, timers, and results between a hierarchy of
* program components (modules).
*/
#ifndef FX_DATANODE_H
#define FX_DATANODE_H
#include "fastlib/base/common.h"
EXTERN_C_BEGIN
/**
* A node composed of a key-value pair, metadata, and child nodes.
*
* Use datanode_init and datanode_lookup to create and obtain nodes.
*
* Nodes are always stored in linked lists, hence the pointer to the
* next element. Strings key and val are assumed to be "owned" by the
* datanode and will be freed when it is destroyed; never set these to
* string constants. Other pointers specify the heirachy of nodes and
* are maintained internally.
*
* Fields mod_type and val_type primarily serve as conveniences to
* external code. The datanode_read and datanode_write functions
* optionally map mod_type to and from a character, and all functions
* ignore the value stored at a node if val_type is negative (needed,
* for instance, if val is not a string). Both fields default to 0.
*
* Field meta allows external code to denote, e.g., constraints for
* val. It is copied by reference and never freed, and thus may be
* set to constant or externally managed strings. Its intended use is
* for lists of nominal values, numeric bounds, and regexp matching.
*
* @see datanode_init, datanode_lookup, datanode_read
*/
struct datanode {
/** The intended use of the node; managed externally. */
int mod_type;
/** The type of data stored at the node; managed externally. */
int val_type;
/** Additional information about the node; managed extermally. */
const char *meta;
/** String to match during lookup and pathing. */
char *key;
/** The node's data; assumed string unless val_type negative. */
char *val;
/** Beginning of a linked list of child nodes or NULL. */
struct datanode *first_child;
/** End of linked list; NULL iff first_child is NULL. */
struct datanode *last_child;
/** Pointer to a sibling node in containing linked list. */
struct datanode *next;
/** The node's parent; used in pathing and printing. */
struct datanode *parent;
};
/**
* Initializes a blank datanode.
*
* @param node a freshly constructed datanode
* @param key the name of the datanode; e.g. "" for root
*
* @see datanode_destruct, datanode_lookup, struct datanode
*/
void datanode_init(struct datanode *node, const char *key);
/**
* Frees memory allocated for all node beneath a given node.
*
* @param node the node to destruct
*
* @see datanode_init
*/
void datanode_destroy(struct datanode *node);
/**
* The same as datanode_lookup, except that the input path is
* destructively modified (slashes replaced with '\0').
*
* @param node the containing node of the node to find
* @param path the path to the node to find; destructively modified
* @param create whether to create the node if it does not exist
* @returns the found/created node, or NULL if not found
*
* @see datanode_lookup
*/
struct datanode *datanode_lookup_expert(struct datanode *node, char *path,
int create);
/**
* Obtains a node beneath a given node, pathing through child nodes as
* appropriate.
*
* The key passed to this function may be a slash-delimited path as in
* UNIX. Child nodes are (optionally) created if they do not exist,
* and both found and created entries are moved to the ends of their
* containing lists. This causes nodes to be printed in LRU order.
*
* It is never your responsibility to allocate or free memory for
* entire nodes, though when modifying a node's value, you must free
* the old value and provide a new one that may later be freed;
* i.e. do not use string constants, but instead strdup them first.
*
* @param node the containing node of the node to find
* @param path the path of the node to find
* @param create whether to create the node if it does not exist
* @returns the found/created node, or NULL if not found
*
* @see datanode_lookup_expert, datanode_exists, datanode_init
*/
struct datanode *datanode_lookup(struct datanode *node, const char *path,
int create);
/**
* Tests whether any values exists at or beneath a node.
*
* This is a somewhat awkward definition of "exists", but reflects the
* fact that valueless node may be created for metadata purposes only.
* It is equivalent to asking whether a node's key will occur with a
* value or in a path when printing.
*
* @param node the containing node of the node to check for
* @param path the path of the node to chedk for
* @returns whether the node was found
*
* @see datanode_lookup
*/
int datanode_exists(struct datanode *node, const char *path);
/**
* Copies values at and beneath a source node to a destination,
* optionally overwriting.
*
* The destination must already have been initialized via
* datanode_init or obtained via datanode_lookup.
*
* This function also copies mod_type, val_type, and meta even from
* source nodes that do not have values, but only if overwiting or if
* the destination has no value. Further, this function does not copy
* val if val_type is negative (assumed to be non-string).
*
* @param dest the node to receive copied values
* @param src the node to be copied
* @param overwrite whether to overwite existing values
*
* @see datanode_lookup, datanode_init
*/
void datanode_copy(struct datanode *dest, struct datanode *src,
int overwrite);
/**
* Prints all value-containing nodes beneath a given node in LRU
* (least recently used) order.
*
* Node are printed in the format:
* @code
* /path/from/root/key:type value
* @endcode
*
* Type is given by character @c type_char[node->type] if type_char is
* non-NULL; otherwise, it and its preceding colon are omitted. Nodes
* with negative val_type are not printed.
*
* Due to conflicts with certain valid characters in keys and values
* (e.g. colons, spaces, and newlines), non-alphanumeric characters
* other than "_+,-.[]" are converted to '%XX', where XX is the
* hexadecimal ASCII value.
*
* @param node the node to print
* @param stream the output stream
* @param type_char a string of characters indexed by node->type, or
* NULL if types should not be printed
*
* @see fx_module_read, struct datanode
*/
void datanode_write(struct datanode *node, FILE *stream,
const char *type_char);
/**
* Reads nodes from a file stream into a given node.
*
* Input format is identical to the output format for datanode_write.
* The ":type" segment is optional, with type set to 0 if emitted and
* left unchanged if type_chars is NULL (it still defaults to 0 for
* newly created nodes). Type is set via @c strchr(type_char, c) .
*
* @param node the node to be filled
* @param stream the input stream
* @param type_char a string of characters indexed by node->type, or
* NULL if types should be ignored
* @param overwrite whether to overwerite existing values
*
* @see fx_module_write, struct fx_module, fx_type_marker
*/
void datanode_read(struct datanode *node, FILE *stream,
const char *type_char, int overwrite);
EXTERN_C_END
#endif /* FX_DATANODE_H */