Sun, 14 Dec 2025 17:30:17 +0100
refactor the list and map construction functions and remove the simple macros
relates to #780
relates to #622
| 1390 | 1 | # Key/Value List |
| 2 | ||
| 3 | The key/value list is a linked list of key/value pairs. | |
| 4 | It implements both the `CxList` and `CxMap` interfaces. | |
| 5 | ||
| 6 | ```C | |
| 7 | #include <cx/kv_list.h> | |
| 8 | ||
| 9 | CxList *cxKvListCreate(const CxAllocator *allocator, | |
|
1605
55b13f583356
refactor the list and map construction functions and remove the simple macros
Mike Becker <universe@uap-core.de>
parents:
1394
diff
changeset
|
10 | size_t elem_size); |
| 1390 | 11 | |
| 12 | CxMap *cxKvListCreateAsMap(const CxAllocator *allocator, | |
|
1605
55b13f583356
refactor the list and map construction functions and remove the simple macros
Mike Becker <universe@uap-core.de>
parents:
1394
diff
changeset
|
13 | size_t elem_size); |
| 1390 | 14 | ``` |
| 15 | ||
| 16 | The lists are created as usual linked lists with an additional map to look up items by key. | |
| 17 | The map is created with the same allocator as the list. | |
| 18 | You can use either interface to access the list. | |
| 19 | Also, defining destructors on either interface will work as if you defined them on the list. | |
| 20 | Using the list interface to insert items will insert them without an assigned key, | |
| 21 | but you can always set a key later using the `cxKvListSetKey()` function (see [](#special-functions) below). | |
| 22 | ||
| 23 | > The special thing about key/value lists when used with the map interface is, | |
| 24 | > that when you iterate over the map, the elements are returned in the order they appear in the list. | |
| 25 | > In contrast, a normal hash map will return the elements in arbitrary order. | |
| 26 | > This way you can use a key/value list as an ordered map. | |
| 27 | > {style="note"} | |
| 28 | ||
| 29 | ## Converting between the Interfaces | |
| 30 | ||
| 31 | To easily convert between the `CxList` and `CxMap` interfaces, we provide the following functions. | |
| 32 | ||
| 33 | ```C | |
| 34 | #include <cx/kv_list.h> | |
| 35 | ||
| 36 | CxMap *cxKvListAsMap(CxList *list); | |
| 37 | ||
| 38 | CxList *cxKvListAsList(CxMap *map); | |
| 39 | ``` | |
| 40 | ||
| 41 | They must only be used on lists that have been created as key/value lists. | |
| 42 | Using them with other lists will result in undefined behavior. | |
| 43 | ||
| 44 | ## Special Functions | |
| 45 | ||
| 46 | The key/value list has some special functions that are not part of the `CxList` or `CxMap` interface. | |
| 47 | They also may only be used with lists that have been created as key/value lists. | |
| 48 | Using them with other lists will result in undefined behavior. | |
| 49 | ||
| 50 | ```C | |
| 51 | #include <cx/kv_list.h> | |
| 52 | ||
| 53 | int cxKvListSetKey(CxList *list, size_t index, KeyType key); | |
| 54 | ||
| 55 | int cxKvListRemoveKey(CxList *list, size_t index); | |
| 56 | ||
| 1394 | 57 | const CxHashKey *cxKvListGetKey(CxList *list, size_t index); |
| 58 | ||
| 1390 | 59 | int cxKvListAdd(CxList *list, KeyType key, void *value); |
| 60 | ||
| 61 | int cxKvListInsert(CxList *list, size_t index, | |
| 62 | KeyType key, void *value); | |
| 63 | ``` | |
| 64 | ||
| 65 | > All functions working with keys are implemented as generics, so that the following types are supported: | |
| 66 | > `CxHashKey`, `cxstring`, `cxmutstr`, `const char*`, and `char*`. | |
| 67 | > When we write `KeyType`, we mean any of these types. | |
| 68 | > {style="note"} | |
| 69 | ||
| 70 | The `cxKvListSetKey()` and `cxKvListRemoveKey()` functions are used to set or remove the key of an element. | |
| 71 | They return zero on success and non-zero on failure. | |
| 72 | A failure can happen when the index is out of bounds or when a memory allocation failed. | |
| 73 | The `cxKvListSetKey()` function also returns non-zero if the key already exists for _another_ element. | |
| 1394 | 74 | With `cxKvListGetKey()`, you can retrieve the key of an element. |
| 75 | This function returns `NULL` when an element has no key assigned or the index is out of bounds. | |
| 1390 | 76 | |
| 77 | With the `cxKvListAdd()` and `cxKvListInsert()` functions, you can add a new element to the list and immediately assign a key to it. | |
| 78 | The `cxKvListAdd()` function will add the element at the end of the list, | |
| 79 | while the `cxKvListInsert()` function will insert the element at the specified index. | |
| 80 | ||
| 81 | > The effect of `cxKvListAdd()` using the list interface and `cxMapPut()` using the map interface is the same. |