/* * Copyright (C) 2010-2020 Red Hat, Inc. * * Author: Angus Salkeld * * This file is part of libqb. * * libqb is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2.1 of the License, or * (at your option) any later version. * * libqb 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libqb. If not, see . */ #ifndef QB_MAP_H_DEFINED #define QB_MAP_H_DEFINED #include #ifndef S_SPLINT_S #include #endif /* S_SPLINT_S */ /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* *INDENT-ON* */ /** * @file qbmap.h * This provides a map interface to a Patricia trie, hashtable or skiplist. * * @par Ordering * The hashtable is NOT ordered, but ptrie and skiplist are. * * @par Iterating * Below is a simple example of how to iterate over a map. * @code * const char *p; * void *data; * qb_map_iter_t *it = qb_map_iter_create(m); * for (p = qb_map_iter_next(it, &data); p; p = qb_map_iter_next(it, &data)) { * printf("%s > %s\n", p, (char*) data); * } * qb_map_iter_free(it); * @endcode * * Deletion of items within the iterator is supported. But note do not * free the item memory in the iterator. If you need to free the data * items then register for a notifier and free the memory there. This * is required as the items are reference counted. * @code * qb_map_notify_add(m, NULL, my_map_free_handler, * QB_MAP_NOTIFY_FREE, NULL); * @endcode * * @par Notifications * These allow you to get callbacks when values are inserted/removed or * replaced. * @note hashtable only supports deletion and replacement notificatins. * There is also a special global callback for freeing deleted and replaced * values (QB_MAP_NOTIFY_FREE). * @see qb_map_notify_add() qb_map_notify_del_2() * * @par Prefix matching * The ptrie supports prefixes in the iterator: * * @code * it = qb_map_pref_iter_create(m, "aa"); * while ((p = qb_map_iter_next(it, &data)) != NULL) { * printf("%s > %s\n", p, (char*)data); * } * qb_map_iter_free(it); * @endcode * * The ptrie also supports prefixes in notifications: * (remember to pass QB_MAP_NOTIFY_RECURSIVE into the notify_add. * @code * qb_map_notify_add(m, "root", my_map_notification, * (QB_MAP_NOTIFY_INSERTED| * QB_MAP_NOTIFY_DELETED| * QB_MAP_NOTIFY_REPLACED| * QB_MAP_NOTIFY_RECURSIVE), * NULL); * * @endcode */ /** * This is an opaque data type representing an instance of a map. */ typedef struct qb_map qb_map_t; /** * This is an opaque data type representing an iterator instance. */ typedef struct qb_map_iter qb_map_iter_t; #define QB_MAP_NOTIFY_DELETED 1 #define QB_MAP_NOTIFY_REPLACED 2 #define QB_MAP_NOTIFY_INSERTED 4 #define QB_MAP_NOTIFY_RECURSIVE 8 #define QB_MAP_NOTIFY_FREE 16 typedef void (*qb_map_notify_fn)(uint32_t event, char* key, void* old_value, void* value, void* user_data); typedef int32_t (*qb_map_transverse_fn)(const char* key, void* value, void* user_data); /** * Create an unsorted map based on a hashtable. * * @param max_size maximum size of the hashtable * * @return the map instance */ qb_map_t* qb_hashtable_create(size_t max_size); /** * Create a sorted map using a skiplist. * * @return the map instance */ qb_map_t* qb_skiplist_create(void); /** * Create a sorted map using a Patricia trie or "Radix tree". * * @htmlonly * See the wikipedia Radix_tree * and Trie pages. * @endhtmlonly */ qb_map_t* qb_trie_create(void); /** * print out the nodes in the trie * * (for debug purposes) */ void qb_trie_dump(qb_map_t* m); /** * Add a notifier to the map. * * @param m the map instance * @param key the key (or prefix) to attach the notification to. * @param fn the callback * @param events the type of events to register for. * @param user_data a pointer to be passed into the callback * * @note QB_MAP_NOTIFY_INSERTED is only valid on tries. * @note you can use key prefixes with trie maps. * * @retval 0 success * @retval -errno failure */ int32_t qb_map_notify_add(qb_map_t* m, const char* key, qb_map_notify_fn fn, int32_t events, void *user_data); /** * Delete a notifier from the map. * * @note the key,fn and events must match those you added. * * @param m the map instance * @param key the key (or prefix) to attach the notification to. * @param fn the callback * @param events the type of events to register for. * * @retval 0 success * @retval -errno failure */ int32_t qb_map_notify_del(qb_map_t* m, const char* key, qb_map_notify_fn fn, int32_t events); /** * Delete a notifier from the map (including the userdata). * * @note the key, fn, events and userdata must match those you added. * * @param m the map instance * @param key the key (or prefix) to attach the notification to. * @param fn the callback * @param events the type of events to register for. * @param user_data a pointer to be passed into the callback * * @retval 0 success * @retval -errno failure */ int32_t qb_map_notify_del_2(qb_map_t* m, const char* key, qb_map_notify_fn fn, int32_t events, void *user_data); /** * Inserts a new key and value into a qb_map_t. * * If the key already exists in the qb_map_t, it gets replaced by the new key. */ void qb_map_put(qb_map_t *map, const char* key, const void* value); /** * Gets the value corresponding to the given key. * * @retval NULL (if the key does not exist) * @retval a pointer to the value */ void* qb_map_get(qb_map_t *map, const char* key); /** * Removes a key/value pair from a map. */ int32_t qb_map_rm(qb_map_t *map, const char* key); /** * Get the number of items in the map. */ size_t qb_map_count_get(qb_map_t *map); /** * Calls the given function for each of the key/value pairs in the map. * * The function is passed the key and value of each pair, and the given data * parameter. The map is traversed in sorted order. */ void qb_map_foreach(qb_map_t *map, qb_map_transverse_fn func, void* user_data); /** * Create an iterator */ qb_map_iter_t* qb_map_iter_create(qb_map_t *map); /** * Create a prefix iterator. * * This will iterate over all items with the given * prefix. * @note this is only supported by the trie. */ qb_map_iter_t* qb_map_pref_iter_create(qb_map_t *map, const char* prefix); /** * Get the next item * * @param i the iterator * @param value (out) the next item's value * * @retval the next key * @retval NULL - the end of the iteration */ const char* qb_map_iter_next(qb_map_iter_t* i, void** value); /** * free the iterator * * @param i the iterator */ void qb_map_iter_free(qb_map_iter_t* i); /** * Destroy the map, removes all the items from the map. */ void qb_map_destroy(qb_map_t *map); /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* *INDENT-ON* */ #endif /* QB_MAP_H_DEFINED */