UNIXworkcode

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