#ifndef UCS_ARRAY_H_
#define UCS_ARRAY_H_
#include <ucs/sys/compiler_def.h>
#include <ucs/sys/preprocessor.h>
BEGIN_C_DECLS
#define UCS_ARRAY_DECLARE_TYPE(_name, _index_type, _value_type) \
typedef struct { \
_value_type *buffer; \
_index_type length; \
_index_type capacity; \
} ucs_array_t(_name); \
\
typedef _value_type UCS_ARRAY_IDENTIFIER(_name, _value_type_t);
#define UCS_ARRAY_DECLARE_FUNCS(_name, _index_type, _value_type, _scope) \
\
_scope ucs_status_t \
UCS_ARRAY_IDENTIFIER(_name, _reserve)(ucs_array_t(_name) *array, \
_index_type min_capacity); \
\
_scope ucs_status_t \
UCS_ARRAY_IDENTIFIER(_name, _append)(ucs_array_t(_name) *array, \
_index_type *index_p)
#define UCS_ARRAY_DYNAMIC_INITIALIZER \
{ NULL, 0, 0 }
#define UCS_ARRAY_FIXED_INITIALIZER(_buffer, _capacity) \
{ (_buffer), 0, ucs_array_init_fixed_capacity(_capacity) }
#define UCS_ARRAY_ALLOC_ONSTACK(_name, _capacity) \
({ \
typedef UCS_ARRAY_IDENTIFIER(_name, _value_type_t) value_t; \
UCS_STATIC_ASSERT((_capacity) * sizeof(value_t) <= UCS_ALLOCA_MAX_SIZE); \
(value_t*)alloca((_capacity) * sizeof(value_t)); \
})
#define UCS_ARRAY_DEFINE_ONSTACK(_var, _name, _capacity) \
ucs_array_t(_name) _var = \
UCS_ARRAY_FIXED_INITIALIZER(UCS_ARRAY_ALLOC_ONSTACK(_name, _capacity), \
(_capacity))
#define ucs_array_t(_name) \
UCS_ARRAY_IDENTIFIER(_name, _t)
#define ucs_array_init_fixed_capacity(_capacity) \
(((_capacity) & UCS_ARRAY_CAP_MASK) | UCS_ARRAY_CAP_FLAG_FIXED)
#define ucs_array_init_dynamic(_array) \
{ \
(_array)->buffer = NULL; \
(_array)->length = 0; \
(_array)->capacity = 0; \
}
#define ucs_array_init_fixed(_array, _buffer, _capacity) \
{ \
(_array)->buffer = (_buffer); \
(_array)->length = 0; \
(_array)->capacity = ucs_array_init_fixed_capacity(_capacity); \
}
#define ucs_array_cleanup_dynamic(_array) \
{ \
ucs_assert(!ucs_array_is_fixed(_array)); \
ucs_free((_array)->buffer); \
}
#define ucs_array_reserve(_name, _array, _min_capacity) \
UCS_ARRAY_IDENTIFIER(_name, _reserve)(_array, _min_capacity)
#define ucs_array_append(_name, _array) \
UCS_ARRAY_IDENTIFIER(_name, _append)(_array)
#define ucs_array_length(_array) \
((_array)->length)
#define ucs_array_capacity(_array) \
((_array)->capacity & UCS_ARRAY_CAP_MASK)
#define ucs_array_is_fixed(_array) \
((_array)->capacity & UCS_ARRAY_CAP_FLAG_FIXED)
#define ucs_array_elem(_array, _index) \
((_array)->buffer[_index])
#define ucs_array_is_empty(_array) \
(ucs_array_length(_array) == 0)
#define ucs_array_begin(_array) \
((_array)->buffer)
#define ucs_array_last(_array) \
((_array)->buffer + ucs_array_length(_array) - 1)
#define ucs_array_end(_array) \
((_array)->buffer + ucs_array_length(_array))
#define ucs_array_available_length(_array) \
(ucs_array_capacity(_array) - ucs_array_length(_array))
#define ucs_array_set_length(_array, _new_length) \
{ \
ucs_assertv((_new_length) <= ucs_array_capacity(_array), \
"new_length=%zu capacity=%zu", \
(size_t)(_new_length), \
(size_t)ucs_array_capacity(_array)); \
ucs_array_length(_array) = (_new_length); \
}
#define ucs_array_for_each(_elem, _array) \
for (_elem = ucs_array_begin(_array); _elem < ucs_array_end(_array); ++_elem)
#define UCS_ARRAY_CAP_FLAG_FIXED UCS_BIT(0)
#define UCS_ARRAY_CAP_MASK (~UCS_ARRAY_CAP_FLAG_FIXED)
#define UCS_ARRAY_IDENTIFIER(_name, _suffix) \
UCS_PP_TOKENPASTE(ucs_array_, UCS_PP_TOKENPASTE(_name, _suffix))
END_C_DECLS
#endif