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