xref: /netbsd-src/common/lib/libppath/ppath.c (revision 33ce21e27d1c67d4ec652b9a5aa092ee2684f8d2)
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@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