/* * Copyright (C) Igor Sysoev * Copyright (C) NGINX, Inc. */ #include 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 = 0; 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--; }