array.c | array.c | |||
---|---|---|---|---|
skipping to change at line 32 | skipping to change at line 32 | |||
#include <qb/qbarray.h> | #include <qb/qbarray.h> | |||
#define MAX_BIN_ELEMENTS 256 | #define MAX_BIN_ELEMENTS 256 | |||
#define MAX_BINS 256 | #define MAX_BINS 256 | |||
#define BIN_NUM_GET(_idx_) (_idx_ >> 8) | #define BIN_NUM_GET(_idx_) (_idx_ >> 8) | |||
#define ELEM_NUM_GET(_idx_) (_idx_ & 0xff) | #define ELEM_NUM_GET(_idx_) (_idx_ & 0xff) | |||
struct qb_array { | struct qb_array { | |||
void *bin[MAX_BIN_ELEMENTS]; | void *bin[MAX_BINS]; | |||
size_t max_elements; | size_t max_elements; | |||
size_t element_size; | size_t element_size; | |||
size_t num_bins; | size_t num_bins; | |||
size_t autogrow_elements; | ||||
}; | }; | |||
qb_array_t* qb_array_create(size_t max_elements, size_t element_size) | qb_array_t * | |||
qb_array_create(size_t max_elements, size_t element_size) | ||||
{ | ||||
return qb_array_create_2(max_elements, element_size, 0); | ||||
} | ||||
qb_array_t * | ||||
qb_array_create_2(size_t max_elements, size_t element_size, | ||||
size_t autogrow_elements) | ||||
{ | { | |||
int32_t i; | int32_t i; | |||
struct qb_array *a = calloc(1, sizeof(struct qb_array)); | struct qb_array *a = NULL; | |||
if (max_elements > (MAX_BIN_ELEMENTS*MAX_BINS)) { | if (max_elements > (MAX_BIN_ELEMENTS * MAX_BINS)) { | |||
errno = -EINVAL; | errno = -EINVAL; | |||
return NULL; | return NULL; | |||
} | } | |||
if (element_size < 1) { | if (element_size < 1) { | |||
errno = -EINVAL; | errno = -EINVAL; | |||
return NULL; | return NULL; | |||
} | } | |||
if (autogrow_elements > MAX_BIN_ELEMENTS) { | ||||
errno = -EINVAL; | ||||
return NULL; | ||||
} | ||||
a = calloc(1, sizeof(struct qb_array)); | ||||
if (a == NULL) { | ||||
return NULL; | ||||
} | ||||
a->element_size = element_size; | a->element_size = element_size; | |||
a->max_elements = max_elements; | a->max_elements = max_elements; | |||
a->num_bins = (max_elements / MAX_BIN_ELEMENTS) + 1; | a->num_bins = QB_MIN((max_elements / MAX_BIN_ELEMENTS) + 1, MAX_BINS | |||
); | ||||
a->autogrow_elements = autogrow_elements; | ||||
for (i = 0; i < MAX_BINS; i++) { | for (i = 0; i < MAX_BINS; i++) { | |||
if (i < a->num_bins) { | if (i < a->num_bins) { | |||
a->bin[i] = calloc(MAX_BIN_ELEMENTS, element_size); | a->bin[i] = calloc(MAX_BIN_ELEMENTS, element_size); | |||
} else { | } else { | |||
a->bin[i] = NULL; | a->bin[i] = NULL; | |||
} | } | |||
} | } | |||
return a; | return a; | |||
} | } | |||
int32_t qb_array_index(struct qb_array* a, int32_t idx, void** element_out) | int32_t | |||
qb_array_index(struct qb_array * a, int32_t idx, void **element_out) | ||||
{ | { | |||
int32_t b; | int32_t b; | |||
int32_t elem; | int32_t elem; | |||
char *bin; | char *bin; | |||
if (a == NULL || element_out == NULL) { | if (a == NULL || element_out == NULL) { | |||
return -EINVAL; | return -EINVAL; | |||
} | } | |||
if (idx >= a->max_elements || idx < 0) { | if (idx < 0) { | |||
return -EINVAL; | return -ERANGE; | |||
} | ||||
if (idx >= a->max_elements) { | ||||
elem = idx + a->autogrow_elements; | ||||
if (a->autogrow_elements == 0) { | ||||
return -ERANGE; | ||||
} else { | ||||
int32_t rc = qb_array_grow(a, elem); | ||||
if (rc != 0) { | ||||
return rc; | ||||
} | ||||
} | ||||
} | } | |||
b = BIN_NUM_GET(idx); | b = BIN_NUM_GET(idx); | |||
assert(b < a->num_bins); | assert(b < a->num_bins); | |||
elem = ELEM_NUM_GET(idx); | elem = ELEM_NUM_GET(idx); | |||
assert(elem < MAX_BIN_ELEMENTS); | assert(elem < MAX_BIN_ELEMENTS); | |||
bin = a->bin[b]; | bin = a->bin[b]; | |||
*element_out = (bin + (a->element_size * elem)); | *element_out = (bin + (a->element_size * elem)); | |||
return 0; | return 0; | |||
} | } | |||
int32_t qb_array_grow(struct qb_array* a, size_t max_elements) | size_t | |||
qb_array_num_bins_get(struct qb_array * a) | ||||
{ | ||||
if (a == NULL) { | ||||
return -EINVAL; | ||||
} | ||||
return a->num_bins; | ||||
} | ||||
size_t | ||||
qb_array_elems_per_bin_get(struct qb_array * a) | ||||
{ | ||||
if (a == NULL) { | ||||
return -EINVAL; | ||||
} | ||||
return MAX_BIN_ELEMENTS; | ||||
} | ||||
int32_t | ||||
qb_array_grow(struct qb_array * a, size_t max_elements) | ||||
{ | { | |||
int32_t i; | int32_t i; | |||
int32_t old_bins; | int32_t old_bins; | |||
if (a == NULL || max_elements > (MAX_BIN_ELEMENTS*MAX_BINS)) { | if (a == NULL || max_elements > (MAX_BIN_ELEMENTS * MAX_BINS)) { | |||
return -EINVAL; | return -EINVAL; | |||
} | } | |||
if (max_elements <= a->max_elements) { | if (max_elements <= a->max_elements) { | |||
return 0; | return 0; | |||
} | } | |||
a->max_elements = max_elements; | a->max_elements = max_elements; | |||
if (a->num_bins >= ((max_elements / MAX_BIN_ELEMENTS) + 1)) { | if (a->num_bins >= ((max_elements / MAX_BIN_ELEMENTS) + 1)) { | |||
return 0; | return 0; | |||
} | } | |||
old_bins = a->num_bins; | old_bins = a->num_bins; | |||
a->num_bins = ((max_elements / MAX_BIN_ELEMENTS) + 1); | a->num_bins = QB_MIN((max_elements / MAX_BIN_ELEMENTS) + 1, MAX_BINS ); | |||
for (i = old_bins; i < a->num_bins; i++) { | for (i = old_bins; i < a->num_bins; i++) { | |||
if (a->bin[i] == NULL) { | if (a->bin[i] == NULL) { | |||
a->bin[i] = calloc(MAX_BIN_ELEMENTS, a->element_size ); | a->bin[i] = calloc(MAX_BIN_ELEMENTS, a->element_size ); | |||
} | } | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
void qb_array_free(struct qb_array* a) | void | |||
qb_array_free(struct qb_array *a) | ||||
{ | { | |||
int32_t i; | int32_t i; | |||
for (i = 0; i < a->num_bins; i++) { | for (i = 0; i < a->num_bins; i++) { | |||
free(a->bin[i]); | free(a->bin[i]); | |||
} | } | |||
free(a); | free(a); | |||
} | } | |||
End of changes. 13 change blocks. | ||||
12 lines changed or deleted | 63 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |