mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-05-05 23:41:10 +00:00
"finish" qfplist
This is an imperfect revision of history.
This commit is contained in:
parent
2a36c74120
commit
aadf6ebf6a
2 changed files with 314 additions and 69 deletions
|
@ -29,18 +29,20 @@
|
||||||
#ifndef __QF_qfplist_h_
|
#ifndef __QF_qfplist_h_
|
||||||
#define __QF_qfplist_h_
|
#define __QF_qfplist_h_
|
||||||
|
|
||||||
#include "QF/qtypes.h"
|
/** \addtogroup utils */
|
||||||
|
//@{
|
||||||
|
|
||||||
// Ugly defines for fast checking and conversion from char to number
|
/** \defgroup qfplist Property lists
|
||||||
#define inrange(ch,min,max) ((ch) >= (min) && (ch) <= (max))
|
*/
|
||||||
#define char2num(ch) \
|
//@{
|
||||||
inrange((ch), '0', '9') ? ((ch) - 0x30) \
|
|
||||||
: (inrange((ch), 'a', 'f') ? ((ch) - 0x57) : ((ch) - 0x37))
|
#include "QF/qtypes.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
There are four types of data that can be stored in a property list:
|
There are four types of data that can be stored in a property list:
|
||||||
|
|
||||||
QFDictionary A list of values, each associated with a key (a C string).
|
QFDictionary A list of values, each associated with a key (a C
|
||||||
|
string).
|
||||||
QFArray A list of indexed values
|
QFArray A list of indexed values
|
||||||
QFString A string.
|
QFString A string.
|
||||||
QFBinary Random binary data. The parser doesn't load these yet.
|
QFBinary Random binary data. The parser doesn't load these yet.
|
||||||
|
@ -64,9 +66,9 @@ inrange((ch), '0', '9') ? ((ch) - 0x30) \
|
||||||
|
|
||||||
<!-- in the following paragram, the \< and \> are just < and >. the \ is
|
<!-- in the following paragram, the \< and \> are just < and >. the \ is
|
||||||
for doxygen -->
|
for doxygen -->
|
||||||
QFBinary data (though not loaded currently) is hex-encoded and contained
|
QFBinary data is hex-encoded and contained within angle brackets, \< \>.
|
||||||
within angle brackets, \< \>. The length of the encoded data must be an even
|
The length of the encoded data must be an even number, so while \<FF00\>
|
||||||
number, so while \<FF00\> is valid, \<F00\> isn't.
|
is valid, \<F00\> isn't.
|
||||||
|
|
||||||
Property lists may contain C-style or BCPL-style comments.
|
Property lists may contain C-style or BCPL-style comments.
|
||||||
*/
|
*/
|
||||||
|
@ -111,63 +113,79 @@ typedef struct plbinary_s plbinary_t;
|
||||||
|
|
||||||
struct hashtab_s;
|
struct hashtab_s;
|
||||||
|
|
||||||
/**
|
/** Create an in-memory representation of the contents of a property list.
|
||||||
\fn plitem_t *PL_GetPropertyList (const char *string)
|
|
||||||
\brief Create an in-memory representation of the contents of a property list
|
|
||||||
|
|
||||||
\param string the saved plist, as read from a file.
|
\param string the saved plist, as read from a file.
|
||||||
|
|
||||||
\return Returns an object equivalent to the passed-in string.
|
\return Returns an object equivalent to the passed-in string.
|
||||||
You are responsible for freeing the object returned.
|
\note You are responsible for freeing the object returned.
|
||||||
*/
|
*/
|
||||||
plitem_t *PL_GetPropertyList (const char *);
|
plitem_t *PL_GetPropertyList (const char *string);
|
||||||
|
|
||||||
/**
|
/** Create a property list string from the in-memory representation.
|
||||||
\fn plitem_t *PL_ObjectForKey (plitem_t *dict, const char *key)
|
|
||||||
\brief Retrieve a value from a dictionary object.
|
\param pl the in-memory representation
|
||||||
|
\return the text representation of the property list
|
||||||
|
\note You are responsible for freeing the string returned.
|
||||||
|
*/
|
||||||
|
char *PL_WritePropertyList (plitem_t *pl);
|
||||||
|
|
||||||
|
/** Retrieve the type of an object.
|
||||||
|
|
||||||
|
\param item The object
|
||||||
|
\return the type of the object
|
||||||
|
*/
|
||||||
|
pltype_t PL_Type (plitem_t *item);
|
||||||
|
|
||||||
|
/** Retrieve a string from a string object.
|
||||||
|
|
||||||
|
\param string The string object
|
||||||
|
\return pointer to the actual string value or NULL if string isn't a
|
||||||
|
string.
|
||||||
|
\note You are NOT responsible for freeing the returned object. It will
|
||||||
|
be destroyed when its container is.
|
||||||
|
*/
|
||||||
|
const char *PL_String (plitem_t *string);
|
||||||
|
|
||||||
|
/** Retrieve a value from a dictionary object.
|
||||||
|
|
||||||
\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 You are NOT responsible for freeing the returned object. It will
|
isn't a dictionary.
|
||||||
|
\note You are NOT responsible for freeing the returned object. It will
|
||||||
be destroyed when its container is.
|
be destroyed when its container is.
|
||||||
*/
|
*/
|
||||||
plitem_t *PL_ObjectForKey (plitem_t *, const char *);
|
plitem_t *PL_ObjectForKey (plitem_t *dict, const char *key);
|
||||||
|
|
||||||
/**
|
/** Retrieve a value from an array object.
|
||||||
\fn plitem_t *PL_ObjectAtIndex (plitem_t *array, int index)
|
|
||||||
\brief 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 associated with the key, or NULL if not found or array
|
||||||
\return You are NOT responsible for freeing the returned object. It will
|
isn't an array.
|
||||||
|
\note You are NOT responsible for freeing the returned object. It will
|
||||||
be destroyed when its container is.
|
be destroyed when its container is.
|
||||||
*/
|
*/
|
||||||
plitem_t *PL_ObjectAtIndex (plitem_t *, int);
|
plitem_t *PL_ObjectAtIndex (plitem_t *array, int index);
|
||||||
|
|
||||||
/**
|
/** Retrieve a list of all keys in a dictionary.
|
||||||
\fn plitem_t *PL_D_AllKeys (plitem_t *dict)
|
|
||||||
\brief 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 Returns an Array containing Strings. You are responsible for
|
\note You are responsible for freeing this array.
|
||||||
freeing this array.
|
|
||||||
*/
|
*/
|
||||||
plitem_t *PL_D_AllKeys (plitem_t *);
|
plitem_t *PL_D_AllKeys (plitem_t *dict);
|
||||||
|
|
||||||
/**
|
/** Retrieve the number of keys in a dictionary.
|
||||||
\brief Retrieve the number of keys in a dictionalry
|
|
||||||
|
|
||||||
\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.
|
||||||
*/
|
*/
|
||||||
int PL_D_NumKeys (plitem_t *);
|
int PL_D_NumKeys (plitem_t *dict);
|
||||||
|
|
||||||
/**
|
/** Add a key/value pair to a dictionary.
|
||||||
\fn qboolean PL_D_AddObject (plitem_t *dict, plitem_t *key, plitem_t *value)
|
|
||||||
|
|
||||||
\param dict The dictionary to add the key/value pair to
|
\param dict The dictionary to add the key/value pair to
|
||||||
\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
|
||||||
|
@ -175,54 +193,54 @@ int PL_D_NumKeys (plitem_t *);
|
||||||
|
|
||||||
\return true on success, false on failure
|
\return true on success, false on failure
|
||||||
|
|
||||||
Note: the dictionary becomes the owner of both the key and
|
\note the dictionary becomes the owner of both the key and the value.
|
||||||
the value.
|
|
||||||
*/
|
*/
|
||||||
qboolean PL_D_AddObject (plitem_t *, plitem_t *, plitem_t *);
|
qboolean PL_D_AddObject (plitem_t *dict, plitem_t *key, plitem_t *value);
|
||||||
|
|
||||||
|
/** Add an item to an array.
|
||||||
|
|
||||||
/**
|
|
||||||
\fn qboolean PL_A_AddObject (plitem_t *array, plitem_t *item)
|
|
||||||
\param array The array to add the item to
|
\param array The array to add the item to
|
||||||
\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
|
||||||
|
|
||||||
Note: the array becomes the owner of the added item.
|
\note the array becomes the owner of the added item.
|
||||||
*/
|
*/
|
||||||
qboolean PL_A_AddObject (plitem_t *, plitem_t *);
|
qboolean PL_A_AddObject (plitem_t *array, plitem_t *item);
|
||||||
|
|
||||||
|
/** Retrieve the number of items in an array.
|
||||||
|
|
||||||
/**
|
|
||||||
\param array The array to get the number of objects in
|
\param array The array to get the number of objects in
|
||||||
|
|
||||||
\return number of objects in the array
|
\return number of objects in the array
|
||||||
*/
|
*/
|
||||||
int PL_A_NumObjects (plitem_t *array);
|
int PL_A_NumObjects (plitem_t *array);
|
||||||
|
|
||||||
/**
|
/** Insert an item into an array before the specified location.
|
||||||
\fn qboolean PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index)
|
|
||||||
\param array The array to add the item to
|
\param array The array to add the item to
|
||||||
\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
|
||||||
|
|
||||||
Note: the array becomes the owner of the added item.
|
\note the array becomes the owner of the added item.
|
||||||
*/
|
*/
|
||||||
qboolean PL_A_InsertObjectAtIndex (plitem_t *, plitem_t *, int);
|
qboolean PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index);
|
||||||
|
|
||||||
plitem_t *PL_NewDictionary (void);
|
plitem_t *PL_NewDictionary (void);
|
||||||
plitem_t *PL_NewArray (void);
|
plitem_t *PL_NewArray (void);
|
||||||
plitem_t *PL_NewData (void *, int);
|
plitem_t *PL_NewData (void *, int);
|
||||||
plitem_t *PL_NewString (const char *);
|
plitem_t *PL_NewString (const char *);
|
||||||
|
|
||||||
/**
|
/** Free a property list object.
|
||||||
\fn void PL_Free (plitem_t *object)
|
|
||||||
\brief 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
|
||||||
only call it on top-level objects.
|
only call it on top-level objects.
|
||||||
|
|
||||||
|
\param item the property list object to be freed
|
||||||
*/
|
*/
|
||||||
void PL_Free (plitem_t *);
|
void PL_Free (plitem_t *item);
|
||||||
|
|
||||||
typedef struct pldata_s { // Unparsed property list string
|
typedef struct pldata_s { // Unparsed property list string
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
|
@ -232,12 +250,7 @@ typedef struct pldata_s { // Unparsed property list string
|
||||||
const char *error;
|
const char *error;
|
||||||
} pldata_t;
|
} pldata_t;
|
||||||
|
|
||||||
/*
|
//@}
|
||||||
Internal prototypes
|
//@}
|
||||||
|
|
||||||
static plist_t *PL_ParsePropertyList (pldata_t *);
|
|
||||||
static qboolean PL_SkipSpace (pldata_t *);
|
|
||||||
static char *PL_ParseQuotedString (pldata_t *);
|
|
||||||
static char *PL_ParseUnquotedString (pldata_t *);
|
|
||||||
*/
|
|
||||||
#endif // __QF_qfplist_h_
|
#endif // __QF_qfplist_h_
|
||||||
|
|
|
@ -35,15 +35,41 @@ static __attribute__ ((unused)) const char rcsid[] =
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "QF/dstring.h"
|
||||||
#include "QF/hash.h"
|
#include "QF/hash.h"
|
||||||
#include "QF/qfplist.h"
|
#include "QF/qfplist.h"
|
||||||
#include "QF/qtypes.h"
|
#include "QF/qtypes.h"
|
||||||
#include "QF/sys.h"
|
#include "QF/sys.h"
|
||||||
|
|
||||||
|
// Ugly defines for fast checking and conversion from char to number
|
||||||
|
#define inrange(ch,min,max) ((ch) >= (min) && (ch) <= (max))
|
||||||
|
#define char2num(ch) \
|
||||||
|
inrange((ch), '0', '9') ? ((ch) - 0x30) \
|
||||||
|
: (inrange((ch), 'a', 'f') ? ((ch) - 0x57) : ((ch) - 0x37))
|
||||||
|
|
||||||
|
static byte quotable_bitmap[32];
|
||||||
|
static inline int
|
||||||
|
is_quotable (byte x)
|
||||||
|
{
|
||||||
|
return quotable_bitmap[x / 8] & (1 << (x % 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_quotables (void)
|
||||||
|
{
|
||||||
|
const char *unquotables = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz!#$%&*+-./:?@|~_^";
|
||||||
|
const byte *c;
|
||||||
|
memset (quotable_bitmap, ~0, sizeof (quotable_bitmap));
|
||||||
|
for (c = unquotables; *c; c++)
|
||||||
|
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 const char *
|
static const char *
|
||||||
dict_get_key (void *i, void *unused)
|
dict_get_key (void *i, void *unused)
|
||||||
|
@ -143,6 +169,14 @@ PL_Free (plitem_t *item)
|
||||||
free (item);
|
free (item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
PL_String (plitem_t *string)
|
||||||
|
{
|
||||||
|
if (string->type != QFString)
|
||||||
|
return NULL;
|
||||||
|
return string->data;
|
||||||
|
}
|
||||||
|
|
||||||
plitem_t *
|
plitem_t *
|
||||||
PL_ObjectForKey (plitem_t *dict, const char *key)
|
PL_ObjectForKey (plitem_t *dict, const char *key)
|
||||||
{
|
{
|
||||||
|
@ -159,22 +193,23 @@ PL_ObjectForKey (plitem_t *dict, const char *key)
|
||||||
plitem_t *
|
plitem_t *
|
||||||
PL_D_AllKeys (plitem_t *dict)
|
PL_D_AllKeys (plitem_t *dict)
|
||||||
{
|
{
|
||||||
void **list;
|
void **list, **l;
|
||||||
dictkey_t *current;
|
dictkey_t *current;
|
||||||
plitem_t *array;
|
plitem_t *array;
|
||||||
|
|
||||||
if (dict->type != QFDictionary)
|
if (dict->type != QFDictionary)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(list = Hash_GetList ((hashtab_t *) dict->data)))
|
if (!(l = list = Hash_GetList ((hashtab_t *) dict->data)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(array = PL_NewArray ()))
|
if (!(array = PL_NewArray ()))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while ((current = (dictkey_t *) *list++)) {
|
while ((current = (dictkey_t *) *l++)) {
|
||||||
PL_A_AddObject (array, PL_NewString (current->key));
|
PL_A_AddObject (array, PL_NewString (current->key));
|
||||||
}
|
}
|
||||||
|
free (list);
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
@ -333,6 +368,53 @@ PL_SkipSpace (pldata_t *pl)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline byte
|
||||||
|
to_hex (byte a)
|
||||||
|
{
|
||||||
|
if (a >= '0' && a <= '9')
|
||||||
|
return a - '0';
|
||||||
|
if (a >= 'A' && a <= 'F')
|
||||||
|
return a - 'A' + 10;
|
||||||
|
return a - 'a' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline byte
|
||||||
|
make_byte (byte h, byte l)
|
||||||
|
{
|
||||||
|
return (to_hex (h) << 4) | to_hex (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
PL_ParseData (pldata_t *pl, int *len)
|
||||||
|
{
|
||||||
|
unsigned int start = ++pl->pos;
|
||||||
|
int nibbles = 0, i;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
while (pl->pos < pl->end) {
|
||||||
|
if (isxdigit (pl->ptr[pl->pos])) {
|
||||||
|
nibbles++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pl->ptr[pl->pos] == '>') {
|
||||||
|
if (nibbles & 1) {
|
||||||
|
pl->error = "invalid data, missing nibble";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*len = nibbles / 2;
|
||||||
|
str = malloc (*len);
|
||||||
|
for (i = 0; i < *len; i++)
|
||||||
|
str[i] = make_byte (pl->ptr[start + i * 2],
|
||||||
|
pl->ptr[start + i * 2 + 1]);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
pl->error = "invalid character in data";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pl->error = "Reached end of string while parsing data";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
PL_ParseQuotedString (pldata_t *pl)
|
PL_ParseQuotedString (pldata_t *pl)
|
||||||
{
|
{
|
||||||
|
@ -478,7 +560,7 @@ PL_ParseUnquotedString (pldata_t *pl)
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
while (pl->pos < pl->end) {
|
while (pl->pos < pl->end) {
|
||||||
if (!isalnum ((byte) pl->ptr[pl->pos]) && pl->ptr[pl->pos] != '_')
|
if (is_quotable (pl->ptr[pl->pos]))
|
||||||
break;
|
break;
|
||||||
pl->pos++;
|
pl->pos++;
|
||||||
}
|
}
|
||||||
|
@ -622,9 +704,16 @@ PL_ParsePropertyListItem (pldata_t *pl)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '<':
|
case '<': {
|
||||||
pl->error = "Unexpected character in string (binary data unsupported)";
|
int len;
|
||||||
|
char *str = PL_ParseData (pl, &len);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return PL_NewData (str, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case '"': {
|
case '"': {
|
||||||
char *str = PL_ParseQuotedString (pl);
|
char *str = PL_ParseQuotedString (pl);
|
||||||
|
@ -654,6 +743,9 @@ PL_GetPropertyList (const char *string)
|
||||||
pldata_t *pl = calloc (1, sizeof (pldata_t));
|
pldata_t *pl = calloc (1, sizeof (pldata_t));
|
||||||
plitem_t *newpl = NULL;
|
plitem_t *newpl = NULL;
|
||||||
|
|
||||||
|
if (!quotable_bitmap[0])
|
||||||
|
init_quotables ();
|
||||||
|
|
||||||
pl->ptr = string;
|
pl->ptr = string;
|
||||||
pl->pos = 0;
|
pl->pos = 0;
|
||||||
pl->end = strlen (string);
|
pl->end = strlen (string);
|
||||||
|
@ -670,3 +762,143 @@ PL_GetPropertyList (const char *string)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_tabs (dstring_t *dstr, int num)
|
||||||
|
{
|
||||||
|
int len = strlen (dstr->str);
|
||||||
|
|
||||||
|
dstr->size = len + num + 1;
|
||||||
|
dstring_adjust (dstr);
|
||||||
|
memset (dstr->str + len, '\t', num);
|
||||||
|
dstr->str[len + num] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_string (dstring_t *dstr, const char *str)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
for (s = str; *s && !is_quotable (*s); s++)
|
||||||
|
;
|
||||||
|
if (!*s) {
|
||||||
|
dstring_appendstr (dstr, str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dstring_appendstr (dstr, "\"");
|
||||||
|
while (*str) {
|
||||||
|
for (s = str; (*s && isascii ((byte) *s) && isprint ((byte) *s)
|
||||||
|
&& *s != '\\' && *s != '\"'); s++)
|
||||||
|
;
|
||||||
|
dstring_appendsubstr (dstr, str, s - str);
|
||||||
|
if (*s) {
|
||||||
|
switch (*s) {
|
||||||
|
case '\"':
|
||||||
|
case '\\':
|
||||||
|
c = *s;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
c = 'n';
|
||||||
|
break;
|
||||||
|
case '\a':
|
||||||
|
c = 'a';
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
c = 'b';
|
||||||
|
break;
|
||||||
|
case '\f':
|
||||||
|
c = 'f';
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
c = 'r';
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
c = 't';
|
||||||
|
break;
|
||||||
|
case '\v':
|
||||||
|
c = 'v';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c = 0;
|
||||||
|
dasprintf (dstr, "\\%03o", (byte) *s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c)
|
||||||
|
dasprintf (dstr, "\\%c", c);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
str = s;
|
||||||
|
}
|
||||||
|
dstring_appendstr (dstr, "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_item (dstring_t *dstr, plitem_t *item, int level)
|
||||||
|
{
|
||||||
|
void **list, **l;
|
||||||
|
dictkey_t *current;
|
||||||
|
plarray_t *array;
|
||||||
|
plbinary_t *binary;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
switch (item->type) {
|
||||||
|
case QFDictionary:
|
||||||
|
dstring_appendstr (dstr, "{\n");
|
||||||
|
l = list = Hash_GetList ((hashtab_t *) item->data);
|
||||||
|
while ((current = (dictkey_t *) *l++)) {
|
||||||
|
write_tabs (dstr, level + 1);
|
||||||
|
write_string (dstr, current->key);
|
||||||
|
dstring_appendstr (dstr, " = ");
|
||||||
|
write_item (dstr, current->value, level + 1);
|
||||||
|
dstring_appendstr (dstr, ";\n");
|
||||||
|
}
|
||||||
|
free (list);
|
||||||
|
write_tabs (dstr, level);
|
||||||
|
dstring_appendstr (dstr, "}");
|
||||||
|
break;
|
||||||
|
case QFArray:
|
||||||
|
dstring_appendstr (dstr, "(\n");
|
||||||
|
array = (plarray_t *) item->data;
|
||||||
|
for (i = 0; i < array->numvals; i++) {
|
||||||
|
write_tabs (dstr, level + 1);
|
||||||
|
write_item (dstr, array->values[i], level + 1);
|
||||||
|
if (i < array->numvals - 1)
|
||||||
|
dstring_appendstr (dstr, ",\n");
|
||||||
|
}
|
||||||
|
dstring_appendstr (dstr, "\n");
|
||||||
|
write_tabs (dstr, level);
|
||||||
|
dstring_appendstr (dstr, ")");
|
||||||
|
break;
|
||||||
|
case QFBinary:
|
||||||
|
dstring_appendstr (dstr, "<");
|
||||||
|
binary = (plbinary_t *) item->data;
|
||||||
|
for (i = 0; i < (int) binary->size; i++)
|
||||||
|
dasprintf (dstr, "%02X", ((char *) binary->data)[i]);
|
||||||
|
dstring_appendstr (dstr, ">");
|
||||||
|
break;
|
||||||
|
case QFString:
|
||||||
|
write_string (dstr, item->data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
PL_WritePropertyList (plitem_t *pl)
|
||||||
|
{
|
||||||
|
dstring_t *dstr = dstring_newstr ();
|
||||||
|
|
||||||
|
if (!quotable_bitmap[0])
|
||||||
|
init_quotables ();
|
||||||
|
write_item (dstr, pl, 0);
|
||||||
|
dstring_appendstr (dstr, "\n");
|
||||||
|
return dstring_freeze (dstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pltype_t
|
||||||
|
PL_Type (plitem_t *item)
|
||||||
|
{
|
||||||
|
return item->type;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue