UAP Common Extensions 4.0 Help

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.

#include <cx/collection.h> struct my_fancy_collection_s { CX_COLLECTION_BASE; // adds a member named 'collection' struct my_collection_data_s *data; };

Base Attributes of a Collection

The following attributes are declared by the CX_COLLECTION_BASE macro:

Attribute

Description

allocator

The allocator that shall be used for the collection data.

elem_size

The size of one element in bytes.

size

The size, meaning the number of elements, currently stored.

simple_cmp

A function to compare two elements.

advanced_cmp

A function that compares two elements and supports custom data. If specified, this has precedence over the simple_cmp function.

cmp_data

A pointer to the custom data that shall be passed to the advanced_cmp function.

simple_destructor

An optional simple destructor function.

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.

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.

Comparator Functions

For working with comparators, the following macros are defined:

cxSetCompareFunc(c, func) cxSetAdvancedCompareFunc(c, func, data) // use in your collection's implementation cx_invoke_compare_func(c, left, right) // the following two can be used to optimize loops cx_invoke_simple_compare_func(c, left, right) cx_invoke_advanced_compare_func(c, left, right)

If an advanced compare function is specified, cx_invoke_compare_func() will only invoke the advanced comparator. Otherwise, the simple comparator is invoked. If neither comparator is specified, invoking a comparator leads to undefined behavior.

In contrast to the destructors (below), comparators must always be invoked with a pointer to the element's data. That means, if the collection is storing pointers, you must dereference the pointers to those pointers first, before invoking the comparator. The reason for this is that the comparator cannot know if an argument points to an element of the collection or to external data the elements shall be compared with.

A typical use case would be this:

void *arg = // ... passed as argument void *elem = // ... get a pointer to the element void *data; // manually ... if (cxCollectionStoresPointers(this_collection)) { data = *(void**)elem; } else { data = elem; } // ... or with a convenience macro data = cx_deref(this_collection, elem); int result = cx_invoke_compare_func(this_collection, data, arg);

Destructor Functions

For working with destructors, the following macros are defined:

cxSetDestructor(c, destr) cxSetAdvancedDestructor(c, destr, data) // use in your collection's implementation cx_invoke_destructor(c, elem) cx_invoke_destructor_raw(c, elem) // the following two can be used to optimize loops cx_invoke_simple_destructor(c, elem) cx_invoke_advanced_destructor(c, elem)

With cxSetDestructor() you can assign a simple destructor function to an instance of your collection. Similarly, you can assign an advanced destructor with custom data by using cxSetAdvancedDestructor.

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).

31 December 2025