|
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 "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 } |