/* eurephia_values.c -- Generic interface for processing key->value pairs * * GPLv2 only - Copyright (C) 2008 - 2012 * David Sommerseth * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; version 2 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** * @file eurephia_values.c * @author David Sommerseth * @date 2008-08-06 * * @brief Generic interface for handling key->value pairs * */ #include #include #include #include #include #include #include /** * Clears the values of a eurephiaVALUES key/value record. * This function does not remove the record from the stack, but * only frees the key and value pointers and sets them to NULL. * * @param vls Pointer to the eurephiaVALUES record to be cleared */ void eClear_key_value(eurephiaVALUES *vls) { if( vls != NULL ) { free_nullsafe(NULL, vls->key); free_nullsafe(NULL, vls->val); } } /** * Internal function. Makes sure a eurephiaVALUES stack is freed up * * @param vls Pointer to a eurephiaVALUES stack. */ void do_free_vals(eurephiaVALUES *vls) { if( vls->next != NULL ) { do_free_vals(vls->next); } eClear_key_value(vls); free_nullsafe(NULL, vls); } /** * Function for freeing up an eurephiaVALUES stack. This function is normally not called * directly, but usually via the eFree_values(...) macro. * * @param ctx eurephiaCTX * @param vls Pointer to a eurephiaVALUES stack to be freed. */ void eFree_values_func(eurephiaCTX *ctx, eurephiaVALUES *vls) { DEBUG(ctx, 31, "Function call: eFree_values(ctx, vls(%i))", (vls != NULL ? vls->evid : -1)); if( (vls == NULL) ) { return; } do_free_vals(vls); } /** * Retrieve an eurephiaVALUES element for a given value key * * @param vls Pointer to the eurephiaVALUES stack where to search for the element * @param key String containing the key name of the value requested. * * @return Returns an eurephiaVALUES element on success, otherwise NULL. */ eurephiaVALUES *eGet_valuestruct(eurephiaVALUES *vls, const char *key) { eurephiaVALUES *ptr = NULL; if( (vls == NULL) || (key == NULL) ) { return NULL; } ptr = vls; while( ptr != NULL ) { if( (ptr->key != NULL) && (strcmp(key, ptr->key) == 0) ) { return ptr; } ptr = ptr->next; } return NULL; } /** * Retrieves the value of a given key from an eurephiaVALUES stack. * * @param vls Pointer to an eurephiaVALUES stack where to search for the value * @param key String containing the key name of the value requested * * @return Returns a string (char *) with the requested value if found, otherwise NULL. */ char *eGet_value(eurephiaVALUES *vls, const char *key) { eurephiaVALUES *ptr = NULL; ptr = eGet_valuestruct(vls, key); return (ptr != NULL ? ptr->val : NULL); } /** * Creates a new eurephiaVALUES stack * * @param ctx eurephiaCTX * @param evgid int value, giving the stack an ID number. Useful when looking through log files later on. * * @return Returns an empty eurephiaVALUES struct on success, otherwise NULL. */ eurephiaVALUES *eCreate_value_space(eurephiaCTX *ctx, int evgid) { eurephiaVALUES *ptr = NULL; DEBUG(ctx, 32, "Function call: eCreate_value_space(ctx, %i)", evgid); ptr = (eurephiaVALUES *) malloc_nullsafe(ctx, sizeof(eurephiaVALUES) + 2); if( ptr == NULL ) { return NULL; } ptr->evgid = evgid; return ptr; } /** * Adds a new eurephiaVALUES stack to another eurephiaVALUES stack. If the evgid value differs, it will * be overwritten with the value of the destination stack. * * @param ctx eurephiaCTX * @param vls Destination eurephiaVALUES stack * @param newval Source eurephiaVALUES stack */ void eAdd_valuestruct(eurephiaCTX *ctx, eurephiaVALUES *vls, eurephiaVALUES *newval) { eurephiaVALUES *ptr = NULL; int vid = 0; DEBUG(ctx, 31, "Function call: eAdd_valuestruct(ctx, vls(%i), '%s', '%s')", (vls != NULL ? vls->evgid : -1), newval->key, newval->val); assert(vls != NULL); if( (vls->key == NULL) && (vls->val == NULL) && (vls->next == NULL) && (vls->evid == 0)) { // Update header record if it is empty, by copying newval record. Free newval afterwards vls->key = strdup_nullsafe(newval->key); vls->val = strdup_nullsafe(newval->val); vls->evid = 0; vls->next = NULL; do_free_vals(newval); } else { // Add values to the value chain, loop to the end and append it ptr = vls; while( ptr->next != NULL ) { ptr = ptr->next; vid = (vid > ptr->evid ? vid : ptr->evid); } newval->evid = vid+1; // Increase the value counter newval->evgid = ptr->evgid; ptr->next = newval; } } /** * Adds a new key/value pair to an eurephiaVALUES stack * * @param ctx eurephiaCTX * @param vls Destination eurephiaVALUES stack * @param key Key name for the value being stored * @param val Value to be stored */ void eAdd_value(eurephiaCTX *ctx, eurephiaVALUES *vls, const char *key, const char *val) { eurephiaVALUES *ptr = NULL; DEBUG(ctx, 31, "Function call: eAdd_value(ctx, vls(%i), '%s', '%s')", (vls != NULL ? vls->evgid : -1), key, val); assert(vls != NULL); // Allocate buffer and save values ptr = eCreate_value_space(ctx, vls->evid); if( ptr == NULL ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not add the new value"); return; } ptr->key = strdup_nullsafe(key); ptr->val = strdup_nullsafe(val); ptr->evgid = vls->evgid; // Add value struct to the chain eAdd_valuestruct(ctx, vls, ptr); } /** * Removes the key/value pair identified by evgid and evid from the given eurephiaVALUES chain * * @param ctx eurephiaCTX * @param vls Pointer to an eurephiaVALUES chain with the data * @param evgid Group ID of the chain * @param evid Element ID of the chain element to be removed * * @return Returns a pointer to the chain. The pointer is only changed if the first element in the * chain is deleted */ eurephiaVALUES *eRemove_value(eurephiaCTX *ctx, eurephiaVALUES *vls, unsigned int evgid, unsigned int evid) { eurephiaVALUES *ptr = NULL, *prev_ptr = NULL; int found = 0; DEBUG(ctx, 31, "Function call: eRemove_valuestruct(ctx, vls(%i), %i, %i)", (vls != NULL ? vls->evgid : -1), evgid, evid); // Find the value element for( ptr = vls; ptr != NULL; ptr = ptr->next ) { if( (ptr->evgid == evgid) && (ptr->evid == evid) ) { found = 1; break; } prev_ptr = ptr; } if( !found ) { return vls; } if( ptr != vls ) { prev_ptr->next = ptr->next; ptr->next = NULL; eFree_values_func(ctx, ptr); return vls; } else { prev_ptr = ptr->next; ptr->next = NULL; eFree_values_func(ctx, ptr); return prev_ptr; } }