1. Added doxygen-style comments to document all functions.
authorscottmk <scottmk@9efc2488-bf62-4759-914b-345cdb29e865>
Mon, 22 Feb 2010 17:53:35 +0000 (17:53 +0000)
committerscottmk <scottmk@9efc2488-bf62-4759-914b-345cdb29e865>
Mon, 22 Feb 2010 17:53:35 +0000 (17:53 +0000)
2. For osrfConfigHasDefault() and osrfConfigCleanup(): added a formal void parameter
so that the header will contain prototypes rather than mere declarations.

3. In osrfConfigValueObject: added a sanity check for a non-loaded configuration.

4. In osrfConfigGetValueList(): replaced a call to jsonObjectToSimpleString() with
a call to jsonObjectGetString(), in order to eliminate a malloc() and free().

5. Tidied up the white space here and there.

M    include/opensrf/osrfConfig.h
M    src/libopensrf/osrfConfig.c

git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1929 9efc2488-bf62-4759-914b-345cdb29e865

include/opensrf/osrfConfig.h
src/libopensrf/osrfConfig.c

index e732497..75490f7 100644 (file)
@@ -16,6 +16,23 @@ GNU General Public License for more details.
 #ifndef OSRF_CONFIG_H
 #define OSRF_CONFIG_H
 
+/**
+       @file osrfConfig.h
+       @brief Routines for loading, storing, and searching configurations.
+
+       A configuration file, encoded as XML, is loaded and translated into a jsonObject.  This
+       object is stored in an osrfConfig, along with an optional context string which, if
+       present, restricts subsequent searches to a subset of the jsonObject.
+
+       In theory the context string could identify multiple subtrees of the total configuration.
+       In practice it is used to partition a configuration file into different pieces, each piece
+       to be used by a different application.
+
+       Normally an application loads a default configuration, accessible from every linked
+       module.  It is also possible, although seldom useful, to create and search a configuration
+       distinct from the default configuration.
+*/
+
 #include <opensrf/xml_utils.h>
 #include <opensrf/utils.h>
 #include <opensrf/string_array.h>
