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