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