} secondary;
};
+/* Variant form of struct key which doesn't contain dynamic data, used
+ * for lookups. */
+struct constkey {
+ int primary;
+ union {
+ int i;
+ const char *s;
+ } secondary;
+};
+
struct value {
union {
int intval;
char *stringval;
- Filename fileval;
- FontSpec fontval;
+ Filename *fileval;
+ FontSpec *fontval;
} u;
};
}
}
+static int conf_cmp_constkey(void *av, void *bv)
+{
+ struct key *a = (struct key *)av;
+ struct constkey *b = (struct constkey *)bv;
+
+ if (a->primary < b->primary)
+ return -1;
+ else if (a->primary > b->primary)
+ return +1;
+ switch (subkeytypes[a->primary]) {
+ case TYPE_INT:
+ if (a->secondary.i < b->secondary.i)
+ return -1;
+ else if (a->secondary.i > b->secondary.i)
+ return +1;
+ return 0;
+ case TYPE_STR:
+ return strcmp(a->secondary.s, b->secondary.s);
+ default:
+ return 0;
+ }
+}
+
/*
* Free any dynamic data items pointed to by a 'struct key'. We
* don't free the structure itself, since it's probably part of a
{
if (type == TYPE_STR)
sfree(val->u.stringval);
+ else if (type == TYPE_FILENAME)
+ filename_free(val->u.fileval);
+ else if (type == TYPE_FONT)
+ fontspec_free(val->u.fontval);
}
/*
to->u.stringval = dupstr(from->u.stringval);
break;
case TYPE_FILENAME:
- to->u.fileval = from->u.fileval;
+ to->u.fileval = filename_copy(from->u.fileval);
break;
case TYPE_FONT:
- to->u.fontval = from->u.fontval;
+ to->u.fontval = fontspec_copy(from->u.fontval);
break;
}
}
struct conf_entry *entry, *entry2;
int i;
+ conf_clear(newconf);
+
for (i = 0; (entry = index234(oldconf->tree, i)) != NULL; i++) {
entry2 = snew(struct conf_entry);
copy_key(&entry2->key, &entry->key);
char *conf_get_str_strs(Conf *conf, int primary,
char *subkeyin, char **subkeyout)
{
- struct key key;
+ struct constkey key;
struct conf_entry *entry;
assert(subkeytypes[primary] == TYPE_STR);
entry = findrel234(conf->tree, &key, NULL, REL234_GT);
} else {
key.secondary.s = "";
- entry = findrel234(conf->tree, &key, NULL, REL234_GE);
+ entry = findrel234(conf->tree, &key, conf_cmp_constkey, REL234_GE);
}
if (!entry || entry->key.primary != primary)
return NULL;
char *conf_get_str_nthstrkey(Conf *conf, int primary, int n)
{
- struct key key;
+ struct constkey key;
struct conf_entry *entry;
int index;
assert(valuetypes[primary] == TYPE_STR);
key.primary = primary;
key.secondary.s = "";
- entry = findrelpos234(conf->tree, &key, NULL, REL234_GE, &index);
+ entry = findrelpos234(conf->tree, &key, conf_cmp_constkey,
+ REL234_GE, &index);
if (!entry || entry->key.primary != primary)
return NULL;
entry = index234(conf->tree, index + n);
key.primary = primary;
entry = find234(conf->tree, &key, NULL);
assert(entry);
- return &entry->value.u.fileval;
+ return entry->value.u.fileval;
}
FontSpec *conf_get_fontspec(Conf *conf, int primary)
key.primary = primary;
entry = find234(conf->tree, &key, NULL);
assert(entry);
- return &entry->value.u.fontval;
+ return entry->value.u.fontval;
}
void conf_set_int(Conf *conf, int primary, int value)
assert(subkeytypes[primary] == TYPE_NONE);
assert(valuetypes[primary] == TYPE_FILENAME);
entry->key.primary = primary;
- entry->value.u.fileval = *value; /* structure copy */
+ entry->value.u.fileval = filename_copy(value);
conf_insert(conf, entry);
}
assert(subkeytypes[primary] == TYPE_NONE);
assert(valuetypes[primary] == TYPE_FONT);
entry->key.primary = primary;
- entry->value.u.fontval = *value; /* structure copy */
+ entry->value.u.fontval = fontspec_copy(value);
conf_insert(conf, entry);
}
size += 1 + strlen(entry->value.u.stringval);
break;
case TYPE_FILENAME:
- size += sizeof(entry->value.u.fileval);
+ size += filename_serialise(entry->value.u.fileval, NULL);
break;
case TYPE_FONT:
- size += sizeof(entry->value.u.fontval);
+ size += fontspec_serialise(entry->value.u.fontval, NULL);
break;
}
}
*data++ = 0;
break;
case TYPE_FILENAME:
- memcpy(data, &entry->value.u.fileval,
- sizeof(entry->value.u.fileval));
- data += sizeof(entry->value.u.fileval);
+ data += filename_serialise(entry->value.u.fileval, data);
break;
case TYPE_FONT:
- memcpy(data, &entry->value.u.fontval,
- sizeof(entry->value.u.fontval));
- data += sizeof(entry->value.u.fontval);
+ data += fontspec_serialise(entry->value.u.fontval, data);
break;
}
}
unsigned char *data = (unsigned char *)vdata;
unsigned char *start = data;
struct conf_entry *entry;
- int primary;
+ unsigned primary;
+ int used;
unsigned char *zero;
while (maxsize >= 4) {
primary = GET_32BIT_MSB_FIRST(data);
data += 4, maxsize -= 4;
- if ((unsigned)primary >= N_CONFIG_OPTIONS)
+ if (primary >= N_CONFIG_OPTIONS)
break;
entry = snew(struct conf_entry);
sfree(entry);
goto done;
}
- entry->key.secondary.i = GET_32BIT_MSB_FIRST(data);
+ entry->key.secondary.i = toint(GET_32BIT_MSB_FIRST(data));
data += 4, maxsize -= 4;
break;
case TYPE_STR:
sfree(entry);
goto done;
}
- entry->value.u.intval = GET_32BIT_MSB_FIRST(data);
+ entry->value.u.intval = toint(GET_32BIT_MSB_FIRST(data));
data += 4, maxsize -= 4;
break;
case TYPE_STR:
data = zero + 1;
break;
case TYPE_FILENAME:
- if (maxsize < sizeof(entry->value.u.fileval)) {
+ entry->value.u.fileval =
+ filename_deserialise(data, maxsize, &used);
+ if (!entry->value.u.fileval) {
if (subkeytypes[entry->key.primary] == TYPE_STR)
sfree(entry->key.secondary.s);
sfree(entry);
goto done;
}
- memcpy(&entry->value.u.fileval, data,
- sizeof(entry->value.u.fileval));
- data += sizeof(entry->value.u.fileval);
- maxsize -= sizeof(entry->value.u.fileval);
+ data += used;
+ maxsize -= used;
break;
case TYPE_FONT:
- if (maxsize < sizeof(entry->value.u.fontval)) {
+ entry->value.u.fontval =
+ fontspec_deserialise(data, maxsize, &used);
+ if (!entry->value.u.fontval) {
if (subkeytypes[entry->key.primary] == TYPE_STR)
sfree(entry->key.secondary.s);
sfree(entry);
goto done;
}
- memcpy(&entry->value.u.fontval, data,
- sizeof(entry->value.u.fontval));
- data += sizeof(entry->value.u.fontval);
- maxsize -= sizeof(entry->value.u.fontval);
+ data += used;
+ maxsize -= used;
break;
}
conf_insert(conf, entry);