dmi_vector_initialize

Synopsis

#include <opendmi/utils/vector.h>

typedef bool dmi_vector_match_fn(uintptr_t entry, uintptr_t key);

typedef struct dmi_vector {
    uintptr_t           *data;
    size_t               capacity;
    size_t               length;
    dmi_vector_match_fn *matcher;
    dmi_context_t       *context;
} dmi_vector_t;

bool dmi_vector_initialize(dmi_vector_t *vector, dmi_context_t *context, dmi_vector_match_fn *matcher);
bool dmi_vector_clear(dmi_vector_t *vector);

bool dmi_vector_push(dmi_vector_t *vector, uintptr_t value);
bool dmi_vector_pop(dmi_vector_t *vector, uintptr_t *value);
bool dmi_vector_get(const dmi_vector_t *vector, size_t index, uintptr_t *value);

bool dmi_vector_find(const dmi_vector_t *vector, uintptr_t key, uintptr_t *value);
bool dmi_vector_exists(const dmi_vector_t *vector, uintptr_t key);

size_t dmi_vector_length(const dmi_vector_t *vector);
bool dmi_vector_is_empty(const dmi_vector_t *vector);

Description

A vector, dmi_vector_t, is an array of uintptr_t values, typically pointers cast to uintptr_t, which grows as values are appended to it. The vector is a variable of the caller, usually a member of a structure; it owns the memory of the array, but not whatever the values point to.

The data member points to the array, length is the number of values the array holds, and capacity the number it can hold before it is grown. The members are read, but are changed only by the functions.

The dmi_vector_initialize function sets the vector up empty, with no memory allocated, with context as the context its errors are raised against, and with matcher as the function dmi_vector_find and dmi_vector_exists compare the values with keys by. The dmi_vector_clear function removes all values and frees the array, and leaves the vector empty, as dmi_vector_initialize does, with the context and the matcher kept. A vector is cleared once it is no longer needed.

The dmi_vector_push function appends value to the vector, growing the array by 16 values when it is full. The dmi_vector_pop function removes the last value and stores it in the variable value points to; the array is freed once the last value is removed.

The dmi_vector_get function stores the value at index, counted from zero, in the variable value points to.

The dmi_vector_find function calls the matcher with each value, in order, and key, and stores the first value it returns true for in the variable value points to. The dmi_vector_exists function tells whether there is such a value.

The dmi_vector_length function returns the number of values in the vector, and the dmi_vector_is_empty function tells whether there are none. Both take a nullptr vector as an empty one.

Parameters

vector

Vector to work on.

context

Context to raise the errors of the vector against, or nullptr if there is none, in which case the errors are not recorded.

matcher

Function to compare the values with keys by, or nullptr if the vector is not searched.

value

For dmi_vector_push, value to append. For dmi_vector_get, variable to store the value in. For dmi_vector_pop and dmi_vector_find, variable to store the value in, or nullptr if the value is not needed.

index

Index of the value, counted from zero.

key

Key to pass to the matcher.

entry

Value of the vector the matcher compares with key.

Return value

The dmi_vector_initialize, dmi_vector_clear, dmi_vector_push and dmi_vector_get functions return true on success, and false on failure. If dmi_vector_push fails, the vector is left as it was.

The dmi_vector_pop function returns true if a value has been removed, and false if the vector is empty, which is not an error, so that a vector can be emptied by popping its values until there is none, or on failure.

The dmi_vector_find and dmi_vector_exists functions return true if a value matches key, and false if none does, which is not an error either, or on failure.

Errors

DMI_ERROR_ARGUMENT_NULL

Raised if vector is nullptr, or, for dmi_vector_get, if value is nullptr.

DMI_ERROR_ARGUMENT_INVALID

Raised by dmi_vector_get if index is out of range.

DMI_ERROR_STATE_INVALID

Raised by dmi_vector_find and dmi_vector_exists if the vector has no matcher.

DMI_ERROR_OUT_OF_MEMORY

Raised by dmi_vector_push if the array cannot be grown.

The errors are raised against the context of the vector, and reach no error queue if the vector has none, or if vector itself is nullptr. The one of dmi_vector_initialize is raised against context.

Example

static bool match_name(uintptr_t entry, uintptr_t key)
{
    return strcmp((const char *)entry, (const char *)key) == 0;
}

dmi_vector_t names;

dmi_vector_initialize(&names, context, match_name);

if (!dmi_vector_push(&names, (uintptr_t)"cpu") ||
    !dmi_vector_push(&names, (uintptr_t)"memory")) {
    dmi_vector_clear(&names);
    return false;
}

if (dmi_vector_exists(&names, (uintptr_t)"memory"))
    puts("found");

for (size_t i = 0; i < dmi_vector_length(&names); i++) {
    uintptr_t value;

    if (dmi_vector_get(&names, i, &value))
        puts((const char *)value);
}

dmi_vector_clear(&names);

See also

realloc(3)