mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-06-02 01:21:17 +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.
|
\return Returns an object equivalent to the passed-in string.
|
||||||
\note You are responsible for freeing the returned object.
|
\note You are responsible for freeing the returned object.
|
||||||
*/
|
*/
|
||||||
plitem_t *PL_GetPropertyList (const char *string,
|
plitem_t *PL_GetPropertyList (const char *string, struct hashctx_s **hashctx);
|
||||||
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.
|
/** 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
|
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));
|
QFile *file = QFile_GetFile (pr, P_INT (pr, 0));
|
||||||
plitem_t *plitem;
|
plitem_t *plitem;
|
||||||
long offset;
|
long offset;
|
||||||
|
@ -205,19 +205,61 @@ bi_PL_GetFromFile (progs_t *pr, void *_res)
|
||||||
Qread (file, buf, len);
|
Qread (file, buf, len);
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
|
|
||||||
plitem = PL_GetPropertyList (buf, pr->hashctx);
|
plitem = get (buf, pr->hashctx);
|
||||||
free (buf);
|
free (buf);
|
||||||
|
|
||||||
R_INT (pr) = plist_retain (res, plitem);
|
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
|
static void
|
||||||
bi_PL_GetPropertyList (progs_t *pr, void *_res)
|
bi_PL_GetPropertyList (progs_t *pr, void *_res)
|
||||||
{
|
{
|
||||||
plist_resources_t *res = _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
|
static void
|
||||||
|
@ -481,6 +523,10 @@ plist_compare (const void *k1, const void *k2, void *unused)
|
||||||
static builtin_t builtins[] = {
|
static builtin_t builtins[] = {
|
||||||
bi(PL_GetFromFile, 1, p(ptr)),
|
bi(PL_GetFromFile, 1, p(ptr)),
|
||||||
bi(PL_GetPropertyList, 1, p(string)),
|
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_WritePropertyList, 1, p(ptr)),
|
||||||
bi(PL_Type, 1, p(ptr)),
|
bi(PL_Type, 1, p(ptr)),
|
||||||
bi(PL_Line, 1, p(ptr)),
|
bi(PL_Line, 1, p(ptr)),
|
||||||
|
|
|
@ -936,8 +936,9 @@ pl_parsepropertylistitem (pldata_t *pl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VISIBLE plitem_t *
|
static plitem_t *
|
||||||
PL_GetPropertyList (const char *string, hashctx_t **hashctx)
|
pl_parseitem (const char *string, hashctx_t **hashctx,
|
||||||
|
plitem_t *(*parse) (pldata_t *))
|
||||||
{
|
{
|
||||||
plitem_t *newpl = NULL;
|
plitem_t *newpl = NULL;
|
||||||
|
|
||||||
|
@ -951,7 +952,7 @@ PL_GetPropertyList (const char *string, hashctx_t **hashctx)
|
||||||
.hashctx = hashctx,
|
.hashctx = hashctx,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(newpl = pl_parsepropertylistitem (&pl))) {
|
if (!(newpl = parse (&pl))) {
|
||||||
if (pl.errmsg) {
|
if (pl.errmsg) {
|
||||||
Sys_Printf ("plist: %d,%d: %s\n", pl.line, pl.pos - pl.line_start,
|
Sys_Printf ("plist: %d,%d: %s\n", pl.line, pl.pos - pl.line_start,
|
||||||
pl.errmsg->str);
|
pl.errmsg->str);
|
||||||
|
@ -962,6 +963,57 @@ PL_GetPropertyList (const char *string, hashctx_t **hashctx)
|
||||||
return newpl;
|
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
|
static void
|
||||||
write_tabs (dstring_t *dstr, int num)
|
write_tabs (dstring_t *dstr, int num)
|
||||||
{
|
{
|
||||||
|
|
|
@ -700,18 +700,14 @@ qfs_load_config (void)
|
||||||
goto no_config;
|
goto no_config;
|
||||||
|
|
||||||
len = Qfilesize (f);
|
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);
|
Qclose (f);
|
||||||
|
|
||||||
// convert the config file to a plist dictionary
|
|
||||||
buf[0] = '{';
|
|
||||||
buf[len + 1] = '}';
|
|
||||||
buf[len + 2] = 0;
|
|
||||||
if (qfs_gd_plist)
|
if (qfs_gd_plist)
|
||||||
PL_Free (qfs_gd_plist);
|
PL_Free (qfs_gd_plist);
|
||||||
qfs_gd_plist = PL_GetPropertyList (buf, 0);
|
qfs_gd_plist = PL_GetDictionary (buf, 0);
|
||||||
free (buf);
|
free (buf);
|
||||||
if (qfs_gd_plist && PL_Type (qfs_gd_plist) == QFDictionary)
|
if (qfs_gd_plist && PL_Type (qfs_gd_plist) == QFDictionary)
|
||||||
return; // done
|
return; // done
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue