From c6a8829a52ae878466b9ce21ed2b4ea492d203d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Jul 2020 12:05:34 +0900 Subject: [PATCH] [util] Add code to parse a plist array to an array --- include/QF/qfplist.h | 10 +++++++++ libs/util/qfplist.c | 49 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 5d719b840..089c04856 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -99,6 +99,14 @@ typedef struct plfield_s { void *data; ///< additional data for \a parser } plfield_t; +typedef struct plelement_s { + pltype_t type; ///< the required type of the array elements + size_t stride; ///< the size of each element + void *(*alloc) (size_t size); ///< allocator for array memory + plparser_t parser; ///< custom parser function + void *data; ///< additional data for \a parser +} plelement_t; + /** Create an in-memory representation of the contents of a property list. \param string the saved plist, as read from a file. @@ -316,6 +324,8 @@ void PL_Free (plitem_t *item); */ int PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, plitem_t *messages); +int PL_ParseArray (const plfield_t *fields, const plitem_t *dict, + void *data, plitem_t *messages); ///@} diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 35f136374..6949d3e53 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1130,8 +1130,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, void **list, **l; dictkey_t *current; int result; - int (*parser) (const plfield_t *, const plitem_t *, void *, - plitem_t *); + plparser_t parser; if (dict->type != QFDictionary) { pl_message (messages, dict, "error: not a dictionary object"); @@ -1177,3 +1176,49 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, free (list); return result; } + +VISIBLE int +PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, + plitem_t *messages) +{ + int result; + plparser_t parser; + plarray_t *plarray = (plarray_t *) array->data; + plelement_t *element = (plelement_t *) field->data; + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr; + plfield_t f = { 0, 0, element->type, element->parser, element->data }; + + if (array->type != QFArray) { + pl_message (messages, array, "error: not an array object"); + return 0; + } + if (field->parser) { + parser = field->parser; + } else { + parser = pl_default_parser; + } + + arr = DARRAY_ALLOCFIXED (arr_t, plarray->numvals * element->stride, + element->alloc); + + for (int i = 0; i < plarray->numvals; i++) { + plitem_t *item = plarray->values[i]; + void *eledata = &arr->a[i * element->stride]; + + if (item->type != element->type) { + pl_message (messages, item, + "error: element %d is the wrong type" + " Got %s, expected %s", i, + pl_types[element->type], + pl_types[item->type]); + result = 0; + } else { + if (!parser (&f, item, eledata, messages)) { + result = 0; + } + } + } + *(arr_t **) data = arr; + return result; +}