Permalink
Fetching contributors…
Cannot retrieve contributors at this time
208 lines (186 sloc) 7.35 KB
#ifndef LIBNAGIOS_KVVEC_H_INCLUDED
#define LIBNAGIOS_KVVEC_H_INCLUDED
/**
* @file kvvec.h
* @brief Key/value vector library function and type declarations
*
* The kvvec library is nifty as either a configuration meta-format
* or for IPC purposes. Take a look at the buf2kvvec() and kvvec2buf()
* pair of functions for the latter.
* @{
*/
/**
* key/value pair
* One of the two major components of the kvvec api
*/
struct key_value {
char *key; /**< The key */
char *value; /**< The value */
int key_len; /**< Length of key */
int value_len; /**< Length of value */
};
/**
* key/value vector buffer. Actually just a buffer, but one that gets
* used as return value and internal tracker for kvvec2buf()
*/
struct kvvec_buf {
char *buf; /**< The buffer */
unsigned long buflen; /**< Length of buffer */
unsigned long bufsize; /**< Size of buffer (includes overalloc) */
};
/**
* key/value vector struct
* This is the main component of the kvvec library
* @note This should be made opaque, with a kvvec_foreach() using a
* callback to iterate over key/value pairs.
*/
struct kvvec {
struct key_value *kv; /**< The key/value array */
int kv_alloc; /**< Allocated size of key/value array */
int kv_pairs; /**< Number of key/value pairs */
int kvv_sorted; /**< Determines if this kvvec has been sorted */
};
/** Portable initializer for stack-allocated key/value vectors */
#define KVVEC_INITIALIZER { NULL, 0, 0, 0 }
/** Parameters for kvvec_destroy() */
#define KVVEC_FREE_KEYS 1 /**< Free keys when destroying a kv vector */
#define KVVEC_FREE_VALUES 2 /**< Free values when destroying a kv vector */
/** Free both keys and values when destroying a kv vector */
#define KVVEC_FREE_ALL (KVVEC_FREE_KEYS | KVVEC_FREE_VALUES)
#define KVVEC_ASSIGN 0 /**< Assign from buf in buf2kvvec_prealloc() */
#define KVVEC_COPY 1 /**< Copy from buf in buf2kvvec_prealloc() */
#define KVVEC_APPEND 2 /**< Don't reset kvvec in buf2kvvec_prealloc() */
/**
* Initialize a previously allocated key/value vector
*
* @param kvv The key/value vector to initialize
* @param hint Number of key/value pairs we expect to store
* @return Pointer to a struct kvvec, properly initialized
*/
extern struct kvvec *kvvec_init(struct kvvec *kvv, int hint);
/**
* Create a key/value vector
*
* @param hint Number of key/value pairs we expect to store
* @return Pointer to a struct kvvec, properly initialized
*/
extern struct kvvec *kvvec_create(int hint);
/**
* Resize a key/value vector
* Used by kvvec_grow(). If size is smaller than the current number of
* used key/value slots, -1 is returned.
*
* @param[in] kvv The key/value vector to resize
* @param[in] size The size to grow to
* @return 0 on success, < 0 on errors
*/
extern int kvvec_resize(struct kvvec *kvv, int size);
/**
* Grow a key/value vector.
* Used internally as needed by the kvvec api. If 'hint' is zero, the
* key/value capacity is increased by a third of the current capacity
* plus a small constant number. This uses kvvec_resize() internally.
*
* @param kvv The key/value vector to grow
* @param hint The amount of key/value slots we should grow by
* @return 0 on success, < 0 on errors
*/
extern int kvvec_grow(struct kvvec *kvv, int hint);
/**
* Return remaining storage capacity of key/value vector
* @param[in] kvv The key/value vector to check
* @return Number of key/value pairs that can be stored without growing
*/
extern unsigned int kvvec_capacity(struct kvvec *kvv);
/**
* Sort a key/value vector alphabetically by key name
* @param kvv The key/value vector to sort
* @return 0
*/
extern int kvvec_sort(struct kvvec *kvv);
/**
* Add a key/value pair to an existing key/value vector, with
* lengths of strings already calculated
* @param kvv The key/value vector to add this key/value pair to
* @param key The key
* @param keylen Length of the key
* @param value The value
* @param valuelen Length of the value
* @return 0 on success, < 0 on errors
*/
extern int kvvec_addkv_wlen(struct kvvec *kvv, const char *key, int keylen, const char *value, int valuelen);
/**
* Shortcut to kvvec_addkv_wlen() when lengths aren't known
* @param kvv The key/value vector to add this key/value pair to
* @param key The key
* @param value The value
* @return 0 on success, < 0 on errors
*/
#define kvvec_addkv(kvv, key, value) kvvec_addkv_wlen(kvv, key, 0, value, 0)
/**
* Walk each key/value pair in a key/value vector, sending them
* as arguments to a callback function. The callback function has
* no control over the iteration process and must not delete or
* modify the key/value vector it's operating on.
* @param kvv The key/value vector to walk
* @param arg Extra argument to the callback function
* @param callback Callback function
* @return 0 on success, < 0 on errors
*/
extern int kvvec_foreach(struct kvvec *kvv, void *arg, int (*callback)(struct key_value *, void *));
/**
* Destroy a key/value vector
* @param kvv The key/value vector to destroy
* @param flags or'ed combination of KVVEC_FREE_{KEYS,VALUES}, or KVVEC_FREE_ALL
* @return 0 on success, < 0 on errors
*/
extern int kvvec_destroy(struct kvvec *kvv, int flags);
/**
* Free key/value pairs associated with a key/value vector
* @param kvv The key/value vector to operate on
* @param flags flags or'ed combination of KVVEC_FREE_{KEYS,VALUES}, or KVVEC_FREE_ALL
*/
void kvvec_free_kvpairs(struct kvvec *kvv, int flags);
/**
* Create a linear buffer of all the key/value pairs and
* return it as a kvvec_buf. The caller must free() all
* pointers in the returned kvvec_buf
* (FIXME: add kvvec_buf_destroy(), or move this and its counterpart
* out of the kvvec api into a separate one)
*
* @param kvv The key/value vector to convert
* @param kv_sep Character separating keys and their values
* @param pair_sep Character separating key/value pairs
* @param overalloc Integer determining how much extra data we should
* allocate. The overallocated memory is filled with
* nul bytes.
* @return A pointer to a newly created kvvec_buf structure
*/
extern struct kvvec_buf *kvvec2buf(struct kvvec *kvv, char kv_sep, char pair_sep, int overalloc);
/**
* Create a key/value vector from a pre-parsed buffer. Immensely
* useful for ipc in combination with kvvec2buf().
*
* @param str The buffer to convert to a key/value vector
* @param len Length of buffer to convert
* @param kvsep Character separating key and value
* @param pair_sep Character separating key/value pairs
* @param flags bitmask. See KVVEC_{ASSIGN,COPY,APPEND} for values
* @return The created key/value vector
*/
extern struct kvvec *buf2kvvec(char *str, unsigned int len, const char kvsep, const char pair_sep, int flags);
/**
* Parse a buffer into the pre-allocated key/value vector. Immensely
* useful for ipc in combination with kvvec2buf().
*
* @param kvv A pre-allocated key/value vector to populate
* @param str The buffer to convert to a key/value vector
* @param len Length of buffer to convert
* @param kvsep Character separating key and value
* @param pair_sep Character separating key/value pairs
* @param flags bitmask. See KVVEC_{ASSIGN,COPY,APPEND} for values
* @return The number of pairs in the created key/value vector
*/
extern int buf2kvvec_prealloc(struct kvvec *kvv, char *str, unsigned int len, const char kvsep, const char pair_sep, int flags);
/** @} */
#endif /* INCLUDE_kvvec_h__ */