plist.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /*
  42. * MODULE: plist.c
  43. *
  44. * DESCRIPTION:
  45. *
  46. * This module implements property lists. A property list is an
  47. * ordered array of property values. Each property value has an
  48. * handle for some data item, and may have a reference to
  49. * another property list which describes the type of the data
  50. * item. Each property value has a property index which specifies
  51. * its position in the property list. A property value may also
  52. * have a name. Since the data item associated with a property
  53. * value may reference another property list, it is possible to
  54. * construct arbitrary linked structures of property lists.
  55. *
  56. * IMPLEMENTATION NOTES:
  57. */
  58. #include "netsite.h"
  59. #include "base/plist.h"
  60. #include "plist_pvt.h"
  61. int plistHashSizes[] = PLSTSIZES;
  62. /*
  63. * FUNCTION: PListAssignValue
  64. *
  65. * DESCRIPTION:
  66. *
  67. * This function sets the value and/or type of a defined property
  68. * in given property list. If the property type is specified as
  69. * NULL, it is unchanged. However, the property value is always
  70. * set to the specified value.
  71. *
  72. * ARGUMENTS:
  73. *
  74. * plist - handle for the property list
  75. * pname - the property name
  76. * pvalue - the new property value
  77. * ptype - the new property type, or NULL
  78. *
  79. * RETURNS:
  80. *
  81. * If successful, the property index of the referenced property is
  82. * returned as the function value. Errors are indicated by a
  83. * negative return code as defined in plist.h.
  84. */
  85. NSAPI_PUBLIC int
  86. PListAssignValue(PList_t plist, const char *pname,
  87. const void *pvalue, PList_t ptype)
  88. {
  89. PListStruct_t *pl = (PListStruct_t *)plist;
  90. PLValueStruct_t *pv;
  91. int pindex;
  92. int i;
  93. if (!plist) return ERRPLUNDEF;
  94. /* Got a symbol table for this property list? */
  95. if (pl->pl_symtab) {
  96. /* Yes, compute hash of specified name */
  97. i = PListHashName(pl->pl_symtab, pname);
  98. /* Search hash collision list for matching name */
  99. for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
  100. if (!strcmp(pname, pv->pv_name)) {
  101. /* Name match, get property index */
  102. pindex = pv->pv_pi;
  103. /* Set the new value */
  104. pv->pv_value = (char *)pvalue;
  105. /* Set type if type is given */
  106. if (ptype) pv->pv_type = (PListStruct_t *)ptype;
  107. /* Return the property index */
  108. return pindex;
  109. }
  110. }
  111. }
  112. /* Error - specified property name is undefined */
  113. return ERRPLUNDEF;
  114. }
  115. /*
  116. * FUNCTION: PListCreate
  117. *
  118. * DESCRIPTION:
  119. *
  120. * This function creates a new property list and returns a handle for
  121. * it. It allows the caller to reserve a specified number of
  122. * property indices at the beginning of the list, and also to limit
  123. * the total number of property values that may be added to the list.
  124. *
  125. * ARGUMENTS:
  126. *
  127. * mempool - handle for a memory pool to be associated
  128. * with the new property list
  129. * resvprop - number of reserved property indices
  130. * maxprop - maximum number of properties in list
  131. * (zero or negative imposes no limit)
  132. * flags - unused, reserved, must be zero
  133. *
  134. * RETURNS:
  135. *
  136. * If successful, the function return value is a handle for the new
  137. * property list. Otherwise NULL is returned.
  138. */
  139. NSAPI_PUBLIC PList_t
  140. PListCreate(pool_handle_t *mempool, int resvprop, int maxprop, int flags)
  141. {
  142. PListStruct_t *plist; /* pointer to property list structure */
  143. int i;
  144. plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t));
  145. if (plist) {
  146. /* Negative maxprop is the same as zero, i.e. no limit */
  147. if (maxprop < 0) maxprop = 0;
  148. /* If resvprop and maxprop are both specified, limit resvprop */
  149. if (resvprop > 0) {
  150. if (maxprop && (resvprop > maxprop)) resvprop = maxprop;
  151. }
  152. else resvprop = 0;
  153. /* Initialize property list structure */
  154. plist->pl_mempool = mempool;
  155. plist->pl_symtab = NULL;
  156. plist->pl_maxprop = maxprop;
  157. plist->pl_resvpi = resvprop;
  158. plist->pl_initpi = resvprop;
  159. plist->pl_lastpi = resvprop;
  160. /* Set initialize size for array of property value pointers */
  161. plist->pl_cursize = (resvprop) ? resvprop : PLIST_DEFSIZE;
  162. /* Allocate the initial array of property value pointers */
  163. plist->pl_ppval = (pb_entry **)pool_malloc(mempool,
  164. (plist->pl_cursize *
  165. sizeof(PLValueStruct_t *)));
  166. if (!plist->pl_ppval) {
  167. /* Failed - insufficient memory */
  168. pool_free(mempool, (void *)plist);
  169. plist = NULL;
  170. }
  171. else {
  172. /* NULL out pointers in the reserved index range, if any */
  173. for (i = 0; i < plist->pl_lastpi; ++i) {
  174. plist->pl_ppval[i] = 0;
  175. }
  176. }
  177. }
  178. return (PList_t)plist;
  179. }
  180. /*
  181. * FUNCTION: PListDefProp
  182. *
  183. * DESCRIPTION:
  184. *
  185. * This function creates a new property in a specified property list.
  186. * The 'pindex' argument may be used to request a particular property
  187. * index for the new property. If 'pindex' is greater than zero,
  188. * the specified value is used as the new property's index, provided
  189. * there is no property at that index already. If 'pindex' is zero,
  190. * then the next available property index is assigned to the new
  191. * property. A name may optionally be specified for the new property.
  192. *
  193. * ARGUMENTS:
  194. *
  195. * plist - handle for the property list
  196. * pindex - new property index (or zero)
  197. * pname - new property name (or NULL)
  198. *
  199. * RETURNS:
  200. *
  201. * If successful, the index of the new property is returned as the
  202. * function value. Errors are indicated by a negative return code
  203. * as defined in plist.h.
  204. */
  205. NSAPI_PUBLIC int
  206. PListDefProp(PList_t plist, int pindex, const char *pname, const int flags)
  207. {
  208. PListStruct_t *pl = (PListStruct_t *)plist;
  209. PLValueStruct_t **ppval;
  210. PLValueStruct_t *pv;
  211. int cursize;
  212. int i;
  213. int wrapped;
  214. if (!plist) return ERRPLUNDEF;
  215. ppval = (PLValueStruct_t **)(pl->pl_ppval);
  216. /* Is pindex specified? */
  217. if (pindex > 0) {
  218. /* Yes, is it in the reserved range? */
  219. if (flags != PLFLG_IGN_RES && pindex > pl->pl_resvpi) {
  220. /* No, error */
  221. return ERRPLINVPI;
  222. }
  223. i = pindex - 1;
  224. if (ppval[i]) {
  225. /* Error - property already exists at specified index */
  226. return ERRPLEXIST;
  227. }
  228. }
  229. else {
  230. /*
  231. * Look for a free property index, starting at pl_lastpi + 1.
  232. * (Note that i is the property index - 1)
  233. */
  234. for (wrapped = 0, i = pl->pl_lastpi; ;) {
  235. /* Are we in an initialized part of the array? */
  236. if (i < pl->pl_initpi) {
  237. /* Yes, use this index if it's free */
  238. if (ppval[i] == 0) break;
  239. /* Otherwise step to the next one */
  240. ++i;
  241. }
  242. else {
  243. /* Have we reached the end yet? */
  244. if (i < pl->pl_cursize) {
  245. /*
  246. * We are above the highest initialized index, but
  247. * still within the allocated size. An index in
  248. * this range can be used with no further checks.
  249. */
  250. ppval[i] = 0;
  251. }
  252. else {
  253. /*
  254. * It's looking like time to grow the array, but
  255. * first go back and look for an unused, unreserved
  256. * index that might have been freed.
  257. */
  258. if (!wrapped) {
  259. i = pl->pl_resvpi;
  260. wrapped = 1;
  261. continue;
  262. }
  263. /*
  264. * Grow the array unless there is a specified maximum
  265. * size and we've reached it.
  266. */
  267. i = pl->pl_cursize;
  268. if (pl->pl_maxprop && (i > pl->pl_maxprop)) {
  269. /* Error - property list is full */
  270. return ERRPLFULL;
  271. }
  272. /* Increase planned size of list */
  273. cursize = i + PLIST_DEFGROW;
  274. /* Reallocate the array of property value pointers */
  275. ppval = (PLValueStruct_t **)pool_realloc(pl->pl_mempool,
  276. (void *)ppval,
  277. (cursize * sizeof(PLValueStruct_t *)));
  278. if (!ppval) {
  279. /* Error - insufficient memory */
  280. return ERRPLNOMEM;
  281. }
  282. /* Initialize the first new entry and select it */
  283. ppval[i] = NULL;
  284. pl->pl_ppval = (pb_entry **)ppval;
  285. pl->pl_cursize = cursize;
  286. }
  287. /* Update the highest initialized index value */
  288. pl->pl_initpi = i + 1;
  289. break;
  290. }
  291. }
  292. /* Set the starting point for the next allocation */
  293. pl->pl_lastpi = i + 1;
  294. }
  295. /* We have a property index (i + 1). Create a new property value */
  296. pv = (PLValueStruct_t *)pool_calloc(pl->pl_mempool,
  297. 1, sizeof(PLValueStruct_t));
  298. if (!pv) {
  299. /* Error - insufficient memory */
  300. return ERRPLNOMEM;
  301. }
  302. pv->pv_pbentry.param = &pv->pv_pbparam;
  303. pv->pv_pi = i + 1;
  304. ppval[i] = pv;
  305. /* Name the property if the name was specified */
  306. if (pname) {
  307. /* XXX Maybe should delete property if naming fails */
  308. return PListNameProp(plist, i + 1, pname);
  309. }
  310. /* Return the property index of the new property */
  311. return i + 1;
  312. }
  313. /*
  314. * FUNCTION: PListDeleteProp
  315. *
  316. * DESCRIPTION:
  317. *
  318. * This function deletes a property from a specified property list.
  319. * The property can be specified by its property index, using a
  320. * pindex value greater than zero, or by its name, by specifying
  321. * pindex as zero and pname as the property name. This does not
  322. * have any effect on the data referenced by the property value,
  323. * if any, nor does it have any effect on the property list that
  324. * describes the property value's type, if any.
  325. *
  326. * ARGUMENTS:
  327. *
  328. * plist - handle for the property list
  329. * pindex - the property index, or zero
  330. * pname - the property name, or NULL
  331. */
  332. NSAPI_PUBLIC const void *
  333. PListDeleteProp(PList_t plist, int pindex, const char *pname_in)
  334. {
  335. PListStruct_t *pl = (PListStruct_t *)plist;
  336. PLValueStruct_t **ppval;
  337. PLValueStruct_t **pvp;
  338. PLValueStruct_t *pv = NULL;
  339. int i;
  340. const void *pvalue = NULL;
  341. char *pname = (char *)pname_in;
  342. if (!plist) return NULL;
  343. ppval = (PLValueStruct_t **)(pl->pl_ppval);
  344. /* Check for valid property index */
  345. if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
  346. /* Get the pointer to the property structure */
  347. pv = ppval[pindex - 1];
  348. pname = 0;
  349. if (pv) {
  350. pname = pv->pv_name;
  351. }
  352. }
  353. if (pname && pl->pl_symtab) {
  354. /* Compute hash of specified property name */
  355. i = PListHashName(pl->pl_symtab, pname);
  356. /* Search hash collision list for matching name */
  357. for (pvp = &pl->pl_symtab->pt_hash[i]; *pvp; pvp = &(*pvp)->pv_next) {
  358. pv = *pvp;
  359. if (!strcmp(pname, pv->pv_name)) {
  360. /* Found it. Get its index and remove it. */
  361. pindex = pv->pv_pi;
  362. *pvp = pv->pv_next;
  363. break;
  364. }
  365. }
  366. }
  367. /* Found the indicated property by index or name? */
  368. if (pv) {
  369. /* Yes, remove it from the property list */
  370. ppval[pindex - 1] = NULL;
  371. /* Free the property name, if any */
  372. if (pv->pv_name) {
  373. pool_free(pl->pl_mempool, (void *)(pv->pv_name));
  374. }
  375. pvalue = pv->pv_value;
  376. /* Free the property */
  377. pool_free(pl->pl_mempool, (void *)pv);
  378. }
  379. return(pvalue);
  380. }
  381. /*
  382. * FUNCTION: PListFindValue
  383. *
  384. * DESCRIPTION:
  385. *
  386. * This function retrieves the value and type of a property with a
  387. * specified property name. If the pvalue argument is non-NULL,
  388. * it specifies a location in which to return the property value.
  389. * Similarly, if ptype is non-NULL, it specifies where the property
  390. * list describing the property type is to be returned. If a
  391. * property has no value, the value returned for pvalue is NULL.
  392. * If a property has no type, the value returned for ptype is NULL.
  393. * A property can have a value, a type, both, or neither.
  394. *
  395. * ARGUMENTS:
  396. *
  397. * plist - handle for the property list
  398. * pname - pointer to property name string
  399. * pvalue - property value return pointer
  400. * ptype - property type return pointer
  401. *
  402. * RETURNS:
  403. *
  404. * If successful, the index of the referenced property is returned
  405. * as the function value. Errors are indicated by a negative
  406. * return code as defined in plist.h.
  407. */
  408. NSAPI_PUBLIC int
  409. PListFindValue(PList_t plist, const char *pname, void **pvalue, PList_t *ptype)
  410. {
  411. PListStruct_t *pl = (PListStruct_t *)plist;
  412. PLValueStruct_t *pv;
  413. int pindex;
  414. int i;
  415. if (!plist) return ERRPLUNDEF;
  416. /* Got a symbol table for this property list? */
  417. if (pl->pl_symtab) {
  418. /* Yes, compute hash of specified name */
  419. i = PListHashName(pl->pl_symtab, pname);
  420. /* Search hash collision list for matching name */
  421. for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
  422. if (!strcmp(pname, pv->pv_name)) {
  423. /* Name match, get property index */
  424. pindex = pv->pv_pi;
  425. /* Return the value if requested */
  426. if (pvalue) *pvalue = (void *)(pv->pv_value);
  427. /* Return the type if requested */
  428. if (ptype) *ptype = (PList_t)(pv->pv_type);
  429. /* Return the property index */
  430. return pindex;
  431. }
  432. }
  433. }
  434. /* Error - specified property name is undefined */
  435. return ERRPLUNDEF;
  436. }
  437. /*
  438. * FUNCTION: PListInitProp
  439. *
  440. * DESCRIPTION:
  441. *
  442. * This function combines the functions of PListDefProp() and
  443. * PListSetValue(), defining a new property and assigning it an
  444. * initial value and optionally a type and/or a name.
  445. *
  446. * ARGUMENTS:
  447. *
  448. * plist - handle for the property list
  449. * pindex - a reserved property index, or zero
  450. * pname - the new property name, or NULL
  451. * pvalue - the new property value
  452. * ptype - the new property type, or NULL
  453. *
  454. * RETURNS:
  455. *
  456. * If successful, the property index (pindex) is returned as the
  457. * function value. Errors are indicated by a negative return code
  458. * as defined in plist.h.
  459. */
  460. NSAPI_PUBLIC int
  461. PListInitProp(PList_t plist, int pindex, const char *pname,
  462. const void *pvalue, PList_t ptype)
  463. {
  464. int rv;
  465. if (!plist) return ERRPLUNDEF;
  466. /* Create the property */
  467. rv = PListDefProp(plist, pindex, pname, PLFLG_USE_RES);
  468. if (rv > 0) {
  469. /* If that worked, set the value and type */
  470. rv = PListSetValue(plist, rv, pvalue, ptype);
  471. }
  472. return rv;
  473. }
  474. /*
  475. * FUNCTION: PListNew
  476. *
  477. * DESCRIPTION:
  478. *
  479. * This function creates a new property list, using the specified
  480. * memory pool for allocating the internal data structures used to
  481. * represent it. If the mempool argument is NULL, the default
  482. * memory pool is used.
  483. *
  484. * ARGUMENTS:
  485. *
  486. * mempool - handle for a memory pool to be associated
  487. * with the new property list
  488. *
  489. * RETURNS:
  490. *
  491. * If successful, the function return value is a handle for the new
  492. * property list. Otherwise NULL is returned.
  493. */
  494. NSAPI_PUBLIC PList_t
  495. PListNew(pool_handle_t *mempool)
  496. {
  497. /* Just call PListCreate with default parameters */
  498. return PListCreate(mempool, 0, 0, 0);
  499. }
  500. /*
  501. * FUNCTION: PListDestroy
  502. *
  503. * DESCRIPTION:
  504. *
  505. * This function destroys a specified property list. This means
  506. * that any dynamic memory which was allocated as a result of calls
  507. * to the property list API is freed to the memory pool from which
  508. * it was allocated. Property value data is not freed, nor are
  509. * any property lists associated with property types.
  510. *
  511. * ARGUMENTS:
  512. *
  513. * plist - handle for the property list
  514. */
  515. void
  516. PListDestroy(PList_t plist)
  517. {
  518. PListStruct_t *pl = (PListStruct_t *)plist;
  519. PLValueStruct_t **ppval;
  520. PLValueStruct_t *pv;
  521. int i;
  522. if (!plist) return;
  523. /* Free the property name symbol table if any */
  524. if (pl->pl_symtab) {
  525. pool_free(pl->pl_mempool, (void *)(pl->pl_symtab));
  526. }
  527. ppval = (PLValueStruct_t **)(pl->pl_ppval);
  528. /* Loop over the initialized property indices */
  529. for (i = 0; i < pl->pl_initpi; ++i) {
  530. /* Got a property here? */
  531. pv = ppval[i];
  532. if (pv) {
  533. /* Free the property name string if any */
  534. if (pv->pv_name) {
  535. pool_free(pl->pl_mempool, (void *)(pv->pv_name));
  536. }
  537. /* Free the property value structure */
  538. pool_free(pl->pl_mempool, (void *)pv);
  539. }
  540. }
  541. /* Free the array of pointers to property values */
  542. pool_free(pl->pl_mempool, (void *)ppval);
  543. /* Free the property list head */
  544. pool_free(pl->pl_mempool, (void *)pl);
  545. }
  546. /*
  547. * FUNCTION: PListGetValue
  548. *
  549. * DESCRIPTION:
  550. *
  551. * This function retrieves the value and type of the property with
  552. * the property index given by pindex in the specified property
  553. * list. The pindex argument must specify the index of a defined
  554. * property. If the pvalue argument is non-NULL, it specifies a
  555. * location in which to return the property value. Similarly, if
  556. * ptype is non-NULL, it specifies where the property list
  557. * describing the property type is to be returned. If a property
  558. * has no value, the value returned for pvalue is NULL. If a
  559. * property has no type, the value returned for ptype is NULL. A
  560. * property can have a value, a type, both, or neither.
  561. *
  562. * ARGUMENTS:
  563. *
  564. * plist - handle for the property list
  565. * pindex - the property index
  566. * pvalue - property value return pointer
  567. * ptype - property type return pointer
  568. *
  569. * RETURNS:
  570. *
  571. * If successful, the property index (pindex) is returned as the
  572. * function value. Errors are indicated by a negative return code
  573. * as defined in plist.h.
  574. */
  575. NSAPI_PUBLIC int
  576. PListGetValue(PList_t plist, int pindex, void **pvalue, PList_t *ptype)
  577. {
  578. PListStruct_t *pl = (PListStruct_t *)plist;
  579. PLValueStruct_t **ppval;
  580. PLValueStruct_t *pv;
  581. if (!plist) return ERRPLUNDEF;
  582. ppval = (PLValueStruct_t **)(pl->pl_ppval);
  583. /* Check for valid property index */
  584. if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
  585. /* Does the property exist? */
  586. pv = ppval[pindex - 1];
  587. if (pv) {
  588. /* Yes, return the value if requested */
  589. if (pvalue) *pvalue = (void *)(pv->pv_value);
  590. /* Return the type if requested */
  591. if (ptype) *ptype = (PList_t)(pv->pv_type);
  592. /* Successful return */
  593. return pindex;
  594. }
  595. }
  596. /* Error - invalid property index or non-existent property */
  597. return ERRPLINVPI;
  598. }
  599. /*
  600. * FUNCTION: PListHashName
  601. *
  602. * DESCRIPTION:
  603. *
  604. * This function hashes a given property name for a specified
  605. * symbol table. It produces a value that can be used as an
  606. * index in the pt_hash array associated with the symbol table.
  607. *
  608. * ARGUMENTS:
  609. *
  610. * symtab - pointer to the symbol table
  611. * pname - pointer to the property name string
  612. *
  613. * RETURNS:
  614. *
  615. * The hash index is returned as the function value.
  616. */
  617. int
  618. PListHashName(PLSymbolTable_t *symtab, const char *pname)
  619. {
  620. unsigned int hashval = 0; /* hash value */
  621. while (*pname) {
  622. hashval = (hashval<<5) ^ (*pname++ & 0x7f);
  623. }
  624. return hashval % PLSIZENDX(symtab->pt_sizendx);
  625. }
  626. /*
  627. * FUNCTION: PListNameProp
  628. *
  629. * DESCRIPTION:
  630. *
  631. * This function assigns a name to a defined property with the
  632. * property index, pindex. If the property has an existing name,
  633. * it will be replaced with the name specified by pname.
  634. *
  635. * ARGUMENTS:
  636. *
  637. * plist - handle for the property list
  638. * pindex - the property index
  639. * pname - the new property name
  640. *
  641. * RETURNS:
  642. *
  643. * If successful, the property index (pindex) is returned as the
  644. * function value. Errors are indicated by a negative return code
  645. * as defined in plist.h.
  646. */
  647. NSAPI_PUBLIC int
  648. PListNameProp(PList_t plist, int pindex, const char *pname)
  649. {
  650. PListStruct_t *pl = (PListStruct_t *)plist;
  651. PLValueStruct_t *pv;
  652. PLSymbolTable_t *pt;
  653. int i;
  654. if (!plist) return ERRPLUNDEF;
  655. pt = pl->pl_symtab;
  656. /* Check for valid property index */
  657. if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
  658. /* Does the property exist? */
  659. pv = ((PLValueStruct_t **)(pl->pl_ppval))[pindex - 1];
  660. if (pv) {
  661. /* If it has a name already, unname it */
  662. if (pv->pv_name) {
  663. PLValueStruct_t **pvp;
  664. /* Get hash bucket index */
  665. i = PListHashName(pt, pv->pv_name);
  666. /* Seach hash collision list for this property */
  667. for (pvp = &pt->pt_hash[i];
  668. *pvp; pvp = &(*pvp)->pv_next) {
  669. if (*pvp == pv) {
  670. /* Remove it from the list */
  671. *pvp = pv->pv_next;
  672. break;
  673. }
  674. }
  675. /* Free the current name string */
  676. pool_free(pl->pl_mempool, (void *)(pv->pv_name));
  677. }
  678. /* Got a new name? */
  679. if (pname) {
  680. /* Yes, is there a hash table? */
  681. if (!pt) {
  682. /* No, create one */
  683. pt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1,
  684. PLHASHSIZE(0));
  685. if (!pt) {
  686. return ERRPLNOMEM;
  687. }
  688. pl->pl_symtab = pt;
  689. }
  690. else {
  691. /* Is it time to grow the hash table? */
  692. i = PLSIZENDX(pt->pt_sizendx);
  693. /* cannot allow pt->pt_sizendx == PLMAXSIZENDX */
  694. if (((size_t)(pt->pt_sizendx + 1) < PLMAXSIZENDX) &&
  695. pt->pt_nsyms >= (i + i)) {
  696. PLSymbolTable_t *npt;
  697. /* Yes, allocate the new table */
  698. npt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1,
  699. PLHASHSIZE(pt->pt_sizendx+1));
  700. if (npt) {
  701. PLValueStruct_t *opv;
  702. PLValueStruct_t *npv;
  703. int j;
  704. npt->pt_sizendx = pt->pt_sizendx + 1;
  705. npt->pt_nsyms = pt->pt_nsyms;
  706. /* Rehash all the names into the new table */
  707. for (i = 0; i < PLSIZENDX(pt->pt_sizendx); ++i) {
  708. for (opv = pt->pt_hash[i]; opv; opv = npv) {
  709. npv = opv->pv_next;
  710. j = PListHashName(npt, opv->pv_name);
  711. opv->pv_next = npt->pt_hash[j];
  712. npt->pt_hash[j] = opv;
  713. }
  714. }
  715. pl->pl_symtab = npt;
  716. /* Free the old symbol table */
  717. pool_free(pl->pl_mempool, (void *)pt);
  718. pt = npt;
  719. }
  720. }
  721. }
  722. /* Duplicate the name string */
  723. pv->pv_name = pool_strdup(pl->pl_mempool, (char *)pname);
  724. /* Add name to symbol table */
  725. i = PListHashName(pt, pname);
  726. pv->pv_next = pt->pt_hash[i];
  727. pt->pt_hash[i] = pv;
  728. }
  729. /* Successful return */
  730. return pindex;
  731. }
  732. }
  733. /* Error - invalid property index or non-existent property */
  734. return ERRPLINVPI;
  735. }
  736. /*
  737. * FUNCTION: PListSetType
  738. *
  739. * DESCRIPTION:
  740. *
  741. * This function sets the property type of the defined property
  742. * with the property index, pindex. The property list describing
  743. * the property type is specified by ptype. If ptype is NULL,
  744. * the property type will be set to be undefined (NULL).
  745. *
  746. *
  747. * ARGUMENTS:
  748. *
  749. * plist - handle for the property list
  750. * pindex - the property index
  751. * ptype - the new property type, or NULL
  752. *
  753. * RETURNS:
  754. *
  755. * If successful, the property index (pindex) is returned as the
  756. * function value. Errors are indicated by a negative return code
  757. * as defined in plist.h.
  758. */
  759. NSAPI_PUBLIC int
  760. PListSetType(PList_t plist, int pindex, PList_t ptype)
  761. {
  762. PListStruct_t *pl = (PListStruct_t *)plist;
  763. PLValueStruct_t **ppval;
  764. PLValueStruct_t *pv;
  765. if (!plist) return ERRPLUNDEF;
  766. ppval = (PLValueStruct_t **)(pl->pl_ppval);
  767. /* Check for valid property index */
  768. if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
  769. /* Does the property exist? */
  770. pv = ppval[pindex - 1];
  771. if (pv) {
  772. /* Yes, set the new type */
  773. pv->pv_type = ptype;
  774. /* Successful return */
  775. return pindex;
  776. }
  777. }
  778. /* Error - invalid property index or non-existent property */
  779. return ERRPLINVPI;
  780. }
  781. /*
  782. * FUNCTION: PListSetValue
  783. *
  784. * DESCRIPTION:
  785. *
  786. * This function sets the value and optionally the type of a
  787. * defined property in a given property list. The pindex argument
  788. * specifies the property index, which must be greater than zero.
  789. * The ptype argument specifies a property list that describes the
  790. * property type. If ptype is NULL, the property type, if any, is
  791. * unchanged by this function. However, the property value is
  792. * always set to the value given by pvalue.
  793. *
  794. * ARGUMENTS:
  795. *
  796. * plist - handle for the property list
  797. * pindex - the property index
  798. * pvalue - the new property value
  799. * ptype - the new property type, or NULL
  800. *
  801. * RETURNS:
  802. *
  803. * If successful, the property index (pindex) is returned as the
  804. * function value. Errors are indicated by a negative return code
  805. * as defined in plist.h.
  806. */
  807. NSAPI_PUBLIC int
  808. PListSetValue(PList_t plist, int pindex, const void *pvalue, PList_t ptype)
  809. {
  810. PListStruct_t *pl = (PListStruct_t *)plist;
  811. PLValueStruct_t **ppval;
  812. PLValueStruct_t *pv;
  813. if (!plist) return ERRPLUNDEF;
  814. ppval = (PLValueStruct_t **)(pl->pl_ppval);
  815. /* Check for valid property index */
  816. if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
  817. /* Does the property exist? */
  818. pv = ppval[pindex - 1];
  819. if (pv) {
  820. /* Yes, set the new value */
  821. pv->pv_value = (char *)pvalue;
  822. /* Set type if type is given */
  823. if (ptype) pv->pv_type = (PListStruct_t *)ptype;
  824. /* Successful return */
  825. return pindex;
  826. }
  827. }
  828. /* Error - invalid property index or non-existent property */
  829. return ERRPLINVPI;
  830. }
  831. /*
  832. * FUNCTION: PListEnumerate
  833. *
  834. * DESCRIPTION:
  835. *
  836. * This function walks through a specified property list
  837. * calling a user supplied function with the property
  838. * name and value as parameters.
  839. *
  840. * ARGUMENTS:
  841. *
  842. * plist - handle for the property list
  843. * user_func - handle for the user function
  844. */
  845. NSAPI_PUBLIC void
  846. PListEnumerate(PList_t plist, PListFunc_t *user_func, void *user_data)
  847. {
  848. PListStruct_t *pl = (PListStruct_t *)plist;
  849. PLValueStruct_t **ppval;
  850. PLValueStruct_t *pv;
  851. int i;
  852. if (!plist) return;
  853. ppval = (PLValueStruct_t **)(pl->pl_ppval);
  854. /* Loop over the initialized property indices */
  855. for (i = 0; i < pl->pl_initpi; ++i) {
  856. /* Got a property here? */
  857. pv = ppval[i];
  858. if (pv) {
  859. (*user_func)(pv->pv_name, pv->pv_value, user_data);
  860. }
  861. }
  862. }
  863. /*
  864. * FUNCTION: PListCreateDuplicate
  865. *
  866. * DESCRIPTION:
  867. *
  868. * This function creates a new property list and returns a handle for
  869. * it. The source plist provides the new plists parameters.
  870. *
  871. * ARGUMENTS:
  872. *
  873. * src_plist - source plist to duplicate
  874. * mempool - handle for a memory pool to be associated
  875. * with the new property list, only
  876. * used if flags is set to PLFLG_NEW_MPOOL
  877. * flags - if PLFLG_NEW_MPOOL uses new_mempool
  878. * parameter
  879. *
  880. * RETURNS:
  881. *
  882. * If successful, the function return value is a handle for the new
  883. * property list. Otherwise NULL is returned.
  884. */
  885. static PList_t
  886. PListCreateDuplicate(PList_t src_plist, pool_handle_t *new_mempool, int flags)
  887. {
  888. PListStruct_t *plist; /* pointer to property list structure */
  889. int i;
  890. pool_handle_t *mempool;
  891. mempool = (flags == PLFLG_NEW_MPOOL) ? new_mempool : src_plist->pl_mempool;
  892. plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t));
  893. if (plist) {
  894. /* Initialize property list structure */
  895. plist->pl_mempool = mempool;
  896. plist->pl_symtab = NULL;
  897. plist->pl_maxprop = src_plist->pl_maxprop;
  898. plist->pl_resvpi = src_plist->pl_resvpi;
  899. plist->pl_initpi = src_plist->pl_initpi;
  900. plist->pl_lastpi = src_plist->pl_lastpi;
  901. /* Set initialize size for array of property value pointers */
  902. plist->pl_cursize = src_plist->pl_cursize;
  903. /* Allocate the initial array of property value pointers */
  904. plist->pl_ppval = (pb_entry **)pool_malloc(mempool,
  905. (plist->pl_cursize *
  906. sizeof(PLValueStruct_t *)));
  907. if (!plist->pl_ppval) {
  908. /* Failed - insufficient memory */
  909. pool_free(mempool, (void *)plist);
  910. plist = NULL;
  911. }
  912. else {
  913. /* NULL out pointers in the reserved index range, if any */
  914. for (i = 0; i < plist->pl_lastpi; ++i) {
  915. plist->pl_ppval[i] = 0;
  916. }
  917. }
  918. }
  919. return (PList_t)plist;
  920. }
  921. /*
  922. * FUNCTION: PListDuplicate
  923. *
  924. * DESCRIPTION:
  925. *
  926. * This function duplicates a specified PList_t.
  927. *
  928. * ARGUMENTS:
  929. *
  930. * plist - handle for the property list
  931. * mempool - handle for a memory pool to be associated
  932. * with the new property list
  933. * resvprop - number of reserved property indices
  934. * maxprop - maximum number of properties in list
  935. * (zero or negative imposes no limit)
  936. * flags - unused, reserved, must be zero
  937. *
  938. * RETURNS:
  939. *
  940. * If successful, the function return value is a handle for the new
  941. * property list. Otherwise NULL is returned.
  942. */
  943. NSAPI_PUBLIC PList_t
  944. PListDuplicate(PList_t plist, pool_handle_t *new_mempool, int flags)
  945. {
  946. PListStruct_t *pl = (PListStruct_t *)plist;
  947. PLValueStruct_t **ppval;
  948. PLValueStruct_t *pv;
  949. int i;
  950. int rv = 0;
  951. PList_t new_plist;
  952. if (!plist) return NULL;
  953. new_plist = PListCreateDuplicate(plist, new_mempool, flags);
  954. if (new_plist == NULL) {
  955. return(NULL);
  956. }
  957. ppval = (PLValueStruct_t **)(pl->pl_ppval);
  958. /* Loop over the initialized property indices */
  959. for (i = 0; i < pl->pl_initpi; ++i) {
  960. /* Got a property here? */
  961. pv = ppval[i];
  962. if (pv) {
  963. /* Create the property */
  964. rv = PListDefProp(new_plist, i + 1, pv->pv_name, PLFLG_IGN_RES);
  965. if (rv > 0) {
  966. /* If that worked, set the value and type */
  967. rv = PListSetValue(new_plist, rv, pv->pv_value, pv->pv_type);
  968. }
  969. if ( rv <= 0 ) {
  970. PListDestroy(new_plist);
  971. return(NULL);
  972. }
  973. }
  974. }
  975. return(new_plist);
  976. }
  977. /*
  978. * FUNCTION: PListGetPool
  979. *
  980. * DESCRIPTION:
  981. *
  982. * This function returns the memory pool the PList is allocated from.
  983. *
  984. * ARGUMENTS:
  985. *
  986. * plist - handle for the property list
  987. *
  988. * RETURNS:
  989. *
  990. * The memory pool address, which can be NULL.
  991. */
  992. NSAPI_PUBLIC pool_handle_t *
  993. PListGetPool(PList_t plist)
  994. {
  995. if (!plist) return NULL;
  996. return(plist->pl_mempool);
  997. }