@@ -25,89 +42,29 @@ GNU General Public License for more details.
 extern "C" {
 #endif
 
+/**
+       @brief Represents a configuration; normally loaded from an XML configuration file.
+*/
 typedef struct {
-       jsonObject* config;
-       char* configContext;
+       jsonObject* config;   /**< Represents the contents of the XML configuration file. */
+       char* configContext;  /**< Context string (optional). */
 } osrfConfig;
 
-
-/**
-       Parses a new config file.  Caller is responsible for freeing the returned
-               config object when finished.  
-       @param configFile The XML config file to parse.
-       @param configContext Optional root of the subtree in the config file where 
-       we will look for values. If it's not provided,  searches will be 
-       performed from the root of the config file
-       @return The config object if the file parses successfully.  Otherwise
-               it returns NULL;
-*/
 osrfConfig* osrfConfigInit(const char* configFile, const char* configContext);
 
-/**
-       @return True if we have a default config defined
-*/
-int osrfConfigHasDefaultConfig();
+int osrfConfigHasDefaultConfig( void );
 
-/**
-       Replaces the config object's json object.  This is useful
-       if you have a json object already and not an XML config
-       file to parse.
-       @param cfg The config object to alter
-       @param obj The json object to use when searching values
-*/
 void osrfConfigReplaceConfig(osrfConfig* cfg, const jsonObject* obj);
 
-/** Deallocates a config object 
-       @param cfg The config object to free
-*/
 void osrfConfigFree(osrfConfig* cfg);
 
-
-/* Assigns the default config file.  This file will be used whenever
-       NULL is passed to config retrieval functions 
-       @param cfg The config object to use as the default config
-*/
 void osrfConfigSetDefaultConfig(osrfConfig* cfg);
 
-/* frees the default config if one exists */
-void osrfConfigCleanup();
+void osrfConfigCleanup( void );
 
-
-/** 
-       Returns the value in the config found at 'path'.
-       If the value found at 'path' is a long or a double,
-       the value is stringified and then returned.
-       The caller must free the returned char* 
-
-       if there is a configContext, then it will be appended to 
-       the front of the path like so: //<configContext>/<path>
-       if no configContext was provided to osfConfigSetFile, then 
-       the path is interpreted literally.
-       @param cfg The config file to search or NULL if the default
-               config should be used
-       @param path The search path
-*/
 char* osrfConfigGetValue(const osrfConfig* cfg, const char* path, ...);
 
-
-/**
- *  @see osrfConfigGetValue
- *  @return jsonObject found at path
- */
-jsonObject* osrfConfigGetValueObject(osrfConfig* cfg, char* path, ...);
-
-
-/** 
-       Puts the list of values found at 'path' into the pre-allocated 
-       string array.  
-       Note that the config node found at 'path' must be an array.
-       @param cfg The config file to search or NULL if the default
-               config should be used
-       @param arr An allocated string_array where the values will
-               be stored
-       @param path The search path
-       @return the number of values added to the string array;
-*/
+jsonObject* osrfConfigGetValueObject(osrfConfig* cfg, const char* path, ...);
 
 int osrfConfigGetValueList(const osrfConfig* cfg, osrfStringArray* arr,
                const char* path, ...);
index d90e272..29ff43c 100644 (file)
@@ -1,9 +1,23 @@
 /* defines the currently used bootstrap config file */
 #include <opensrf/osrfConfig.h>
 
+/**
+       @file osrfConfig.c
+       @brief Routines for managing osrfConfigs to represent configuration information.
+*/
+
+/**
+       @brief Points to the default configuration.
+*/
 static osrfConfig* osrfConfigDefault = NULL;
 
+/**
+       @brief Install a specified osrfConfig as the default configuration.
+       @param cfg Pointer to the configuration to be stored.
 
+       Store the passed pointer for future reference.  The calling code yields ownership of the
+       associated osrfConfig.
+*/
 void osrfConfigSetDefaultConfig(osrfConfig* cfg) {
        if(cfg) {
                if( osrfConfigDefault )
@@ -12,37 +26,69 @@ void osrfConfigSetDefaultConfig(osrfConfig* cfg) {
        }
 }
 
+/**
+       @brief Free an osrfConfig.
+       @param cfg Pointer to the osrfConfig to be freed.
+*/
 void osrfConfigFree(osrfConfig* cfg) {
        if(cfg) {
                jsonObjectFree(cfg->config);
                free(cfg->configContext);
                free(cfg);
-       }       
+       }
 }
 
-
-int osrfConfigHasDefaultConfig() {
+/**
+       @brief Report whether a default configuration has been installed.
+       @return Boolean: true if a default configuration is available, or false if not.
+*/
+int osrfConfigHasDefaultConfig( void ) {
        return ( osrfConfigDefault != NULL );
 }
 
-
-void osrfConfigCleanup() { 
+/**
+       @brief Free the default configuration, if it exists.
+*/
+void osrfConfigCleanup( void ) {
        osrfConfigFree(osrfConfigDefault);
        osrfConfigDefault = NULL;
 }
 
+/**
+       @brief Replace the jsonObject of an osrfConfig.
+       @param cfg The osrfConfig to alter.
+       @param obj The jsonObject to install in the osrfConfig.
 
+       This is useful if you have a json object already, rather than an XML configuration file
+       to parse.
+*/
 void osrfConfigReplaceConfig(osrfConfig* cfg, const jsonObject* obj) {
        if(!cfg || !obj) return;
        jsonObjectFree(cfg->config);
-       cfg->config = jsonObjectClone(obj);     
+       cfg->config = jsonObjectClone(obj);
 }
 
+/**
+       @brief Load an XML configuration file into a jsonObject within an osrfConfig.
+       @param configFile Name of the XML configuration file.
+       @param configContext (Optional) Root of a subtree in the configuration file,
+       @return If successful, a pointer to the resulting osrfConfig; otherwise NULL.
+
+       If @a configContext is not NULL, save a copy of the string to which it points.  It is a
+       tag identifying one or more subtrees within the XML; subsequent searches will examine
+       only matching subtrees.  Otherwise they will search the tree from the root.
+
+       (In practice a configContext is always supplied, so that different programs can share
+       the same configuration file, partitioned by context tags.)
+
+       The calling code is responsible for freeing the returned config object by calling
+       osrfConfigFree().
+*/
 osrfConfig* osrfConfigInit(const char* configFile, const char* configContext) {
        if(!configFile) return NULL;
 
        // Load XML from the configuration file
-       
+
        xmlDocPtr doc = xmlParseFile(configFile);
        if(!doc) {
                osrfLogWarning( OSRF_LOG_MARK, "Unable to parse XML config file %s", configFile);
@@ -50,34 +96,62 @@ osrfConfig* osrfConfigInit(const char* configFile, const char* configContext) {
        }
 
        // Translate it into a jsonObject
-       
        jsonObject* json_config = xmlDocToJSON(doc);
        xmlFreeDoc(doc);
 
        if(!json_config ) {
                osrfLogWarning( OSRF_LOG_MARK, "xmlDocToJSON failed for config %s", configFile);
                return NULL;
-       }       
+       }
 
        // Build an osrfConfig and return it by pointer
-       
        osrfConfig* cfg = safe_malloc(sizeof(osrfConfig));
 
-       if(configContext) cfg->configContext = strdup(configContext);
-       else cfg->configContext = NULL;
+       if( configContext )
+               cfg->configContext = strdup(configContext);
+       else
+               cfg->configContext = NULL;
 
        cfg->config = json_config;
-       
+
        return cfg;
 }
 
+/**
+       @brief Search a configuration for a specified value.
+       @param cfg (Optional) The configuration to search, or NULL for the default configuration.
+       @param path A printf-style format string representing the search path.  Subsequent
+       parameters, if any, are inserted into the format string to form the search path.
+       @return A pointer to a newly allocated string containing the value, if found; otherwise
+       NULL.
+
+       Search for a value in the configuration, as specified by the search path.
+
+       If cfg is NULL, search the default configuration; otherwise search the configuration
+       specified.
+
+       If the configuration includes a configContext, then prepend it to the path, like so:
+       "//<configContext><path>".  Hence the path should begin with a slash to separate it from
+       the context.  Search for the resulting effective path at any level within the
+       configuration.
+
+       If the configuration does @em not include a configContext, then start the search at the
+       root of the configuration.  In this case the path should @em not begin with a slash.
+
+       If the configuration contains more than one entry at locations matching the effective
+       search path, return NULL.
 
+       Return numeric values as numeric strings.
+
+       The calling code is responsible for freeing the returned string by calling free().
+*/
 char* osrfConfigGetValue(const osrfConfig* cfg, const char* path, ...) {
        if(!path) return NULL;
-       if(!cfg) cfg = osrfConfigDefault;
-       if(!cfg) { 
-               osrfLogWarning( OSRF_LOG_MARK, "No Config object in osrfConfigGetValue()"); 
-               return NULL; 
+       if(!cfg)
+               cfg = osrfConfigDefault;
+       if(!cfg) {
+               osrfLogWarning( OSRF_LOG_MARK, "No Config object in osrfConfigGetValue()");
+               return NULL;
        }
 
        VA_LIST_TO_STRING(path);
@@ -89,29 +163,88 @@ char* osrfConfigGetValue(const osrfConfig* cfg, const char* path, ...) {
                obj = jsonObjectExtractIndex( outer_obj, 0 );
                jsonObjectFree( outer_obj );
        } else
-               obj = jsonObjectFindPath( cfg->config, VA_BUF);
+               obj = jsonObjectFindPath( cfg->config, VA_BUF );
 
        char* val = jsonObjectToSimpleString(obj);
        jsonObjectFree(obj);
        return val;
 }
 
-jsonObject* osrfConfigGetValueObject(osrfConfig* cfg, char* path, ...) {
+/**
+       @brief Search for one or more subtrees of a configuration.
+       @param cfg (Optional) The configuration to search, or NULL for the default configuration.
+       @param path A printf-style format string representing the search path.  Subsequent
+       parameters, if any, are inserted into the format string to form the search path.
+       @return A pointer to a jsonObject representing a subset of the specified configuration,
+       if found; otherwise NULL.
+
+       Search for subtrees of the configuration, as specified by the search path.
+
+       If the configuration includes a configContext, then prepend it to the path, like so:
+       "//<configContext><path>".  Hence the path should begin with a slash to separate it from
+       the context.  Search for the resulting effective path at any level within the
+       configuration.
+
+       If the configuration does @em not include a configContext, then start the search at the
+       root of the configuration.  In this case the path should @em not begin with a slash.
+
+       If any entries match the effective path, return copies of them all as elements of a
+       jsonObject of type JSON_ARRAY.
+
+       If no entries match the effective path, return a jsonObject of type JSON_NULL.
+
+       The calling code is responsible for freeing the returned jsonObject by calling
+       jsonObjectFree().
+*/
+jsonObject* osrfConfigGetValueObject(osrfConfig* cfg, const char* path, ...) {
        if(!path) return NULL;
-       if(!cfg) cfg = osrfConfigDefault;
+       if(!cfg)
+               cfg = osrfConfigDefault;
+       if(!cfg) {
+               osrfLogWarning( OSRF_LOG_MARK, "No Config object in osrfConfigGetValueObject()");
+               return NULL;
+       }
+
        VA_LIST_TO_STRING(path);
-       if(cfg->configContext) 
-        return jsonObjectFindPath(cfg->config, "//%s%s", cfg->configContext, VA_BUF);
+       if(cfg->configContext)
+               return jsonObjectFindPath(cfg->config, "//%s%s", cfg->configContext, VA_BUF);
        else
                return jsonObjectFindPath(cfg->config, VA_BUF);
 }
 
+/**
+       @brief Search for one or more values in a configuration, specified by a path.
+       @param cfg (Optional) The configuration to search, or NULL for the default configuration.
+       @param arr Pointer to an osrfStringArray to be populated with values.
+       @param path A printf-style format string representing the search path.  Subsequent
+       parameters, if any, are inserted into the format string to form the search path.
+       @return The number of values loaded into the osrfStringArray.
+
+       Search the configuration for values specified by the search path.  Load any values
+       found (either strings or numbers) into an existing osrfStringArray supplied by the
+       calling code.
+
+       Make no effort to delete any strings that may already be in the osrfStringArray.
+       Ordinarily the calling code should ensure that the osrfStringArray is empty when passed.
+
+       If the configuration includes a configContext, then prepend it to the path, like so:
+       "//<configContext><path>".  Hence the path should begin with a slash to separate it from
+       the context.  Search for the resulting effective path at any level within the
+       configuration.
+
+       If the configuration does @em not include a configContext, then start the search at the
+       root of the configuration.  In this case the path should @em not begin with a slash.
+*/
 int osrfConfigGetValueList(const osrfConfig* cfg, osrfStringArray* arr,
                const char* path, ...) {
 
        if(!arr || !path) return 0;
-       if(!cfg) cfg = osrfConfigDefault;
-       if(!cfg) { osrfLogWarning( OSRF_LOG_MARK, "No Config object!"); return -1;}
+       if(!cfg)
+               cfg = osrfConfigDefault;
+       if(!cfg) {
+               osrfLogWarning( OSRF_LOG_MARK, "No Config object!");
+               return -1;
+       }
 
        VA_LIST_TO_STRING(path);
 
@@ -129,11 +262,10 @@ int osrfConfigGetValueList(const osrfConfig* cfg, osrfStringArray* arr,
                int i;
                for( i = 0; i < obj->size; i++ ) {
 
-                       char* val = jsonObjectToSimpleString(jsonObjectGetIndex(obj, i));
+                       const char* val = jsonObjectGetString( jsonObjectGetIndex(obj, i) );
                        if(val) {
                                count++;
                                osrfStringArrayAdd(arr, val);
-                               free(val);
                        }
                }
        }
@@ -141,4 +273,3 @@ int osrfConfigGetValueList(const osrfConfig* cfg, osrfStringArray* arr,
        jsonObjectFree(obj);
        return count;
 }
-