smart(er) dynamic allocation of key memory.

This commit is contained in:
Enno Rehling 2017-08-20 17:45:03 +02:00
parent 219a3159e8
commit ef68b8123d
1 changed files with 32 additions and 12 deletions

View File

@ -62,6 +62,16 @@ static int keys_lower_bound(int *base, int k, int l, int r) {
return l;
}
static int keys_size(int n) {
/* TODO maybe use log2 from https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog */
assert(n > 0 && n <= 4096);
if (n <= 1) return 1;
if (n <= 4) return 4;
if (n <= 16) return 16;
if (n <= 256) return 256;
return 4096;
}
static int a_readkeys(attrib * a, void *owner, gamedata *data) {
int i, n, *keys;
@ -70,8 +80,7 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) {
if (n == 0) {
return AT_READ_FAIL;
}
keys = malloc(sizeof(int)*(n * 2 + 1));
keys = malloc(sizeof(int)*(keys_size(n) * 2 + 1));
*keys = n;
for (i = 0; i != n; ++i) {
READ_INT(data->store, keys + i * 2 + 1);
@ -108,10 +117,14 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) {
++e;
}
if (e != n) {
keys = realloc(keys, sizeof(int)*(2 * e + 1));
int sz = keys_size(n);
if (e > sz) {
sz = keys_size(e);
keys = realloc(keys, sizeof(int)*(2 * sz + 1));
keys[0] = e;
}
}
}
a->data.v = keys;
return AT_READ_OK;
}
@ -176,9 +189,14 @@ static int *keys_update(int *base, int key, int val)
kv[1] = val;
}
else {
int sz = keys_size(n);
assert(kv[0] > key);
base = realloc(base, (n * 2 + 3) * sizeof(int));
kv = keys_get(base, l);
if (n + 1 > sz) {
ptrdiff_t diff = kv - base;
sz = keys_size(n + 1);
base = realloc(base, (sz * 2 + 1) * sizeof(int));
kv = base + diff;
}
base[0] = n + 1;
memmove(kv + 2, kv, 2 * sizeof(int) * (n - l));
kv[0] = key;
@ -186,7 +204,11 @@ static int *keys_update(int *base, int key, int val)
}
}
else {
base = realloc(base, (n * 2 + 3) * sizeof(int));
int sz = keys_size(n);
if (n + 1 > sz) {
sz = keys_size(n + 1);
base = realloc(base, (sz * 2 + 1) * sizeof(int));
}
base[0] = n + 1;
kv = keys_get(base, l);
kv[0] = key;
@ -206,7 +228,8 @@ void key_set(attrib ** alist, int key, int val)
}
keys = (int *)a->data.v;
if (!keys) {
a->data.v = keys = malloc(3 * sizeof(int));
int sz = keys_size(1);
a->data.v = keys = malloc((2 * sz + 1) * sizeof(int));
keys[0] = 1;
keys[1] = key;
keys[2] = val;
@ -230,12 +253,9 @@ void key_unset(attrib ** alist, int key)
if (l < n) {
int *kv = keys_get(keys, l);
if (kv[0] == key) {
memmove(kv, kv + 2, (n - l - 1) * 2 * sizeof(int));
// TODO: realloc to smaller size?
keys[0]--;
kv[1] = 0; /* do not delete, just set to 0 */
}
}
assert(keys[0] < 4096 && keys[0]>0);
}
}
}