| 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/ | ||||