Home | History | Annotate | Line # | Download | only in libppath
ppath.c revision 1.1
      1 /* $NetBSD: ppath.c,v 1.1 2011/08/25 14:55:36 dyoung Exp $ */
      2 /* $Id: ppath.c,v 1.1 2011/08/25 14:55:36 dyoung Exp $ */
      3 /*-
      4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by David Young <dyoung (at) NetBSD.org>.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __RCSID("$Id: ppath.c,v 1.1 2011/08/25 14:55:36 dyoung Exp $");
     34 
     35 #include <ppath/ppath.h>
     36 #include <ppath/ppath_impl.h>
     37 
     38 enum _ppath_type {
     39 	  PPATH_T_IDX = 0
     40 	, PPATH_T_KEY = 1
     41 };
     42 
     43 typedef enum _ppath_type ppath_type_t;
     44 
     45 struct _ppath_component {
     46 	unsigned int	pc_refcnt;
     47 	ppath_type_t	pc_type;
     48 	union {
     49 		char *u_key;
     50 		unsigned int u_idx;
     51 	} pc_u;
     52 #define pc_key pc_u.u_key
     53 #define pc_idx pc_u.u_idx
     54 };
     55 
     56 struct _ppath {
     57 	unsigned int	p_refcnt;
     58 	unsigned int	p_len;
     59 	ppath_component_t *p_cmpt[PPATH_MAX_COMPONENTS];
     60 };
     61 
     62 static int ppath_copydel_object_of_type(prop_object_t, prop_object_t *,
     63     const ppath_t *, prop_type_t);
     64 static int ppath_copyset_object_helper(prop_object_t, prop_object_t *,
     65     const ppath_t *, const prop_object_t);
     66 
     67 static void
     68 ppath_strfree(char *s)
     69 {
     70 	size_t size = strlen(s) + 1;
     71 
     72 	ppath_free(s, size);
     73 }
     74 
     75 static char *
     76 ppath_strdup(const char *s)
     77 {
     78 	size_t size = strlen(s) + 1;
     79 	char *p;
     80 
     81 	if ((p = ppath_alloc(size)) == NULL)
     82 		return NULL;
     83 
     84 	return strcpy(p, s);
     85 }
     86 
     87 int
     88 ppath_component_idx(const ppath_component_t *pc)
     89 {
     90 	if (pc->pc_type != PPATH_T_IDX)
     91 		return -1;
     92 	return pc->pc_idx;
     93 }
     94 
     95 const char *
     96 ppath_component_key(const ppath_component_t *pc)
     97 {
     98 	if (pc->pc_type != PPATH_T_KEY)
     99 		return NULL;
    100 	return pc->pc_key;
    101 }
    102 
    103 ppath_component_t *
    104 ppath_idx(unsigned int idx)
    105 {
    106 	ppath_component_t *pc;
    107 
    108 	if ((pc = ppath_alloc(sizeof(*pc))) == NULL)
    109 		return NULL;
    110 	pc->pc_idx = idx;
    111 	pc->pc_type = PPATH_T_IDX;
    112 	pc->pc_refcnt = 1;
    113 	ppath_component_extant_inc();
    114 	return pc;
    115 }
    116 
    117 ppath_component_t *
    118 ppath_key(const char *key)
    119 {
    120 	ppath_component_t *pc;
    121 
    122 	if ((pc = ppath_alloc(sizeof(*pc))) == NULL)
    123 		return NULL;
    124 
    125 	if ((pc->pc_key = ppath_strdup(key)) == NULL) {
    126 		ppath_free(pc, sizeof(*pc));
    127 		return NULL;
    128 	}
    129 	pc->pc_type = PPATH_T_KEY;
    130 	pc->pc_refcnt = 1;
    131 	ppath_component_extant_inc();
    132 	return pc;
    133 }
    134 
    135 ppath_component_t *
    136 ppath_component_retain(ppath_component_t *pc)
    137 {
    138 	ppath_assert(pc->pc_refcnt != 0);
    139 	pc->pc_refcnt++;
    140 
    141 	return pc;
    142 }
    143 
    144 void
    145 ppath_component_release(ppath_component_t *pc)
    146 {
    147 	ppath_assert(pc->pc_refcnt != 0);
    148 
    149 	if (--pc->pc_refcnt != 0)
    150 		return;
    151 	if (pc->pc_type == PPATH_T_KEY)
    152 		ppath_strfree(pc->pc_key);
    153 	ppath_component_extant_dec();
    154 	ppath_free(pc, sizeof(*pc));
    155 }
    156 
    157 ppath_t *
    158 ppath_create(void)
    159 {
    160 	ppath_t *p;
    161 
    162 	if ((p = ppath_alloc(sizeof(*p))) == NULL)
    163 		return NULL;
    164 
    165 	p->p_refcnt = 1;
    166 	ppath_extant_inc();
    167 
    168 	return p;
    169 }
    170 
    171 ppath_t *
    172 ppath_pop(ppath_t *p, ppath_component_t **pcp)
    173 {
    174 	ppath_component_t *pc;
    175 
    176 	if (p == NULL || p->p_len == 0)
    177 		return NULL;
    178 
    179 	pc = p->p_cmpt[--p->p_len];
    180 
    181 	if (pcp != NULL)
    182 		*pcp = pc;
    183 	else
    184 		ppath_component_release(pc);
    185 
    186 	return p;
    187 }
    188 
    189 ppath_t *
    190 ppath_push(ppath_t *p, ppath_component_t *pc)
    191 {
    192 	if (p == NULL || p->p_len == __arraycount(p->p_cmpt))
    193 		return NULL;
    194 
    195 	p->p_cmpt[p->p_len++] = ppath_component_retain(pc);
    196 
    197 	return p;
    198 }
    199 
    200 ppath_component_t *
    201 ppath_component_at(const ppath_t *p, unsigned int i)
    202 {
    203 	ppath_component_t *pc;
    204 
    205 	if (p == NULL || i >= p->p_len)
    206 		return NULL;
    207 
    208 	pc = p->p_cmpt[i];
    209 
    210 	return ppath_component_retain(pc);
    211 }
    212 
    213 unsigned int
    214 ppath_length(const ppath_t *p)
    215 {
    216 	return p->p_len;
    217 }
    218 
    219 ppath_t *
    220 ppath_subpath(const ppath_t *p, unsigned int first, unsigned int exclast)
    221 {
    222 	unsigned int i;
    223 	ppath_t *np;
    224 	ppath_component_t *pc;
    225 
    226 	if (p == NULL || (np = ppath_create()) == NULL)
    227 		return NULL;
    228 
    229 	for (i = first; i < exclast; i++) {
    230 		if ((pc = ppath_component_at(p, i)) == NULL)
    231 			break;
    232 		ppath_push(np, pc);
    233 		ppath_component_release(pc);
    234 	}
    235 	return np;
    236 }
    237 
    238 ppath_t *
    239 ppath_push_idx(ppath_t *p0, unsigned int idx)
    240 {
    241 	ppath_component_t *pc;
    242 	ppath_t *p;
    243 
    244 	if ((pc = ppath_idx(idx)) == NULL)
    245 		return NULL;
    246 
    247 	p = ppath_push(p0, pc);
    248 	ppath_component_release(pc);
    249 	return p;
    250 }
    251 
    252 ppath_t *
    253 ppath_push_key(ppath_t *p0, const char *key)
    254 {
    255 	ppath_component_t *pc;
    256 	ppath_t *p;
    257 
    258 	if ((pc = ppath_key(key)) == NULL)
    259 		return NULL;
    260 
    261 	p = ppath_push(p0, pc);
    262 	ppath_component_release(pc);
    263 	return p;
    264 }
    265 
    266 ppath_t *
    267 ppath_replace_idx(ppath_t *p, unsigned int idx)
    268 {
    269 	ppath_component_t *pc0, *pc;
    270 
    271 	if (p == NULL || p->p_len == 0)
    272 		return NULL;
    273 
    274 	pc0 = p->p_cmpt[p->p_len - 1];
    275 
    276 	if (pc0->pc_type != PPATH_T_IDX)
    277 		return NULL;
    278 
    279 	if ((pc = ppath_idx(idx)) == NULL)
    280 		return NULL;
    281 
    282 	p->p_cmpt[p->p_len - 1] = pc;
    283 	ppath_component_release(pc0);
    284 
    285 	return p;
    286 }
    287 
    288 ppath_t *
    289 ppath_replace_key(ppath_t *p, const char *key)
    290 {
    291 	ppath_component_t *pc0, *pc;
    292 
    293 	if (p == NULL || p->p_len == 0)
    294 		return NULL;
    295 
    296 	pc0 = p->p_cmpt[p->p_len - 1];
    297 
    298 	if (pc0->pc_type != PPATH_T_KEY)
    299 		return NULL;
    300 
    301 	if ((pc = ppath_key(key)) == NULL)
    302 		return NULL;
    303 
    304 	p->p_cmpt[p->p_len - 1] = pc;
    305 	ppath_component_release(pc0);
    306 
    307 	return p;
    308 }
    309 
    310 ppath_t *
    311 ppath_copy(const ppath_t *p0)
    312 {
    313 	ppath_t *p;
    314 	unsigned int i;
    315 
    316 	if ((p = ppath_create()) == NULL)
    317 		return NULL;
    318 
    319 	for (i = 0; i < p0->p_len; i++)
    320 		p->p_cmpt[i] = ppath_component_retain(p0->p_cmpt[i]);
    321 	p->p_len = p0->p_len;
    322 	return p;
    323 }
    324 
    325 ppath_t *
    326 ppath_retain(ppath_t *p)
    327 {
    328 	assert(p->p_refcnt != 0);
    329 
    330 	p->p_refcnt++;
    331 
    332 	return p;
    333 }
    334 
    335 void
    336 ppath_release(ppath_t *p)
    337 {
    338 	unsigned int i;
    339 
    340 	assert(p->p_refcnt != 0);
    341 
    342 	if (--p->p_refcnt != 0)
    343 		return;
    344 
    345 	for (i = 0; i < p->p_len; i++)
    346 		ppath_component_release(p->p_cmpt[i]);
    347 
    348 	ppath_extant_dec();
    349 	ppath_free(p, sizeof(*p));
    350 }
    351 
    352 static prop_object_t
    353 ppath_lookup_helper(prop_object_t o0, const ppath_t *p, prop_object_t *pop,
    354     ppath_component_t **pcp, unsigned int *ip)
    355 {
    356 	unsigned int i;
    357 	prop_object_t o, po;
    358 	ppath_type_t t;
    359 	ppath_component_t *pc = NULL;
    360 
    361 	for (po = NULL, o = o0, i = 0; i < p->p_len && o != NULL; i++) {
    362 		pc = p->p_cmpt[i];
    363 		t = pc->pc_type;
    364 		switch (prop_object_type(o)) {
    365 		case PROP_TYPE_ARRAY:
    366 			po = o;
    367 			o = (t == PPATH_T_IDX)
    368 			    ? prop_array_get(o, pc->pc_idx)
    369 			    : NULL;
    370 			break;
    371 		case PROP_TYPE_DICTIONARY:
    372 			po = o;
    373 			o = (t == PPATH_T_KEY)
    374 			    ? prop_dictionary_get(o, pc->pc_key)
    375 			    : NULL;
    376 			break;
    377 		default:
    378 			o = NULL;
    379 			break;
    380 		}
    381 	}
    382 	if (pop != NULL)
    383 		*pop = po;
    384 	if (pcp != NULL)
    385 		*pcp = pc;
    386 	if (ip != NULL)
    387 		*ip = i;
    388 	return o;
    389 }
    390 
    391 prop_object_t
    392 ppath_lookup(prop_object_t o, const ppath_t *p)
    393 {
    394 	return ppath_lookup_helper(o, p, NULL, NULL, NULL);
    395 }
    396 
    397 static int
    398 ppath_create_object_and_release(prop_object_t o, const ppath_t *p,
    399     prop_object_t v)
    400 {
    401 	int rc;
    402 
    403 	rc = ppath_create_object(o, p, v);
    404 	prop_object_release(v);
    405 	return rc;
    406 }
    407 
    408 int
    409 ppath_create_string(prop_object_t o, const ppath_t *p, const char *s)
    410 {
    411 	return ppath_create_object_and_release(o, p,
    412 	    prop_string_create_cstring(s));
    413 }
    414 
    415 int
    416 ppath_create_data(prop_object_t o, const ppath_t *p,
    417     const void *data, size_t size)
    418 {
    419 	return ppath_create_object_and_release(o, p,
    420 	    prop_data_create_data(data, size));
    421 }
    422 
    423 int
    424 ppath_create_uint64(prop_object_t o, const ppath_t *p, uint64_t u)
    425 {
    426 	return ppath_create_object_and_release(o, p,
    427 	    prop_number_create_unsigned_integer(u));
    428 }
    429 
    430 int
    431 ppath_create_int64(prop_object_t o, const ppath_t *p, int64_t i)
    432 {
    433 	return ppath_create_object_and_release(o, p,
    434 	    prop_number_create_integer(i));
    435 }
    436 
    437 int
    438 ppath_create_bool(prop_object_t o, const ppath_t *p, bool b)
    439 {
    440 	return ppath_create_object_and_release(o, p, prop_bool_create(b));
    441 }
    442 
    443 int
    444 ppath_create_object(prop_object_t o, const ppath_t *p, prop_object_t v)
    445 {
    446 	unsigned int i;
    447 	ppath_component_t *pc;
    448 	prop_object_t po;
    449 
    450 	if (ppath_lookup_helper(o, p, &po, &pc, &i) != NULL)
    451 		return EEXIST;
    452 
    453 	if (i != ppath_length(p))
    454 		return ENOENT;
    455 
    456 	switch (pc->pc_type) {
    457 	case PPATH_T_IDX:
    458 		return prop_array_set(po, pc->pc_idx, v) ? 0 : ENOMEM;
    459 	case PPATH_T_KEY:
    460 		return prop_dictionary_set(po, pc->pc_key, v) ? 0 : ENOMEM;
    461 	default:
    462 		return ENOENT;
    463 	}
    464 }
    465 
    466 int
    467 ppath_set_object(prop_object_t o, const ppath_t *p, prop_object_t v)
    468 {
    469 	ppath_component_t *pc;
    470 	prop_object_t po;
    471 
    472 	if (ppath_lookup_helper(o, p, &po, &pc, NULL) == NULL)
    473 		return ENOENT;
    474 
    475 	switch (pc->pc_type) {
    476 	case PPATH_T_IDX:
    477 		return prop_array_set(po, pc->pc_idx, v) ? 0 : ENOMEM;
    478 	case PPATH_T_KEY:
    479 		return prop_dictionary_set(po, pc->pc_key, v) ? 0 : ENOMEM;
    480 	default:
    481 		return ENOENT;
    482 	}
    483 }
    484 
    485 static int
    486 ppath_set_object_and_release(prop_object_t o, const ppath_t *p, prop_object_t v)
    487 {
    488 	prop_object_t ov;
    489 	int rc;
    490 
    491 	if (v == NULL)
    492 		return ENOMEM;
    493 
    494 	if ((ov = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    495 		return ENOENT;
    496 
    497 	if (prop_object_type(ov) != prop_object_type(v))
    498 		return EFTYPE;
    499 
    500 	rc = ppath_set_object(o, p, v);
    501 	prop_object_release(v);
    502 	return rc;
    503 }
    504 
    505 int
    506 ppath_get_object(prop_object_t o, const ppath_t *p, prop_object_t *vp)
    507 {
    508 	prop_object_t v;
    509 
    510 	if ((v = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    511 		return ENOENT;
    512 
    513 	if (vp != NULL)
    514 		*vp = v;
    515 	return 0;
    516 }
    517 
    518 static int
    519 ppath_get_object_of_type(prop_object_t o, const ppath_t *p, prop_object_t *vp,
    520     prop_type_t t)
    521 {
    522 	int rc;
    523 
    524 	if ((rc = ppath_get_object(o, p, vp)) != 0)
    525 		return rc;
    526 
    527 	return (prop_object_type(*vp) == t) ? 0 : EFTYPE;
    528 }
    529 
    530 int
    531 ppath_delete_object(prop_object_t o, const ppath_t *p)
    532 {
    533 	ppath_component_t *pc;
    534 	prop_object_t po;
    535 
    536 	if (ppath_lookup_helper(o, p, &po, &pc, NULL) == NULL)
    537 		return ENOENT;
    538 
    539 	switch (pc->pc_type) {
    540 	case PPATH_T_IDX:
    541 		prop_array_remove(po, pc->pc_idx);
    542 		return 0;
    543 	case PPATH_T_KEY:
    544 		prop_dictionary_remove(po, pc->pc_key);
    545 		return 0;
    546 	default:
    547 		return ENOENT;
    548 	}
    549 }
    550 
    551 static int
    552 ppath_delete_object_of_type(prop_object_t o, const ppath_t *p, prop_type_t t)
    553 {
    554 	prop_object_t v;
    555 
    556 	if ((v = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    557 		return ENOENT;
    558 
    559 	if (prop_object_type(v) != t)
    560 		return EFTYPE;
    561 
    562 	return ppath_delete_object(o, p);
    563 }
    564 
    565 int
    566 ppath_copydel_string(prop_object_t o, prop_object_t *op, const ppath_t *p)
    567 {
    568 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_STRING);
    569 }
    570 
    571 int
    572 ppath_copydel_data(prop_object_t o, prop_object_t *op, const ppath_t *p)
    573 {
    574 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_DATA);
    575 }
    576 
    577 int
    578 ppath_copydel_uint64(prop_object_t o, prop_object_t *op, const ppath_t *p)
    579 {
    580 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_NUMBER);
    581 }
    582 
    583 int
    584 ppath_copydel_int64(prop_object_t o, prop_object_t *op, const ppath_t *p)
    585 {
    586 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_NUMBER);
    587 }
    588 
    589 int
    590 ppath_copydel_bool(prop_object_t o, prop_object_t *op, const ppath_t *p)
    591 {
    592 	return ppath_copydel_object_of_type(o, op, p, PROP_TYPE_BOOL);
    593 }
    594 
    595 static int
    596 ppath_copydel_object_of_type(prop_object_t o, prop_object_t *op,
    597     const ppath_t *p, prop_type_t t)
    598 {
    599 	prop_object_t v;
    600 
    601 	if ((v = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    602 		return ENOENT;
    603 
    604 	if (prop_object_type(v) != t)
    605 		return EFTYPE;
    606 
    607 	return ppath_copydel_object(o, op, p);
    608 }
    609 
    610 int
    611 ppath_copydel_object(prop_object_t o, prop_object_t *op, const ppath_t *p)
    612 {
    613 	return ppath_copyset_object_helper(o, op, p, NULL);
    614 }
    615 
    616 int
    617 ppath_copyset_object(prop_object_t o, prop_object_t *op, const ppath_t *p,
    618     const prop_object_t v)
    619 {
    620 	ppath_assert(v != NULL);
    621 	return ppath_copyset_object_helper(o, op, p, v);
    622 }
    623 
    624 static int
    625 ppath_copyset_object_helper(prop_object_t o, prop_object_t *op,
    626     const ppath_t *p0, const prop_object_t v0)
    627 {
    628 	bool copy, success;
    629 	ppath_component_t *npc, *pc;
    630 	ppath_t *cp, *p;
    631 	prop_object_t npo = NULL, po, v;
    632 
    633 	for (cp = p = ppath_copy(p0), v = v0;
    634 	     p != NULL;
    635 	     p = ppath_pop(p, NULL), v = npo) {
    636 
    637 		if (ppath_lookup_helper(o, p, &po, &pc, NULL) == NULL)
    638 			return ENOENT;
    639 
    640 		if (pc == NULL)
    641 			break;
    642 
    643 		if (ppath_lookup_helper(*op, p, &npo, &npc, NULL) == NULL)
    644 			npo = po;
    645 
    646 		copy = (npo == po);
    647 
    648 		switch (pc->pc_type) {
    649 		case PPATH_T_IDX:
    650 			if (copy && (npo = prop_array_copy_mutable(po)) == NULL)
    651 				return ENOMEM;
    652 			success = (v == NULL)
    653 			    ? (prop_array_remove(npo, pc->pc_idx), true)
    654 			    : prop_array_set(npo, pc->pc_idx, v);
    655 			break;
    656 		case PPATH_T_KEY:
    657 			if (copy &&
    658 			    (npo = prop_dictionary_copy_mutable(po)) == NULL)
    659 				return ENOMEM;
    660 			success = (v == NULL)
    661 			    ? (prop_dictionary_remove(npo, pc->pc_key), true)
    662 			    : prop_dictionary_set(npo, pc->pc_key, v);
    663 			break;
    664 		default:
    665 			return ENOENT;
    666 		}
    667 		if (!success) {
    668 			if (copy)
    669 				prop_object_release(npo);
    670 			return ENOMEM;
    671 		}
    672 	}
    673 
    674 	if (cp == NULL)
    675 		return ENOMEM;
    676 
    677 	ppath_release(cp);
    678 
    679 	if (op != NULL && npo != NULL)
    680 		*op = npo;
    681 	else if (npo != NULL)
    682 		prop_object_release(npo);
    683 
    684 	return 0;
    685 }
    686 
    687 static int
    688 ppath_copyset_object_and_release(prop_object_t o, prop_object_t *op,
    689     const ppath_t *p, prop_object_t v)
    690 {
    691 	prop_object_t ov;
    692 	int rc;
    693 
    694 	if (v == NULL)
    695 		return ENOMEM;
    696 
    697 	if ((ov = ppath_lookup_helper(o, p, NULL, NULL, NULL)) == NULL)
    698 		return ENOENT;
    699 
    700 	if (prop_object_type(ov) != prop_object_type(v))
    701 		return EFTYPE;
    702 
    703 	rc = ppath_copyset_object(o, op, p, v);
    704 	prop_object_release(v);
    705 	return rc;
    706 }
    707 
    708 int
    709 ppath_copyset_bool(prop_object_t o, prop_object_t *op, const ppath_t *p, bool b)
    710 {
    711 	return ppath_copyset_object_and_release(o, op, p, prop_bool_create(b));
    712 }
    713 
    714 int
    715 ppath_set_bool(prop_object_t o, const ppath_t *p, bool b)
    716 {
    717 	return ppath_set_object_and_release(o, p, prop_bool_create(b));
    718 }
    719 
    720 int
    721 ppath_get_bool(prop_object_t o, const ppath_t *p, bool *bp)
    722 {
    723 	prop_object_t v;
    724 	int rc;
    725 
    726 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_BOOL)) != 0)
    727 		return rc;
    728 
    729 	if (bp != NULL)
    730 		*bp = prop_bool_true(v);
    731 
    732 	return 0;
    733 }
    734 
    735 int
    736 ppath_delete_bool(prop_object_t o, const ppath_t *p)
    737 {
    738 	return ppath_delete_object_of_type(o, p, PROP_TYPE_BOOL);
    739 }
    740 
    741 int
    742 ppath_copyset_data(prop_object_t o, prop_object_t *op, const ppath_t *p,
    743     const void *data, size_t size)
    744 {
    745 	return ppath_copyset_object_and_release(o, op, p,
    746 	    prop_data_create_data(data, size));
    747 }
    748 
    749 int
    750 ppath_set_data(prop_object_t o, const ppath_t *p, const void *data, size_t size)
    751 {
    752 	return ppath_set_object_and_release(o, p,
    753 	    prop_data_create_data(data, size));
    754 }
    755 
    756 int
    757 ppath_get_data(prop_object_t o, const ppath_t *p, const void **datap,
    758     size_t *sizep)
    759 {
    760 	prop_object_t v;
    761 	int rc;
    762 
    763 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_DATA)) != 0)
    764 		return rc;
    765 
    766 	if (datap != NULL)
    767 		*datap = prop_data_data_nocopy(v);
    768 	if (sizep != NULL)
    769 		*sizep = prop_data_size(v);
    770 
    771 	return 0;
    772 }
    773 
    774 int
    775 ppath_dup_data(prop_object_t o, const ppath_t *p, void **datap, size_t *sizep)
    776 {
    777 	prop_object_t v;
    778 	int rc;
    779 
    780 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_DATA)) != 0)
    781 		return rc;
    782 
    783 	if (datap != NULL)
    784 		*datap = prop_data_data(v);
    785 	if (sizep != NULL)
    786 		*sizep = prop_data_size(v);
    787 
    788 	return 0;
    789 }
    790 
    791 int
    792 ppath_delete_data(prop_object_t o, const ppath_t *p)
    793 {
    794 	return ppath_delete_object_of_type(o, p, PROP_TYPE_DATA);
    795 }
    796 
    797 int
    798 ppath_copyset_int64(prop_object_t o, prop_object_t *op, const ppath_t *p,
    799     int64_t i)
    800 {
    801 	return ppath_copyset_object_and_release(o, op, p,
    802 	    prop_number_create_integer(i));
    803 }
    804 
    805 int
    806 ppath_set_int64(prop_object_t o, const ppath_t *p, int64_t i)
    807 {
    808 	return ppath_set_object_and_release(o, p,
    809 	    prop_number_create_integer(i));
    810 }
    811 
    812 int
    813 ppath_get_int64(prop_object_t o, const ppath_t *p, int64_t *ip)
    814 {
    815 	prop_object_t v;
    816 	int rc;
    817 
    818 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_DATA)) != 0)
    819 		return rc;
    820 
    821 	if (prop_number_unsigned(v))
    822 		return EFTYPE;
    823 
    824 	if (ip != NULL)
    825 		*ip = prop_number_integer_value(v);
    826 
    827 	return 0;
    828 }
    829 
    830 int
    831 ppath_delete_int64(prop_object_t o, const ppath_t *p)
    832 {
    833 	return ppath_delete_object_of_type(o, p, PROP_TYPE_NUMBER);
    834 }
    835 
    836 int
    837 ppath_copyset_string(prop_object_t o, prop_object_t *op, const ppath_t *p,
    838     const char *s)
    839 {
    840 	return ppath_copyset_object_and_release(o, op, p,
    841 	    prop_string_create_cstring(s));
    842 }
    843 
    844 int
    845 ppath_set_string(prop_object_t o, const ppath_t *p, const char *s)
    846 {
    847 	return ppath_set_object_and_release(o, p,
    848 	    prop_string_create_cstring(s));
    849 }
    850 
    851 int
    852 ppath_get_string(prop_object_t o, const ppath_t *p, const char **sp)
    853 {
    854 	int rc;
    855 	prop_object_t v;
    856 
    857 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_STRING)) != 0)
    858 		return rc;
    859 
    860 	if (sp != NULL)
    861 		*sp = prop_string_cstring_nocopy(v);
    862 
    863 	return 0;
    864 }
    865 
    866 int
    867 ppath_dup_string(prop_object_t o, const ppath_t *p, char **sp)
    868 {
    869 	int rc;
    870 	prop_object_t v;
    871 
    872 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_STRING)) != 0)
    873 		return rc;
    874 
    875 	if (sp != NULL)
    876 		*sp = prop_string_cstring(v);
    877 
    878 	return 0;
    879 }
    880 
    881 int
    882 ppath_delete_string(prop_object_t o, const ppath_t *p)
    883 {
    884 	return ppath_delete_object_of_type(o, p, PROP_TYPE_STRING);
    885 }
    886 
    887 int
    888 ppath_copyset_uint64(prop_object_t o, prop_object_t *op, const ppath_t *p,
    889     uint64_t u)
    890 {
    891 	return ppath_copyset_object_and_release(o, op, p,
    892 	    prop_number_create_unsigned_integer(u));
    893 }
    894 
    895 int
    896 ppath_set_uint64(prop_object_t o, const ppath_t *p, uint64_t u)
    897 {
    898 	return ppath_set_object_and_release(o, p,
    899 	    prop_number_create_unsigned_integer(u));
    900 }
    901 
    902 int
    903 ppath_get_uint64(prop_object_t o, const ppath_t *p, uint64_t *up)
    904 {
    905 	prop_object_t v;
    906 	int rc;
    907 
    908 	if ((rc = ppath_get_object_of_type(o, p, &v, PROP_TYPE_DATA)) != 0)
    909 		return rc;
    910 
    911 	if (!prop_number_unsigned(v))
    912 		return EFTYPE;
    913 
    914 	if (up != NULL)
    915 		*up = prop_number_unsigned_integer_value(v);
    916 
    917 	return 0;
    918 }
    919 
    920 int
    921 ppath_delete_uint64(prop_object_t o, const ppath_t *p)
    922 {
    923 	return ppath_delete_object_of_type(o, p, PROP_TYPE_NUMBER);
    924 }
    925