1/*************************************************** 2 * File name: dict.c 3 * 4 * Copyright 200X Gigle Semiconductor as an unpublished work. 5 * All Rights Reserved. 6 * 7 * The information contained herein is confidential 8 * property of Company. The user, copying, transfer or 9 * disclosure of such information is prohibited except 10 * by express written agreement with Company. 11 * 12 * First written on 03/08/2010 by Toni Homedes i Saun. 13 * 14 ***************************************************/ 15/** \file dict.c 16 */ 17/** \defgroup dict Simple Dictionnary 18 * 19 * \ingroup gigled Gigle Daemon 20 * 21 * \brief Simple key/value dictionary implementation 22 * 23 * Simples't possible implementation of a dictionary. Expected number of 24 * entries is very low (about 10~20) so emphasis has been given to simplicity 25 * to reduce risk 26 * 27 * The dictionnary is based on a single linked list and a head pointer. 28 * Elements are always unshifted at the front of the list; no order is kept. 29 * 30 * $Id: dict.c 245438 2011-03-10 01:54:50Z rnuti $ 31 */ 32/*@{*/ 33 34/*************************************************** 35* Include section 36***************************************************/ 37 38/* FILE-CSTYLED */ 39 40#include "dict.h" 41 42#include <errno.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46 47/*************************************************** 48 * Local Defines Section 49 ***************************************************/ 50 51/*************************************************** 52 * Local Constants Section 53 ***************************************************/ 54 55/*************************************************** 56 * Local Typedefs Section 57 ***************************************************/ 58 59/** \brief Dict list node 60 */ 61typedef struct s_dict_node { 62 struct s_dict_node *next; /**< \brief Pointer to next node of NULL if NIL */ 63 char * key; /**< \brief Pointer to malloc'ed key copy */ 64 char * value; /**< \brief Pointer to malloc'ed value copy */ 65} 66 t_dict_node; 67 68/*************************************************** 69 * Local Variables Section 70 ***************************************************/ 71 72/** This macro for easier rewriting */ 73#define Dict_head (*(t_dict_node **)dict) 74 75/************************************************** 76 * Function Prototype Section 77 * Add prototypes for all local functions defined 78 * in this file 79 ***************************************************/ 80static t_dict_node *DictInternalFind(dict_hdl_t dict, const char * const key); 81static void DictInternalFreeNode(t_dict_node ** const p); 82 83/*************************************************** 84 * Function Definition Section 85 * Define all public and local functions from now on 86 **************************************************/ 87 88/************************************************** 89 * Function name : static t_dict_node *DictInternalFind(const char * const key) 90 * Created by : Toni Homedes i Saun 91 * Date created : 03-08-2010 92 * Notes : Public function 93 * Restrictions (pre-conditions) 94 * Odd modes (post-conditions) 95 **************************************************/ 96/** \brief Searches for given key and returns pointer to the whole node 97 * 98 * \param[in] key Pointer to the key to search for 99 * 100 * \return Pointer to the found node or NULL if not 101 * 102 **************************************************/ 103static t_dict_node *DictInternalFind(const dict_hdl_t dict, const char * const key) 104{ 105 t_dict_node *p; 106 107 /* run over list looking for key */ 108 for (p = Dict_head; p; p = p->next) 109 if (!strcmp(key, p->key)) 110 break; 111 return p; 112} 113 114/************************************************** 115 * Function name : static void DictInternalFreeNode(t_dict_node ** const p) 116 * Created by : Toni Homedes i Saun 117 * Date created : 03-08-2010 118 * Notes : Public function 119 * Restrictions (pre-conditions) 120 * Odd modes (post-conditions) 121 **************************************************/ 122/** \brief Frees passed node and related mallocs and relinks list 123 * 124 * \param[in,out] p Pointer to the pointer holding node to delete 125 * 126 **************************************************/ 127static void DictInternalFreeNode(t_dict_node ** const p) 128{ 129 if (*p) 130 { 131 t_dict_node *tmp = (*p)->next; 132 free((*p)->key); 133 free((*p)->value); 134 free(*p); 135 *p = tmp; 136 } 137} 138 139/************************************************** 140 * Function name : dict_hdl_t DictNew(void) 141 * Created by : Toni Homedes i Saun 142 * Date created : 05-10-2010 143 * Notes : Public function 144 * Restrictions (pre-conditions) 145 * Odd modes (post-conditions) 146 **************************************************/ 147/** \brief Creates a new Dictionary 148 * 149 * \return New dictionnary handle 150 * 151 **************************************************/ 152dict_hdl_t DictNew(void) 153{ 154 t_dict_node * const *dict = malloc(sizeof (t_dict_node*)); 155 if (!dict) 156 { 157 perror("Can't get memory for dict handle"); 158 exit(EXIT_FAILURE); 159 } 160 Dict_head = NULL; 161 return (dict_hdl_t)dict; 162} 163 164/************************************************** 165 * Function name : static t_dict_node *DictInternalFind(const char * const key) 166 * Created by : Toni Homedes i Saun 167 * Date created : 03-08-2010 168 * Notes : Public function 169 * Restrictions (pre-conditions) 170 * Odd modes (post-conditions) 171 **************************************************/ 172/** \brief Searches for given key and returns pointer to the whole node 173 * 174 * \param[in] key Pointer to the key to search for 175 * 176 * \return Pointer to the found node or NULL if not 177 * 178 **************************************************/ 179void DictFree(dict_hdl_t dict) 180{ 181 if (dict) 182 DictDoEmpty(dict); 183 184 free((void *)dict); 185} 186 187/************************************************** 188 * Function name : void DictSet(const char * const key, const char * const 189 * value) 190 * Created by : Toni Homedes i Saun 191 * Date created : 03-08-2010 192 * Notes : Public function 193 * Restrictions (pre-conditions) 194 * Odd modes (post-conditions) 195 **************************************************/ 196/** \brief Sets given value in the dictionary 197 * 198 * \param[in] key Key to store 199 * \param[in] value Value to store 200 * 201 **************************************************/ 202void DictSet(const dict_hdl_t dict, const char * const key, const char * const 203 value) 204{ 205 t_dict_node *node = DictInternalFind(dict, key); 206 207 if (node) 208 { 209 if (strcmp(node->value, value)) 210 { 211 free(node->value); 212 node->value = strdup(value); 213 } 214 } 215 else 216 { 217 /* Inset new node in linked list */ 218 /* for this application we are assuming we'll never run out of memory */ 219 node = malloc(sizeof *node); 220 node->key = strdup(key); 221 node->value = strdup(value); 222 node->next = Dict_head; 223 Dict_head = node; 224 } 225} 226 227/************************************************** 228 * Function name : const char *DictGet(const char * const key) 229 * value) 230 * Created by : Toni Homedes i Saun 231 * Date created : 03-08-2010 232 * Notes : Public function 233 * Restrictions (pre-conditions) 234 * Odd modes (post-conditions) 235 **************************************************/ 236/** \brief Gets a key's value from the dictionnary 237 * 238 * \param[in] key Key to store 239 * 240 * \returns value if found or NULL if not 241 * 242 **************************************************/ 243const char *DictGet(const dict_hdl_t dict, const char * const key) 244{ 245 t_dict_node *node = DictInternalFind(dict, key); 246 return node ? node->value : NULL; 247} 248 249/************************************************** 250 * Function name : void DictDelete(const char * const key) 251 * Created by : Toni Homedes i Saun 252 * Date created : 03-08-2010 253 * Notes : Public function 254 * Restrictions (pre-conditions) 255 * Odd modes (post-conditions) 256 **************************************************/ 257/** \brief Deletes given value from the dictionary 258 * 259 * \param[in] key Key to delete 260 * 261 **************************************************/ 262void DictDelete(const dict_hdl_t dict, const char * const key) 263{ 264 t_dict_node **p; 265 266 /* run over list looking for key keeping a * to previous for relinking */ 267 for (p = &Dict_head; *p; p = &(*p)->next) 268 if (!strcmp(key, (*p)->key)) 269 break; 270 271 DictInternalFreeNode(p); 272} 273 274/************************************************** 275 * Function name : int DictIsEmpty(void) 276 * Created by : Toni Homedes i Saun 277 * Date created : 03-08-2010 278 * Notes : Public function 279 * Restrictions (pre-conditions) 280 * Odd modes (post-conditions) 281 **************************************************/ 282/** \brief Checks if the dictionary is empty 283 * 284 **************************************************/ 285int DictIsEmpty(const dict_hdl_t dict) 286{ 287 return NULL == Dict_head; 288} 289 290/************************************************** 291 * Function name : void DictDoEmpty(void) 292 * Created by : Toni Homedes i Saun 293 * Date created : 03-08-2010 294 * Notes : Public function 295 * Restrictions (pre-conditions) 296 * Odd modes (post-conditions) 297 **************************************************/ 298/** \brief Empties the dictionary 299 * 300 **************************************************/ 301void DictDoEmpty(const dict_hdl_t dict) 302{ 303 while (Dict_head) 304 { 305 DictInternalFreeNode(&Dict_head); 306 } 307} 308 309/************************************************** 310 * Function name : void DictMap(void (*fn)(const char *key, const char *value)) 311 * Created by : Toni Homedes i Saun 312 * Date created : 03-08-2010 313 * Notes : Public function 314 * Restrictions (pre-conditions) 315 * Odd modes (post-conditions) 316 **************************************************/ 317/** \brief Maps a function on all dictionary entries. Order is random. 318 * 319 * \param[in] fn Fucntion to be mapped 320 * 321 **************************************************/ 322void DictMap(const dict_hdl_t dict, void (*fn)(const char *key, const char *value)) 323{ 324 t_dict_node *p; 325 for (p = Dict_head; p; p = p->next) 326 fn(p->key, p->value); 327} 328 329/************************************************** 330 * Function name : dict_iterator_t DictIteratorNew(dict_hdl_t dict) 331 * value) 332 * Created by : Toni Homedes i Saun 333 * Date created : 06-10-2010 334 * Notes : Public function 335 * Restrictions (pre-conditions) 336 * Odd modes (post-conditions) 337 **************************************************/ 338/** \brief Create a new Dict Iterator 339 * 340 * \param[in] dict Dictionnary 341 * 342 **************************************************/ 343dict_iterator_t DictIteratorNew(dict_hdl_t dict) 344{ 345 t_dict_node ** const iterator = malloc(sizeof (t_dict_node*)); 346 if (!iterator) 347 { 348 perror("Can't get memory for iterator handle"); 349 exit(EXIT_FAILURE); 350 } 351 *iterator = Dict_head; 352 return (dict_iterator_t)iterator; 353} 354 355/************************************************** 356 * Function name : void DictSet(const char * const key, const char * const 357 * value) 358 * Created by : Toni Homedes i Saun 359 * Date created : 06-10-2010 360 * Notes : Public function 361 * Restrictions (pre-conditions) 362 * Odd modes (post-conditions) 363 **************************************************/ 364/** \brief Destroys given iterator 365 * 366 * \param[in] iterator Iterator to destroy 367 * 368 **************************************************/ 369void DictIteratorFree(dict_iterator_t iterator) 370{ 371 free((void *)iterator); 372} 373 374/************************************************** 375 * Function name : const char *DictIteratorKey(dict_iterator_t iterator) 376 * Created by : Toni Homedes i Saun 377 * Date created : 06-10-2010 378 * Notes : Public function 379 * Restrictions (pre-conditions) 380 * Odd modes (post-conditions) 381 **************************************************/ 382/** \brief Returns key for given iterator 383 * 384 * \param[in] iterator Iterator to use 385 * 386 **************************************************/ 387const char *DictIteratorKey(dict_iterator_t iterator) 388{ 389 t_dict_node **p = (t_dict_node **)iterator; 390 391 return *p ? (*p)->key : NULL; 392} 393 394/************************************************** 395 * Function name : void DictSet(const char * const key, const char * const 396 * value) 397 * Created by : Toni Homedes i Saun 398 * Date created : 06-10-2010 399 * Notes : Public function 400 * Restrictions (pre-conditions) 401 * Odd modes (post-conditions) 402 **************************************************/ 403/** \brief Advances given iterator 404 * 405 * \param[in] iterator Iterator to advance 406 * 407 **************************************************/ 408int DictIteratorAdvance(dict_iterator_t iterator) 409{ 410 t_dict_node **p = (t_dict_node **)iterator; 411 412 if (*p) 413 *p = (*p)->next; 414 415 return *p != NULL; 416} 417 418/*@}*/ 419