Sun, 24 Aug 2025 17:11:53 +0200
create a header file for the new key-value-lists
kick-off for issue #461
src/cx/kv_list.h | file | annotate | diff | comparison | revisions |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cx/kv_list.h Sun Aug 24 17:11:53 2025 +0200 @@ -0,0 +1,234 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @file kv_list.h + * @brief Linked list implementation with key/value-lookup. + * @author Mike Becker + * @author Olaf Wintermann + * @copyright 2-Clause BSD License + */ + +#ifndef UCX_KV_LIST_H +#define UCX_KV_LIST_H + +#include "common.h" +#include "list.h" +#include "map.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Allocates a linked list with a lookup-map for storing elements with @p elem_size bytes each. + * + * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of + * copies of the added elements, and the compare function will be automatically set + * to cx_cmp_ptr(), if none is given. + * + * After creating the list, it can also be used as a map after converting the pointer + * to a CxMap pointer with cxKvListAsMap(). + * When you want to use the list interface again, you can also convert the map pointer back + * with cxKvListAsList(). + * + * @param allocator the allocator for allocating the list nodes + * (if @c NULL, the cxDefaultAllocator will be used) + * @param comparator the comparator for the elements + * (if @c NULL, and the list is not storing pointers, sort and find + * functions will not work) + * @param elem_size the size of each element in bytes + * @return the created list + * @see cxKvListAsMap() + * @see cxKvListAsList() + */ +cx_attr_nodiscard +cx_attr_malloc +cx_attr_dealloc(cxListFree, 1) +cx_attr_export +CxList *cxKvListCreate( + const CxAllocator *allocator, + cx_compare_func comparator, + size_t elem_size +); + +/** + * Allocates a linked list with a lookup-map for storing elements with @p elem_size bytes each. + * + * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of + * copies of the added elements, and the compare function will be automatically set + * to cx_cmp_ptr(), if none is given. + * + * This function creates the list with cxKvListCreate() and immediately applies + * cxKvListAsMap(). If you want to use the returned object as a list, you can call + * cxKvListAsList() later. + * + * @param allocator the allocator for allocating the list nodes + * (if @c NULL, the cxDefaultAllocator will be used) + * @param comparator the comparator for the elements + * (if @c NULL, and the list is not storing pointers, sort and find + * functions will not work) + * @param elem_size the size of each element in bytes + * @return the created list wrapped into the CxMap interface + * @see cxKvListAsMap() + * @see cxKvListAsList() + */ +cx_attr_nodiscard +cx_attr_malloc +cx_attr_dealloc(cxMapFree, 1) +cx_attr_export +CxMap *cxKvListCreateAsMap( + const CxAllocator *allocator, + cx_compare_func comparator, + size_t elem_size +); + +/** + * Allocates a linked list with a lookup-map for storing elements with @p elem_size bytes each. + * + * The list will use cxDefaultAllocator and no comparator function. If you want + * to call functions that need a comparator, you must either set one immediately + * after list creation or use cxKvListCreate(). + * + * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of + * copies of the added elements, and the compare function will be automatically set + * to cx_cmp_ptr(). + * + * After creating the list, it can also be used as a map after converting the pointer + * to a CxMap pointer with cxKvListAsMap(). + * When you want to use the list interface again, you can also convert the map pointer back + * with cxKvListAsList(). + * + * @param elem_size (@c size_t) the size of each element in bytes + * @return (@c CxList*) the created list + * @see cxKvListAsMap() + * @see cxKvListAsList() + */ +#define cxKvListCreateSimple(elem_size) cxKvListCreate(NULL, NULL, elem_size) + +/** + * Allocates a linked list with a lookup-map for storing elements with @p elem_size bytes each. + * + * The list will use cxDefaultAllocator and no comparator function. If you want + * to call functions that need a comparator, you must either set one immediately + * after list creation or use cxKvListCreate(). + * + * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of + * copies of the added elements, and the compare function will be automatically set + * to cx_cmp_ptr(). + * + * This macro behaves as if the list was created with cxKvListCreateSimple() and + * immediately followed up by cxKvListAsMap(). + * If you want to use the returned object as a list, you can call cxKvListAsList() later. + * + * @param elem_size (@c size_t) the size of each element in bytes + * @return (@c CxMap*) the created list wrapped into the CxMap interface + * @see cxKvListAsMap() + * @see cxKvListAsList() + */ +#define cxKvListCreateAsMapSimple(elem_size) cxKvListCreateAsMap(NULL, NULL, elem_size) + +/** + * Converts a map pointer belonging to a key-value-List back to the original list pointer. + * + * @param map a map pointer that was returned by a call to cxKvListAsMap() + * @return the original list pointer + */ +cx_attr_nodiscard +cx_attr_nonnull +cx_attr_returns_nonnull +cx_attr_export +CxList *cxKvListAsList(CxMap *map); + +/** + * Converts a map pointer belonging to a key-value-List back to the original list pointer. + * + * @param list a list created by cxKvListCreate() or cxKvListCreateSimple() + * @return a map pointer that lets you use the list as if it was a map + */ +cx_attr_nodiscard +cx_attr_nonnull +cx_attr_returns_nonnull +cx_attr_export +CxMap *cxKvListAsMap(CxList *list); + +/** + * Sets or updates the key of a list item. + * + * This is, for example, useful when you have inserted an element using the CxList interface, + * and now you want to associate this element with a key. + * + * @param list (@c CxList*) the list + * @param key (@c CxHashKey, @c char*, @c cxstring, or @c cxmutstr) the key + * @param index (@c size_t) the index of the element in the list + * @retval zero success + * @retval non-zero memory allocation failure or the index is out of bounds + */ +#define cxKvListSetKey(list, key, index) + +/** + * Removes the key for a list item. + * + * This can be useful if you want to explicitly remove an item from the lookup map, + * for example, when you want to prevent a deletion by cxMapClear(). + * + * @param list (@c CxList*) the list + * @param key (@c CxHashKey, @c char*, @c cxstring, or @c cxmutstr) the key + * @param index (@c size_t) the index of the element in the list + * @retval zero success + * @retval non-zero the index is out of bounds + */ +#define cxKvListRemoveKey(list, key, index) + +/** + * Inserts an item into the list at the specified index and associates it with the specified key. + * + * @param list (@c CxList*) the list + * @param index (@c size_t) the index the inserted element shall have + * @param key (@c CxHashKey, @c char*, @c cxstring, or @c cxmutstr) the key + * @param value (@c void*) the value + * @retval zero success + * @retval non-zero memory allocation failure or the index is out of bounds + */ +#define cxKvListInsert(list, index, key, value) + +/** + * Adds an item into the list and associates it with the specified key. + * + * @param list (@c CxList*) the list + * @param key (@c CxHashKey, @c char*, @c cxstring, or @c cxmutstr) the key + * @param value (@c void*) the value + * @retval zero success + * @retval non-zero memory allocation failure or the index is out of bounds + */ +#define cxKvListAdd(list, index, key, value) cxKvListInsert(list, list->collection.size, key, value) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // UCX_KV_LIST_H