mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 22:31:05 +00:00
[plist] Add parsing for bare dictionaries and arrays
Requiring top-level {} or () for (usually) hand-written files is awkward and even a little error prone, and certainly ugly at times. With this, loaders that expect a particular format can specify the format a little more directly.
This commit is contained in:
parent
e57a06f37b
commit
ea77df2daa
4 changed files with 137 additions and 17 deletions
|
@ -143,8 +143,34 @@ typedef struct plelement_s {
|
|||
\return Returns an object equivalent to the passed-in string.
|
||||
\note You are responsible for freeing the returned object.
|
||||
*/
|
||||
plitem_t *PL_GetPropertyList (const char *string,
|
||||
struct hashctx_s **hashctx);
|
||||
plitem_t *PL_GetPropertyList (const char *string, struct hashctx_s **hashctx);
|
||||
|
||||
/** Create a property list from a bare dictionary list.
|
||||
|
||||
The input is treated as a list of dictionary key-value pairs without the
|
||||
enclosing { or }.
|
||||
|
||||
\param string dicitionary list string.
|
||||
\param hashctx Hashlink chain to use when creating dictionaries (see
|
||||
Hash_NewTable()). May be null.
|
||||
|
||||
\return Returns a dictionary object.
|
||||
\note You are responsible for freeing the returned object.
|
||||
*/
|
||||
plitem_t *PL_GetDictionary (const char *string, struct hashctx_s **hashctx);
|
||||
|
||||
/** Create a property list from a bare array list.
|
||||
|
||||
The input is treated as a list of array values without the enclosing ( or ).
|
||||
|
||||
\param string array list string.
|
||||
\param hashctx Hashlink chain to use when creating dictionaries (see
|
||||
Hash_NewTable()). May be null.
|
||||
|
||||
\return Returns an array object.
|
||||
\note You are responsible for freeing the returned object.
|
||||
*/
|
||||
plitem_t *PL_GetArray (const char *string, struct hashctx_s **hashctx);
|
||||
|
||||
/** Create a property list string from the in-memory representation.
|
||||
|
||||
|
|
|
@ -188,9 +188,9 @@ plist_retain (plist_resources_t *res, plitem_t *plitem)
|
|||
}
|
||||
|
||||
static void
|
||||
bi_PL_GetFromFile (progs_t *pr, void *_res)
|
||||
bi_pl_getfromfile (progs_t *pr, plist_resources_t *res,
|
||||
plitem_t *get (const char *, struct hashctx_s **))
|
||||
{
|
||||
plist_resources_t *res = _res;
|
||||
QFile *file = QFile_GetFile (pr, P_INT (pr, 0));
|
||||
plitem_t *plitem;
|
||||
long offset;
|
||||
|
@ -205,19 +205,61 @@ bi_PL_GetFromFile (progs_t *pr, void *_res)
|
|||
Qread (file, buf, len);
|
||||
buf[len] = 0;
|
||||
|
||||
plitem = PL_GetPropertyList (buf, pr->hashctx);
|
||||
plitem = get (buf, pr->hashctx);
|
||||
free (buf);
|
||||
|
||||
R_INT (pr) = plist_retain (res, plitem);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_pl_get (progs_t *pr, plist_resources_t *res,
|
||||
plitem_t *get (const char *, struct hashctx_s **))
|
||||
{
|
||||
plitem_t *plitem = get (P_GSTRING (pr, 0), pr->hashctx);
|
||||
|
||||
R_INT (pr) = plist_retain (res, plitem);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_PL_GetFromFile (progs_t *pr, void *_res)
|
||||
{
|
||||
plist_resources_t *res = _res;
|
||||
bi_pl_getfromfile (pr, res, PL_GetPropertyList);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_PL_GetPropertyList (progs_t *pr, void *_res)
|
||||
{
|
||||
plist_resources_t *res = _res;
|
||||
plitem_t *plitem = PL_GetPropertyList (P_GSTRING (pr, 0), pr->hashctx);
|
||||
bi_pl_get (pr, res, PL_GetPropertyList);
|
||||
}
|
||||
|
||||
R_INT (pr) = plist_retain (res, plitem);
|
||||
static void
|
||||
bi_PL_GetDictionaryFromFile (progs_t *pr, void *_res)
|
||||
{
|
||||
plist_resources_t *res = _res;
|
||||
bi_pl_getfromfile (pr, res, PL_GetDictionary);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_PL_GetDictionary (progs_t *pr, void *_res)
|
||||
{
|
||||
plist_resources_t *res = _res;
|
||||
bi_pl_get (pr, res, PL_GetDictionary);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_PL_GetArrayFromFile (progs_t *pr, void *_res)
|
||||
{
|
||||
plist_resources_t *res = _res;
|
||||
bi_pl_getfromfile (pr, res, PL_GetArray);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_PL_GetArray (progs_t *pr, void *_res)
|
||||
{
|
||||
plist_resources_t *res = _res;
|
||||
bi_pl_get (pr, res, PL_GetArray);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -481,6 +523,10 @@ plist_compare (const void *k1, const void *k2, void *unused)
|
|||
static builtin_t builtins[] = {
|
||||
bi(PL_GetFromFile, 1, p(ptr)),
|
||||
bi(PL_GetPropertyList, 1, p(string)),
|
||||
bi(PL_GetDictionary, 1, p(string)),
|
||||
bi(PL_GetDictionaryFromFile, 1, p(string)),
|
||||
bi(PL_GetArray, 1, p(string)),
|
||||
bi(PL_GetArrayFromFile, 1, p(string)),
|
||||
bi(PL_WritePropertyList, 1, p(ptr)),
|
||||
bi(PL_Type, 1, p(ptr)),
|
||||
bi(PL_Line, 1, p(ptr)),
|
||||
|
|
|
@ -936,8 +936,9 @@ pl_parsepropertylistitem (pldata_t *pl)
|
|||
}
|
||||
}
|
||||
|
||||
VISIBLE plitem_t *
|
||||
PL_GetPropertyList (const char *string, hashctx_t **hashctx)
|
||||
static plitem_t *
|
||||
pl_parseitem (const char *string, hashctx_t **hashctx,
|
||||
plitem_t *(*parse) (pldata_t *))
|
||||
{
|
||||
plitem_t *newpl = NULL;
|
||||
|
||||
|
@ -951,7 +952,7 @@ PL_GetPropertyList (const char *string, hashctx_t **hashctx)
|
|||
.hashctx = hashctx,
|
||||
};
|
||||
|
||||
if (!(newpl = pl_parsepropertylistitem (&pl))) {
|
||||
if (!(newpl = parse (&pl))) {
|
||||
if (pl.errmsg) {
|
||||
Sys_Printf ("plist: %d,%d: %s\n", pl.line, pl.pos - pl.line_start,
|
||||
pl.errmsg->str);
|
||||
|
@ -962,6 +963,57 @@ PL_GetPropertyList (const char *string, hashctx_t **hashctx)
|
|||
return newpl;
|
||||
}
|
||||
|
||||
VISIBLE plitem_t *
|
||||
PL_GetPropertyList (const char *string, hashctx_t **hashctx)
|
||||
{
|
||||
return pl_parseitem (string, hashctx, pl_parsepropertylistitem);
|
||||
}
|
||||
|
||||
|
||||
static plitem_t *
|
||||
pl_getdictionary (pldata_t *pl)
|
||||
{
|
||||
plitem_t *dict = PL_NewDictionary (pl->hashctx);
|
||||
dict->line = pl->line;
|
||||
|
||||
while (pl_skipspace (pl, 1)) {
|
||||
if (!pl_parsekeyvalue (pl, dict, 1)) {
|
||||
PL_Free (dict);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
VISIBLE plitem_t *
|
||||
PL_GetDictionary (const char *string, hashctx_t **hashctx)
|
||||
{
|
||||
return pl_parseitem (string, hashctx, pl_getdictionary);
|
||||
}
|
||||
|
||||
static plitem_t *
|
||||
pl_getarray (pldata_t *pl)
|
||||
{
|
||||
plitem_t *array = PL_NewArray ();
|
||||
array->line = pl->line;
|
||||
|
||||
while (pl_skipspace (pl, 1)) {
|
||||
if (!pl_parsevalue (pl, array, 1)) {
|
||||
PL_Free (array);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
VISIBLE plitem_t *
|
||||
PL_GetArray (const char *string, hashctx_t **hashctx)
|
||||
{
|
||||
return pl_parseitem (string, hashctx, pl_getarray);
|
||||
}
|
||||
|
||||
static void
|
||||
write_tabs (dstring_t *dstr, int num)
|
||||
{
|
||||
|
|
|
@ -700,18 +700,14 @@ qfs_load_config (void)
|
|||
goto no_config;
|
||||
|
||||
len = Qfilesize (f);
|
||||
buf = malloc (len + 3); // +3 for { } and \0
|
||||
buf = malloc (len + 1); // +1 for nul
|
||||
|
||||
Qread (f, buf + 1, len);
|
||||
Qread (f, buf, len);
|
||||
Qclose (f);
|
||||
|
||||
// convert the config file to a plist dictionary
|
||||
buf[0] = '{';
|
||||
buf[len + 1] = '}';
|
||||
buf[len + 2] = 0;
|
||||
if (qfs_gd_plist)
|
||||
PL_Free (qfs_gd_plist);
|
||||
qfs_gd_plist = PL_GetPropertyList (buf, 0);
|
||||
qfs_gd_plist = PL_GetDictionary (buf, 0);
|
||||
free (buf);
|
||||
if (qfs_gd_plist && PL_Type (qfs_gd_plist) == QFDictionary)
|
||||
return; // done
|
||||
|
|
Loading…
Reference in a new issue