Initial Commit
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
#include "malunal/container.h"
|
||||
|
||||
typedef container_exception_t
|
||||
(*container_initialize_pfn_t)(
|
||||
container_mptr_t container,
|
||||
allocator_mptr_t allocator,
|
||||
malunal_size_t stride,
|
||||
malunal_size_t capacity
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*container_finalize_pfn_t)(
|
||||
container_mptr_t container
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*container_clear_pfn_t)(
|
||||
container_mptr_t container
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*container_append_pfn_t)(
|
||||
container_mptr_t container,
|
||||
malunal_iptr_t element
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*container_remove_pfn_t)(
|
||||
container_mptr_t container,
|
||||
malunal_iptr_t element
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*container_contains_pfn_t)(
|
||||
container_iptr_t container,
|
||||
malunal_iptr_t element
|
||||
);
|
||||
|
||||
|
||||
typedef struct {
|
||||
container_initialize_pfn_t const initialize;
|
||||
container_finalize_pfn_t const finalize;
|
||||
container_clear_pfn_t const clear;
|
||||
container_append_pfn_t const append;
|
||||
container_remove_pfn_t const remove;
|
||||
container_contains_pfn_t const contains;
|
||||
} virtual_table_t;
|
||||
|
||||
typedef virtual_table_t* base_vtable_mptr_t;
|
||||
typedef const virtual_table_t* vtable_iptr_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
vtable_iptr_t const vtable;
|
||||
|
||||
allocator_mptr_t allocator;
|
||||
malunal_mptr_t context;
|
||||
malunal_size_t stride;
|
||||
malunal_size_t count;
|
||||
malunal_size_t capacity;
|
||||
} implementation_t;
|
||||
|
||||
typedef implementation_t* impl_mptr_t;
|
||||
typedef const implementation_t* impl_iptr_t;
|
||||
|
||||
|
||||
// Verify these are the same.
|
||||
_Static_assert(
|
||||
CONTAINER_SIZE == sizeof(implementation_t),
|
||||
"container_t must be the same size as its implementation"
|
||||
);
|
||||
|
||||
|
||||
container_exception_t
|
||||
container_allocator(
|
||||
container_iptr_t container,
|
||||
allocator_mptr_t* out
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)container;
|
||||
if (implementation == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTAINER;
|
||||
*out = implementation->allocator;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_stride(
|
||||
container_iptr_t container,
|
||||
malunal_size_t* out
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)container;
|
||||
if (implementation == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTAINER;
|
||||
*out = implementation->stride;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_count(
|
||||
container_iptr_t container,
|
||||
malunal_size_t* out
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)container;
|
||||
if (implementation == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTAINER;
|
||||
*out = implementation->count;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_capacity(
|
||||
container_iptr_t container,
|
||||
malunal_size_t* out
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)container;
|
||||
if (implementation == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTAINER;
|
||||
*out = implementation->capacity;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_initialize(
|
||||
container_mptr_t container,
|
||||
allocator_mptr_t allocator,
|
||||
malunal_size_t stride,
|
||||
malunal_size_t capacity
|
||||
) {
|
||||
impl_mptr_t implementation = (impl_mptr_t)container;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->initialize(container, allocator, stride, capacity)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_finalize(container_mptr_t container) {
|
||||
impl_mptr_t implementation = (impl_mptr_t)container;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->finalize(container)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_clear(container_mptr_t container) {
|
||||
impl_mptr_t implementation = (impl_mptr_t)container;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->clear(container)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_append(
|
||||
container_mptr_t container,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
impl_mptr_t implementation = (impl_mptr_t)container;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->append(container, element)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_remove(
|
||||
container_mptr_t container,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
impl_mptr_t implementation = (impl_mptr_t)container;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->remove(container, element)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
container_contains(
|
||||
container_iptr_t container,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)container;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->contains(container, element)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
@@ -0,0 +1,500 @@
|
||||
#include <memory.h>
|
||||
#include "malunal/containers/vector.h"
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_initialize_pfn_t)(
|
||||
vector_mptr_t vector,
|
||||
allocator_mptr_t allocator,
|
||||
malunal_size_t stride,
|
||||
malunal_size_t capacity
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_finalize_pfn_t)(
|
||||
vector_mptr_t vector
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_clear_pfn_t)(
|
||||
vector_mptr_t vector
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_append_pfn_t)(
|
||||
vector_mptr_t vector,
|
||||
malunal_iptr_t element
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_remove_pfn_t)(
|
||||
vector_mptr_t vector,
|
||||
malunal_iptr_t element
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_contains_pfn_t)(
|
||||
vector_iptr_t vector,
|
||||
malunal_iptr_t element
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_get_pfn_t)(
|
||||
vector_iptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_mptr_t outptr
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_set_pfn_t)(
|
||||
vector_mptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_iptr_t element
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_insert_at_pfn_t)(
|
||||
vector_mptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_iptr_t element
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_remove_at_pfn_t)(
|
||||
vector_mptr_t vector,
|
||||
malunal_size_t index
|
||||
);
|
||||
|
||||
typedef container_exception_t
|
||||
(*vector_index_of_pfn_t)(
|
||||
vector_iptr_t vector,
|
||||
malunal_iptr_t element,
|
||||
malunal_size_t* outidx
|
||||
);
|
||||
|
||||
|
||||
typedef struct VectorVTable {
|
||||
// Container generic.
|
||||
vector_initialize_pfn_t const initialize;
|
||||
vector_finalize_pfn_t const finalize;
|
||||
vector_clear_pfn_t const clear;
|
||||
vector_append_pfn_t const append;
|
||||
vector_remove_pfn_t const remove;
|
||||
vector_contains_pfn_t const contains;
|
||||
|
||||
// Vector specific.
|
||||
vector_get_pfn_t const get;
|
||||
vector_set_pfn_t const set;
|
||||
vector_insert_at_pfn_t const insert_at;
|
||||
vector_remove_at_pfn_t const remove_at;
|
||||
vector_index_of_pfn_t const index_of;
|
||||
} virtual_table_t;
|
||||
|
||||
typedef virtual_table_t* vtable_mptr_t;
|
||||
typedef const virtual_table_t* vtable_iptr_t;
|
||||
|
||||
|
||||
// Identical to container.
|
||||
typedef struct {
|
||||
vtable_iptr_t const vtable;
|
||||
|
||||
allocator_mptr_t allocator;
|
||||
malunal_mptr_t context;
|
||||
malunal_size_t stride;
|
||||
malunal_size_t count;
|
||||
malunal_size_t capacity;
|
||||
} implementation_t;
|
||||
|
||||
typedef implementation_t* impl_mptr_t;
|
||||
typedef const implementation_t* impl_iptr_t;
|
||||
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_initialize_impl(
|
||||
impl_mptr_t vector,
|
||||
allocator_mptr_t allocator,
|
||||
malunal_size_t stride,
|
||||
malunal_size_t capacity
|
||||
) {
|
||||
malunal_size_t bytes = capacity * stride;
|
||||
allocation_result_t result = allocator_acquire(allocator, bytes);
|
||||
if (!result.threw) {
|
||||
vector->allocator = allocator;
|
||||
vector->context = result.address;
|
||||
vector->stride = stride;
|
||||
vector->capacity = capacity;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
switch (result.error) {
|
||||
case ALLOCATION_ERROR_NULL_ALLOCATOR:
|
||||
case ALLOCATION_ERROR_NULL_CONTEXT:
|
||||
case ALLOCATION_ERROR_NULL_UPSTREAM:
|
||||
return CONTAINER_ERROR_NULL_ALLOCATOR;
|
||||
|
||||
case ALLOCATION_ERROR_OUT_OF_MEMORY:
|
||||
return CONTAINER_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_finalize_impl(impl_mptr_t vector) {
|
||||
malunal_size_t bytes = vector->capacity * vector->stride;
|
||||
allocation_error_t error = allocator_release(
|
||||
vector->allocator,
|
||||
vector->context,
|
||||
bytes
|
||||
);
|
||||
|
||||
switch (error) {
|
||||
case ALLOCATION_ERROR_SUCCESS:
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
|
||||
case ALLOCATION_ERROR_NULL_ALLOCATOR:
|
||||
case ALLOCATION_ERROR_NULL_CONTEXT:
|
||||
case ALLOCATION_ERROR_NULL_UPSTREAM:
|
||||
return CONTAINER_ERROR_NULL_ALLOCATOR;
|
||||
|
||||
case ALLOCATION_ERROR_LEAKY_MEMORY:
|
||||
case ALLOCATION_ERROR_NOT_MY_ADDRESS:
|
||||
case ALLOCATION_ERROR_FAILURE:
|
||||
return CONTAINER_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_clear_impl(impl_mptr_t vector) {
|
||||
vector->count = 0;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_append_impl(
|
||||
impl_mptr_t vector,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
if (vector->context == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTEXT;
|
||||
|
||||
if (vector->count < vector->capacity)
|
||||
goto copy_element;
|
||||
|
||||
malunal_size_t doubled = vector->capacity * 2;
|
||||
allocation_result_t result = allocator_reacquire(
|
||||
vector->allocator,
|
||||
vector->context,
|
||||
vector->capacity * vector->stride,
|
||||
doubled * vector->stride
|
||||
);
|
||||
|
||||
if (!result.threw) {
|
||||
vector->context = result.address;
|
||||
vector->capacity = doubled;
|
||||
goto copy_element;
|
||||
}
|
||||
|
||||
switch (result.error) {
|
||||
case ALLOCATION_ERROR_NULL_ALLOCATOR:
|
||||
case ALLOCATION_ERROR_NULL_UPSTREAM:
|
||||
case ALLOCATION_ERROR_NULL_CONTEXT:
|
||||
return CONTAINER_ERROR_NULL_ALLOCATOR;
|
||||
|
||||
case ALLOCATION_ERROR_LEAKY_MEMORY:
|
||||
case ALLOCATION_ERROR_NOT_MY_ADDRESS:
|
||||
case ALLOCATION_ERROR_FAILURE:
|
||||
return CONTAINER_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
copy_element:
|
||||
malunal_uint8_t* buffer = vector->context;
|
||||
buffer = buffer + vector->stride * vector->count;
|
||||
memcpy(buffer, element, vector->stride);
|
||||
|
||||
vector->count++;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_remove_impl(
|
||||
impl_mptr_t vector,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
if (vector->context == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTEXT;
|
||||
|
||||
malunal_size_t index = 0;
|
||||
vector_mptr_t erased = (vector_mptr_t)vector;
|
||||
container_exception_t error = vector_index_of(erased, element, &index);
|
||||
if (error != CONTAINER_ERROR_SUCCESS)
|
||||
return error;
|
||||
|
||||
return index != -1
|
||||
? vector_remove_at(erased, index)
|
||||
: CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_contains_impl(
|
||||
impl_iptr_t vector,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
if (vector->context == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTEXT;
|
||||
|
||||
malunal_size_t index = 0;
|
||||
vector_mptr_t erased = (vector_mptr_t)vector;
|
||||
container_exception_t error = vector_index_of(erased, element, &index);
|
||||
if (error != CONTAINER_ERROR_SUCCESS)
|
||||
return error;
|
||||
|
||||
return index != -1
|
||||
? CONTAINER_ERROR_SUCCESS
|
||||
: CONTAINER_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_get_def_impl(
|
||||
impl_iptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_mptr_t outptr
|
||||
) {
|
||||
if (vector->context == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTEXT;
|
||||
|
||||
if (index < 0 || index >= vector->count)
|
||||
return CONTAINER_ERROR_OUT_OF_BOUNDS;
|
||||
|
||||
malunal_uint8_t* buffer = vector->context;
|
||||
buffer = buffer + vector->stride * index;
|
||||
memcpy(outptr, buffer, vector->stride);
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_set_def_impl(
|
||||
impl_mptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
if (vector->context == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTEXT;
|
||||
|
||||
if (index < 0 || index >= vector->count)
|
||||
return CONTAINER_ERROR_OUT_OF_BOUNDS;
|
||||
|
||||
malunal_uint8_t* buffer = vector->context;
|
||||
buffer = buffer + vector->stride * index;
|
||||
memcpy(buffer, element, vector->stride);
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_insert_at_def_impl(
|
||||
impl_mptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
if (vector->context == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTEXT;
|
||||
|
||||
if (index < 0 || index > vector->count)
|
||||
return CONTAINER_ERROR_OUT_OF_BOUNDS;
|
||||
|
||||
if (vector->count < vector->capacity)
|
||||
goto insert_element;
|
||||
|
||||
malunal_size_t doubled = vector->capacity * 2;
|
||||
allocation_result_t result = allocator_reacquire(
|
||||
vector->allocator,
|
||||
vector->context,
|
||||
vector->capacity * vector->stride,
|
||||
doubled * vector->stride
|
||||
);
|
||||
|
||||
if (!result.threw) {
|
||||
vector->context = result.address;
|
||||
vector->capacity = doubled;
|
||||
goto insert_element;
|
||||
}
|
||||
|
||||
switch (result.error) {
|
||||
case ALLOCATION_ERROR_NULL_ALLOCATOR:
|
||||
case ALLOCATION_ERROR_NULL_UPSTREAM:
|
||||
case ALLOCATION_ERROR_NULL_CONTEXT:
|
||||
return CONTAINER_ERROR_NULL_ALLOCATOR;
|
||||
|
||||
case ALLOCATION_ERROR_LEAKY_MEMORY:
|
||||
case ALLOCATION_ERROR_NOT_MY_ADDRESS:
|
||||
case ALLOCATION_ERROR_FAILURE:
|
||||
return CONTAINER_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
insert_element:
|
||||
malunal_size_t offset = vector->stride * index;
|
||||
malunal_uint8_t* orig = vector->context;
|
||||
orig = orig + offset;
|
||||
|
||||
malunal_size_t window = vector->count - index;
|
||||
malunal_size_t bytes = vector->stride * window;
|
||||
malunal_uint8_t* dest = orig + vector->stride;
|
||||
memmove(dest, orig, bytes);
|
||||
memcpy(orig, element, vector->stride);
|
||||
vector->count++;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_remove_at_def_impl(
|
||||
impl_mptr_t vector,
|
||||
malunal_size_t index
|
||||
) {
|
||||
if (vector->context == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTEXT;
|
||||
|
||||
if (index < 0 || index >= vector->count)
|
||||
return CONTAINER_ERROR_OUT_OF_BOUNDS;
|
||||
|
||||
malunal_size_t offset = vector->stride * index;
|
||||
malunal_uint8_t* dest = vector->context;
|
||||
dest = dest + offset;
|
||||
|
||||
malunal_size_t window = vector->count - index;
|
||||
malunal_size_t bytes = vector->stride * window;
|
||||
malunal_uint8_t* orig = dest + vector->stride;
|
||||
memmove(dest, orig, bytes);
|
||||
vector->count--;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
container_exception_t
|
||||
vector_index_of_def_impl(
|
||||
impl_mptr_t vector,
|
||||
malunal_iptr_t element,
|
||||
malunal_size_t* outidx
|
||||
) {
|
||||
if (vector->context == NULL_ADDRESS)
|
||||
return CONTAINER_ERROR_NULL_CONTEXT;
|
||||
|
||||
malunal_size_t index = 0;
|
||||
malunal_uint8_t* buffer = vector->context;
|
||||
while (index < vector->count) {
|
||||
if (memcmp(buffer, element, vector->stride) == 0) {
|
||||
*outidx = index;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
index += 1;
|
||||
buffer += vector->stride;
|
||||
}
|
||||
|
||||
*outidx = -1;
|
||||
return CONTAINER_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
container_exception_t
|
||||
vector_get(
|
||||
vector_iptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_mptr_t outptr
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)vector;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->get(vector, index, outptr)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
vector_set(
|
||||
vector_mptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)vector;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->set(vector, index, element)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
vector_insert_at(
|
||||
vector_mptr_t vector,
|
||||
malunal_size_t index,
|
||||
malunal_iptr_t element
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)vector;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->insert_at(vector, index, element)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
vector_remove_at(
|
||||
vector_mptr_t vector,
|
||||
malunal_size_t index
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)vector;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->remove_at(vector, index)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
container_exception_t
|
||||
vector_index_of(
|
||||
vector_mptr_t vector,
|
||||
malunal_iptr_t element,
|
||||
malunal_size_t* outidx
|
||||
) {
|
||||
impl_iptr_t implementation = (impl_iptr_t)vector;
|
||||
return implementation != NULL_ADDRESS
|
||||
? implementation->vtable->index_of(vector, element, outidx)
|
||||
: CONTAINER_ERROR_NULL_CONTAINER;
|
||||
}
|
||||
|
||||
|
||||
static const
|
||||
virtual_table_t vector_vtable = {
|
||||
.initialize = (vector_initialize_pfn_t)&vector_initialize_impl,
|
||||
.finalize = (vector_finalize_pfn_t)&vector_finalize_impl,
|
||||
.clear = (vector_clear_pfn_t)&vector_clear_impl,
|
||||
.append = (vector_append_pfn_t)&vector_append_impl,
|
||||
.remove = (vector_remove_pfn_t)&vector_remove_impl,
|
||||
.contains = (vector_contains_pfn_t)&vector_contains_impl,
|
||||
.get = (vector_get_pfn_t)&vector_get_def_impl,
|
||||
.set = (vector_set_pfn_t)&vector_set_def_impl,
|
||||
.insert_at = (vector_insert_at_pfn_t)&vector_insert_at_def_impl,
|
||||
.remove_at = (vector_remove_at_pfn_t)&vector_remove_at_def_impl,
|
||||
.index_of = (vector_index_of_pfn_t)&vector_index_of_def_impl
|
||||
};
|
||||
|
||||
vector_t
|
||||
vector_container() {
|
||||
implementation_t implementation = {
|
||||
.vtable = &vector_vtable,
|
||||
.allocator = NULL_ADDRESS,
|
||||
.context = NULL_ADDRESS,
|
||||
.stride = 0,
|
||||
.count = 0,
|
||||
.capacity = 0,
|
||||
};
|
||||
|
||||
vector_t result;
|
||||
memcpy(
|
||||
&result,
|
||||
&implementation,
|
||||
sizeof(implementation_t)
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user