static int sol_vector_grow(struct sol_vector *v, uint16_t amount) { size_t new_cap, old_cap; uint16_t new_len; if (v->len > UINT16_MAX - amount) return -EOVERFLOW; new_len = v->len + amount; old_cap = align_power2(v->len); new_cap = align_power2(new_len); if (new_cap != old_cap) { void *data; int r; size_t data_size; r = sol_util_size_mul(v->elem_size, new_cap, &data_size); SOL_INT_CHECK(r, < 0, r); data = realloc(v->data, data_size); if (!data) return -ENOMEM; v->data = data; }
static void test_align_power2(void) { unsigned int i; static const struct { unsigned int input; unsigned int output; } table[] = { { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 4 }, { 4, 4 }, { 5, 8 }, { 6, 8 }, { 7, 8 }, { 8, 8 }, { 15, 16 }, { 16, 16 }, { 17, 32 }, }; for (i = 0; i < SOL_UTIL_ARRAY_SIZE(table); i++) { unsigned int actual; actual = align_power2(table[i].input); if (actual != table[i].output) { fprintf(stderr, "Error calling align_power2(%u), got %u but expected %u\n", table[i].input, actual, table[i].output); ASSERT(false); } } }
SOL_API int sol_buffer_ensure(struct sol_buffer *buf, size_t min_size) { int err; SOL_NULL_CHECK(buf, -EINVAL); if (min_size >= SIZE_MAX - nul_byte_size(buf)) return -EINVAL; if (buf->capacity >= min_size) return 0; err = sol_buffer_resize(buf, align_power2(min_size + nul_byte_size(buf))); if (err == -EPERM) return -ENOMEM; return err; }
struct ringbuf *ringbuf_new(size_t size) { struct ringbuf *ringbuf; size_t real_size; if (size < 2 || size > UINT_MAX) return NULL; /* Find the next power of two for size */ real_size = align_power2(size); ringbuf = new0(struct ringbuf, 1); ringbuf->buffer = malloc(real_size); if (!ringbuf->buffer) { free(ringbuf); return NULL; } ringbuf->size = real_size; ringbuf->in = RINGBUF_RESET; ringbuf->out = RINGBUF_RESET; return ringbuf; }