forked from github/server
smart(er) dynamic allocation of key memory.
This commit is contained in:
parent
219a3159e8
commit
ef68b8123d
|
@ -62,6 +62,16 @@ static int keys_lower_bound(int *base, int k, int l, int r) {
|
||||||
return l;
|
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) {
|
static int a_readkeys(attrib * a, void *owner, gamedata *data) {
|
||||||
int i, n, *keys;
|
int i, n, *keys;
|
||||||
|
|
||||||
|
@ -70,8 +80,7 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) {
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return AT_READ_FAIL;
|
return AT_READ_FAIL;
|
||||||
}
|
}
|
||||||
|
keys = malloc(sizeof(int)*(keys_size(n) * 2 + 1));
|
||||||
keys = malloc(sizeof(int)*(n * 2 + 1));
|
|
||||||
*keys = n;
|
*keys = n;
|
||||||
for (i = 0; i != n; ++i) {
|
for (i = 0; i != n; ++i) {
|
||||||
READ_INT(data->store, keys + i * 2 + 1);
|
READ_INT(data->store, keys + i * 2 + 1);
|
||||||
|
@ -108,8 +117,12 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) {
|
||||||
++e;
|
++e;
|
||||||
}
|
}
|
||||||
if (e != n) {
|
if (e != n) {
|
||||||
keys = realloc(keys, sizeof(int)*(2 * e + 1));
|
int sz = keys_size(n);
|
||||||
keys[0] = e;
|
if (e > sz) {
|
||||||
|
sz = keys_size(e);
|
||||||
|
keys = realloc(keys, sizeof(int)*(2 * sz + 1));
|
||||||
|
keys[0] = e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a->data.v = keys;
|
a->data.v = keys;
|
||||||
|
@ -176,9 +189,14 @@ static int *keys_update(int *base, int key, int val)
|
||||||
kv[1] = val;
|
kv[1] = val;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
int sz = keys_size(n);
|
||||||
assert(kv[0] > key);
|
assert(kv[0] > key);
|
||||||
base = realloc(base, (n * 2 + 3) * sizeof(int));
|
if (n + 1 > sz) {
|
||||||
kv = keys_get(base, l);
|
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;
|
base[0] = n + 1;
|
||||||
memmove(kv + 2, kv, 2 * sizeof(int) * (n - l));
|
memmove(kv + 2, kv, 2 * sizeof(int) * (n - l));
|
||||||
kv[0] = key;
|
kv[0] = key;
|
||||||
|
@ -186,7 +204,11 @@ static int *keys_update(int *base, int key, int val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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;
|
base[0] = n + 1;
|
||||||
kv = keys_get(base, l);
|
kv = keys_get(base, l);
|
||||||
kv[0] = key;
|
kv[0] = key;
|
||||||
|
@ -206,7 +228,8 @@ void key_set(attrib ** alist, int key, int val)
|
||||||
}
|
}
|
||||||
keys = (int *)a->data.v;
|
keys = (int *)a->data.v;
|
||||||
if (!keys) {
|
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[0] = 1;
|
||||||
keys[1] = key;
|
keys[1] = key;
|
||||||
keys[2] = val;
|
keys[2] = val;
|
||||||
|
@ -230,12 +253,9 @@ void key_unset(attrib ** alist, int key)
|
||||||
if (l < n) {
|
if (l < n) {
|
||||||
int *kv = keys_get(keys, l);
|
int *kv = keys_get(keys, l);
|
||||||
if (kv[0] == key) {
|
if (kv[0] == key) {
|
||||||
memmove(kv, kv + 2, (n - l - 1) * 2 * sizeof(int));
|
kv[1] = 0; /* do not delete, just set to 0 */
|
||||||
// TODO: realloc to smaller size?
|
|
||||||
keys[0]--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(keys[0] < 4096 && keys[0]>0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue