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/