113 lines
3.5 KiB
C
113 lines
3.5 KiB
C
|
/* This software is licensed by the MIT License, see LICENSE file */
|
||
|
/* Copyright © 2022 Gregory Lirent */
|
||
|
|
||
|
#include "include.h"
|
||
|
#include "../__internal/assert.h"
|
||
|
|
||
|
arr_t array_copy(const arr_t* s) {
|
||
|
arr_t x = { .mem = 0, .size = 0, .type = 0 };
|
||
|
|
||
|
if (s->size > 0) {
|
||
|
assert(!is_null(s->mem));
|
||
|
|
||
|
x.type = s->type;
|
||
|
x.size = s->size;
|
||
|
|
||
|
if (s->type >= VTYPE_STRING) {
|
||
|
void *p, *v, *e;
|
||
|
void (*init)(void*, const void*);
|
||
|
|
||
|
x.mem = p = malloc(array_allocated_nmemb(s));
|
||
|
v = s->mem;
|
||
|
e = array_end(&x);
|
||
|
|
||
|
switch (s->type) { default: abort();
|
||
|
case VTYPE_STRING: init = (void*)string_copy_init; break;
|
||
|
case VTYPE_ARRAY: init = (void*) array_copy_init; break;
|
||
|
case VTYPE_LIST: init = (void*) list_copy_init; break;
|
||
|
case VTYPE_MAP: init = (void*) map_copy_init; break;
|
||
|
case VTYPE_SET: init = (void*) vset_copy_init; break;
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
init(p, v);
|
||
|
p += vtype_size(x.type);
|
||
|
v += vtype_size(x.type);
|
||
|
} while (p < e);
|
||
|
|
||
|
} else x.mem = memndup(s->mem, array_allocated_nmemb(s));
|
||
|
}
|
||
|
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
arr_t* array_duplicate(const arr_t* s) {
|
||
|
arr_t* x = malloc(sizeof(*x));
|
||
|
|
||
|
if (s->size > 0) {
|
||
|
assert(!is_null(s->mem));
|
||
|
|
||
|
x->type = s->type;
|
||
|
x->size = s->size;
|
||
|
|
||
|
if (s->type >= VTYPE_STRING) {
|
||
|
void *p, *v, *e;
|
||
|
void (*init)(void*, const void*);
|
||
|
|
||
|
x->mem = p = malloc(array_allocated_nmemb(s));
|
||
|
v = s->mem;
|
||
|
e = array_end(x);
|
||
|
|
||
|
switch (s->type) { default: abort();
|
||
|
case VTYPE_STRING: init = (void*)string_copy_init; break;
|
||
|
case VTYPE_ARRAY: init = (void*) array_copy_init; break;
|
||
|
case VTYPE_LIST: init = (void*) list_copy_init; break;
|
||
|
case VTYPE_MAP: init = (void*) map_copy_init; break;
|
||
|
case VTYPE_SET: init = (void*) vset_copy_init; break;
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
init(p, v);
|
||
|
p += vtype_size(x->type);
|
||
|
v += vtype_size(x->type);
|
||
|
} while (p < e);
|
||
|
|
||
|
} else x->mem = memndup(s->mem, array_allocated_nmemb(s));
|
||
|
} else memset(x, 0, sizeof(*x));
|
||
|
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
void array_copy_init(arr_t* x, const arr_t* s) {
|
||
|
if (s->size > 0) {
|
||
|
assert(!is_null(s->mem));
|
||
|
|
||
|
x->type = s->type;
|
||
|
x->size = s->size;
|
||
|
|
||
|
if (s->type >= VTYPE_STRING) {
|
||
|
void *p, *v, *e;
|
||
|
void (*init)(void*, const void*);
|
||
|
|
||
|
x->mem = p = malloc(array_allocated_nmemb(s));
|
||
|
v = s->mem;
|
||
|
e = array_end(x);
|
||
|
|
||
|
switch (s->type) { default: abort();
|
||
|
case VTYPE_STRING: init = (void*)string_copy_init; break;
|
||
|
case VTYPE_ARRAY: init = (void*) array_copy_init; break;
|
||
|
case VTYPE_LIST: init = (void*) list_copy_init; break;
|
||
|
case VTYPE_MAP: init = (void*) map_copy_init; break;
|
||
|
case VTYPE_SET: init = (void*) vset_copy_init; break;
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
init(p, v);
|
||
|
p += vtype_size(x->type);
|
||
|
v += vtype_size(x->type);
|
||
|
} while (p < e);
|
||
|
|
||
|
} else x->mem = memndup(s->mem, array_allocated_nmemb(s));
|
||
|
} else memset(x, 0, sizeof(*x));
|
||
|
}
|