Advertisement
Guest User

Untitled

a guest
Sep 21st, 2014
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.52 KB | None | 0 0
  1. const KVSpair *pairA = (const KVSpair*) a;
  2.  
  3. KVSstore *store = kvs_create(strcmp);
  4. KVSpair *p;
  5. int i = 0;
  6.  
  7. kvs_put(store, "abc", "123");
  8. kvs_put(store, "ghi", "789");
  9. kvs_put(store, "def", "456");
  10.  
  11. while ((p = kvs_pair(store, i++))) {
  12. printf("%s: %sn", (char *)p->key, (char *)p->value);
  13. }
  14.  
  15. #ifndef __KVS_H__
  16. #define __KVS_H__
  17.  
  18. #ifdef __cplusplus
  19. extern "C" {
  20. #endif
  21.  
  22. #include <stdlib.h>
  23. #include <string.h>
  24.  
  25. #define KVS_SPACE_INCREMENT 8
  26.  
  27. typedef int KVScompare(const char *a, const char *b);
  28.  
  29. typedef const void KVSkey;
  30.  
  31. typedef void KVSvalue;
  32.  
  33. typedef struct {
  34. KVSkey *key;
  35. KVSvalue *value;
  36. } KVSpair;
  37.  
  38. typedef struct KVSstore KVSstore;
  39.  
  40. /** Create a new key-value store.
  41.  
  42. @param compare
  43. A function to compare keys. If the store will only contain string keys,
  44. use strcmp, or use NULL for the default behavior of comparing memory
  45. addresses, or use a custom function matching the signature of strcmp.
  46.  
  47. @return
  48. A pointer to the store.
  49. */
  50. KVSstore *kvs_create(KVScompare *compare);
  51.  
  52. /** Destroy a key-value store.
  53.  
  54. @param store
  55. A pointer to the store.
  56. */
  57. void kvs_destroy(KVSstore *store);
  58.  
  59. /** Store a value.
  60.  
  61. @param store
  62. A pointer to the store.
  63.  
  64. @param key
  65. A key used to retrieve the value later. If the key already exists, the
  66. new value will be stored in place of the old one, unless value is NULL
  67. in which case the key-value pair will be removed from the store.
  68.  
  69. @param value
  70. A pointer to the data being stored, or NULL to remove an existing value.
  71. */
  72. void kvs_put(KVSstore *store, KVSkey *key, KVSvalue *value);
  73.  
  74. /** Retrieve a value.
  75.  
  76. @param store
  77. A pointer to the store.
  78.  
  79. @param key
  80. A key used to retrieve the value.
  81.  
  82. @return
  83. A pointer to the retrieved value, or NULL if not found.
  84. */
  85. KVSvalue *kvs_get(KVSstore *store, KVSkey *key);
  86.  
  87. /** Remove a value from the store.
  88.  
  89. @param store
  90. A pointer to the store.
  91.  
  92. @param key
  93. A key identifying the value to be removed.
  94. */
  95. void kvs_remove(KVSstore *store, KVSkey *key);
  96.  
  97. /** Get the number of values in a store.
  98.  
  99. @param store
  100. A pointer to the store.
  101.  
  102. @return
  103. The number of values contained in the store.
  104. */
  105. size_t kvs_length(KVSstore *store);
  106.  
  107. /** Get a key-value pair at a given index.
  108.  
  109. @param store
  110. A pointer to the store.
  111.  
  112. @param index
  113. The index of the key-value pair.
  114.  
  115. @return
  116. A pointer to the key-value pair, or NULL if the index is out or range.
  117. */
  118. KVSpair *kvs_pair(KVSstore *store, size_t index);
  119.  
  120. #ifdef __cplusplus
  121. }
  122. #endif
  123.  
  124. #endif /* #define __KVS_H__ */
  125.  
  126. #include "kvs.h"
  127. #include <stdio.h>
  128.  
  129. struct KVSstore {
  130. KVSpair *pairs;
  131. KVScompare *compare;
  132. size_t length;
  133. size_t space;
  134. };
  135.  
  136. static const size_t kvs_pair_size = sizeof(KVSpair);
  137.  
  138. static const size_t kvs_store_size = sizeof(KVSstore);
  139.  
  140. static KVSpair *kvs_search(KVSstore *store, KVSkey *key, int exact) {
  141. KVSpair *pairs = store->pairs;
  142. size_t lbound = 0;
  143. size_t rbound = store->length;
  144. while (lbound < rbound) {
  145. size_t index = lbound + ((rbound - lbound) >> 1);
  146. KVSpair *element = pairs + index;
  147. int result = store->compare(key, element->key);
  148. if (result < 0) {
  149. rbound = index;
  150. } else if (result > 0) {
  151. lbound = index + 1;
  152. } else {
  153. return element;
  154. }
  155. }
  156. return exact ? NULL : pairs + lbound;
  157. }
  158.  
  159. static KVSpair *kvs_get_pair(KVSstore *store, KVSkey *key) {
  160. if ((!store) || (!store->pairs)) {
  161. return NULL;
  162. }
  163. return kvs_search(store, key, 1);
  164. }
  165.  
  166. static void kvs_abort_if_null(void *pointer, const char *message) {
  167. if (pointer == NULL) {
  168. fprintf(stderr, "%sn", message);
  169. exit(-1);
  170. }
  171. }
  172.  
  173. static void kvs_resize_pairs(KVSstore *store, size_t amount) {
  174. if (!store) {
  175. return;
  176. }
  177. store->length += amount;
  178. if (store->space > store->length) {
  179. return;
  180. }
  181. store->space += KVS_SPACE_INCREMENT;
  182. store->pairs = realloc(store->pairs, kvs_pair_size * store->space);
  183. kvs_abort_if_null(store->pairs, "out of memory");
  184. }
  185.  
  186. static size_t kvs_get_pair_index(KVSstore *store, KVSpair *pair) {
  187. if ((!store) || (!pair)) {
  188. return -1;
  189. }
  190. return pair - store->pairs;
  191. }
  192.  
  193. static size_t kvs_get_bytes_from_pair(KVSstore *store, KVSpair *pair) {
  194. size_t pair_index;
  195. if ((!store) || (!pair)) {
  196. return 0;
  197. }
  198. pair_index = kvs_get_pair_index(store, pair);
  199. return (store->length - pair_index) * kvs_pair_size;
  200. }
  201.  
  202. static void kvs_create_pair(KVSstore *store, KVSkey *key, KVSvalue *value) {
  203. KVSpair *pair;
  204. if (!store) {
  205. return;
  206. }
  207. pair = kvs_search(store, key, 0);
  208. if (pair < store->pairs + store->length) {
  209. size_t bytes = kvs_get_bytes_from_pair(store, pair);
  210. memmove(pair + 1, pair, bytes);
  211. }
  212. pair->key = key;
  213. pair->value = value;
  214. kvs_resize_pairs(store, +1);
  215. }
  216.  
  217. static void kvs_remove_pair(KVSstore *store, KVSpair *pair) {
  218. if ((!store) || (!pair)) {
  219. return;
  220. }
  221. memmove(pair, pair + 1, kvs_get_bytes_from_pair(store, pair + 1));
  222. kvs_resize_pairs(store, -1);
  223. }
  224.  
  225. static int kvs_compare_pointers(const char *a, const char *b) {
  226. return a - b;
  227. }
  228.  
  229. KVSstore *kvs_create(KVScompare compare) {
  230. KVSstore *store = malloc(kvs_store_size);
  231. kvs_abort_if_null(store, "out of memory");
  232. store->pairs = NULL;
  233. store->length = 0;
  234. store->space = 0;
  235. if (compare) {
  236. store->compare = compare;
  237. } else {
  238. store->compare = kvs_compare_pointers;
  239. }
  240. kvs_resize_pairs(store, 0);
  241. return store;
  242. }
  243.  
  244. void kvs_destroy(KVSstore *store) {
  245. if (!store) {
  246. return;
  247. }
  248. if (store->pairs) {
  249. free(store->pairs);
  250. }
  251. free(store);
  252. }
  253.  
  254. void kvs_put(KVSstore *store, KVSkey *key, void *value) {
  255. KVSpair *pair = kvs_get_pair(store, key);
  256. if (pair) {
  257. if (value) {
  258. pair->value = value;
  259. } else {
  260. kvs_remove_pair(store, pair);
  261. }
  262. } else if (value) {
  263. kvs_create_pair(store, key, value);
  264. }
  265. }
  266.  
  267. KVSvalue *kvs_get(KVSstore *store, KVSkey *key) {
  268. KVSpair *pair = kvs_get_pair(store, key);
  269. return pair ? pair->value : NULL;
  270. }
  271.  
  272. void kvs_remove(KVSstore *store, KVSkey *key) {
  273. kvs_put(store, key, NULL);
  274. }
  275.  
  276. size_t kvs_length(KVSstore *store) {
  277. if (!store) {
  278. return 0;
  279. }
  280. return store->length;
  281. }
  282.  
  283. KVSpair *kvs_pair(KVSstore *store, size_t index) {
  284. if ((!store) || (index < 0) || (index >= store->length)) {
  285. return NULL;
  286. }
  287. return store->pairs + index;
  288. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement