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

1073 lines
35 KiB
C

// Copyright 2007 Georgia Institute of Technology. All rights reserved.
/**
* @file fx.h
*
* Integration support for the FASTexec experiment-running system.
* This system automates the parsing of command line inputs,
* management of timers, and reporting of results. It simultaneously
* makes it easy for you to extend your program's interface and to
* document your program in a manner conveniently accessible by users.
*/
#ifndef FX_H
#define FX_H
#include "datanode.h"
#include "fastlib/base/common.h"
EXTERN_C_BEGIN
/** Somewhat clearer module typename for use with fx. */
typedef struct datanode fx_module;
/** Sonewhat clearer timer typename for use with fx. */
typedef struct stopwatch fx_timer;
/** The datanode under which all fx information is stored. */
extern fx_module *fx_root;
/**
* The various kinds of data entries.
*
* This type is primarily used to make sure that entries are used
* consistently. Undocumented entries are created as FX_UNKNOWN and
* their types set upon use.
*
* Note: the fx_module_is_type function is very sensative to the
* integer values of the fx_mod_t enum and thus must be updated if any
* changes are made to its values.
*
* @see struct fx_entry_doc, fx_module_is_type
*/
typedef enum {
/** An undocumented entry. */
FX_UNKNOWN = 0,
/** An entry with children but no value. */
FX_MODULE,
/** Inputs from the command line or calling modules. */
FX_PARAM,
/** A kind of FX_PARAM; inputs that must be specified. */
FX_REQUIRED,
/** A kind of FX_PARAM; inputs that must not be specified. */
FX_RESERVED,
/** A kind of FX_PARAM; inputs from the command line. */
FX_PROVIDED,
/** A kind of FX_PARAM; indicates a default value. */
FX_DEFAULT,
/** Reported results. */
FX_RESULT,
/** Managed timers. */
FX_TIMER
} fx_mod_t;
/** Markers for fx_mod_t values: UMPQVPDTR */
extern char fx_mod_marker[];
/** Human-readable names for fx_mod_t values. */
extern const char *fx_mod_name[];
/**
* The type of the value stored at an entry.
*
* As with fx_mod_t, the purpose of this type is to make sure that
* entries are used consistently. Except for FX_CUSTOM, all values
* are stored in string format and are implicitly converted upon use.
*
* @see fx_param_str, fx_param_double, fx_param_int, fx_param_bool
*/
typedef enum {
/** An arbitrary string. */
FX_STR = 0,
/** Readable by scanf("%lf", ...). */
FX_DOUBLE,
/** Readable by scanf("%lld", ...). */
FX_INT,
/** In either set "1tTyY" or "0fFnN". */
FX_BOOL,
/** Comma-separated strings. */
FX_STR_LIST,
/** Comma-separated doubles. */
FX_DOUBLE_LIST,
/** Comma-separated ints. */
FX_INT_LIST,
/** Comma-separated bools. */
FX_BOOL_LIST,
/** Some other type, e.g. a timer. */
FX_CUSTOM = -1
} fx_val_t;
/** Human-readable names for fx_val_t values. */
extern const char *fx_val_name[];
struct fx_module_doc;
/**
* Documentation for an entry, for use with fx_module_doc.
*
* You should define a constant list of these at the top of any
* file/class that makes use of an fx_module. Such lists should be
* terminated by FX_ENTRY_DOC_DONE.
*
* @see fx_module_doc, fx_submodule_doc, fx_init
*/
typedef struct fx_entry_doc {
/** The entry's name; paths allowed. */
const char *key;
/** The entry's usage type, e.g. FX_REQUIRED. */
fx_mod_t mod_type;
/** The entry's data type, e.g. FX_INT. */
fx_val_t val_type;
/** Currently unused; constraints on val. */
const char *meta;
/** Information to print on --help. */
const char *text;
} fx_entry_doc;
/**
* Documentation for a submodule, for use with fx_module_doc.
*
* You should define a constant list of these at the top of any
* file/class that makes use of an fx_module. Such lists should be
* terminated by FX_SUBMODULE_DOC_DONE.
*
* @see fx_module_doc, fx_entry_doc, fx_init
*/
typedef struct fx_submodule_doc {
/** The submodule's name; paths allowed. */
const char *key;
/** The submodule's documentation. */
const struct fx_module_doc *doc;
/** Information to print on --help. */
const char *text;
} fx_submodule_doc;
/**
* Documentation for an fx_module, used triply to provide usage
* information, to check input variables for correctness, and to
* enforce that programmers indeed do document their parameters.
*
* In addition to lists of fx_entry_docs and fx_submodule_docs, you
* should define a constant of type fx_module_doc at the top of any
* file/class that makes use of an fx_module. This constant is then
* used with either fx_init or other fx_submodule_docs.
*
* Example (a hypothetical manifold method):
* @code
* const fx_entry_doc manifold_entries[] = {
* {"maxiter", FX_PARAM, FX_INT, NULL,
* " Maximum number of refinement iterations (def 50).\n"},
*
* {"thresh", FX_REQUIRED, FX_DOUBLE, NULL,
* " Threshold parameter of the algorithm.\n"
* " Smaller is more accurate but slower.\n"},
*
* {"emit_iter_times", FX_PARAM, FX_BOOL, NULL,
* " Whether to emit running times for each iteration.\n"}
*
* {"time_i", FX_TIMER, FX_DOUBLE, NULL,
* " The running time of iteration i.\n"},
*
* {"total_time", FX_TIMER, FX_DOUBLE, NULL,
* " The running time of all iterations.\n"},
*
* {"sq_error", FX_RESULT, FX_DOUBLE, NULL,
* " The squared error of the final result.\n"},
*
* {"knn_i/k", FX_RESERVED, FX_INT, NULL,
* " Reserved (selected by algorithm).\n"},
*
* FX_ENTRY_DOC_DONE
* };
*
* const fx_submodule_doc manifold_submodules[] = {
* {"knn_i", &knn_doc,
* " The k-nearest-neighbors step used in each iteration.\n"},
*
* FX_SUBMODULE_DOC_DONE
* };
*
* const fx_moduld_doc manifold_doc = {
* manifold_entries, manifold_submodules,
* "An implementation of a hypothetical manifold method.\n"
* };
* @endcode
*
* In the above, note that "knn_i/k" is a reserved parameter. This
* fx_entry_doc will path into the knn_i submodule and override its
* documented type (normally an FX_PARAM). The manifold module is
* then free to assume that "knn_i/k" has not been set on the command
* line, which would be mistaken because the algorithm sets this
* parameter itself.
*
* Also observe documentation for timer "time_i". This is not
* literally the name of the timer entries that will be emitted, but
* instead serves as a stub to be copied into new entries "time_1",
* "time_2", and so forth. The same copying will occur for the knn_i
* submodule for each iteration.
*
* The above is incomplete, however. It is the documentation for the
* manifold module, but not the documentation for the entire program.
* In the same file that defines main, there should be an additional
* fx_module_doc that references manifold_doc as well as parameters
* listing which files to open, etc. This documentation would include
* &manifold_doc as one of its submodules.
*
* @see struct fx_entry_doc, struct fx_submodule_doc, fx_init
*/
typedef struct fx_module_doc {
/** All entries (params, timers, results) used by the module. */
const struct fx_entry_doc *entries;
/** All submodules used by the module. */
const struct fx_submodule_doc *submodules;
/** Information to print on --help. */
const char *text;
} fx_module_doc;
/** A terminator for lists of fx_entry_docs. */
#define FX_ENTRY_DOC_DONE {NULL, (fx_mod_t)0, (fx_val_t)0, NULL}
/** A terminator for lists of fx_submodule_docs. */
#define FX_SUBMODULE_DOC_DONE {NULL, NULL, NULL}
/**
* Tests whether an entry could be considered to be of a given type.
*
* Types have hierarchical relationships given as follows:
* @code
* FX_UNKNOWN
* FX_MODULE
* FX_PARAM
* FX_REQUIRED
* FX_RESERVED
* FX_PROVIDED
* FX_DEFAULT
* FX_TIMER
* FX_RESULT
* @endcode
*
* Thus, FX_REQUIRED may also serve as FX_PARAM, but not the other way
* around; additionally FX_RESERVED, FX_PROVIDED, and FX_DEFAULT
* satisfy FX_REQUIRED. Note that any kind of entry other than an
* FX_UNKNOWN may serve as an FX_MODULE, meaning that every kind of
* entry is permitted to have child entries and, equivalently, that it
* is possible for entries with children (modules) to have values.
*
* @param entry the entry to be tested
* @param type the type to look for, i.e. is mod of this type?
*
* @see fx_mod_t, struct fx_module
*/
int fx_module_is_type(fx_module *entry, fx_mod_t type);
/**
* Obtains a string parameter, failing if unspecified.
*
* @see fx_param_str
*/
const char *fx_param_str_req(fx_module *mod, const char *key);
/**
* Obtains a floating-point parameter, failing if unspecified.
*
* @see fx_param_double
*/
double fx_param_double_req(fx_module *mod, const char *key);
/**
* Obtains an integral parameter, failing if unspecified.
*
* @see fx_param_int
*/
long long fx_param_int_req(fx_module *mod, const char *key);
/**
* Obtains a boolean parameter, failing if unspecified.
*
* @see fx_param_bool
*/
int fx_param_bool_req(fx_module *mod, const char *key);
/**
* Obtains a list of strings from a parameter, failing if unspecified.
*
* @see fx_param_str_list
*/
const char **fx_param_str_list_req(fx_module *mod, const char *key,
size_t *size_ptr);
/**
* Obtains a list of floating-point values from a parameter, failing
* if unspecified.
*
* @see fx_param_double_list
*/
double *fx_param_double_list_req(fx_module *mod, const char *key,
size_t *size_ptr);
/**
* Obtains a list of integral values from a parameter, failing if
* unspecified.
*
* @see fx_param_int_list
*/
long long *fx_param_list_int_req(fx_module *mod, const char *key,
size_t *size_ptr);
/**
* Obtains a list of boolean values from a parameter, failing if
* unspecified.
*
* @see fx_param_int_list
*/
int *fx_param_bool_list_req(fx_module *mod, const char *key,
size_t *size_ptr);
/**
* Obtains a string parameter, using the provided default if
* unspecified.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @param def value used if parameter not given
* @returns a const char *; do not free
*
* @see fx_param_double, fx_param_int, fx_param_bool,
* fx_param_str_list, fx_param_str_req, fx_set_param_str,
* fx_default_param
*/
const char *fx_param_str(fx_module *mod, const char *key, const char *def);
/**
* Obtains a floating-point parameter, using the provided default if
* unspecified.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @param def value used if parameter not given
* @returns a double
*
* @see fx_param_str, fx_param_double_list, fx_param_double_req,
* fx_set_param_double
*/
double fx_param_double(fx_module *mod, const char *key, double def);
/**
* Obtains an integral parameter, using the provided default if
* unspecified.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @param def value used if parameter not given
* @returns a long long; type may be converted implicitly
*
* @see fx_param_str, fx_param_int_list, fx_param_int_req
* fx_set_param_int
*/
long long fx_param_int(fx_module *mod, const char *key, long long def);
/**
* Obtains a boolean parameter, using the provided default if
* unspecified.
*
* Booleans should be given with leading character in either set
* "1tTyY" for true or "0fFnN" for false. The empty string is also
* considered true, and thus booleans set on the command line with
* "--some/bool" (omitting the '=t') are true.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @param def value used if parameter not given
* @returns an int with value 1 or 0
*
* @see fx_param_str, fx_param_bool_list, fx_param_bool_req
* fx_set_param_bool
*/
int fx_param_bool(fx_module *mod, const char *key, int def);
/**
* Obtains a list of comma-separated strings from a parameter, using
* the trailing arguments as defaults if unspecified.
*
* Element strings may contain escaped commas given by "%2c". Because
* '%' is itself be escaped, this is "%252c" from the command line.
*
* Input *size_ptr must be initialized. If nonzero, it establishes a
* required list length. For example, you may set *size_ptr = 0 but
* then use it for multiple lists to ensure they are the same length.
*
* Do not free the returned list.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @param size_ptr receives the length of the list or establishes the
* required length of the list if nonzero
* @param def_size the number of trailing arguments
* @param ... values to be used if parameter not given
* @returns a const char **; do not free
*
* @see fx_param_double_list, fx_param_int_list, fx_param_bool_list,
* fx_param_str, fx_param_str_array, fx_param_str_list_req,
* fx_set_param_str_list, fx_default_param_list
*/
const char **fx_param_str_list(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size, ...);
/**
* Obtains a list of comma-separated floating-point values from a
* parameter, using the trailing arguments as defaults if unspecified.
*
* Input *size_ptr must be initialized. If nonzero, it establishes a
* required list length. For example, you may set *size_ptr = 0 but
* then use it for multiple lists to ensure they are the same length.
*
* Do not free the returned list.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @param size_ptr receives the length of the list or establishes the
* required length of the list if nonzero
* @param def_size the number of trailing arguments
* @param ... values to be used if parameter not given
* @returns a double *; do not free
*
* @see fx_param_str_list, fx_param_double, fx_param_double_array,
* fx_param_double_list_req, fx_set_param_double_list
*/
double *fx_param_double_list(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size, ...);
/**
* Obtains a list of comma-separated integral values from a parameter,
* using the trailing arguments as defaults if unspecified.
*
* Input *size_ptr must be initialized. If nonzero, it establishes a
* required list length. For example, you may set *size_ptr = 0 but
* then use it for multiple lists to ensure they are the same length.
*
* Do not free the returned list.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @param size_ptr receives the length of the list or establishes the
* required length of the list if nonzero
* @param def_size the number of trailing arguments
* @param ... values to be used if parameter not given
* @returns a long long *; no implicit type conversion; do not free
*
* @see fx_param_str_list, fx_param_int, fx_param_int_array,
* fx_param_int_list_req, fx_set_param_int_list
*/
long long *fx_param_int_list(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size, ...);
/**
* Obtains a list of comma-separated boolean values from a parameter,
* using the trailing arguments as defaults if unspecified.
*
* Input *size_ptr must be initialized. If nonzero, it establishes a
* required list length. For example, you may set *size_ptr = 0 but
* then use it for multiple lists to ensure they are the same length.
*
* Do not free the returned list.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @param size_ptr receives the length of the list or establishes the
* required length of the list if nonzero
* @param def_size the number of trailing arguments
* @param ... values to be used if parameter not given
* @returns an int * with values 1 or 0; do not free
*
* @see fx_param_str_list, fx_param_bool, fx_param_bool_array,
* fx_param_bool_list_req, fx_set_param_bool_list
*/
int *fx_param_bool_list(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size, ...);
/**
* Obtains a list of comma-separated strings from a parameter, using
* the provided array as defaults if unspecified.
*
* @see fx_param_str_list
*/
const char **fx_param_str_array(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size,
const char *const *def_array);
/**
* Obtains a list of comma-separated floating-point values from a
* parameter, using the provided array as defaults if unspecified.
*
* @see fx_param_double_list
*/
double *fx_param_double_array(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size,
const double *def_array);
/**
* Obtains a list of comma-separated integral values from a parameter,
* using the provided array as defaults if unspecified.
*
* @see fx_param_int_list
*/
long long *fx_param_int_array(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size,
const long long *def_array);
/**
* Obtains a list of comma-separated boolean values from a parameter,
* using the provided array as defaults if unspecified.
*
* @see fx_param_bool_list
*/
int *fx_param_bool_array(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size,
const int *def_array);
/**
* Sets a reserved parameter to a given string.
*
* @see fx_param_str, fx_set_param_str_list, fx_result_str,
* fx_format_param
*/
void fx_set_param_str(fx_module *mod, const char *key, const char *val);
/**
* Sets a reserved parameter to a given double.
*
* @see fx_param_double, fx_set_param_double_list, fx_result_double
*/
void fx_set_param_double(fx_module *mod, const char *key, double val);
/**
* Sets a reserved parameter to a given int.
*
* @see fx_param_int, fx_set_param_int_list, fx_result_int
*/
void fx_set_param_int(fx_module *mod, const char *key, long long val);
/**
* Sets a reserved parameter to a given bool.
*
* @see fx_param_bool, fx_set_param_bool_list, fx_result_bool
*/
void fx_set_param_bool(fx_module *mod, const char *key, int val);
/**
* Sets a reserved parameter to a given list of strings.
*
* @see fx_param_str_list, fx_set_param_str, fx_set_param_str_array,
* fx_result_str_list, fx_format_param_list
*/
void fx_set_param_str_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Sets a reserved parameter to a given list of doubles.
*
* @see fx_param_double_list, fx_set_param_double,
* fx_set_param_double_array, fx_result_double_list
*/
void fx_set_param_double_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Sets a reserved parameter to a given list of ints.
*
* @see fx_param_int_list, fx_set_param_int, fx_set_param_int_array,
* fx_result_int_list
*/
void fx_set_param_int_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Sets a reserved parameter to a given list of bools.
*
* @see fx_param_bool_list, fx_set_param_bool,
* fx_set_param_bool_array, fx_result_bool_list
*/
void fx_set_param_bool_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Sets a reserved parameter to a given array of strings.
*
* @see fx_param_str_array, fx_set_param_str_list
*/
void fx_set_param_str_array(fx_module *mod, const char *key,
size_t size, const char *const *array);
/**
* Sets a reserved parameter to a given array of doubles.
*
* @see fx_param_double_array, fx_set_param_double_list
*/
void fx_set_param_double_array(fx_module *mod, const char *key,
size_t size, const double *array);
/**
* Sets a reserved parameter to a given array of ints.
*
* @see fx_param_int_array, fx_set_param_int_list
*/
void fx_set_param_int_array(fx_module *mod, const char *key,
size_t size, const long long *array);
/**
* Sets a reserved parameter to a given array of booleans.
*
* @see fx_param_bool_array, fx_set_param_bool_list
*/
void fx_set_param_bool_array(fx_module *mod, const char *key,
size_t size, const int *array);
/**
* Defaults a parameter to a string formatted as in printf.
*
* @see fx_param_str, fx_default_param_list, fx_format_param
*/
COMPILER_PRINTF(3, 4)
void fx_default_param(fx_module *mod, const char *key,
const char *def_format, ...);
/**
* Defaults a parameter to a list of strings formatted as in printf.
*
* Values should be provided in batches composed of element format
* strings followed by their arguments.
*
* Example (the cheese stands alone):
* @code
* fx_default_param_list(root, "foo", 3,
* "%s chases %s", dog_name, cat_name,
* "%d mice observed", mouse_count,
* "%g%% cheese remaining", 100 * cheese);
* @endcode
*
* @see fx_param_str_list, fx_default_param, fx_format_param_list
*/
void fx_default_param_list(fx_module *mod, const char *key,
size_t *size_ptr, size_t def_size, ...);
/**
* Sets a reserved parameter to a string formatted as in printf.
*
* @see fx_set_param_str, fx_default_param, fx_format_param_list
*/
COMPILER_PRINTF(3, 4)
void fx_format_param(fx_module *mod, const char *key,
const char *format, ...);
/**
* Sets a reserved parameter to a list of strings formatted as in
* printf.
*
* Values should be provided in batches composed of element format
* strings followed by their arguments.
*
* @see fx_set_param_str_list, fx_default_param_list, fx_format_param
*/
void fx_format_param_format(fx_module *mod, const char *key,
size_t size, ...);
/**
* Unsets a parameter's value, effectively removing the entry.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
*
* @param fx_param_exists, fx_param_str
*/
void fx_clear_param(fx_module *mod, const char *key);
/**
* Tests whether a parameter has been specified.
*
* @param mod the parameter's containing module
* @param key the name of the parameter; paths allowed
* @returns whether the parameter has a value
*
* @see fx_param_clear, fx_param_str
*/
int fx_param_exists(fx_module *mod, const char *key);
/**
* Obtains a string result, failing if not found.
*
* @param mod the result's containing module
* @param key the name of the result; paths allowed
* @returns a const char *; do not free
*
* @see fx_result_str, fx_get_result_str_list, fx_param_str
*/
const char *fx_get_result_str(fx_module *mod, const char *key);
/**
* Obtains a floating-point result, failing if not found.
*
* @param mod the result's containing module
* @param key the name of the result; paths allowed
* @returns a double
*
* @see fx_result_double, fx_get_result_double_list, fx_param_double
*/
double fx_get_result_double(fx_module *mod, const char *key);
/**
* Obtains an integral result, failing if not found.
*
* @param mod the result's containing module
* @param key the name of the result; paths allowed
* @returns a long long; type may be converted implicitly
*
* @see fx_result_int, fx_get_result_int_list, fx_param_int
*/
long long fx_get_result_int(fx_module *mod, const char *key);
/**
* Obtains a boolean result, failing if not found.
*
* @param mod the result's containing module
* @param key the name of the result; paths allowed
* @returns an int with value 1 or 0
*
* @see fx_result_bool, fx_get_result_bool_list, fx_param_bool
*/
int fx_get_result_bool(fx_module *mod, const char *key);
/**
* Obtains a list of strings from a result, failing if not found.
*
* @see fx_get_result_str, fx_result_str_list, fx_param_str_list
*/
const char **fx_get_result_str_list(fx_module *mod, const char *key,
size_t *size_ptr);
/**
* Obtains a list of floating-point values from a result, failing if
* not found.
*
* @see fx_get_result_double, fx_result_double_list,
* fx_param_double_list
*/
double *fx_get_result_double_list(fx_module *mod, const char *key,
size_t *size_ptr);
/**
* Obtains a list of integral values from a result, failing if not
* found.
*
* @see fx_param_int_list, fx_get_result_int, fx_result_int_list
*/
long long *fx_get_result_list_int(fx_module *mod, const char *key,
size_t *size_ptr);
/**
* Obtains a list of boolean values from a result, failing if not
* found.
*
* @see fx_get_result_bool, fx_result_bool_list, fx_param_bool_list
*/
int *fx_get_result_bool_list(fx_module *mod, const char *key,
size_t *size_ptr);
/**
* Sets a result to a given string.
*
* @see fx_result_dobule, fx_result_int, fx_result_bool,
* fx_result_str_list, fx_get_result_str, fx_param_str,
* fx_format_result
*/
void fx_result_str(fx_module *mod, const char *key, const char *val);
/**
* Sets a result to a given double.
*
* @see fx_result_str, fx_result_double_list, fx_get_result_double,
* fx_param_double
*/
void fx_result_double(fx_module *mod, const char *key, double val);
/**
* Sets a result to a given int.
*
* @see fx_result_str, fx_result_int_list, fx_get_result_int,
* fx_param_int
*/
void fx_result_int(fx_module *mod, const char *key, long long val);
/**
* Sets a result to a given bool.
*
* @see fx_result_str, fx_result_bool_list, fx_get_result_bool,
* fx_param_bool
*/
void fx_result_bool(fx_module *mod, const char *key, int val);
/**
* Sets a result to a given list of strings.
*
* @see fx_get_result_str_list, fx_result_str, fx_result_str_array,
* fx_param_str_list, fx_format_result_list
*/
void fx_result_str_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Sets a result to a given list of doubles.
*
* @see fx_get_result_double_list, fx_result_double,
* fx_result_double_array, fx_param_double_list
*/
void fx_result_double_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Sets a result to a given list of ints.
*
* @see fx_get_result_int_list, fx_result_int, fx_result_int_array,
* fx_param_int_list
*/
void fx_result_int_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Sets a result to a given list of bools.
*
* @see fx_get_result_bool_list, fx_result_bool, fx_result_bool_array,
* fx_param_bool_list
*/
void fx_result_bool_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Sets a result to a given array of strings.
*
* @see fx_result_str_list, fx_param_str_list
*/
void fx_result_str_array(fx_module *mod, const char *key,
size_t size, const char *const *array);
/**
* Sets a result to a given array of doubles.
*
* @see fx_result_double_list, fx_param_double_list
*/
void fx_result_double_array(fx_module *mod, const char *key,
size_t size, const double *array);
/**
* Sets a result to a given array of ints.
*
* @see fx_result_int_list, fx_param_int_list
*/
void fx_result_int_array(fx_module *mod, const char *key,
size_t size, const long long *array);
/**
* Sets a result to a given array of bools.
*
* @see fx_result_bool_list, fx_param_bool_list
*/
void fx_result_bool_array(fx_module *mod, const char *key,
size_t size, const int *array);
/**
* Sets a result to a string formatted as in printf.
*
* @see fx_result_str, fx_format_result_list, fx_format_param
*/
COMPILER_PRINTF(3, 4)
void fx_format_result(fx_module *mod, const char *key,
const char *format, ...);
/**
* Sets a result to a list of strings formatted as in printf.
*
* Values should be provided in batches composed of element format
* strings followed by their arguments.
*
* @see fx_result_str_list, fx_format_result, fx_format_param_list
*/
void fx_format_result_list(fx_module *mod, const char *key,
size_t size, ...);
/**
* Unsets a result's value, effectively removing the entry.
*
* @param mod the result's containing module
* @param key the name of the result; paths allowed
*
* @param fx_result_exists, fx_param_exists, fx_result_str
*/
void fx_clear_result(fx_module *mod, const char *key);
/**
* Tests whether a result has been specified.
*
* @param mod the result's containing module
* @param key the name of the result; paths allowed
* @returns whether the result has a value
*
* @see fx_result_clear, fx_param_clear, fx_result_str
*/
int fx_result_exists(fx_module *mod, const char *key);
/**
* Gets a timer for the purpose of reading its time.
*
* @param mod the timer's containing module
* @param key the name of the timer; paths allowed
* @returns an fx_timer * (struct stopwatch *); do not free
*
* @see struct stopwatch, fx_timer_start, fx_timer_stop
*/
fx_timer *fx_get_timer(fx_module *mod, const char *key);
/**
* Starts or continues a named timer, or creates one if it does not
* exist.
*
* @param mod the timer's containing module
* @param key the name of the timer; paths allowed
*
* @see fx_timer_stop, fx_reset_timer, fx_get_timer
*/
void fx_timer_start(fx_module *mod, const char *key);
/**
* Pauses a named timer.
*
* @param mod the timer's containing module
* @param key the name of the timer; paths allowed
*
* @see fx_timer_start, fx_reset_timer, fx_get_timer
*/
void fx_timer_stop(fx_module *mod, const char *key);
/**
* Resets a named timer's total time to zero.
*
* @param mod the timer's containing module
* @param key the name of the timer; paths allowed
*
* @see fx_timer_start, fx_timer_stop, fx_get_timer
*/
void fx_reset_timer(fx_module *mod, const char *key);
/**
* Paths into a submodule of a FASTexec module, permitting access of
* contained parameters without explicitly pathing to them.
*
* If the submodule does not exist, it is created and is initialy
* empty. Parameter access will then populate it with defaults.
*
* Submodules serve to compartmentalize modular components of a
* program, e.g. so that their parameters and results may be managed
* separately from those of other components. Working within a
* submodule should be understood as changing the working directory in
* a UNIX file system. Like the terms "directory" and "subdirectory",
* there is no real distinction between "module" and "submodule"
* except relative to one another.
*
* Example (tree building command line input):
* @code
* ./myprog --r=data.txt --r/leaf_size=30 --r/split_median
* @endcode
*
* Example (tree building parameter parsing):
* @code
* const char *r_file = fx_param_str_req(root, "r")
* ...
* fx_module *r_mod = fx_submodule(root, "r");
* int leaf_size = fx_param_int(r_mod, "leaf_size", 30);
* int split_median = fx_param_bool(r_mod, "split_median", 0);
* @code
*
* Note that submodules may also have values. It is possible to
* obtain the value of "r" from r_mod with @c fx_param_str(r_mod, ".")
*
* @param mod the containing module of the submodule
* @param key the name of the submodule; paths allowed
* @returns an fx_module * (struct datanode *); do not free
*
* @see fx_copy_module, fx_param_str, fx_init, fx_done
*/
fx_module *fx_submodule(fx_module *mod, const char *key);
/**
* Copies a (sub)module, its contents, and documentation to a new
* location.
*
* This function is primarily useful when iterative steps of an
* algorithm deserve their own submodules for parameters and results.
*
* Example (hypothetical manifold method's iteration):
* @code
* fx_param_int(manifold_mod, "knn_i/leaf_size", 5);
* while (...) {
* fx_module *knn_i =
* fx_copy_module(manifold_mod, "knn_i", "knn_%d", iter);
* fx_set_param_int(knn_i, "k", cur_k);
* ...
* AllKNN allknn;
* allknn.Init(knn_i);
* ...
* }
* @endcode
*
* This code first provides an alternate default for parameter
* "leaf_size" of knn_i, which may have been specified on the command
* line and is presumably different from the default that class AllKNN
* uses. It then copies the submodule (replicating any command line
* arguments and the default for "leaf_size") for each iteration of a
* loop, setting a specific value for "k".
*
* Example (forwarding documentation):
* @code
* while(...) {
* fx_module *timer_mod =
* fx_copy_module(manifold_mod, "time_i", "time_%d", iter);
* ...
* fx_timer_start(timer_mod, ".");
* ...
* }
* @endcode
*
* FASTexec is rather pedantic about documentation, but tricks like
* the above allow you to have run-time generated entries that borrow
* documentation from entries specified in the fx_entry_docs. Also,
* the printf-like formatting of destination names makes it easier for
* you to give your generated entries unique names.
*
* @param mod the containing module of the source and destination
* @param src_key the name of the source submodule; paths allowed
* @param dest_format a format string for the destination name
* @param ... format arguments, as in printf
* @returns the dest fx_module * (struct datanode *); do not free
*
* @see fx_submodule, fx_param_str, fx_init, fx_done
*/
COMPILER_PRINTF(3, 4)
fx_module *fx_copy_module(fx_module *mod, const char *src_key,
const char *dest_format, ...);
/**
* Prints help information from a FASTexec documentation structure for
* a given submodule.
*
* This function is somewhat distinct from other FASTexec routines
* because it works directly on the fx_module_doc structure rather
* than an fx_module. Pathing works similarly, though ".." does not
* work because documentation structures do not necessarily have
* unique parents. Use "" to obtain the structure's root details.
*
* All possible matches to the queried key are printed to screen.
*
* @param doc the documentation structure containing the submodule
* @param key the name of the submodule; paths allowed
*
* @see fx_module_doc, fx_init
*/
success_t fx_help(const fx_module_doc *doc, const char *key);
/**
* Creates and prepares an fx_module for use given the command line
* and a documentation structure.
*
* You should always use fx_init to create fx_modules and fx_done when
* finished with them.
*
* This function performs numerous additional tasks such as loading
* files specified with "--fx/load", reporting system information, and
* initializing debug-mode parameters.
*
* You may use fx_init in the absense of command line arguments by
* setting argc = 0 and argv = NULL. You may use fx_init in the
* absense of documentation by setting doc = NULL, but this will
* elicit many warnings about undocumented entries and submodules.
*
* You may use fx_init more than once in a program, but note that each
* use that parses the command line (or a command-line-like structure)
* will reset globals associated with base/debug.h.
*
* @param argc as in main
* @param argv as in main
* @param doc a FASTexec documentation structure
* @returns an fx_module * (struct datanode *); free with fx_done
*
* @see fx_done, fx_param_int, fx_module_doc
*/
fx_module *fx_init(int argc, char **argv, const fx_module_doc *doc);
/**
* Finalizes, emits, and destructs an fx_module.
*
* You should always use fx_init to create fx_modules and fx_done when
* finished with them.
*
* Parameter settings, measured times, and results are printed to
* screen unless boolean fx/silent has been set (from the command line
* or otherwise). This information is also written to the file given
* by string fx/store, if provided.
*
* You may also optionally emit rusage information by setting boolean
* fx/rusage.
*
* @see fx_param_init
*/
void fx_done(fx_module *root);
EXTERN_C_END
#endif