src/server/util/plist.c

changeset 14
b8bf95b39952
parent 1
3c066d52342d
equal deleted inserted replaced
13:1fdbf4170ef4 14:b8bf95b39952
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5 *
6 * THE BSD LICENSE
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * Neither the name of the nor the names of its contributors may be
18 * used to endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * MODULE: plist.c
36 *
37 * DESCRIPTION:
38 *
39 * This module implements property lists. A property list is an
40 * ordered array of property values. Each property value has an
41 * handle for some data item, and may have a reference to
42 * another property list which describes the type of the data
43 * item. Each property value has a property index which specifies
44 * its position in the property list. A property value may also
45 * have a name. Since the data item associated with a property
46 * value may reference another property list, it is possible to
47 * construct arbitrary linked structures of property lists.
48 *
49 * IMPLEMENTATION NOTES:
50 */
51
52 #include "../daemon/netsite.h"
53 #include "plist.h"
54 #include "plist_pvt.h"
55
56 int plistHashSizes[] = PLSTSIZES;
57
58 /*
59 * FUNCTION: PListAssignValue
60 *
61 * DESCRIPTION:
62 *
63 * This function sets the value and/or type of a defined property
64 * in given property list. If the property type is specified as
65 * NULL, it is unchanged. However, the property value is always
66 * set to the specified value.
67 *
68 * ARGUMENTS:
69 *
70 * plist - handle for the property list
71 * pname - the property name
72 * pvalue - the new property value
73 * ptype - the new property type, or NULL
74 *
75 * RETURNS:
76 *
77 * If successful, the property index of the referenced property is
78 * returned as the function value. Errors are indicated by a
79 * negative return code as defined in plist.h.
80 */
81
82 NSAPI_PUBLIC int
83 PListAssignValue(PList_t plist, const char *pname,
84 const void *pvalue, PList_t ptype)
85 {
86 PListStruct_t *pl = (PListStruct_t *)plist;
87 PLValueStruct_t *pv;
88 int pindex;
89 int i;
90
91 if (!plist) return ERRPLUNDEF;
92
93 /* Got a symbol table for this property list? */
94 if (pl->pl_symtab) {
95
96 /* Yes, compute hash of specified name */
97 i = PListHashName(pl->pl_symtab, pname);
98
99 /* Search hash collision list for matching name */
100 for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
101
102 if (!strcmp(pname, pv->pv_name)) {
103
104 /* Name match, get property index */
105 pindex = pv->pv_pi;
106
107 /* Set the new value */
108 pv->pv_value = (char *)pvalue;
109
110 /* Set type if type is given */
111 if (ptype) pv->pv_type = (PListStruct_t *)ptype;
112
113 /* Return the property index */
114 return pindex;
115 }
116 }
117 }
118
119 /* Error - specified property name is undefined */
120 return ERRPLUNDEF;
121 }
122
123 /*
124 * FUNCTION: PListCreate
125 *
126 * DESCRIPTION:
127 *
128 * This function creates a new property list and returns a handle for
129 * it. It allows the caller to reserve a specified number of
130 * property indices at the beginning of the list, and also to limit
131 * the total number of property values that may be added to the list.
132 *
133 * ARGUMENTS:
134 *
135 * mempool - handle for a memory pool to be associated
136 * with the new property list
137 * resvprop - number of reserved property indices
138 * maxprop - maximum number of properties in list
139 * (zero or negative imposes no limit)
140 * flags - unused, reserved, must be zero
141 *
142 * RETURNS:
143 *
144 * If successful, the function return value is a handle for the new
145 * property list. Otherwise NULL is returned.
146 */
147
148 NSAPI_PUBLIC PList_t
149 PListCreate(pool_handle_t *mempool, int resvprop, int maxprop, int flags)
150 {
151 PListStruct_t *plist; /* pointer to property list structure */
152 int i;
153
154 plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t));
155 if (plist) {
156
157 /* Negative maxprop is the same as zero, i.e. no limit */
158 if (maxprop < 0) maxprop = 0;
159
160 /* If resvprop and maxprop are both specified, limit resvprop */
161 if (resvprop > 0) {
162 if (maxprop && (resvprop > maxprop)) resvprop = maxprop;
163 }
164 else resvprop = 0;
165
166 /* Initialize property list structure */
167 plist->pl_mempool = mempool;
168 plist->pl_symtab = NULL;
169 plist->pl_maxprop = maxprop;
170 plist->pl_resvpi = resvprop;
171 plist->pl_initpi = resvprop;
172 plist->pl_lastpi = resvprop;
173
174 /* Set initialize size for array of property value pointers */
175 plist->pl_cursize = (resvprop) ? resvprop : PLIST_DEFSIZE;
176
177 /* Allocate the initial array of property value pointers */
178 plist->pl_ppval = (pb_entry **)pool_malloc(mempool,
179 (plist->pl_cursize *
180 sizeof(PLValueStruct_t *)));
181 if (!plist->pl_ppval) {
182
183 /* Failed - insufficient memory */
184 pool_free(mempool, (void *)plist);
185 plist = NULL;
186 }
187 else {
188 /* NULL out pointers in the reserved index range, if any */
189 for (i = 0; i < plist->pl_lastpi; ++i) {
190 plist->pl_ppval[i] = 0;
191 }
192 }
193 }
194
195 return (PList_t)plist;
196 }
197
198 /*
199 * FUNCTION: PListDefProp
200 *
201 * DESCRIPTION:
202 *
203 * This function creates a new property in a specified property list.
204 * The 'pindex' argument may be used to request a particular property
205 * index for the new property. If 'pindex' is greater than zero,
206 * the specified value is used as the new property's index, provided
207 * there is no property at that index already. If 'pindex' is zero,
208 * then the next available property index is assigned to the new
209 * property. A name may optionally be specified for the new property.
210 *
211 * ARGUMENTS:
212 *
213 * plist - handle for the property list
214 * pindex - new property index (or zero)
215 * pname - new property name (or NULL)
216 *
217 * RETURNS:
218 *
219 * If successful, the index of the new property is returned as the
220 * function value. Errors are indicated by a negative return code
221 * as defined in plist.h.
222 */
223
224 NSAPI_PUBLIC int
225 PListDefProp(PList_t plist, int pindex, const char *pname, const int flags)
226 {
227 PListStruct_t *pl = (PListStruct_t *)plist;
228 PLValueStruct_t *pv;
229
230 if (!plist) return ERRPLUNDEF;
231
232 /* Is pindex specified? */
233 if (pindex > 0) {
234
235 /* Yes, is it in the reserved range? */
236 if (flags != PLFLG_IGN_RES && pindex > pl->pl_resvpi) {
237 /* No, error */
238 return ERRPLINVPI;
239 }
240
241 PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval);
242 if (ppval[pindex - 1]) {
243 /* Error - property already exists at specified index */
244 return ERRPLEXIST;
245 }
246 }
247 else {
248
249 /* Look for a free property index */
250 pindex = PListGetFreeIndex(pl);
251 if (pindex < 1) {
252 /* Error - no free property index */
253 return pindex;
254 }
255 }
256
257 /* We have a property index. Create a new property value */
258 pv = (PLValueStruct_t *)pool_calloc(pl->pl_mempool,
259 1, sizeof(PLValueStruct_t));
260 if (!pv) {
261
262 /* Error - insufficient memory */
263 return ERRPLNOMEM;
264 }
265
266 PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval);
267 pv->pv_pbentry.param = &pv->pv_pbparam;
268 pv->pv_pi = pindex;
269 pv->pv_mempool = pl->pl_mempool;
270 ppval[pindex - 1] = pv;
271
272 /* Name the property if the name was specified */
273 if (pname) {
274
275 /* XXX Maybe should delete property if naming fails */
276 return PListNameProp(plist, pindex, pname);
277 }
278
279 /* Return the property index of the new property */
280 return pindex;
281 }
282
283 /*
284 * FUNCTION: PListDeleteProp
285 *
286 * DESCRIPTION:
287 *
288 * This function deletes a property from a specified property list.
289 * The property can be specified by its property index, using a
290 * pindex value greater than zero, or by its name, by specifying
291 * pindex as zero and pname as the property name. This does not
292 * have any effect on the data referenced by the property value,
293 * if any, nor does it have any effect on the property list that
294 * describes the property value's type, if any.
295 *
296 * ARGUMENTS:
297 *
298 * plist - handle for the property list
299 * pindex - the property index, or zero
300 * pname - the property name, or NULL
301 */
302
303 NSAPI_PUBLIC const void *
304 PListDeleteProp(PList_t plist, int pindex, const char *pname_in)
305 {
306 PListStruct_t *pl = (PListStruct_t *)plist;
307 PLValueStruct_t **ppval;
308 PLValueStruct_t **pvp;
309 PLValueStruct_t *pv = NULL;
310 int i;
311 const void *pvalue = NULL;
312 char *pname = (char *)pname_in;
313
314 if (!plist) return NULL;
315
316 ppval = (PLValueStruct_t **)(pl->pl_ppval);
317
318 /* Check for valid property index */
319 if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
320
321 /* Get the pointer to the property structure */
322 pv = ppval[pindex - 1];
323 pname = 0;
324 if (pv) {
325 pname = pv->pv_name;
326 }
327 }
328
329 if (pname && pl->pl_symtab) {
330
331 /* Compute hash of specified property name */
332 i = PListHashName(pl->pl_symtab, pname);
333
334 /* Search hash collision list for matching name */
335 for (pvp = &pl->pl_symtab->pt_hash[i]; *pvp; pvp = &(*pvp)->pv_next) {
336
337 pv = *pvp;
338 if (!strcmp(pname, pv->pv_name)) {
339
340 /* Found it. Get its index and remove it. */
341 pindex = pv->pv_pi;
342 *pvp = pv->pv_next;
343 pl->pl_symtab->pt_nsyms--;
344 break;
345 }
346 pv = NULL;
347 }
348 }
349
350 /* Found the indicated property by index or name? */
351 if (pv) {
352
353 /* Yes, remove it from the property list */
354 ppval[pindex - 1] = NULL;
355
356 /* Free the property name, if any */
357 if (pv->pv_name) {
358 pool_free(pv->pv_mempool, (void *)(pv->pv_name));
359 }
360 pvalue = pv->pv_value;
361
362 /* Free the property */
363 pool_free(pv->pv_mempool, (void *)pv);
364 }
365 return(pvalue);
366 }
367
368 /*
369 * FUNCTION: PListFindValue
370 *
371 * DESCRIPTION:
372 *
373 * This function retrieves the value and type of a property with a
374 * specified property name. If the pvalue argument is non-NULL,
375 * it specifies a location in which to return the property value.
376 * Similarly, if ptype is non-NULL, it specifies where the property
377 * list describing the property type is to be returned. If a
378 * property has no value, the value returned for pvalue is NULL.
379 * If a property has no type, the value returned for ptype is NULL.
380 * A property can have a value, a type, both, or neither.
381 *
382 * ARGUMENTS:
383 *
384 * plist - handle for the property list
385 * pname - pointer to property name string
386 * pvalue - property value return pointer
387 * ptype - property type return pointer
388 *
389 * RETURNS:
390 *
391 * If successful, the index of the referenced property is returned
392 * as the function value. Errors are indicated by a negative
393 * return code as defined in plist.h.
394 */
395
396 NSAPI_PUBLIC int
397 PListFindValue(PList_t plist, const char *pname, void **pvalue, PList_t *ptype)
398 {
399 PListStruct_t *pl = (PListStruct_t *)plist;
400 PLValueStruct_t *pv;
401 int pindex;
402 int i;
403
404 if (!plist) return ERRPLUNDEF;
405
406 /* Got a symbol table for this property list? */
407 if (pl->pl_symtab) {
408
409 /* Yes, compute hash of specified name */
410 i = PListHashName(pl->pl_symtab, pname);
411
412 /* Search hash collision list for matching name */
413 for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
414
415 if (!strcmp(pname, pv->pv_name)) {
416
417 /* Name match, get property index */
418 pindex = pv->pv_pi;
419
420 /* Return the value if requested */
421 if (pvalue) *pvalue = (void *)(pv->pv_value);
422
423 /* Return the type if requested */
424 if (ptype) *ptype = (PList_t)(pv->pv_type);
425
426 /* Return the property index */
427 return pindex;
428 }
429 }
430 }
431
432 /* Error - specified property name is undefined */
433 return ERRPLUNDEF;
434 }
435
436 /*
437 * FUNCTION: PListInitProp
438 *
439 * DESCRIPTION:
440 *
441 * This function combines the functions of PListDefProp() and
442 * PListSetValue(), defining a new property and assigning it an
443 * initial value and optionally a type and/or a name.
444 *
445 * ARGUMENTS:
446 *
447 * plist - handle for the property list
448 * pindex - a reserved property index, or zero
449 * pname - the new property name, or NULL
450 * pvalue - the new property value
451 * ptype - the new property type, or NULL
452 *
453 * RETURNS:
454 *
455 * If successful, the property index (pindex) is returned as the
456 * function value. Errors are indicated by a negative return code
457 * as defined in plist.h.
458 */
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
466 if (!plist) return ERRPLUNDEF;
467
468 /* Create the property */
469 rv = PListDefProp(plist, pindex, pname, PLFLG_USE_RES);
470 if (rv > 0) {
471
472 /* If that worked, set the value and type */
473 rv = PListSetValue(plist, rv, pvalue, ptype);
474 }
475
476 return rv;
477 }
478
479 /*
480 * FUNCTION: PListNew
481 *
482 * DESCRIPTION:
483 *
484 * This function creates a new property list, using the specified
485 * memory pool for allocating the internal data structures used to
486 * represent it. If the mempool argument is NULL, the default
487 * memory pool is used.
488 *
489 * ARGUMENTS:
490 *
491 * mempool - handle for a memory pool to be associated
492 * with the new property list
493 *
494 * RETURNS:
495 *
496 * If successful, the function return value is a handle for the new
497 * property list. Otherwise NULL is returned.
498 */
499
500 NSAPI_PUBLIC PList_t
501 PListNew(pool_handle_t *mempool)
502 {
503 /* Just call PListCreate with default parameters */
504 return PListCreate(mempool, 0, 0, 0);
505 }
506
507 /*
508 * FUNCTION: PListDestroy
509 *
510 * DESCRIPTION:
511 *
512 * This function destroys a specified property list. This means
513 * that any dynamic memory which was allocated as a result of calls
514 * to the property list API is freed to the memory pool from which
515 * it was allocated. Property value data is not freed, nor are
516 * any property lists associated with property types.
517 *
518 * ARGUMENTS:
519 *
520 * plist - handle for the property list
521 */
522
523 void
524 PListDestroy(PList_t plist)
525 {
526 PListStruct_t *pl = (PListStruct_t *)plist;
527 PLValueStruct_t **ppval;
528 PLValueStruct_t *pv;
529 int i;
530
531 if (!plist) return;
532
533 /* Free the property name symbol table if any */
534 if (pl->pl_symtab) {
535 pool_free(pl->pl_mempool, (void *)(pl->pl_symtab));
536 }
537
538 ppval = (PLValueStruct_t **)(pl->pl_ppval);
539
540 /* Loop over the initialized property indices */
541 for (i = 0; i < pl->pl_initpi; ++i) {
542
543 /* Got a property here? */
544 pv = ppval[i];
545 if (pv) {
546
547 /* Free the property name string if any */
548 if (pv->pv_name) {
549 pool_free(pv->pv_mempool, (void *)(pv->pv_name));
550 }
551
552 /* Free the property value structure */
553 pool_free(pv->pv_mempool, (void *)pv);
554 }
555 }
556
557 /* Free the array of pointers to property values */
558 pool_free(pl->pl_mempool, (void *)ppval);
559
560 /* Free the property list head */
561 pool_free(pl->pl_mempool, (void *)pl);
562 }
563
564 /*
565 * FUNCTION: PListGetValue
566 *
567 * DESCRIPTION:
568 *
569 * This function retrieves the value and type of the property with
570 * the property index given by pindex in the specified property
571 * list. The pindex argument must specify the index of a defined
572 * property. If the pvalue argument is non-NULL, it specifies a
573 * location in which to return the property value. Similarly, if
574 * ptype is non-NULL, it specifies where the property list
575 * describing the property type is to be returned. If a property
576 * has no value, the value returned for pvalue is NULL. If a
577 * property has no type, the value returned for ptype is NULL. A
578 * property can have a value, a type, both, or neither.
579 *
580 * ARGUMENTS:
581 *
582 * plist - handle for the property list
583 * pindex - the property index
584 * pvalue - property value return pointer
585 * ptype - property type return pointer
586 *
587 * RETURNS:
588 *
589 * If successful, the property index (pindex) is returned as the
590 * function value. Errors are indicated by a negative return code
591 * as defined in plist.h.
592 */
593
594 NSAPI_PUBLIC int
595 PListGetValue(PList_t plist, int pindex, void **pvalue, PList_t *ptype)
596 {
597 PListStruct_t *pl = (PListStruct_t *)plist;
598 PLValueStruct_t **ppval;
599 PLValueStruct_t *pv;
600
601 if (!plist) return ERRPLUNDEF;
602
603 ppval = (PLValueStruct_t **)(pl->pl_ppval);
604
605 /* Check for valid property index */
606 if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
607
608 /* Does the property exist? */
609 pv = ppval[pindex - 1];
610 if (pv) {
611
612 /* Yes, return the value if requested */
613 if (pvalue) *pvalue = (void *)(pv->pv_value);
614
615 /* Return the type if requested */
616 if (ptype) *ptype = (PList_t)(pv->pv_type);
617
618 /* Successful return */
619 return pindex;
620 }
621 }
622
623 /* Error - invalid property index or non-existent property */
624 return ERRPLINVPI;
625 }
626
627 /*
628 * FUNCTION: PListHash
629 *
630 * DESCRIPTION:
631 *
632 * This function hashes a given string.
633 *
634 * ARGUMENTS:
635 *
636 * string - pointer to the string to hash
637 *
638 * RETURNS:
639 *
640 * The hash value is returned as the function value.
641 */
642
643 unsigned int
644 PListHash(const char *string)
645 {
646 unsigned int hashval = 0; /* hash value */
647
648 while (*string) {
649 hashval = (hashval<<5) ^ (*string++ & 0x7f);
650 }
651
652 return hashval;
653 }
654
655 /*
656 * FUNCTION: PListHashName
657 *
658 * DESCRIPTION:
659 *
660 * This function hashes a given property name for a specified
661 * symbol table. It produces a value that can be used as an
662 * index in the pt_hash array associated with the symbol table.
663 *
664 * ARGUMENTS:
665 *
666 * symtab - pointer to the symbol table
667 * pname - pointer to the property name string
668 *
669 * RETURNS:
670 *
671 * The hash index is returned as the function value.
672 */
673
674 int
675 PListHashName(PLSymbolTable_t *symtab, const char *pname)
676 {
677 return PListHash(pname) % PLSIZENDX(symtab->pt_sizendx);
678 }
679
680 /*
681 * FUNCTION: PListNameProp
682 *
683 * DESCRIPTION:
684 *
685 * This function assigns a name to a defined property with the
686 * property index, pindex. If the property has an existing name,
687 * it will be replaced with the name specified by pname.
688 *
689 * ARGUMENTS:
690 *
691 * plist - handle for the property list
692 * pindex - the property index
693 * pname - the new property name
694 *
695 * RETURNS:
696 *
697 * If successful, the property index (pindex) is returned as the
698 * function value. Errors are indicated by a negative return code
699 * as defined in plist.h.
700 */
701
702 NSAPI_PUBLIC int
703 PListNameProp(PList_t plist, int pindex, const char *pname)
704 {
705 PListStruct_t *pl = (PListStruct_t *)plist;
706 PLValueStruct_t *pv;
707 PLSymbolTable_t *pt;
708 int i;
709
710 if (!plist) return ERRPLUNDEF;
711
712 pt = pl->pl_symtab;
713
714 /* Check for valid property index */
715 if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
716
717 /* Does the property exist? */
718 pv = ((PLValueStruct_t **)(pl->pl_ppval))[pindex - 1];
719 if (pv) {
720
721 /* If it has a name already, unname it */
722 if (pv->pv_name) {
723 PLValueStruct_t **pvp;
724
725 /* Get hash bucket index */
726 i = PListHashName(pt, pv->pv_name);
727
728 /* Seach hash collision list for this property */
729 for (pvp = &pt->pt_hash[i];
730 *pvp; pvp = &(*pvp)->pv_next) {
731
732 if (*pvp == pv) {
733
734 /* Remove it from the list */
735 *pvp = pv->pv_next;
736 pt->pt_nsyms--;
737 break;
738 }
739 }
740
741 /* Free the current name string */
742 pool_free(pv->pv_mempool, (void *)(pv->pv_name));
743 }
744
745 /* Got a new name? */
746 if (pname) {
747
748 /* Allocate/grow the symbol table as needed */
749 pt = PListSymbolTable(pl);
750 if (!pt) {
751 return ERRPLNOMEM;
752 }
753
754 /* Duplicate the name string */
755 pv->pv_name = pool_strdup(pv->pv_mempool, (char *)pname);
756
757 /* Add name to symbol table */
758 i = PListHashName(pt, pname);
759 pv->pv_next = pt->pt_hash[i];
760 pt->pt_hash[i] = pv;
761 pt->pt_nsyms++;
762 }
763
764 /* Successful return */
765 return pindex;
766 }
767 }
768
769 /* Error - invalid property index or non-existent property */
770 return ERRPLINVPI;
771 }
772
773 /*
774 * FUNCTION: PListSetType
775 *
776 * DESCRIPTION:
777 *
778 * This function sets the property type of the defined property
779 * with the property index, pindex. The property list describing
780 * the property type is specified by ptype. If ptype is NULL,
781 * the property type will be set to be undefined (NULL).
782 *
783 *
784 * ARGUMENTS:
785 *
786 * plist - handle for the property list
787 * pindex - the property index
788 * ptype - the new property type, or NULL
789 *
790 * RETURNS:
791 *
792 * If successful, the property index (pindex) is returned as the
793 * function value. Errors are indicated by a negative return code
794 * as defined in plist.h.
795 */
796
797 NSAPI_PUBLIC int
798 PListSetType(PList_t plist, int pindex, PList_t ptype)
799 {
800 PListStruct_t *pl = (PListStruct_t *)plist;
801 PLValueStruct_t **ppval;
802 PLValueStruct_t *pv;
803
804 if (!plist) return ERRPLUNDEF;
805
806 ppval = (PLValueStruct_t **)(pl->pl_ppval);
807
808 /* Check for valid property index */
809 if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
810
811 /* Does the property exist? */
812 pv = ppval[pindex - 1];
813 if (pv) {
814
815 /* Yes, set the new type */
816 pv->pv_type = ptype;
817
818 /* Successful return */
819 return pindex;
820 }
821 }
822
823 /* Error - invalid property index or non-existent property */
824 return ERRPLINVPI;
825 }
826
827 /*
828 * FUNCTION: PListSetValue
829 *
830 * DESCRIPTION:
831 *
832 * This function sets the value and optionally the type of a
833 * defined property in a given property list. The pindex argument
834 * specifies the property index, which must be greater than zero.
835 * The ptype argument specifies a property list that describes the
836 * property type. If ptype is NULL, the property type, if any, is
837 * unchanged by this function. However, the property value is
838 * always set to the value given by pvalue.
839 *
840 * ARGUMENTS:
841 *
842 * plist - handle for the property list
843 * pindex - the property index
844 * pvalue - the new property value
845 * ptype - the new property type, or NULL
846 *
847 * RETURNS:
848 *
849 * If successful, the property index (pindex) is returned as the
850 * function value. Errors are indicated by a negative return code
851 * as defined in plist.h.
852 */
853
854 NSAPI_PUBLIC int
855 PListSetValue(PList_t plist, int pindex, const void *pvalue, PList_t ptype)
856 {
857 PListStruct_t *pl = (PListStruct_t *)plist;
858 PLValueStruct_t **ppval;
859 PLValueStruct_t *pv;
860
861 if (!plist) return ERRPLUNDEF;
862
863 ppval = (PLValueStruct_t **)(pl->pl_ppval);
864
865 /* Check for valid property index */
866 if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
867
868 /* Does the property exist? */
869 pv = ppval[pindex - 1];
870 if (pv) {
871
872 /* Yes, set the new value */
873 pv->pv_value = (char *)pvalue;
874
875 /* Set type if type is given */
876 if (ptype) pv->pv_type = (PListStruct_t *)ptype;
877
878 /* Successful return */
879 return pindex;
880 }
881 }
882
883 /* Error - invalid property index or non-existent property */
884 return ERRPLINVPI;
885 }
886
887 /*
888 * FUNCTION: PListEnumerate
889 *
890 * DESCRIPTION:
891 *
892 * This function walks through a specified property list
893 * calling a user supplied function with the property
894 * name and value as parameters.
895 *
896 * ARGUMENTS:
897 *
898 * plist - handle for the property list
899 * user_func - handle for the user function
900 */
901
902 NSAPI_PUBLIC void
903 PListEnumerate(PList_t plist, PListFunc_t *user_func, void *user_data)
904 {
905 PListStruct_t *pl = (PListStruct_t *)plist;
906 PLValueStruct_t **ppval;
907 PLValueStruct_t *pv;
908 int i;
909
910 if (!plist) return;
911
912 ppval = (PLValueStruct_t **)(pl->pl_ppval);
913
914 /* Loop over the initialized property indices */
915 for (i = 0; i < pl->pl_initpi; ++i) {
916
917 /* Got a property here? */
918 pv = ppval[i];
919 if (pv) {
920 (*user_func)(pv->pv_name, pv->pv_value, user_data);
921 }
922
923 }
924
925 }
926
927 /*
928 * FUNCTION: PListCreateDuplicate
929 *
930 * DESCRIPTION:
931 *
932 * This function creates a new property list and returns a handle for
933 * it. The source plist provides the new plists parameters.
934 *
935 * ARGUMENTS:
936 *
937 * src_plist - source plist to duplicate
938 * mempool - handle for a memory pool to be associated
939 * with the new property list, only
940 * used if flags is set to PLFLG_NEW_MPOOL
941 * flags - if PLFLG_NEW_MPOOL uses new_mempool
942 * parameter
943 *
944 * RETURNS:
945 *
946 * If successful, the function return value is a handle for the new
947 * property list. Otherwise NULL is returned.
948 */
949
950 static PList_t
951 PListCreateDuplicate(PList_t src_plist, pool_handle_t *new_mempool, int flags)
952 {
953 PListStruct_t *plist; /* pointer to property list structure */
954 int i;
955 pool_handle_t *mempool;
956
957 mempool = (flags == PLFLG_NEW_MPOOL) ? new_mempool : src_plist->pl_mempool;
958
959 plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t));
960 if (plist) {
961
962 /* Initialize property list structure */
963 plist->pl_mempool = mempool;
964 plist->pl_symtab = NULL;
965 plist->pl_maxprop = src_plist->pl_maxprop;
966 plist->pl_resvpi = src_plist->pl_resvpi;
967 plist->pl_initpi = src_plist->pl_initpi;
968 plist->pl_lastpi = src_plist->pl_lastpi;
969
970 /* Set initialize size for array of property value pointers */
971 plist->pl_cursize = src_plist->pl_cursize;
972
973 /* Allocate the initial array of property value pointers */
974 plist->pl_ppval = (pb_entry **)pool_malloc(mempool,
975 (plist->pl_cursize *
976 sizeof(PLValueStruct_t *)));
977 if (!plist->pl_ppval) {
978
979 /* Failed - insufficient memory */
980 pool_free(mempool, (void *)plist);
981 plist = NULL;
982 }
983 else {
984 /* NULL out pointers in the reserved index range, if any */
985 for (i = 0; i < plist->pl_lastpi; ++i) {
986 plist->pl_ppval[i] = 0;
987 }
988 }
989 }
990
991 return (PList_t)plist;
992 }
993
994
995 /*
996 * FUNCTION: PListDuplicate
997 *
998 * DESCRIPTION:
999 *
1000 * This function duplicates a specified PList_t.
1001 *
1002 * ARGUMENTS:
1003 *
1004 * plist - handle for the property list
1005 * mempool - handle for a memory pool to be associated
1006 * with the new property list
1007 * resvprop - number of reserved property indices
1008 * maxprop - maximum number of properties in list
1009 * (zero or negative imposes no limit)
1010 * flags - unused, reserved, must be zero
1011 *
1012 * RETURNS:
1013 *
1014 * If successful, the function return value is a handle for the new
1015 * property list. Otherwise NULL is returned.
1016 */
1017
1018 NSAPI_PUBLIC PList_t
1019 PListDuplicate(PList_t plist, pool_handle_t *new_mempool, int flags)
1020 {
1021 PListStruct_t *pl = (PListStruct_t *)plist;
1022 PLValueStruct_t **ppval;
1023 PLValueStruct_t *pv;
1024 int i;
1025 int rv = 0;
1026 PList_t new_plist;
1027
1028 if (!plist) return NULL;
1029
1030 new_plist = PListCreateDuplicate(plist, new_mempool, flags);
1031 if (new_plist == NULL) {
1032 return(NULL);
1033 }
1034
1035 ppval = (PLValueStruct_t **)(pl->pl_ppval);
1036
1037 /* Loop over the initialized property indices */
1038 for (i = 0; i < pl->pl_initpi; ++i) {
1039
1040 /* Got a property here? */
1041 pv = ppval[i];
1042 if (pv) {
1043 /* Create the property */
1044 rv = PListDefProp(new_plist, i + 1, pv->pv_name, PLFLG_IGN_RES);
1045 if (rv > 0) {
1046
1047 /* If that worked, set the value and type */
1048 rv = PListSetValue(new_plist, rv, pv->pv_value, pv->pv_type);
1049 }
1050
1051 if ( rv <= 0 ) {
1052 PListDestroy(new_plist);
1053 return(NULL);
1054 }
1055 }
1056
1057 }
1058
1059 return(new_plist);
1060 }
1061
1062 /*
1063 * FUNCTION: PListGetPool
1064 *
1065 * DESCRIPTION:
1066 *
1067 * This function returns the memory pool the PList is allocated from.
1068 *
1069 * ARGUMENTS:
1070 *
1071 * plist - handle for the property list
1072 *
1073 * RETURNS:
1074 *
1075 * The memory pool address, which can be NULL.
1076 */
1077
1078 NSAPI_PUBLIC pool_handle_t *
1079 PListGetPool(PList_t plist)
1080 {
1081 if (!plist) return NULL;
1082
1083 return(plist->pl_mempool);
1084 }
1085
1086 /*
1087 * FUNCTION: PListGetFreeIndex
1088 *
1089 * DESCRIPTION:
1090 *
1091 * This function returns an available property index.
1092 *
1093 * ARGUMENTS:
1094 *
1095 * plist - handle for the property list
1096 *
1097 * RETURNS:
1098 *
1099 * If successful, an available property index is returned as the
1100 * function value. Errors are indicated by a negative return code
1101 * as defined in plist.h.
1102 */
1103
1104 int
1105 PListGetFreeIndex(PListStruct_t *pl)
1106 {
1107 PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval);
1108 int wrapped;
1109 int i;
1110
1111 /*
1112 * Look for a free property index, starting at pl_lastpi + 1.
1113 * (Note that i is the property index - 1)
1114 */
1115 for (wrapped = 0, i = pl->pl_lastpi; ;) {
1116
1117 /* Are we in an initialized part of the array? */
1118 if (i < pl->pl_initpi) {
1119
1120 /* Yes, use this index if it's free */
1121 if (ppval[i] == 0) break;
1122
1123 /* Otherwise step to the next one */
1124 ++i;
1125 }
1126 else {
1127
1128 /* Have we reached the end yet? */
1129 if (i < pl->pl_cursize) {
1130
1131 /*
1132 * We are above the highest initialized index, but
1133 * still within the allocated size. An index in
1134 * this range can be used with no further checks.
1135 */
1136 ppval[i] = 0;
1137 }
1138 else {
1139
1140 /*
1141 * It's looking like time to grow the array, but
1142 * first go back and look for an unused, unreserved
1143 * index that might have been freed.
1144 */
1145 if (!wrapped) {
1146
1147 i = pl->pl_resvpi;
1148 wrapped = 1;
1149 continue;
1150 }
1151
1152 /*
1153 * Grow the array unless there is a specified maximum
1154 * size and we've reached it.
1155 */
1156 i = pl->pl_cursize;
1157 if (pl->pl_maxprop && (i > pl->pl_maxprop)) {
1158
1159 /* Error - property list is full */
1160 return ERRPLFULL;
1161 }
1162
1163 /* Increase planned size of list */
1164 int cursize = i + PLIST_DEFGROW;
1165
1166 /* Reallocate the array of property value pointers */
1167 ppval = (PLValueStruct_t **)pool_realloc(pl->pl_mempool,
1168 (void *)ppval,
1169 (cursize * sizeof(PLValueStruct_t *)));
1170 if (!ppval) {
1171
1172 /* Error - insufficient memory */
1173 return ERRPLNOMEM;
1174 }
1175
1176 /* Initialize the first new entry and select it */
1177 ppval[i] = NULL;
1178 pl->pl_ppval = (pb_entry **)ppval;
1179 pl->pl_cursize = cursize;
1180 }
1181
1182 /* Update the highest initialized index value */
1183 pl->pl_initpi = i + 1;
1184 break;
1185 }
1186 }
1187
1188 /* Set the starting point for the next allocation */
1189 pl->pl_lastpi = i + 1;
1190
1191 return i + 1;
1192 }
1193
1194 /*
1195 * FUNCTION: PListSymbolTable
1196 *
1197 * DESCRIPTION:
1198 *
1199 * This function allocates or grows a property list's symbol table as
1200 * needed.
1201 *
1202 * ARGUMENTS:
1203 *
1204 * plist - handle for the property list
1205 *
1206 * RETURNS:
1207 *
1208 * If successful, a pointer to the symbol table is returned as the
1209 * function value. Errors are indicated by a NULL return code.
1210 */
1211
1212 PLSymbolTable_t *
1213 PListSymbolTable(PListStruct_t *pl)
1214 {
1215 PLSymbolTable_t *pt;
1216 int i;
1217
1218 pt = pl->pl_symtab;
1219
1220 /* Is there a hash table? */
1221 if (!pl->pl_symtab) {
1222
1223 /* No, create one */
1224 pt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1, PLHASHSIZE(0));
1225
1226 pl->pl_symtab = pt;
1227 }
1228 else {
1229
1230 /* Is it time to grow the hash table? */
1231 i = PLSIZENDX(pt->pt_sizendx);
1232 if ((pt->pt_sizendx < PLMAXSIZENDX) && pt->pt_nsyms >= (i + i)) {
1233
1234 PLSymbolTable_t *npt;
1235
1236 /* Yes, allocate the new table */
1237 npt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1,
1238 PLHASHSIZE(pt->pt_sizendx+1));
1239 if (npt) {
1240 npt->pt_sizendx = pt->pt_sizendx + 1;
1241 npt->pt_nsyms = pt->pt_nsyms;
1242
1243 /* Rehash all the names into the new table, preserving order */
1244 for (i = 0; i < PLSIZENDX(pt->pt_sizendx); ++i) {
1245 /* While there are names at this hash index... */
1246 while (pt->pt_hash[i]) {
1247 PLValueStruct_t **pvp;
1248 int j;
1249
1250 /* Find the last name at this hash index */
1251 for (pvp = &pt->pt_hash[i]; (*pvp)->pv_next; pvp = &(*pvp)->pv_next);
1252
1253 /* Move the name to the new table */
1254 j = PListHashName(npt, (*pvp)->pv_name);
1255 (*pvp)->pv_next = npt->pt_hash[j];
1256 npt->pt_hash[j] = (*pvp);
1257
1258 /* Remove the name from the old table */
1259 *pvp = NULL;
1260 }
1261 }
1262
1263 pl->pl_symtab = npt;
1264
1265 /* Free the old symbol table */
1266 pool_free(pl->pl_mempool, (void *)pt);
1267 pt = npt;
1268 }
1269 }
1270 }
1271
1272 return pl->pl_symtab;
1273 }

mercurial