/*
 *
 * Copyright (c) Vaisala Group 2009. All rights reserved.
 *
 * The terms "Vaisala" and "Vaisala Group" are defined as
 * "Vaisala Oyj and all its subsidiaries".
 *
 */

/** @file config_set.h
 *  Configuration Set API.
 */

#ifndef CONFIG_ITEM_H
#define CONFIG_ITEM_H

#ifdef __cplusplus
extern "C" {
#endif

/** @defgroup gr_confset Configuration Set

The configuration set is a container of configuration name-value
pairs. A number of value types is supported. This container is
implemented as a hash table with the name of each pair used as a key.

 *  @ingroup gr_sigmet
 *  @{
 */

/** Supported value types */
enum cfg_val_type{
    UNKN_VAL, /**< Undefined/unknown data type */
    INT_VAL,  /**< Plain integer value (int) */
    DBL_VAL,  /**< Double precision floating point (double)*/
    U64_VAL,  /**< 64-bit unsigned integer (uint64_t) */
    STR_VAL,  /**< String value (char*) */
    BIN_BUF   /**< Binary blob */
};

/** Hash table size order.

Hash table size order determines number of buckets in the
configuration set hash table
*/
enum hash_size_order {
    HASH_TINY   =  4, /**< 2^4  =   16 buckets */ 
    HASH_XSMALL =  5, /**< 2^5  =   32 buckets */ 
    HASH_SMALL  =  6, /**< 2^6  =   64 buckets */ 
    HASH_MEDIUM =  7, /**< 2^7  =  128 buckets */ 
    HASH_NORMAL =  8, /**< 2^8  =  256 buckets */
    HASH_LARGE  =  9, /**< 2^9  =  512 buckets */
    HASH_XLARGE = 10, /**< 2^10 = 1024 buckets */
    HASH_HUGE   = 11, /**< 2^11 = 2048 buckets */
    HASH_XHUGE  = 12  /**< 2^12 = 4096 buckets */
}; 

/* ===================================================================== */
/** Create an  empty configuration set container 

The configuration set hash table is not resizable, the number of
buckets is set during initialization.

 *  @param hash_order determines size of the hash table.
 *  @return  Pointer to created container if successful, NULL if failed.
 */
struct config_set * cfgset_new(enum hash_size_order hash_order);

/** Free memory used by the configuration set container and its contents.
 *
 * @param cfgset configuration set to delete
 */
void cfgset_delete(struct config_set * cfgset);

/* ===================================================================== */

/** Compare two sets of configuration parameters. Returns 1 if identical
 * and 0 if differ
 */
int cfgset_compare(const struct config_set * cfgset_1,
                   const struct config_set * cfgset_2);

/* ===================================================================== */

struct config_set * cfgset_add_int(struct config_set *cfgset,
                                   const char *name, int val);
struct config_set * cfgset_add_double(struct config_set *cfgset,
                                      const char *name, double value);
struct config_set * cfgset_add_uint64(struct config_set *cfgset,
                                      const char *name, uint64_t value);
struct config_set * cfgset_add_string(struct config_set *cfgset,
                                      const char *name, const char *value);
struct config_set * cfgset_add_buf(struct config_set *cfgset, const char *name,
                                   const void * buf, size_t len);

struct config_set * cfgset_remove(struct config_set *cfgset,
                                  const char *name);
/* ===================================================================== */

enum cfg_val_type cfgset_get_type(const struct config_set * cfgset, const char *name);

/* ===================================================================== */

int      cfgset_get_int(const struct config_set * cfgset, const char *name);
double   cfgset_get_double(const struct config_set * cfgset, const char *name);
uint64_t cfgset_get_uint64(const struct config_set * cfgset, const char *name);
char *   cfgset_get_string(const struct config_set * cfgset, const char *name,
                           char * buf, size_t len);
void *   cfgset_get_buf(struct config_set *cfgset, const char *name,
                        void * buf, size_t * len);

/* ===================================================================== */

int cfgset_set_int(struct config_set * cfgset,
                   const char *name, int value);
int cfgset_set_double(struct config_set * cfgset,
                      const char *name, double value);
int cfgset_set_uint64(struct config_set * cfgset,
                      const char *name, uint64_t value);
int cfgset_set_string(struct config_set * cfgset,
                      const char *name, const char *value);

/* ===================================================================== */

int cfgset_set_units(struct config_set *cfgset, const char *name,
                     const char *units);

char * cfgset_get_units(const struct config_set * cfgset, const char *name,
                        char * buf, size_t len);

/* ===================================================================== */

struct config_item_handle;

const struct config_item *
cfgset_get_next_item(const struct config_set * cfgset,
                     const struct config_item * hdl);

const char * cfgset_item_get_name(const struct config_item * hdl);

/* ===================================================================== */

/** @}  gr_confset */

#ifdef __cplusplus
}
#endif
#endif /* CONFIG_ITEM_H */
