blob: f810dac17ab82bf5677fab901c5da62b3d85f19a [file] [log] [blame]
/*
* Copyright (C) Igor Sysoev
* Copyright (C) NGINX, Inc.
*/
#include <njs_main.h>
njs_arr_t *
njs_arr_create(njs_mp_t *mp, njs_uint_t n, size_t size)
{
njs_arr_t *arr;
arr = njs_mp_alloc(mp, sizeof(njs_arr_t) + n * size);
if (njs_slow_path(arr == NULL)) {
return NULL;
}
arr->start = (char *) arr + sizeof(njs_arr_t);
arr->items = 0;
arr->item_size = size;
arr->available = n;
arr->pointer = 1;
arr->separate = 1;
arr->mem_pool = mp;
return arr;
}
void *
njs_arr_init(njs_mp_t *mp, njs_arr_t *arr, void *start, njs_uint_t n,
size_t size)
{
arr->start = start;
arr->items = n;
arr->item_size = size;
arr->available = n;
arr->pointer = 0;
arr->separate = 0;
arr->mem_pool = mp;
if (arr->start == NULL) {
arr->separate = 1;
arr->items = 0;
arr->start = njs_mp_alloc(mp, n * size);
}
return arr->start;
}
void
njs_arr_destroy(njs_arr_t *arr)
{
if (arr->separate) {
njs_mp_free(arr->mem_pool, arr->start);
#if (NJS_DEBUG)
arr->start = NULL;
arr->items = 0;
arr->available = 0;
#endif
}
if (arr->pointer) {
njs_mp_free(arr->mem_pool, arr);
}
}
void *
njs_arr_add(njs_arr_t *arr)
{
return njs_arr_add_multiple(arr, 1);
}
void *
njs_arr_add_multiple(njs_arr_t *arr, njs_uint_t items)
{
void *item, *start, *old;
uint32_t n;
n = arr->available;
items += arr->items;
if (items >= n) {
if (n < 16) {
/* Allocate new arr twice as much as current. */
n *= 2;
} else {
/* Allocate new arr half as much as current. */
n += n / 2;
}
if (n < items) {
n = items;
}
start = njs_mp_alloc(arr->mem_pool, n * arr->item_size);
if (njs_slow_path(start == NULL)) {
return NULL;
}
arr->available = n;
old = arr->start;
arr->start = start;
memcpy(start, old, arr->items * arr->item_size);
if (arr->separate == 0) {
arr->separate = 1;
} else {
njs_mp_free(arr->mem_pool, old);
}
}
item = (char *) arr->start + arr->items * arr->item_size;
arr->items = items;
return item;
}
void *
njs_arr_zero_add(njs_arr_t *arr)
{
void *item;
item = njs_arr_add(arr);
if (njs_fast_path(item != NULL)) {
njs_memzero(item, arr->item_size);
}
return item;
}
void
njs_arr_remove(njs_arr_t *arr, void *item)
{
u_char *next, *last, *end;
uint32_t item_size;
item_size = arr->item_size;
end = (u_char *) arr->start + item_size * arr->items;
last = end - item_size;
if (item != last) {
next = (u_char *) item + item_size;
memmove(item, next, end - next);
}
arr->items--;
}