# Collections
UCX defines common attributes for collections.
If you want to implement an own collection data type that uses the same features, you can use the
`CX_COLLECTION_BASE` macro at the beginning of your struct to roll out all members a usual UCX collection has.
This macro will embed a structure in your collection that can be accessed with the member name `collection`.
```c
#include <cx/collection.h>
struct my_fancy_collection_s {
CX_COLLECTION_BASE; // adds a member named 'collection'
struct my_collection_data_s *data;
};
```
> You can always look at the UCX list and map implementations if you need some inspiration.
## Base Attributes of a Collection
The following attributes are declared by the `CX_COLLECTION_BASE` macro:
| Attribute | Description |
|-----------------------|----------------------------------------------------------------------------------------------------------------|
| `allocator` | The [allocator](allocator.h.md) that shall be used for the collection data. |
| `cmpfunc` | A function to [compare](compare.h.md) two elements. |
| `elem_size` | The size of one element in bytes. |
| `size` | The size, meaning the number of elements, currently stored. |
| `simple_destructor` | An optional simple [destructor function](allocator.h.md#destructor-functions). |
| `advanced_destructor` | An optional advanced destructor function. |
| `destructor_data` | A pointer to the custom data that shall be passed to the advanced destructor. |
| `store_pointer` | A `bool` indicating whether this collection stores pointers instead of the element's data. |
| `sorted` | A `bool` indicating whether the elements are currently guaranteed sorted with respect to the compare function. |
The attributes can be accessed directly via the `collection` member of your struct, or with the following convenience macros.
```C
cxCollectionSize(c)
cxCollectionElementSize(c)
cxCollectionStoresPointers(c)
cxCollectionSorted(c)
```
In each case the argument `c` is a pointer to your collection. The macro will then access the base data with `c->collection`.
Similar to the above macros, the `cxCollectionCompareFunc(c,f)` macro can be used to set the compare function.
## Destructor Functions
For working with destructors, the following macros are defined:
```C
cxDefineDestructor(c, destr)
cxDefineAdvancedDestructor(c, destr, data)
// use in your collection's implementation
cx_invoke_destructor(c, elem)
// the following two should not be used
cx_invoke_simple_destructor(c, elem)
cx_invoke_advanced_destructor(c, elem)
```
With `cxDefineDestructor()` you can assign a simple [destructor function](allocator.h.md#destructor-functions)
to an _instance_ of your collection.
Similarly, you can assign an advanced destructor with custom `data` by using `cxDefineAdvancedDestructor`.
Your collection _should_ be supporting destructors by invoking `cx_invoke_destructor()` whenever an element
is removed from your collection _without_ being returned to the caller.
This macro will invoke a simple destructor, if one is assigned, first, and then the advanced destructor (again, if assigned).
> Destructor functions are always invoked with a pointer to the element in your collection.
> If your collection is storing pointers (i.e. `cxCollectionStoresPointers()` returns `true`)
> the `cx_invoke_destructor()` will make sure that the pointer to the element is dereferenced first,
> so that the destructor functions are _always_ invoked with a pointer to the actual element.
{style="note"}
<seealso>
<category ref="apidoc">
<a href="https://ucx.sourceforge.io/api/collection_8h.html">collection.h</a>
</category>
</seealso>