[plist] Add functions to extend dictionaries and arrays

The idea is to make it easy (and efficient) to merge property list
items.
This commit is contained in:
Bill Currie 2023-03-15 19:47:30 +09:00
parent 5255c9c7a8
commit 654b208641
2 changed files with 105 additions and 14 deletions

View file

@ -294,6 +294,20 @@ int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure));
*/
qboolean PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value);
/** Copy contents of one dictionary into another.
The contents of \a srcDict are added to \a dstDict without affecting
\a srcDict. Any collisions in \a dstDict result in those values in
\a dstDict being replaced by the the values from \a srcDict: the new
key-value pairs override the old.
\param dstDict The dictionary to extend
\param srcDict The dictionary from which key-value pairs will be copied
\return true if values were copied, false if nothing was copied (either
dictionary is null, or not a dictionary, or if \a srcDict was empty)
*/
qboolean PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict);
/** Add an item to an array.
\param array The array to which the item will be added
@ -306,6 +320,18 @@ qboolean PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value);
*/
qboolean PL_A_AddObject (plitem_t *array, plitem_t *item);
/** Append contents of one array to another.
The contents of \a srcArray are added to \a dstArray without affecting
\a srcArray. Those values are appended to the destination array values.
\param dstArray The array to extend
\param srcArray The array from which values will be copied
\return true if values were copied, false if nothing was copied (either
array is null, or not an array, or if \a srcArray was empty)
*/
qboolean PL_A_Extend (plitem_t *dstArray, plitem_t *srcArray);
/** Retrieve the number of items in an array.
\param array The array from which to get the number of objects

View file

@ -414,7 +414,7 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value)
dictkey_t *k;
if ((k = Hash_Find (dict->tab, key))) {
value->users++;
PL_Retain (value);
PL_Release (k->value);
k->value = value;
} else {
@ -423,7 +423,7 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value)
if (!k)
return false;
value->users++;
PL_Retain (value);
k->key = strdup (key);
k->value = value;
@ -433,6 +433,60 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value)
return true;
}
VISIBLE qboolean
PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict)
{
if (!dstDict || dstDict->type != QFDictionary
|| !srcDict || srcDict->type != QFDictionary
|| ((pldict_t *) srcDict->data)->keys.size < 1) {
return false;
}
pldict_t *dst = dstDict->data;
pldict_t *src = srcDict->data;
size_t count = dst->keys.size;
DARRAY_RESIZE (&dst->keys, dst->keys.size + src->keys.size);// open space
DARRAY_RESIZE (&dst->keys, count); // put size back so it's correct
for (size_t i = 0; i < src->keys.size; i++) {
dictkey_t *key = src->keys.a[i];
dictkey_t *k;
if ((k = Hash_Find (dst->tab, key->key))) {
PL_Retain (key->value);
PL_Release (k->value);
k->value = key->value;
} else {
k = malloc (sizeof (dictkey_t));
if (!k)
return false;
PL_Retain (key->value);
k->key = strdup (key->key);
k->value = key->value;
Hash_Add (dst->tab, k);
DARRAY_APPEND (&dst->keys, k);
}
}
return true;
}
static qboolean
check_array_size (plarray_t *arr, int count)
{
if (count > arr->maxvals) {
int newmax = (count + 127) & ~127;
int size = newmax * sizeof (plitem_t *);
plitem_t **tmp = realloc (arr->values, size);
if (!tmp)
return false;
arr->maxvals = newmax;
arr->values = tmp;
}
return true;
}
VISIBLE qboolean
PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index)
{
@ -444,17 +498,8 @@ PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index)
arr = (plarray_t *)array->data;
if (arr->numvals == arr->maxvals) {
int size = (arr->maxvals + 128) * sizeof (plitem_t *);
plitem_t **tmp = realloc (arr->values, size);
if (!tmp)
if (!check_array_size (arr, arr->numvals + 1)) {
return false;
arr->maxvals += 128;
arr->values = tmp;
memset (arr->values + arr->numvals, 0,
(arr->maxvals - arr->numvals) * sizeof (plitem_t *));
}
if (index == -1)
@ -466,7 +511,7 @@ PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index)
memmove (arr->values + index + 1, arr->values + index,
(arr->numvals - index) * sizeof (plitem_t *));
item->users++;
PL_Retain (item);
arr->values[index] = item;
arr->numvals++;
return true;
@ -478,6 +523,26 @@ PL_A_AddObject (plitem_t *array, plitem_t *item)
return PL_A_InsertObjectAtIndex (array, item, -1);
}
VISIBLE qboolean
PL_A_Extend (plitem_t *dstArray, plitem_t *srcArray)
{
if (!dstArray || dstArray->type != QFArray
|| !srcArray || srcArray->type != QFArray
|| ((plarray_t *) srcArray->data)->numvals < 1) {
return false;
}
plarray_t *dst = dstArray->data;
plarray_t *src = srcArray->data;
if (!check_array_size (dst, dst->numvals + src->numvals)) {
return false;
}
for (int i = 0; i < src->numvals; i++) {
PL_Retain (src->values[i]);
dst->values[dst->numvals++] = src->values[i];
}
return true;
}
VISIBLE int
PL_A_NumObjects (const plitem_t *array)
{