1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-03 13:47:25 +03:00

nwrap: Add nwrap vector memory management functions

Nwrap vectors  are just more inteligent arrays.
They can look like very simple version of
vectors from C++.

TESTS: Add nwrap_vector tests.

Signed-off-by: Robin Hack <hack.robin@gmail.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
This commit is contained in:
Robin Hack 2015-03-23 14:10:18 +01:00 committed by Michael Adam
parent 6706ee4856
commit ff65d01333

View File

@ -50,6 +50,8 @@
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
/*
* Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us
* the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
@ -477,6 +479,141 @@ struct nwrap_main {
struct nwrap_main *nwrap_main_global;
struct nwrap_main __nwrap_main_global;
/*
* VECTORS
*/
#define DEFAULT_VECTOR_CAPACITY 16
struct nwrap_vector {
void **items;
size_t count;
size_t capacity;
};
/* Macro returns pointer to first element of vector->items array.
*
* nwrap_vector is used as a memory backend which take care of
* memory allocations and other stuff like memory growing.
* nwrap_vectors should not be considered as some abstract structures.
* On this level, vectors are more handy than direct realloc/malloc
* calls.
*
* nwrap_vector->items is array inside nwrap_vector which can be
* directly pointed by libc structure assembled by cwrap itself.
*
* EXAMPLE:
*
* 1) struct hostent contains char **h_addr_list element.
* 2) nwrap_vector holds array of pointers to addresses.
* It's easier to use vector to store results of
* file parsing etc.
*
* Now, pretend that cwrap assembled struct hostent and
* we need to set h_addr_list to point to nwrap_vector.
* Idea behind is to shield users from internal nwrap_vector
* implementation.
* (Yes, not fully - array terminated by NULL is needed because
* it's result expected by libc function caller.)
*
*
* CODE EXAMPLE:
*
* struct hostent he;
* struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
* ... don't care about failed allocation now ...
*
* ... fill nwrap vector ...
*
* struct hostent he;
* he.h_addr_list = nwrap_vector_head(vector);
*
*/
#define nwrap_vector_head(vect) ((void *)((vect)->items))
#define nwrap_vector_foreach(item, vect, iter) \
for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
item != NULL; \
(item) = (vect).items[++iter])
static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
{
if (vector == NULL) {
return false;
}
/* count is initialized by ZERO_STRUCTP */
ZERO_STRUCTP(vector);
vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
if (vector->items == NULL) {
return false;
}
vector->capacity = DEFAULT_VECTOR_CAPACITY;
memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
return true;
}
static bool nwrap_vector_add_item(struct nwrap_vector *cont, void *const item)
{
assert (cont != NULL);
if (cont->items == NULL) {
nwrap_vector_init(cont);
}
if (cont->count == cont->capacity) {
/* Items array _MUST_ be NULL terminated because it's passed
* as result to caller which expect NULL terminated array from libc.
*/
void **items = realloc(cont->items, sizeof(void *) * ((cont->capacity * 2) + 1));
if (items == NULL) {
return false;
}
cont->items = items;
/* Don't count ending NULL to capacity */
cont->capacity *= 2;
}
cont->items[cont->count] = item;
cont->count += 1;
cont->items[cont->count] = NULL;
return true;
}
static bool nwrap_vector_merge(struct nwrap_vector *dst,
struct nwrap_vector *src)
{
void **dst_items = NULL;
size_t count;
if (src->count == 0) {
return true;
}
count = dst->count + src->count;
/* We don't need reallocation if we have enough capacity. */
if (src->count > (dst->capacity - dst->count)) {
dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *));
if (dst_items == NULL) {
return false;
}
dst->items = dst_items;
dst->capacity = count;
}
memcpy((void *)(((long *)dst->items) + dst->count),
src->items,
src->count * sizeof(void *));
dst->count = count;
return true;
}
struct nwrap_cache {
const char *path;
int fd;