summaryrefslogtreecommitdiffstats
path: root/lib/base/plist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/base/plist.cpp')
-rw-r--r--lib/base/plist.cpp1154
1 files changed, 1154 insertions, 0 deletions
diff --git a/lib/base/plist.cpp b/lib/base/plist.cpp
new file mode 100644
index 00000000..fe9d909e
--- /dev/null
+++ b/lib/base/plist.cpp
@@ -0,0 +1,1154 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * MODULE: plist.c
+ *
+ * DESCRIPTION:
+ *
+ * This module implements property lists. A property list is an
+ * ordered array of property values. Each property value has an
+ * handle for some data item, and may have a reference to
+ * another property list which describes the type of the data
+ * item. Each property value has a property index which specifies
+ * its position in the property list. A property value may also
+ * have a name. Since the data item associated with a property
+ * value may reference another property list, it is possible to
+ * construct arbitrary linked structures of property lists.
+ *
+ * IMPLEMENTATION NOTES:
+ */
+
+#include "netsite.h"
+#include "base/plist.h"
+#include "plist_pvt.h"
+
+int plistHashSizes[] = PLSTSIZES;
+
+/*
+ * FUNCTION: PListAssignValue
+ *
+ * DESCRIPTION:
+ *
+ * This function sets the value and/or type of a defined property
+ * in given property list. If the property type is specified as
+ * NULL, it is unchanged. However, the property value is always
+ * set to the specified value.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pname - the property name
+ * pvalue - the new property value
+ * ptype - the new property type, or NULL
+ *
+ * RETURNS:
+ *
+ * If successful, the property index of the referenced property is
+ * returned as the function value. Errors are indicated by a
+ * negative return code as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListAssignValue(PList_t plist, const char *pname,
+ const void *pvalue, PList_t ptype)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t *pv;
+ int pindex;
+ int i;
+
+ if (!plist) return ERRPLUNDEF;
+
+ /* Got a symbol table for this property list? */
+ if (pl->pl_symtab) {
+
+ /* Yes, compute hash of specified name */
+ i = PListHashName(pl->pl_symtab, pname);
+
+ /* Search hash collision list for matching name */
+ for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
+
+ if (!strcmp(pname, pv->pv_name)) {
+
+ /* Name match, get property index */
+ pindex = pv->pv_pi;
+
+ /* Set the new value */
+ pv->pv_value = (char *)pvalue;
+
+ /* Set type if type is given */
+ if (ptype) pv->pv_type = (PListStruct_t *)ptype;
+
+ /* Return the property index */
+ return pindex;
+ }
+ }
+ }
+
+ /* Error - specified property name is undefined */
+ return ERRPLUNDEF;
+}
+
+/*
+ * FUNCTION: PListCreate
+ *
+ * DESCRIPTION:
+ *
+ * This function creates a new property list and returns a handle for
+ * it. It allows the caller to reserve a specified number of
+ * property indices at the beginning of the list, and also to limit
+ * the total number of property values that may be added to the list.
+ *
+ * ARGUMENTS:
+ *
+ * mempool - handle for a memory pool to be associated
+ * with the new property list
+ * resvprop - number of reserved property indices
+ * maxprop - maximum number of properties in list
+ * (zero or negative imposes no limit)
+ * flags - unused, reserved, must be zero
+ *
+ * RETURNS:
+ *
+ * If successful, the function return value is a handle for the new
+ * property list. Otherwise NULL is returned.
+ */
+
+NSAPI_PUBLIC PList_t
+PListCreate(pool_handle_t *mempool, int resvprop, int maxprop, int flags)
+{
+ PListStruct_t *plist; /* pointer to property list structure */
+ int i;
+
+ plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t));
+ if (plist) {
+
+ /* Negative maxprop is the same as zero, i.e. no limit */
+ if (maxprop < 0) maxprop = 0;
+
+ /* If resvprop and maxprop are both specified, limit resvprop */
+ if (resvprop > 0) {
+ if (maxprop && (resvprop > maxprop)) resvprop = maxprop;
+ }
+ else resvprop = 0;
+
+ /* Initialize property list structure */
+ plist->pl_mempool = mempool;
+ plist->pl_symtab = NULL;
+ plist->pl_maxprop = maxprop;
+ plist->pl_resvpi = resvprop;
+ plist->pl_initpi = resvprop;
+ plist->pl_lastpi = resvprop;
+
+ /* Set initialize size for array of property value pointers */
+ plist->pl_cursize = (resvprop) ? resvprop : PLIST_DEFSIZE;
+
+ /* Allocate the initial array of property value pointers */
+ plist->pl_ppval = (pb_entry **)pool_malloc(mempool,
+ (plist->pl_cursize *
+ sizeof(PLValueStruct_t *)));
+ if (!plist->pl_ppval) {
+
+ /* Failed - insufficient memory */
+ pool_free(mempool, (void *)plist);
+ plist = NULL;
+ }
+ else {
+ /* NULL out pointers in the reserved index range, if any */
+ for (i = 0; i < plist->pl_lastpi; ++i) {
+ plist->pl_ppval[i] = 0;
+ }
+ }
+ }
+
+ return (PList_t)plist;
+}
+
+/*
+ * FUNCTION: PListDefProp
+ *
+ * DESCRIPTION:
+ *
+ * This function creates a new property in a specified property list.
+ * The 'pindex' argument may be used to request a particular property
+ * index for the new property. If 'pindex' is greater than zero,
+ * the specified value is used as the new property's index, provided
+ * there is no property at that index already. If 'pindex' is zero,
+ * then the next available property index is assigned to the new
+ * property. A name may optionally be specified for the new property.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pindex - new property index (or zero)
+ * pname - new property name (or NULL)
+ *
+ * RETURNS:
+ *
+ * If successful, the index of the new property is returned as the
+ * function value. Errors are indicated by a negative return code
+ * as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListDefProp(PList_t plist, int pindex, const char *pname, const int flags)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t **ppval;
+ PLValueStruct_t *pv;
+ int cursize;
+ int i;
+ int wrapped;
+
+ if (!plist) return ERRPLUNDEF;
+
+ ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+ /* Is pindex specified? */
+ if (pindex > 0) {
+
+ /* Yes, is it in the reserved range? */
+ if (flags != PLFLG_IGN_RES && pindex > pl->pl_resvpi) {
+ /* No, error */
+ return ERRPLINVPI;
+ }
+
+ i = pindex - 1;
+
+ if (ppval[i]) {
+ /* Error - property already exists at specified index */
+ return ERRPLEXIST;
+ }
+ }
+ else {
+
+ /*
+ * Look for a free property index, starting at pl_lastpi + 1.
+ * (Note that i is the property index - 1)
+ */
+ for (wrapped = 0, i = pl->pl_lastpi; ;) {
+
+ /* Are we in an initialized part of the array? */
+ if (i < pl->pl_initpi) {
+
+ /* Yes, use this index if it's free */
+ if (ppval[i] == 0) break;
+
+ /* Otherwise step to the next one */
+ ++i;
+ }
+ else {
+
+ /* Have we reached the end yet? */
+ if (i < pl->pl_cursize) {
+
+ /*
+ * We are above the highest initialized index, but
+ * still within the allocated size. An index in
+ * this range can be used with no further checks.
+ */
+ ppval[i] = 0;
+ }
+ else {
+
+ /*
+ * It's looking like time to grow the array, but
+ * first go back and look for an unused, unreserved
+ * index that might have been freed.
+ */
+ if (!wrapped) {
+
+ i = pl->pl_resvpi;
+ wrapped = 1;
+ continue;
+ }
+
+ /*
+ * Grow the array unless there is a specified maximum
+ * size and we've reached it.
+ */
+ i = pl->pl_cursize;
+ if (pl->pl_maxprop && (i > pl->pl_maxprop)) {
+
+ /* Error - property list is full */
+ return ERRPLFULL;
+ }
+
+ /* Increase planned size of list */
+ cursize = i + PLIST_DEFGROW;
+
+ /* Reallocate the array of property value pointers */
+ ppval = (PLValueStruct_t **)pool_realloc(pl->pl_mempool,
+ (void *)ppval,
+ (cursize * sizeof(PLValueStruct_t *)));
+ if (!ppval) {
+
+ /* Error - insufficient memory */
+ return ERRPLNOMEM;
+ }
+
+ /* Initialize the first new entry and select it */
+ ppval[i] = NULL;
+ pl->pl_ppval = (pb_entry **)ppval;
+ pl->pl_cursize = cursize;
+ }
+
+ /* Update the highest initialized index value */
+ pl->pl_initpi = i + 1;
+ break;
+ }
+ }
+
+ /* Set the starting point for the next allocation */
+ pl->pl_lastpi = i + 1;
+ }
+
+ /* We have a property index (i + 1). Create a new property value */
+ pv = (PLValueStruct_t *)pool_calloc(pl->pl_mempool,
+ 1, sizeof(PLValueStruct_t));
+ if (!pv) {
+
+ /* Error - insufficient memory */
+ return ERRPLNOMEM;
+ }
+
+ pv->pv_pbentry.param = &pv->pv_pbparam;
+ pv->pv_pi = i + 1;
+ ppval[i] = pv;
+
+ /* Name the property if the name was specified */
+ if (pname) {
+
+ /* XXX Maybe should delete property if naming fails */
+ return PListNameProp(plist, i + 1, pname);
+ }
+
+ /* Return the property index of the new property */
+ return i + 1;
+}
+
+/*
+ * FUNCTION: PListDeleteProp
+ *
+ * DESCRIPTION:
+ *
+ * This function deletes a property from a specified property list.
+ * The property can be specified by its property index, using a
+ * pindex value greater than zero, or by its name, by specifying
+ * pindex as zero and pname as the property name. This does not
+ * have any effect on the data referenced by the property value,
+ * if any, nor does it have any effect on the property list that
+ * describes the property value's type, if any.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pindex - the property index, or zero
+ * pname - the property name, or NULL
+ */
+
+NSAPI_PUBLIC const void *
+PListDeleteProp(PList_t plist, int pindex, const char *pname_in)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t **ppval;
+ PLValueStruct_t **pvp;
+ PLValueStruct_t *pv = NULL;
+ int i;
+ const void *pvalue = NULL;
+ char *pname = (char *)pname_in;
+
+ if (!plist) return NULL;
+
+ ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+ /* Check for valid property index */
+ if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+ /* Get the pointer to the property structure */
+ pv = ppval[pindex - 1];
+ pname = 0;
+ if (pv) {
+ pname = pv->pv_name;
+ }
+ }
+
+ if (pname && pl->pl_symtab) {
+
+ /* Compute hash of specified property name */
+ i = PListHashName(pl->pl_symtab, pname);
+
+ /* Search hash collision list for matching name */
+ for (pvp = &pl->pl_symtab->pt_hash[i]; *pvp; pvp = &(*pvp)->pv_next) {
+
+ pv = *pvp;
+ if (!strcmp(pname, pv->pv_name)) {
+
+ /* Found it. Get its index and remove it. */
+ pindex = pv->pv_pi;
+ *pvp = pv->pv_next;
+ break;
+ }
+ }
+ }
+
+ /* Found the indicated property by index or name? */
+ if (pv) {
+
+ /* Yes, remove it from the property list */
+ ppval[pindex - 1] = NULL;
+
+ /* Free the property name, if any */
+ if (pv->pv_name) {
+ pool_free(pl->pl_mempool, (void *)(pv->pv_name));
+ }
+ pvalue = pv->pv_value;
+
+ /* Free the property */
+ pool_free(pl->pl_mempool, (void *)pv);
+ }
+ return(pvalue);
+}
+
+/*
+ * FUNCTION: PListFindValue
+ *
+ * DESCRIPTION:
+ *
+ * This function retrieves the value and type of a property with a
+ * specified property name. If the pvalue argument is non-NULL,
+ * it specifies a location in which to return the property value.
+ * Similarly, if ptype is non-NULL, it specifies where the property
+ * list describing the property type is to be returned. If a
+ * property has no value, the value returned for pvalue is NULL.
+ * If a property has no type, the value returned for ptype is NULL.
+ * A property can have a value, a type, both, or neither.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pname - pointer to property name string
+ * pvalue - property value return pointer
+ * ptype - property type return pointer
+ *
+ * RETURNS:
+ *
+ * If successful, the index of the referenced property is returned
+ * as the function value. Errors are indicated by a negative
+ * return code as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListFindValue(PList_t plist, const char *pname, void **pvalue, PList_t *ptype)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t *pv;
+ int pindex;
+ int i;
+
+ if (!plist) return ERRPLUNDEF;
+
+ /* Got a symbol table for this property list? */
+ if (pl->pl_symtab) {
+
+ /* Yes, compute hash of specified name */
+ i = PListHashName(pl->pl_symtab, pname);
+
+ /* Search hash collision list for matching name */
+ for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
+
+ if (!strcmp(pname, pv->pv_name)) {
+
+ /* Name match, get property index */
+ pindex = pv->pv_pi;
+
+ /* Return the value if requested */
+ if (pvalue) *pvalue = (void *)(pv->pv_value);
+
+ /* Return the type if requested */
+ if (ptype) *ptype = (PList_t)(pv->pv_type);
+
+ /* Return the property index */
+ return pindex;
+ }
+ }
+ }
+
+ /* Error - specified property name is undefined */
+ return ERRPLUNDEF;
+}
+
+/*
+ * FUNCTION: PListInitProp
+ *
+ * DESCRIPTION:
+ *
+ * This function combines the functions of PListDefProp() and
+ * PListSetValue(), defining a new property and assigning it an
+ * initial value and optionally a type and/or a name.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pindex - a reserved property index, or zero
+ * pname - the new property name, or NULL
+ * pvalue - the new property value
+ * ptype - the new property type, or NULL
+ *
+ * RETURNS:
+ *
+ * If successful, the property index (pindex) is returned as the
+ * function value. Errors are indicated by a negative return code
+ * as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListInitProp(PList_t plist, int pindex, const char *pname,
+ const void *pvalue, PList_t ptype)
+{
+ int rv;
+
+ if (!plist) return ERRPLUNDEF;
+
+ /* Create the property */
+ rv = PListDefProp(plist, pindex, pname, PLFLG_USE_RES);
+ if (rv > 0) {
+
+ /* If that worked, set the value and type */
+ rv = PListSetValue(plist, rv, pvalue, ptype);
+ }
+
+ return rv;
+}
+
+/*
+ * FUNCTION: PListNew
+ *
+ * DESCRIPTION:
+ *
+ * This function creates a new property list, using the specified
+ * memory pool for allocating the internal data structures used to
+ * represent it. If the mempool argument is NULL, the default
+ * memory pool is used.
+ *
+ * ARGUMENTS:
+ *
+ * mempool - handle for a memory pool to be associated
+ * with the new property list
+ *
+ * RETURNS:
+ *
+ * If successful, the function return value is a handle for the new
+ * property list. Otherwise NULL is returned.
+ */
+
+NSAPI_PUBLIC PList_t
+PListNew(pool_handle_t *mempool)
+{
+ /* Just call PListCreate with default parameters */
+ return PListCreate(mempool, 0, 0, 0);
+}
+
+/*
+ * FUNCTION: PListDestroy
+ *
+ * DESCRIPTION:
+ *
+ * This function destroys a specified property list. This means
+ * that any dynamic memory which was allocated as a result of calls
+ * to the property list API is freed to the memory pool from which
+ * it was allocated. Property value data is not freed, nor are
+ * any property lists associated with property types.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ */
+
+void
+PListDestroy(PList_t plist)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t **ppval;
+ PLValueStruct_t *pv;
+ int i;
+
+ if (!plist) return;
+
+ /* Free the property name symbol table if any */
+ if (pl->pl_symtab) {
+ pool_free(pl->pl_mempool, (void *)(pl->pl_symtab));
+ }
+
+ ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+ /* Loop over the initialized property indices */
+ for (i = 0; i < pl->pl_initpi; ++i) {
+
+ /* Got a property here? */
+ pv = ppval[i];
+ if (pv) {
+
+ /* Free the property name string if any */
+ if (pv->pv_name) {
+ pool_free(pl->pl_mempool, (void *)(pv->pv_name));
+ }
+
+ /* Free the property value structure */
+ pool_free(pl->pl_mempool, (void *)pv);
+ }
+ }
+
+ /* Free the array of pointers to property values */
+ pool_free(pl->pl_mempool, (void *)ppval);
+
+ /* Free the property list head */
+ pool_free(pl->pl_mempool, (void *)pl);
+}
+
+/*
+ * FUNCTION: PListGetValue
+ *
+ * DESCRIPTION:
+ *
+ * This function retrieves the value and type of the property with
+ * the property index given by pindex in the specified property
+ * list. The pindex argument must specify the index of a defined
+ * property. If the pvalue argument is non-NULL, it specifies a
+ * location in which to return the property value. Similarly, if
+ * ptype is non-NULL, it specifies where the property list
+ * describing the property type is to be returned. If a property
+ * has no value, the value returned for pvalue is NULL. If a
+ * property has no type, the value returned for ptype is NULL. A
+ * property can have a value, a type, both, or neither.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pindex - the property index
+ * pvalue - property value return pointer
+ * ptype - property type return pointer
+ *
+ * RETURNS:
+ *
+ * If successful, the property index (pindex) is returned as the
+ * function value. Errors are indicated by a negative return code
+ * as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListGetValue(PList_t plist, int pindex, void **pvalue, PList_t *ptype)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t **ppval;
+ PLValueStruct_t *pv;
+
+ if (!plist) return ERRPLUNDEF;
+
+ ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+ /* Check for valid property index */
+ if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+ /* Does the property exist? */
+ pv = ppval[pindex - 1];
+ if (pv) {
+
+ /* Yes, return the value if requested */
+ if (pvalue) *pvalue = (void *)(pv->pv_value);
+
+ /* Return the type if requested */
+ if (ptype) *ptype = (PList_t)(pv->pv_type);
+
+ /* Successful return */
+ return pindex;
+ }
+ }
+
+ /* Error - invalid property index or non-existent property */
+ return ERRPLINVPI;
+}
+
+/*
+ * FUNCTION: PListHashName
+ *
+ * DESCRIPTION:
+ *
+ * This function hashes a given property name for a specified
+ * symbol table. It produces a value that can be used as an
+ * index in the pt_hash array associated with the symbol table.
+ *
+ * ARGUMENTS:
+ *
+ * symtab - pointer to the symbol table
+ * pname - pointer to the property name string
+ *
+ * RETURNS:
+ *
+ * The hash index is returned as the function value.
+ */
+
+int
+PListHashName(PLSymbolTable_t *symtab, const char *pname)
+{
+ unsigned int hashval = 0; /* hash value */
+
+ while (*pname) {
+ hashval = (hashval<<5) ^ (*pname++ & 0x7f);
+ }
+
+ return hashval % PLSIZENDX(symtab->pt_sizendx);
+}
+
+/*
+ * FUNCTION: PListNameProp
+ *
+ * DESCRIPTION:
+ *
+ * This function assigns a name to a defined property with the
+ * property index, pindex. If the property has an existing name,
+ * it will be replaced with the name specified by pname.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pindex - the property index
+ * pname - the new property name
+ *
+ * RETURNS:
+ *
+ * If successful, the property index (pindex) is returned as the
+ * function value. Errors are indicated by a negative return code
+ * as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListNameProp(PList_t plist, int pindex, const char *pname)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t *pv;
+ PLSymbolTable_t *pt;
+ int i;
+
+ if (!plist) return ERRPLUNDEF;
+
+ pt = pl->pl_symtab;
+
+ /* Check for valid property index */
+ if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+ /* Does the property exist? */
+ pv = ((PLValueStruct_t **)(pl->pl_ppval))[pindex - 1];
+ if (pv) {
+
+ /* If it has a name already, unname it */
+ if (pv->pv_name) {
+ PLValueStruct_t **pvp;
+
+ /* Get hash bucket index */
+ i = PListHashName(pt, pv->pv_name);
+
+ /* Seach hash collision list for this property */
+ for (pvp = &pt->pt_hash[i];
+ *pvp; pvp = &(*pvp)->pv_next) {
+
+ if (*pvp == pv) {
+
+ /* Remove it from the list */
+ *pvp = pv->pv_next;
+ break;
+ }
+ }
+
+ /* Free the current name string */
+ pool_free(pl->pl_mempool, (void *)(pv->pv_name));
+ }
+
+ /* Got a new name? */
+ if (pname) {
+
+ /* Yes, is there a hash table? */
+ if (!pt) {
+
+ /* No, create one */
+ pt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1,
+ PLHASHSIZE(0));
+ if (!pt) {
+ return ERRPLNOMEM;
+ }
+
+ pl->pl_symtab = pt;
+ }
+ else {
+
+ /* Is it time to grow the hash table? */
+ i = PLSIZENDX(pt->pt_sizendx);
+ if ((pt->pt_sizendx < PLMAXSIZENDX) &&
+ pt->pt_nsyms >= (i + i)) {
+
+ PLSymbolTable_t *npt;
+
+ /* Yes, allocate the new table */
+ npt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1,
+ PLHASHSIZE(pt->pt_sizendx+1));
+ if (npt) {
+ PLValueStruct_t *opv;
+ PLValueStruct_t *npv;
+ int j;
+
+ npt->pt_sizendx = pt->pt_sizendx + 1;
+ npt->pt_nsyms = pt->pt_nsyms;
+
+ /* Rehash all the names into the new table */
+ for (i = 0; i < PLSIZENDX(pt->pt_sizendx); ++i) {
+ for (opv = pt->pt_hash[i]; opv; opv = npv) {
+ npv = opv->pv_next;
+ j = PListHashName(npt, opv->pv_name);
+ opv->pv_next = npt->pt_hash[j];
+ npt->pt_hash[j] = opv;
+ }
+ }
+
+ pl->pl_symtab = npt;
+
+ /* Free the old symbol table */
+ pool_free(pl->pl_mempool, (void *)pt);
+ pt = npt;
+ }
+ }
+ }
+
+ /* Duplicate the name string */
+ pv->pv_name = pool_strdup(pl->pl_mempool, (char *)pname);
+
+ /* Add name to symbol table */
+ i = PListHashName(pt, pname);
+ pv->pv_next = pt->pt_hash[i];
+ pt->pt_hash[i] = pv;
+ }
+
+ /* Successful return */
+ return pindex;
+ }
+ }
+
+ /* Error - invalid property index or non-existent property */
+ return ERRPLINVPI;
+}
+
+/*
+ * FUNCTION: PListSetType
+ *
+ * DESCRIPTION:
+ *
+ * This function sets the property type of the defined property
+ * with the property index, pindex. The property list describing
+ * the property type is specified by ptype. If ptype is NULL,
+ * the property type will be set to be undefined (NULL).
+ *
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pindex - the property index
+ * ptype - the new property type, or NULL
+ *
+ * RETURNS:
+ *
+ * If successful, the property index (pindex) is returned as the
+ * function value. Errors are indicated by a negative return code
+ * as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListSetType(PList_t plist, int pindex, PList_t ptype)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t **ppval;
+ PLValueStruct_t *pv;
+
+ if (!plist) return ERRPLUNDEF;
+
+ ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+ /* Check for valid property index */
+ if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+ /* Does the property exist? */
+ pv = ppval[pindex - 1];
+ if (pv) {
+
+ /* Yes, set the new type */
+ pv->pv_type = ptype;
+
+ /* Successful return */
+ return pindex;
+ }
+ }
+
+ /* Error - invalid property index or non-existent property */
+ return ERRPLINVPI;
+}
+
+/*
+ * FUNCTION: PListSetValue
+ *
+ * DESCRIPTION:
+ *
+ * This function sets the value and optionally the type of a
+ * defined property in a given property list. The pindex argument
+ * specifies the property index, which must be greater than zero.
+ * The ptype argument specifies a property list that describes the
+ * property type. If ptype is NULL, the property type, if any, is
+ * unchanged by this function. However, the property value is
+ * always set to the value given by pvalue.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * pindex - the property index
+ * pvalue - the new property value
+ * ptype - the new property type, or NULL
+ *
+ * RETURNS:
+ *
+ * If successful, the property index (pindex) is returned as the
+ * function value. Errors are indicated by a negative return code
+ * as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListSetValue(PList_t plist, int pindex, const void *pvalue, PList_t ptype)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t **ppval;
+ PLValueStruct_t *pv;
+
+ if (!plist) return ERRPLUNDEF;
+
+ ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+ /* Check for valid property index */
+ if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+ /* Does the property exist? */
+ pv = ppval[pindex - 1];
+ if (pv) {
+
+ /* Yes, set the new value */
+ pv->pv_value = (char *)pvalue;
+
+ /* Set type if type is given */
+ if (ptype) pv->pv_type = (PListStruct_t *)ptype;
+
+ /* Successful return */
+ return pindex;
+ }
+ }
+
+ /* Error - invalid property index or non-existent property */
+ return ERRPLINVPI;
+}
+
+/*
+ * FUNCTION: PListEnumerate
+ *
+ * DESCRIPTION:
+ *
+ * This function walks through a specified property list
+ * calling a user supplied function with the property
+ * name and value as parameters.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * user_func - handle for the user function
+ */
+
+NSAPI_PUBLIC void
+PListEnumerate(PList_t plist, PListFunc_t *user_func, void *user_data)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t **ppval;
+ PLValueStruct_t *pv;
+ int i;
+
+ if (!plist) return;
+
+ ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+ /* Loop over the initialized property indices */
+ for (i = 0; i < pl->pl_initpi; ++i) {
+
+ /* Got a property here? */
+ pv = ppval[i];
+ if (pv) {
+ (*user_func)(pv->pv_name, pv->pv_value, user_data);
+ }
+
+ }
+
+}
+
+/*
+ * FUNCTION: PListCreateDuplicate
+ *
+ * DESCRIPTION:
+ *
+ * This function creates a new property list and returns a handle for
+ * it. The source plist provides the new plists parameters.
+ *
+ * ARGUMENTS:
+ *
+ * src_plist - source plist to duplicate
+ * mempool - handle for a memory pool to be associated
+ * with the new property list, only
+ * used if flags is set to PLFLG_NEW_MPOOL
+ * flags - if PLFLG_NEW_MPOOL uses new_mempool
+ * parameter
+ *
+ * RETURNS:
+ *
+ * If successful, the function return value is a handle for the new
+ * property list. Otherwise NULL is returned.
+ */
+
+static PList_t
+PListCreateDuplicate(PList_t src_plist, pool_handle_t *new_mempool, int flags)
+{
+ PListStruct_t *plist; /* pointer to property list structure */
+ int i;
+ pool_handle_t *mempool;
+
+ mempool = (flags == PLFLG_NEW_MPOOL) ? new_mempool : src_plist->pl_mempool;
+
+ plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t));
+ if (plist) {
+
+ /* Initialize property list structure */
+ plist->pl_mempool = mempool;
+ plist->pl_symtab = NULL;
+ plist->pl_maxprop = src_plist->pl_maxprop;
+ plist->pl_resvpi = src_plist->pl_resvpi;
+ plist->pl_initpi = src_plist->pl_initpi;
+ plist->pl_lastpi = src_plist->pl_lastpi;
+
+ /* Set initialize size for array of property value pointers */
+ plist->pl_cursize = src_plist->pl_cursize;
+
+ /* Allocate the initial array of property value pointers */
+ plist->pl_ppval = (pb_entry **)pool_malloc(mempool,
+ (plist->pl_cursize *
+ sizeof(PLValueStruct_t *)));
+ if (!plist->pl_ppval) {
+
+ /* Failed - insufficient memory */
+ pool_free(mempool, (void *)plist);
+ plist = NULL;
+ }
+ else {
+ /* NULL out pointers in the reserved index range, if any */
+ for (i = 0; i < plist->pl_lastpi; ++i) {
+ plist->pl_ppval[i] = 0;
+ }
+ }
+ }
+
+ return (PList_t)plist;
+}
+
+
+/*
+ * FUNCTION: PListDuplicate
+ *
+ * DESCRIPTION:
+ *
+ * This function duplicates a specified PList_t.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ * mempool - handle for a memory pool to be associated
+ * with the new property list
+ * resvprop - number of reserved property indices
+ * maxprop - maximum number of properties in list
+ * (zero or negative imposes no limit)
+ * flags - unused, reserved, must be zero
+ *
+ * RETURNS:
+ *
+ * If successful, the function return value is a handle for the new
+ * property list. Otherwise NULL is returned.
+ */
+
+NSAPI_PUBLIC PList_t
+PListDuplicate(PList_t plist, pool_handle_t *new_mempool, int flags)
+{
+ PListStruct_t *pl = (PListStruct_t *)plist;
+ PLValueStruct_t **ppval;
+ PLValueStruct_t *pv;
+ int i;
+ int rv = 0;
+ PList_t new_plist;
+
+ if (!plist) return NULL;
+
+ new_plist = PListCreateDuplicate(plist, new_mempool, flags);
+ if (new_plist == NULL) {
+ return(NULL);
+ }
+
+ ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+ /* Loop over the initialized property indices */
+ for (i = 0; i < pl->pl_initpi; ++i) {
+
+ /* Got a property here? */
+ pv = ppval[i];
+ if (pv) {
+ /* Create the property */
+ rv = PListDefProp(new_plist, i + 1, pv->pv_name, PLFLG_IGN_RES);
+ if (rv > 0) {
+
+ /* If that worked, set the value and type */
+ rv = PListSetValue(new_plist, rv, pv->pv_value, pv->pv_type);
+ }
+
+ if ( rv <= 0 ) {
+ PListDestroy(new_plist);
+ return(NULL);
+ }
+ }
+
+ }
+
+ return(new_plist);
+}
+
+/*
+ * FUNCTION: PListGetPool
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the memory pool the PList is allocated from.
+ *
+ * ARGUMENTS:
+ *
+ * plist - handle for the property list
+ *
+ * RETURNS:
+ *
+ * The memory pool address, which can be NULL.
+ */
+
+NSAPI_PUBLIC pool_handle_t *
+PListGetPool(PList_t plist)
+{
+ if (!plist) return NULL;
+
+ return(plist->pl_mempool);
+}
+