[util] Make plist mostly null-safe

The main purpose is to allow fluent-style:
    const char *targetname = PL_String (PL_ObjectForKey (entity, "targetname"));
    if (targetname && !PL_ObjectForKey (targets, targetname)) {
        PL_D_AddObject (targets, targetname, entity);
    }

[note: the above is iffy due to ownership of entity, but the code from
which the above comes works around the issue]
This commit is contained in:
Bill Currie 2021-03-03 18:01:35 +09:00
parent 60348ab458
commit e3762d8f38
2 changed files with 113 additions and 91 deletions

View file

@ -136,14 +136,14 @@ char *PL_WritePropertyList (const plitem_t *pl);
/** Retrieve the type of an object. /** Retrieve the type of an object.
\param item The object \param item The object. Must not be null.
\return the type of the object \return the type of the object
*/ */
pltype_t PL_Type (const plitem_t *item) __attribute__((pure)); pltype_t PL_Type (const plitem_t *item) __attribute__((pure));
/** Retrieve the line number of an object. /** Retrieve the line number of an object.
\param item The object \param item The object. Must not be null.
\return the line number on which the object began, or 0 if not from a \return the line number on which the object began, or 0 if not from a
string string
*/ */
@ -152,15 +152,16 @@ int PL_Line (const plitem_t *item) __attribute__((pure));
/** Retrieve the data size from a binary object. /** Retrieve the data size from a binary object.
\param binary The binary object \param binary The binary object
\return the size in bytes of the binary object 0 if binary isn't a binary \return the size in bytes of the binary object 0 if \a binary isn't a
object. binary object (includes if \a binary is null).
*/ */
size_t PL_BinarySize (const plitem_t *binary) __attribute__((pure)); size_t PL_BinarySize (const plitem_t *binary) __attribute__((pure));
/** Retrieve the data from a binary object. /** Retrieve the data from a binary object.
\param binary The binary object \param binary The binary object
\return pointer to the actual data or NULL if binary isn't a binary object. \return pointer to the actual data or NULL if \b binary isn't a binary
object (includes if \a binary is null).
\note You are NOT responsible for freeing the returned object. It will \note You are NOT responsible for freeing the returned object. It will
be destroyed when its container is. be destroyed when its container is.
*/ */
@ -170,7 +171,7 @@ const void *PL_BinaryData (const plitem_t *binary) __attribute__((pure));
\param string The string object \param string The string object
\return pointer to the actual string value or NULL if string isn't a \return pointer to the actual string value or NULL if string isn't a
string. string (includes if \a string is null).
\note You are NOT responsible for freeing the returned object. It will \note You are NOT responsible for freeing the returned object. It will
be destroyed when its container is. be destroyed when its container is.
*/ */
@ -180,8 +181,8 @@ const char *PL_String (const plitem_t *string) __attribute__((pure));
\param dict The dictionary to retrieve a value from \param dict The dictionary to retrieve a value from
\param key The unique key associated with the value \param key The unique key associated with the value
\return the value associated with the key, or NULL if not found or dict \return the value associated with the key, or NULL if not found or \a dict
isn't a dictionary. isn't a dictionary (includes if \a dict is null).
\note You are NOT responsible for freeing the returned object. It will \note You are NOT responsible for freeing the returned object. It will
be destroyed when its container is. be destroyed when its container is.
*/ */
@ -191,8 +192,8 @@ plitem_t *PL_ObjectForKey (const plitem_t *dict, const char *key);
\param dict The Dictionary to remove the value from \param dict The Dictionary to remove the value from
\param key The unique key associated with the value to be removed \param key The unique key associated with the value to be removed
\return the value associated with the key, or NULL if not found or dict \return the value associated with the key, or NULL if not found or \a dict
isn't a dictionary. isn't a dictionary (includes if \a dict is null).
\note You are responsible for freeing the returned object. \note You are responsible for freeing the returned object.
*/ */
plitem_t *PL_RemoveObjectForKey (const plitem_t *dict, const char *key); plitem_t *PL_RemoveObjectForKey (const plitem_t *dict, const char *key);
@ -202,19 +203,18 @@ plitem_t *PL_RemoveObjectForKey (const plitem_t *dict, const char *key);
\param dict The dictionary to get the key from \param dict The dictionary to get the key from
\param index The index of the key \param index The index of the key
\return the key at the specified index, or NULL if index is out of range or \return the key at the specified index, or NULL if index is out of range or
dict is not a dictionaly dict is not a dictionary (includes if \a dict is null).
isn't an array.
\note You are NOT responsible for freeing the returned object. It will \note You are NOT responsible for freeing the returned object. It will
be destroyed when its container is. be destroyed when its container is.
*/ */
const char *PL_KeyAtIndex (const plitem_t *array, int index) __attribute__((pure)); const char *PL_KeyAtIndex (const plitem_t *dict, int index) __attribute__((pure));
/** Retrieve a value from an array object. /** Retrieve a value from an array object.
\param array The array to get the value from \param array The array to get the value from
\param index The index within the array to retrieve \param index The index within the array to retrieve
\return the value at the specified index, or NULL if index is out of range \return the value at the specified index, or NULL if \a index is out of
or array is not an array. range or \a array is not an array (includes in \a array is null).
\note You are NOT responsible for freeing the returned object. It will \note You are NOT responsible for freeing the returned object. It will
be destroyed when its container is. be destroyed when its container is.
*/ */
@ -223,7 +223,8 @@ plitem_t *PL_ObjectAtIndex (const plitem_t *array, int index) __attribute__((pur
/** Retrieve a list of all keys in a dictionary. /** Retrieve a list of all keys in a dictionary.
\param dict The dictionary to list \param dict The dictionary to list
\return an Array containing Strings or NULL if dict isn't a dictionary \return an Array containing Strings or NULL if \a dict isn't a dictionary
(includes if \a dict is null).
\note You are responsible for freeing this array. \note You are responsible for freeing this array.
*/ */
plitem_t *PL_D_AllKeys (const plitem_t *dict); plitem_t *PL_D_AllKeys (const plitem_t *dict);
@ -232,7 +233,8 @@ plitem_t *PL_D_AllKeys (const plitem_t *dict);
\param dict The dictionary to get the number of keys of. \param dict The dictionary to get the number of keys of.
\return Returns the number of keys in the dictionary. \return Returns the number of keys in the dictionary or 0 if \a dict isn't
a dictionary (includes if \a dict is null).
*/ */
int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure)); int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure));
@ -242,7 +244,8 @@ int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure));
\param key The key of the key/value pair to be added to the dictionary \param key The key of the key/value pair to be added to the dictionary
\param value The value of the key/value pair to be added to the dictionary \param value The value of the key/value pair to be added to the dictionary
\return true on success, false on failure \return true on success, false on failure (\a dict is null or not a
dictionary)
\note the dictionary becomes the owner of the value. \note the dictionary becomes the owner of the value.
*/ */
@ -253,7 +256,8 @@ qboolean PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value);
\param array The array to which the item will be added \param array The array to which the item will be added
\param item The item to be added to the array \param item The item to be added to the array
\return true on success, false on failure \return true on success, false on failure (\a array is null or not an
array)
\note the array becomes the owner of the added item. \note the array becomes the owner of the added item.
*/ */
@ -263,7 +267,8 @@ qboolean PL_A_AddObject (plitem_t *array, plitem_t *item);
\param array The array from which to get the number of objects \param array The array from which to get the number of objects
\return number of objects in the array \return number of objects in the array or 0 if \a array is null or not
an array.
*/ */
int PL_A_NumObjects (const plitem_t *array) __attribute__((pure)); int PL_A_NumObjects (const plitem_t *array) __attribute__((pure));
@ -273,7 +278,8 @@ int PL_A_NumObjects (const plitem_t *array) __attribute__((pure));
\param item The item to be added to the array \param item The item to be added to the array
\param index The location at which to insert the item into the array \param index The location at which to insert the item into the array
\return true on success, false on failure \return true on success, false on failure (\a array is null or not an
array).
\note the array becomes the owner of the added item. \note the array becomes the owner of the added item.
*/ */
@ -285,7 +291,7 @@ qboolean PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index);
\param array The array from which to remove the value \param array The array from which to remove the value
\param index The index within the array to remove \param index The index within the array to remove
\return the value associated with the index, or NULL if not found or array \return the value associated with the index, or NULL if not found or array
isn't an array. is noll or an array.
\note You are responsible for freeing the returned object. \note You are responsible for freeing the returned object.
*/ */
plitem_t *PL_RemoveObjectAtIndex (plitem_t *array, int index); plitem_t *PL_RemoveObjectAtIndex (plitem_t *array, int index);
@ -323,7 +329,7 @@ plitem_t *PL_NewString (const char *str);
/** Free a property list object. /** Free a property list object.
This function takes care of freeing any referenced property list data, so This function takes care of freeing any referenced property list data, so
call it only on top-level objects. call it only on top-level objects. Safe to call with a null argument.
\param item the property list object to be freed \param item the property list object to be freed
*/ */

View file

@ -132,11 +132,11 @@ init_quotables (void)
quotable_bitmap[*c / 8] &= ~(1 << (*c % 8)); quotable_bitmap[*c / 8] &= ~(1 << (*c % 8));
} }
static plitem_t *PL_ParsePropertyListItem (pldata_t *); static plitem_t *pl_parsepropertylistitem (pldata_t *);
static qboolean PL_SkipSpace (pldata_t *); static qboolean pl_skipspace (pldata_t *);
static char *PL_ParseQuotedString (pldata_t *); static char *pl_parsequotedstring (pldata_t *);
static char *PL_ParseUnquotedString (pldata_t *); static char *pl_parseunquotedstring (pldata_t *);
static char *PL_ParseData (pldata_t *, int *); static char *pl_parsedata (pldata_t *, int *);
static const char * static const char *
dict_get_key (const void *i, void *unused) dict_get_key (const void *i, void *unused)
@ -156,7 +156,7 @@ dict_free (void *i, void *unused)
} }
static plitem_t * static plitem_t *
PL_NewItem (pltype_t type) pl_newitem (pltype_t type)
{ {
plitem_t *item = calloc (1, sizeof (plitem_t)); plitem_t *item = calloc (1, sizeof (plitem_t));
item->type = type; item->type = type;
@ -166,7 +166,7 @@ PL_NewItem (pltype_t type)
VISIBLE plitem_t * VISIBLE plitem_t *
PL_NewDictionary (hashlink_t **hashlinks) PL_NewDictionary (hashlink_t **hashlinks)
{ {
plitem_t *item = PL_NewItem (QFDictionary); plitem_t *item = pl_newitem (QFDictionary);
pldict_t *dict = malloc (sizeof (pldict_t)); pldict_t *dict = malloc (sizeof (pldict_t));
dict->tab = Hash_NewTable (1021, dict_get_key, dict_free, NULL, hashlinks); dict->tab = Hash_NewTable (1021, dict_get_key, dict_free, NULL, hashlinks);
DARRAY_INIT (&dict->keys, 8); DARRAY_INIT (&dict->keys, 8);
@ -177,7 +177,7 @@ PL_NewDictionary (hashlink_t **hashlinks)
VISIBLE plitem_t * VISIBLE plitem_t *
PL_NewArray (void) PL_NewArray (void)
{ {
plitem_t *item = PL_NewItem (QFArray); plitem_t *item = pl_newitem (QFArray);
plarray_t *array = calloc (1, sizeof (plarray_t)); plarray_t *array = calloc (1, sizeof (plarray_t));
item->data = array; item->data = array;
return item; return item;
@ -186,7 +186,7 @@ PL_NewArray (void)
VISIBLE plitem_t * VISIBLE plitem_t *
PL_NewData (void *data, size_t size) PL_NewData (void *data, size_t size)
{ {
plitem_t *item = PL_NewItem (QFBinary); plitem_t *item = pl_newitem (QFBinary);
plbinary_t *bin = malloc (sizeof (plbinary_t)); plbinary_t *bin = malloc (sizeof (plbinary_t));
item->data = bin; item->data = bin;
bin->data = data; bin->data = data;
@ -197,7 +197,7 @@ PL_NewData (void *data, size_t size)
static plitem_t * static plitem_t *
new_string (char *str, int line) new_string (char *str, int line)
{ {
plitem_t *item = PL_NewItem (QFString); plitem_t *item = pl_newitem (QFString);
item->data = str; item->data = str;
item->line = line; item->line = line;
return item; return item;
@ -215,6 +215,9 @@ PL_Free (plitem_t *item)
pldict_t *dict; pldict_t *dict;
plarray_t *array; plarray_t *array;
if (!item) {
return;
}
switch (item->type) { switch (item->type) {
case QFDictionary: case QFDictionary:
dict = item->data; dict = item->data;
@ -252,51 +255,54 @@ PL_Free (plitem_t *item)
VISIBLE size_t VISIBLE size_t
PL_BinarySize (const plitem_t *binary) PL_BinarySize (const plitem_t *binary)
{ {
plbinary_t *bin = (plbinary_t *) binary->data; if (!binary || binary->type != QFBinary) {
if (binary->type != QFBinary)
return 0; return 0;
}
plbinary_t *bin = (plbinary_t *) binary->data;
return bin->size; return bin->size;
} }
VISIBLE const void * VISIBLE const void *
PL_BinaryData (const plitem_t *binary) PL_BinaryData (const plitem_t *binary)
{ {
plbinary_t *bin = (plbinary_t *) binary->data; if (!binary || binary->type != QFBinary) {
if (binary->type != QFBinary)
return 0; return 0;
}
plbinary_t *bin = (plbinary_t *) binary->data;
return bin->data; return bin->data;
} }
VISIBLE const char * VISIBLE const char *
PL_String (const plitem_t *string) PL_String (const plitem_t *string)
{ {
if (string->type != QFString) if (!string || string->type != QFString) {
return NULL; return NULL;
}
return string->data; return string->data;
} }
VISIBLE plitem_t * VISIBLE plitem_t *
PL_ObjectForKey (const plitem_t *item, const char *key) PL_ObjectForKey (const plitem_t *item, const char *key)
{ {
pldict_t *dict = (pldict_t *) item->data; if (!item || item->type != QFDictionary) {
dictkey_t *k;
if (item->type != QFDictionary)
return NULL; return NULL;
}
k = (dictkey_t *) Hash_Find (dict->tab, key); pldict_t *dict = (pldict_t *) item->data;
dictkey_t *k = (dictkey_t *) Hash_Find (dict->tab, key);
return k ? k->value : NULL; return k ? k->value : NULL;
} }
VISIBLE const char * VISIBLE const char *
PL_KeyAtIndex (const plitem_t *item, int index) PL_KeyAtIndex (const plitem_t *item, int index)
{ {
pldict_t *dict = (pldict_t *) item->data; if (!item || item->type != QFDictionary) {
if (item->type != QFDictionary)
return NULL; return NULL;
}
pldict_t *dict = (pldict_t *) item->data;
if (index < 0 || (size_t) index >= dict->keys.size) { if (index < 0 || (size_t) index >= dict->keys.size) {
return NULL; return NULL;
} }
@ -307,13 +313,14 @@ PL_KeyAtIndex (const plitem_t *item, int index)
VISIBLE plitem_t * VISIBLE plitem_t *
PL_RemoveObjectForKey (const plitem_t *item, const char *key) PL_RemoveObjectForKey (const plitem_t *item, const char *key)
{ {
if (!item || item->type != QFDictionary) {
return NULL;
}
pldict_t *dict = (pldict_t *) item->data; pldict_t *dict = (pldict_t *) item->data;
dictkey_t *k; dictkey_t *k;
plitem_t *value; plitem_t *value;
if (item->type != QFDictionary)
return NULL;
k = (dictkey_t *) Hash_Del (dict->tab, key); k = (dictkey_t *) Hash_Del (dict->tab, key);
if (!k) if (!k)
return NULL; return NULL;
@ -332,13 +339,14 @@ PL_RemoveObjectForKey (const plitem_t *item, const char *key)
VISIBLE plitem_t * VISIBLE plitem_t *
PL_D_AllKeys (const plitem_t *item) PL_D_AllKeys (const plitem_t *item)
{ {
if (!item || item->type != QFDictionary) {
return NULL;
}
pldict_t *dict = (pldict_t *) item->data; pldict_t *dict = (pldict_t *) item->data;
dictkey_t *current; dictkey_t *current;
plitem_t *array; plitem_t *array;
if (item->type != QFDictionary)
return NULL;
if (!(array = PL_NewArray ())) if (!(array = PL_NewArray ()))
return NULL; return NULL;
@ -353,32 +361,35 @@ PL_D_AllKeys (const plitem_t *item)
VISIBLE int VISIBLE int
PL_D_NumKeys (const plitem_t *item) PL_D_NumKeys (const plitem_t *item)
{ {
pldict_t *dict = (pldict_t *) item->data; if (!item || item->type != QFDictionary) {
if (item->type != QFDictionary)
return 0; return 0;
}
pldict_t *dict = (pldict_t *) item->data;
return Hash_NumElements (dict->tab); return Hash_NumElements (dict->tab);
} }
VISIBLE plitem_t * VISIBLE plitem_t *
PL_ObjectAtIndex (const plitem_t *array, int index) PL_ObjectAtIndex (const plitem_t *array, int index)
{ {
plarray_t *arr = (plarray_t *) array->data; if (!array || array->type != QFArray) {
if (array->type != QFArray)
return NULL; return NULL;
}
plarray_t *arr = (plarray_t *) array->data;
return index >= 0 && index < arr->numvals ? arr->values[index] : NULL; return index >= 0 && index < arr->numvals ? arr->values[index] : NULL;
} }
VISIBLE qboolean VISIBLE qboolean
PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value)
{ {
if (!item || item->type != QFDictionary || !value) {
return false;
}
pldict_t *dict = (pldict_t *) item->data; pldict_t *dict = (pldict_t *) item->data;
dictkey_t *k; dictkey_t *k;
if (item->type != QFDictionary)
return false;
if ((k = Hash_Find (dict->tab, key))) { if ((k = Hash_Find (dict->tab, key))) {
PL_Free ((plitem_t *) k->value); PL_Free ((plitem_t *) k->value);
k->value = value; k->value = value;
@ -400,10 +411,11 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value)
VISIBLE qboolean VISIBLE qboolean
PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index) PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index)
{ {
plarray_t *arr; if (!array || array->type != QFArray || !item) {
if (array->type != QFArray)
return false; return false;
}
plarray_t *arr;
arr = (plarray_t *)array->data; arr = (plarray_t *)array->data;
@ -442,20 +454,22 @@ PL_A_AddObject (plitem_t *array, plitem_t *item)
VISIBLE int VISIBLE int
PL_A_NumObjects (const plitem_t *array) PL_A_NumObjects (const plitem_t *array)
{ {
if (array->type != QFArray) if (!array || array->type != QFArray) {
return 0; return 0;
}
return ((plarray_t *) array->data)->numvals; return ((plarray_t *) array->data)->numvals;
} }
VISIBLE plitem_t * VISIBLE plitem_t *
PL_RemoveObjectAtIndex (plitem_t *array, int index) PL_RemoveObjectAtIndex (plitem_t *array, int index)
{ {
if (!array || array->type != QFArray) {
return 0;
}
plarray_t *arr; plarray_t *arr;
plitem_t *item; plitem_t *item;
if (array->type != QFArray)
return 0;
arr = (plarray_t *)array->data; arr = (plarray_t *)array->data;
if (index < 0 || index >= arr->numvals) if (index < 0 || index >= arr->numvals)
@ -472,7 +486,7 @@ PL_RemoveObjectAtIndex (plitem_t *array, int index)
} }
static qboolean static qboolean
PL_SkipSpace (pldata_t *pl) pl_skipspace (pldata_t *pl)
{ {
while (pl->pos < pl->end) { while (pl->pos < pl->end) {
char c = pl->ptr[pl->pos]; char c = pl->ptr[pl->pos];
@ -545,7 +559,7 @@ make_byte (byte h, byte l)
} }
static char * static char *
PL_ParseData (pldata_t *pl, int *len) pl_parsedata (pldata_t *pl, int *len)
{ {
unsigned start = ++pl->pos; unsigned start = ++pl->pos;
int nibbles = 0, i; int nibbles = 0, i;
@ -578,7 +592,7 @@ PL_ParseData (pldata_t *pl, int *len)
} }
static char * static char *
PL_ParseQuotedString (pldata_t *pl) pl_parsequotedstring (pldata_t *pl)
{ {
unsigned int start = ++pl->pos; unsigned int start = ++pl->pos;
unsigned int escaped = 0; unsigned int escaped = 0;
@ -731,7 +745,7 @@ PL_ParseQuotedString (pldata_t *pl)
} }
static char * static char *
PL_ParseUnquotedString (pldata_t *pl) pl_parseunquotedstring (pldata_t *pl)
{ {
unsigned int start = pl->pos; unsigned int start = pl->pos;
char *str; char *str;
@ -747,11 +761,11 @@ PL_ParseUnquotedString (pldata_t *pl)
} }
static plitem_t * static plitem_t *
PL_ParsePropertyListItem (pldata_t *pl) pl_parsepropertylistitem (pldata_t *pl)
{ {
plitem_t *item = NULL; plitem_t *item = NULL;
if (!PL_SkipSpace (pl)) if (!pl_skipspace (pl))
return NULL; return NULL;
switch (pl->ptr[pl->pos]) { switch (pl->ptr[pl->pos]) {
@ -762,16 +776,16 @@ PL_ParsePropertyListItem (pldata_t *pl)
pl->pos++; pl->pos++;
while (PL_SkipSpace (pl) && pl->ptr[pl->pos] != '}') { while (pl_skipspace (pl) && pl->ptr[pl->pos] != '}') {
plitem_t *key; plitem_t *key;
plitem_t *value; plitem_t *value;
if (!(key = PL_ParsePropertyListItem (pl))) { if (!(key = pl_parsepropertylistitem (pl))) {
PL_Free (item); PL_Free (item);
return NULL; return NULL;
} }
if (!(PL_SkipSpace (pl))) { if (!(pl_skipspace (pl))) {
PL_Free (key); PL_Free (key);
PL_Free (item); PL_Free (item);
return NULL; return NULL;
@ -793,13 +807,13 @@ PL_ParsePropertyListItem (pldata_t *pl)
pl->pos++; pl->pos++;
// If there is no value, lose the key // If there is no value, lose the key
if (!(value = PL_ParsePropertyListItem (pl))) { if (!(value = pl_parsepropertylistitem (pl))) {
PL_Free (key); PL_Free (key);
PL_Free (item); PL_Free (item);
return NULL; return NULL;
} }
if (!(PL_SkipSpace (pl))) { if (!(pl_skipspace (pl))) {
PL_Free (key); PL_Free (key);
PL_Free (value); PL_Free (value);
PL_Free (item); PL_Free (item);
@ -842,15 +856,15 @@ PL_ParsePropertyListItem (pldata_t *pl)
pl->pos++; pl->pos++;
while (PL_SkipSpace (pl) && pl->ptr[pl->pos] != ')') { while (pl_skipspace (pl) && pl->ptr[pl->pos] != ')') {
plitem_t *value; plitem_t *value;
if (!(value = PL_ParsePropertyListItem (pl))) { if (!(value = pl_parsepropertylistitem (pl))) {
PL_Free (item); PL_Free (item);
return NULL; return NULL;
} }
if (!(PL_SkipSpace (pl))) { if (!(pl_skipspace (pl))) {
PL_Free (value); PL_Free (value);
PL_Free (item); PL_Free (item);
return NULL; return NULL;
@ -879,7 +893,7 @@ PL_ParsePropertyListItem (pldata_t *pl)
case '<': { case '<': {
int len; int len;
char *str = PL_ParseData (pl, &len); char *str = pl_parsedata (pl, &len);
if (!str) { if (!str) {
return NULL; return NULL;
@ -892,7 +906,7 @@ PL_ParsePropertyListItem (pldata_t *pl)
case '"': { case '"': {
int line = pl->line; int line = pl->line;
char *str = PL_ParseQuotedString (pl); char *str = pl_parsequotedstring (pl);
if (!str) { if (!str) {
return NULL; return NULL;
@ -903,7 +917,7 @@ PL_ParsePropertyListItem (pldata_t *pl)
default: { default: {
int line = pl->line; int line = pl->line;
char *str = PL_ParseUnquotedString (pl); char *str = pl_parseunquotedstring (pl);
if (!str) { if (!str) {
return NULL; return NULL;
@ -931,7 +945,7 @@ PL_GetPropertyList (const char *string, hashlink_t **hashlinks)
pl->va_ctx = va_create_context (4); pl->va_ctx = va_create_context (4);
pl->hashlinks = hashlinks; pl->hashlinks = hashlinks;
if ((newpl = PL_ParsePropertyListItem (pl))) { if ((newpl = pl_parsepropertylistitem (pl))) {
va_destroy_context (pl->va_ctx); va_destroy_context (pl->va_ctx);
free (pl); free (pl);
return newpl; return newpl;
@ -1111,10 +1125,12 @@ PL_WritePropertyList (const plitem_t *pl)
{ {
dstring_t *dstr = dstring_newstr (); dstring_t *dstr = dstring_newstr ();
if (!quotable_bitmap[0]) if (pl) {
init_quotables (); if (!quotable_bitmap[0])
write_item (dstr, pl, 0); init_quotables ();
write_string_len (dstr, "\n", 1); write_item (dstr, pl, 0);
write_string_len (dstr, "\n", 1);
}
return dstring_freeze (dstr); return dstring_freeze (dstr);
} }