kvlist.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * kvlist - simple key/value store
  3. *
  4. * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "utils.h"
  21. #include "avl-cmp.h"
  22. #include "blob.h"
  23. #include "kvlist.h"
  24. int kvlist_strlen(struct kvlist *kv, const void *data)
  25. {
  26. return strlen(data) + 1;
  27. }
  28. int kvlist_blob_len(struct kvlist *kv, const void *data)
  29. {
  30. return blob_pad_len(data);
  31. }
  32. void kvlist_init(struct kvlist *kv, int (*get_len)(struct kvlist *kv, const void *data))
  33. {
  34. avl_init(&kv->avl, avl_strcmp, false, NULL);
  35. kv->get_len = get_len;
  36. }
  37. static struct kvlist_node *__kvlist_get(struct kvlist *kv, const char *name)
  38. {
  39. struct kvlist_node *node;
  40. return avl_find_element(&kv->avl, name, node, avl);
  41. }
  42. void *kvlist_get(struct kvlist *kv, const char *name)
  43. {
  44. struct kvlist_node *node;
  45. node = __kvlist_get(kv, name);
  46. if (!node)
  47. return NULL;
  48. return node->data;
  49. }
  50. bool kvlist_delete(struct kvlist *kv, const char *name)
  51. {
  52. struct kvlist_node *node;
  53. node = __kvlist_get(kv, name);
  54. if (node) {
  55. avl_delete(&kv->avl, &node->avl);
  56. free(node);
  57. }
  58. return !!node;
  59. }
  60. bool kvlist_set(struct kvlist *kv, const char *name, const void *data)
  61. {
  62. struct kvlist_node *node;
  63. char *name_buf;
  64. int len = kv->get_len(kv, data);
  65. node = calloc_a(sizeof(struct kvlist_node) + len,
  66. &name_buf, strlen(name) + 1);
  67. if (!node)
  68. return false;
  69. kvlist_delete(kv, name);
  70. memcpy(node->data, data, len);
  71. node->avl.key = strcpy(name_buf, name);
  72. avl_insert(&kv->avl, &node->avl);
  73. return true;
  74. }
  75. void kvlist_free(struct kvlist *kv)
  76. {
  77. struct kvlist_node *node, *tmp;
  78. avl_remove_all_elements(&kv->avl, node, avl, tmp)
  79. free(node);
  80. }