1 /* Copyright (c) 2013, Vsevolod Stakhov 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * 12 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 */ 23 24 #include "ucl.h" 25 #include "ucl_internal.h" 26 #include "ucl_chartable.h" 27 #include "kvec.h" 28 29 #ifndef _WIN32 30 #include <glob.h> 31 #endif 32 33 #ifdef HAVE_LIBGEN_H 34 #include <libgen.h> /* For dirname */ 35 #endif 36 37 typedef kvec_t(ucl_object_t *) ucl_array_t; 38 39 #define UCL_ARRAY_GET(ar, obj) ucl_array_t *ar = \ 40 (ucl_array_t *)((obj) != NULL ? (obj)->value.av : NULL) 41 42 #ifdef HAVE_OPENSSL 43 #include <openssl/err.h> 44 #include <openssl/sha.h> 45 #include <openssl/rsa.h> 46 #include <openssl/ssl.h> 47 #include <openssl/evp.h> 48 #endif 49 50 #ifdef CURL_FOUND 51 #include <curl/curl.h> 52 #endif 53 #ifdef HAVE_FETCH_H 54 #include <fetch.h> 55 #endif 56 57 #ifdef _WIN32 58 #include <windows.h> 59 60 #ifndef PROT_READ 61 #define PROT_READ 1 62 #endif 63 #ifndef PROT_WRITE 64 #define PROT_WRITE 2 65 #endif 66 #ifndef PROT_READWRITE 67 #define PROT_READWRITE 3 68 #endif 69 #ifndef MAP_SHARED 70 #define MAP_SHARED 1 71 #endif 72 #ifndef MAP_PRIVATE 73 #define MAP_PRIVATE 2 74 #endif 75 #ifndef MAP_FAILED 76 #define MAP_FAILED ((void *) -1) 77 #endif 78 79 #ifdef _WIN32 80 #include <limits.h> 81 #define NBBY CHAR_BIT 82 #endif 83 84 static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset) 85 { 86 void *map = NULL; 87 HANDLE handle = INVALID_HANDLE_VALUE; 88 89 switch (prot) { 90 default: 91 case PROT_READ: 92 { 93 handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0); 94 if (!handle) break; 95 map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length); 96 CloseHandle(handle); 97 break; 98 } 99 case PROT_WRITE: 100 { 101 handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0); 102 if (!handle) break; 103 map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length); 104 CloseHandle(handle); 105 break; 106 } 107 case PROT_READWRITE: 108 { 109 handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0); 110 if (!handle) break; 111 map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length); 112 CloseHandle(handle); 113 break; 114 } 115 } 116 if (map == (void *) NULL) { 117 return (void *) MAP_FAILED; 118 } 119 return (void *) ((char *) map + offset); 120 } 121 122 static int ucl_munmap(void *map,size_t length) 123 { 124 if (!UnmapViewOfFile(map)) { 125 return(-1); 126 } 127 return(0); 128 } 129 130 static char* ucl_realpath(const char *path, char *resolved_path) { 131 char *p; 132 char tmp[MAX_PATH + 1]; 133 strncpy(tmp, path, sizeof(tmp)-1); 134 p = tmp; 135 while(*p) { 136 if (*p == '/') *p = '\\'; 137 p++; 138 } 139 return _fullpath(resolved_path, tmp, MAX_PATH); 140 } 141 #else 142 #define ucl_mmap mmap 143 #define ucl_munmap munmap 144 #define ucl_realpath realpath 145 #endif 146 147 typedef void (*ucl_object_dtor) (ucl_object_t *obj); 148 static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, 149 ucl_object_dtor dtor); 150 static void ucl_object_dtor_unref (ucl_object_t *obj); 151 152 static void 153 ucl_object_dtor_free (ucl_object_t *obj) 154 { 155 if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { 156 UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]); 157 } 158 if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { 159 UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]); 160 } 161 /* Do not free ephemeral objects */ 162 if ((obj->flags & UCL_OBJECT_EPHEMERAL) == 0) { 163 if (obj->type != UCL_USERDATA) { 164 UCL_FREE (sizeof (ucl_object_t), obj); 165 } 166 else { 167 struct ucl_object_userdata *ud = (struct ucl_object_userdata *)obj; 168 if (ud->dtor) { 169 ud->dtor (obj->value.ud); 170 } 171 UCL_FREE (sizeof (*ud), obj); 172 } 173 } 174 } 175 176 /* 177 * This is a helper function that performs exactly the same as 178 * `ucl_object_unref` but it doesn't iterate over elements allowing 179 * to use it for individual elements of arrays and multiple values 180 */ 181 static void 182 ucl_object_dtor_unref_single (ucl_object_t *obj) 183 { 184 if (obj != NULL) { 185 #ifdef HAVE_ATOMIC_BUILTINS 186 unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1); 187 if (rc == 0) { 188 #else 189 if (--obj->ref == 0) { 190 #endif 191 ucl_object_free_internal (obj, false, ucl_object_dtor_unref); 192 } 193 } 194 } 195 196 static void 197 ucl_object_dtor_unref (ucl_object_t *obj) 198 { 199 if (obj->ref == 0) { 200 ucl_object_dtor_free (obj); 201 } 202 else { 203 /* This may cause dtor unref being called one more time */ 204 ucl_object_dtor_unref_single (obj); 205 } 206 } 207 208 static void 209 ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor) 210 { 211 ucl_object_t *tmp, *sub; 212 213 while (obj != NULL) { 214 if (obj->type == UCL_ARRAY) { 215 UCL_ARRAY_GET (vec, obj); 216 unsigned int i; 217 218 if (vec != NULL) { 219 for (i = 0; i < vec->n; i ++) { 220 sub = kv_A (*vec, i); 221 if (sub != NULL) { 222 tmp = sub; 223 while (sub) { 224 tmp = sub->next; 225 dtor (sub); 226 sub = tmp; 227 } 228 } 229 } 230 kv_destroy (*vec); 231 UCL_FREE (sizeof (*vec), vec); 232 } 233 } 234 else if (obj->type == UCL_OBJECT) { 235 if (obj->value.ov != NULL) { 236 ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)dtor); 237 } 238 } 239 tmp = obj->next; 240 dtor (obj); 241 obj = tmp; 242 243 if (!allow_rec) { 244 break; 245 } 246 } 247 } 248 249 void 250 ucl_object_free (ucl_object_t *obj) 251 { 252 ucl_object_free_internal (obj, true, ucl_object_dtor_free); 253 } 254 255 size_t 256 ucl_unescape_json_string (char *str, size_t len) 257 { 258 char *t = str, *h = str; 259 int i, uval; 260 261 if (len <= 1) { 262 return len; 263 } 264 /* t is target (tortoise), h is source (hare) */ 265 266 while (len) { 267 if (*h == '\\') { 268 h ++; 269 switch (*h) { 270 case 'n': 271 *t++ = '\n'; 272 break; 273 case 'r': 274 *t++ = '\r'; 275 break; 276 case 'b': 277 *t++ = '\b'; 278 break; 279 case 't': 280 *t++ = '\t'; 281 break; 282 case 'f': 283 *t++ = '\f'; 284 break; 285 case '\\': 286 *t++ = '\\'; 287 break; 288 case '"': 289 *t++ = '"'; 290 break; 291 case 'u': 292 /* Unicode escape */ 293 uval = 0; 294 if (len > 3) { 295 for (i = 0; i < 4; i++) { 296 uval <<= 4; 297 if (isdigit (h[i])) { 298 uval += h[i] - '0'; 299 } 300 else if (h[i] >= 'a' && h[i] <= 'f') { 301 uval += h[i] - 'a' + 10; 302 } 303 else if (h[i] >= 'A' && h[i] <= 'F') { 304 uval += h[i] - 'A' + 10; 305 } 306 else { 307 break; 308 } 309 } 310 h += 3; 311 len -= 3; 312 /* Encode */ 313 if(uval < 0x80) { 314 t[0] = (char)uval; 315 t ++; 316 } 317 else if(uval < 0x800) { 318 t[0] = 0xC0 + ((uval & 0x7C0) >> 6); 319 t[1] = 0x80 + ((uval & 0x03F)); 320 t += 2; 321 } 322 else if(uval < 0x10000) { 323 t[0] = 0xE0 + ((uval & 0xF000) >> 12); 324 t[1] = 0x80 + ((uval & 0x0FC0) >> 6); 325 t[2] = 0x80 + ((uval & 0x003F)); 326 t += 3; 327 } 328 else if(uval <= 0x10FFFF) { 329 t[0] = 0xF0 + ((uval & 0x1C0000) >> 18); 330 t[1] = 0x80 + ((uval & 0x03F000) >> 12); 331 t[2] = 0x80 + ((uval & 0x000FC0) >> 6); 332 t[3] = 0x80 + ((uval & 0x00003F)); 333 t += 4; 334 } 335 else { 336 *t++ = '?'; 337 } 338 } 339 else { 340 *t++ = 'u'; 341 } 342 break; 343 default: 344 *t++ = *h; 345 break; 346 } 347 h ++; 348 len --; 349 } 350 else { 351 *t++ = *h++; 352 } 353 len --; 354 } 355 *t = '\0'; 356 357 return (t - str); 358 } 359 360 char * 361 ucl_copy_key_trash (const ucl_object_t *obj) 362 { 363 ucl_object_t *deconst; 364 365 if (obj == NULL) { 366 return NULL; 367 } 368 if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) { 369 deconst = __DECONST (ucl_object_t *, obj); 370 deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1); 371 if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) { 372 memcpy (deconst->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen); 373 deconst->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0'; 374 } 375 deconst->key = obj->trash_stack[UCL_TRASH_KEY]; 376 deconst->flags |= UCL_OBJECT_ALLOCATED_KEY; 377 } 378 379 return obj->trash_stack[UCL_TRASH_KEY]; 380 } 381 382 char * 383 ucl_copy_value_trash (const ucl_object_t *obj) 384 { 385 ucl_object_t *deconst; 386 387 if (obj == NULL) { 388 return NULL; 389 } 390 if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) { 391 deconst = __DECONST (ucl_object_t *, obj); 392 if (obj->type == UCL_STRING) { 393 394 /* Special case for strings */ 395 deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1); 396 if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) { 397 memcpy (deconst->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len); 398 deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0'; 399 deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE]; 400 } 401 } 402 else { 403 /* Just emit value in json notation */ 404 deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj); 405 deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]); 406 } 407 deconst->flags |= UCL_OBJECT_ALLOCATED_VALUE; 408 } 409 return obj->trash_stack[UCL_TRASH_VALUE]; 410 } 411 412 UCL_EXTERN ucl_object_t* 413 ucl_parser_get_object (struct ucl_parser *parser) 414 { 415 if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) { 416 return ucl_object_ref (parser->top_obj); 417 } 418 419 return NULL; 420 } 421 422 UCL_EXTERN void 423 ucl_parser_free (struct ucl_parser *parser) 424 { 425 struct ucl_stack *stack, *stmp; 426 struct ucl_macro *macro, *mtmp; 427 struct ucl_chunk *chunk, *ctmp; 428 struct ucl_pubkey *key, *ktmp; 429 struct ucl_variable *var, *vtmp; 430 431 if (parser == NULL) { 432 return; 433 } 434 435 if (parser->top_obj != NULL) { 436 ucl_object_unref (parser->top_obj); 437 } 438 439 LL_FOREACH_SAFE (parser->stack, stack, stmp) { 440 free (stack); 441 } 442 HASH_ITER (hh, parser->macroes, macro, mtmp) { 443 free (macro->name); 444 HASH_DEL (parser->macroes, macro); 445 UCL_FREE (sizeof (struct ucl_macro), macro); 446 } 447 LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) { 448 UCL_FREE (sizeof (struct ucl_chunk), chunk); 449 } 450 LL_FOREACH_SAFE (parser->keys, key, ktmp) { 451 UCL_FREE (sizeof (struct ucl_pubkey), key); 452 } 453 LL_FOREACH_SAFE (parser->variables, var, vtmp) { 454 free (var->value); 455 free (var->var); 456 UCL_FREE (sizeof (struct ucl_variable), var); 457 } 458 459 if (parser->err != NULL) { 460 utstring_free (parser->err); 461 } 462 463 if (parser->cur_file) { 464 free (parser->cur_file); 465 } 466 467 UCL_FREE (sizeof (struct ucl_parser), parser); 468 } 469 470 UCL_EXTERN const char * 471 ucl_parser_get_error(struct ucl_parser *parser) 472 { 473 if (parser == NULL) { 474 return NULL; 475 } 476 477 if (parser->err == NULL) 478 return NULL; 479 480 return utstring_body(parser->err); 481 } 482 483 UCL_EXTERN void 484 ucl_parser_clear_error(struct ucl_parser *parser) 485 { 486 if (parser != NULL && parser->err != NULL) { 487 utstring_free(parser->err); 488 parser->err = NULL; 489 } 490 } 491 492 UCL_EXTERN bool 493 ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) 494 { 495 #ifndef HAVE_OPENSSL 496 ucl_create_err (&parser->err, "cannot check signatures without openssl"); 497 return false; 498 #else 499 # if (OPENSSL_VERSION_NUMBER < 0x10000000L) 500 ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported"); 501 return EXIT_FAILURE; 502 # else 503 struct ucl_pubkey *nkey; 504 BIO *mem; 505 506 mem = BIO_new_mem_buf ((void *)key, len); 507 nkey = UCL_ALLOC (sizeof (struct ucl_pubkey)); 508 if (nkey == NULL) { 509 ucl_create_err (&parser->err, "cannot allocate memory for key"); 510 return false; 511 } 512 nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL); 513 BIO_free (mem); 514 if (nkey->key == NULL) { 515 UCL_FREE (sizeof (struct ucl_pubkey), nkey); 516 ucl_create_err (&parser->err, "%s", 517 ERR_error_string (ERR_get_error (), NULL)); 518 return false; 519 } 520 LL_PREPEND (parser->keys, nkey); 521 # endif 522 #endif 523 return true; 524 } 525 526 #ifdef CURL_FOUND 527 struct ucl_curl_cbdata { 528 unsigned char *buf; 529 size_t buflen; 530 }; 531 532 static size_t 533 ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud) 534 { 535 struct ucl_curl_cbdata *cbdata = ud; 536 size_t realsize = size * nmemb; 537 538 cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1); 539 if (cbdata->buf == NULL) { 540 return 0; 541 } 542 543 memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize); 544 cbdata->buflen += realsize; 545 cbdata->buf[cbdata->buflen] = 0; 546 547 return realsize; 548 } 549 #endif 550 551 /** 552 * Fetch a url and save results to the memory buffer 553 * @param url url to fetch 554 * @param len length of url 555 * @param buf target buffer 556 * @param buflen target length 557 * @return 558 */ 559 static bool 560 ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen, 561 UT_string **err, bool must_exist) 562 { 563 564 #ifdef HAVE_FETCH_H 565 struct url *fetch_url; 566 struct url_stat us; 567 FILE *in; 568 569 fetch_url = fetchParseURL (url); 570 if (fetch_url == NULL) { 571 ucl_create_err (err, "invalid URL %s: %s", 572 url, strerror (errno)); 573 return false; 574 } 575 if ((in = fetchXGet (fetch_url, &us, "")) == NULL) { 576 if (!must_exist) { 577 ucl_create_err (err, "cannot fetch URL %s: %s", 578 url, strerror (errno)); 579 } 580 fetchFreeURL (fetch_url); 581 return false; 582 } 583 584 *buflen = us.size; 585 *buf = malloc (*buflen); 586 if (*buf == NULL) { 587 ucl_create_err (err, "cannot allocate buffer for URL %s: %s", 588 url, strerror (errno)); 589 fclose (in); 590 fetchFreeURL (fetch_url); 591 return false; 592 } 593 594 if (fread (*buf, *buflen, 1, in) != 1) { 595 ucl_create_err (err, "cannot read URL %s: %s", 596 url, strerror (errno)); 597 fclose (in); 598 fetchFreeURL (fetch_url); 599 return false; 600 } 601 602 fetchFreeURL (fetch_url); 603 return true; 604 #elif defined(CURL_FOUND) 605 CURL *curl; 606 int r; 607 struct ucl_curl_cbdata cbdata; 608 609 curl = curl_easy_init (); 610 if (curl == NULL) { 611 ucl_create_err (err, "CURL interface is broken"); 612 return false; 613 } 614 if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) { 615 ucl_create_err (err, "invalid URL %s: %s", 616 url, curl_easy_strerror (r)); 617 curl_easy_cleanup (curl); 618 return false; 619 } 620 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback); 621 cbdata.buf = *buf; 622 cbdata.buflen = *buflen; 623 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata); 624 625 if ((r = curl_easy_perform (curl)) != CURLE_OK) { 626 if (!must_exist) { 627 ucl_create_err (err, "error fetching URL %s: %s", 628 url, curl_easy_strerror (r)); 629 } 630 curl_easy_cleanup (curl); 631 if (cbdata.buf) { 632 free (cbdata.buf); 633 } 634 return false; 635 } 636 *buf = cbdata.buf; 637 *buflen = cbdata.buflen; 638 639 return true; 640 #else 641 ucl_create_err (err, "URL support is disabled"); 642 return false; 643 #endif 644 } 645 646 /** 647 * Fetch a file and save results to the memory buffer 648 * @param filename filename to fetch 649 * @param len length of filename 650 * @param buf target buffer 651 * @param buflen target length 652 * @return 653 */ 654 static bool 655 ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen, 656 UT_string **err, bool must_exist) 657 { 658 int fd; 659 struct stat st; 660 661 if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) { 662 if (must_exist) { 663 ucl_create_err (err, "cannot stat file %s: %s", 664 filename, strerror (errno)); 665 } 666 return false; 667 } 668 if (st.st_size == 0) { 669 /* Do not map empty files */ 670 *buf = ""; 671 *buflen = 0; 672 } 673 else { 674 if ((fd = open (filename, O_RDONLY)) == -1) { 675 ucl_create_err (err, "cannot open file %s: %s", 676 filename, strerror (errno)); 677 return false; 678 } 679 if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 680 close (fd); 681 ucl_create_err (err, "cannot mmap file %s: %s", 682 filename, strerror (errno)); 683 return false; 684 } 685 *buflen = st.st_size; 686 close (fd); 687 } 688 689 return true; 690 } 691 692 693 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 694 static inline bool 695 ucl_sig_check (const unsigned char *data, size_t datalen, 696 const unsigned char *sig, size_t siglen, struct ucl_parser *parser) 697 { 698 struct ucl_pubkey *key; 699 char dig[EVP_MAX_MD_SIZE]; 700 unsigned int diglen; 701 EVP_PKEY_CTX *key_ctx; 702 EVP_MD_CTX *sign_ctx = NULL; 703 704 sign_ctx = EVP_MD_CTX_create (); 705 706 LL_FOREACH (parser->keys, key) { 707 key_ctx = EVP_PKEY_CTX_new (key->key, NULL); 708 if (key_ctx != NULL) { 709 if (EVP_PKEY_verify_init (key_ctx) <= 0) { 710 EVP_PKEY_CTX_free (key_ctx); 711 continue; 712 } 713 if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) { 714 EVP_PKEY_CTX_free (key_ctx); 715 continue; 716 } 717 if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) { 718 EVP_PKEY_CTX_free (key_ctx); 719 continue; 720 } 721 EVP_DigestInit (sign_ctx, EVP_sha256 ()); 722 EVP_DigestUpdate (sign_ctx, data, datalen); 723 EVP_DigestFinal (sign_ctx, dig, &diglen); 724 725 if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) { 726 EVP_MD_CTX_destroy (sign_ctx); 727 EVP_PKEY_CTX_free (key_ctx); 728 return true; 729 } 730 731 EVP_PKEY_CTX_free (key_ctx); 732 } 733 } 734 735 EVP_MD_CTX_destroy (sign_ctx); 736 737 return false; 738 } 739 #endif 740 741 /** 742 * Include an url to configuration 743 * @param data 744 * @param len 745 * @param parser 746 * @param err 747 * @return 748 */ 749 static bool 750 ucl_include_url (const unsigned char *data, size_t len, 751 struct ucl_parser *parser, bool check_signature, bool must_exist, 752 unsigned priority) 753 { 754 755 bool res; 756 unsigned char *buf = NULL; 757 size_t buflen = 0; 758 struct ucl_chunk *chunk; 759 char urlbuf[PATH_MAX]; 760 int prev_state; 761 762 snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data); 763 764 if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, must_exist)) { 765 return (!must_exist || false); 766 } 767 768 if (check_signature) { 769 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 770 unsigned char *sigbuf = NULL; 771 size_t siglen = 0; 772 /* We need to check signature first */ 773 snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data); 774 if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) { 775 return false; 776 } 777 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { 778 ucl_create_err (&parser->err, "cannot verify url %s: %s", 779 urlbuf, 780 ERR_error_string (ERR_get_error (), NULL)); 781 if (siglen > 0) { 782 ucl_munmap (sigbuf, siglen); 783 } 784 return false; 785 } 786 if (siglen > 0) { 787 ucl_munmap (sigbuf, siglen); 788 } 789 #endif 790 } 791 792 prev_state = parser->state; 793 parser->state = UCL_STATE_INIT; 794 795 res = ucl_parser_add_chunk_priority (parser, buf, buflen, priority); 796 if (res == true) { 797 /* Remove chunk from the stack */ 798 chunk = parser->chunks; 799 if (chunk != NULL) { 800 parser->chunks = chunk->next; 801 UCL_FREE (sizeof (struct ucl_chunk), chunk); 802 } 803 } 804 805 parser->state = prev_state; 806 free (buf); 807 808 return res; 809 } 810 811 /** 812 * Include a single file to the parser 813 * @param data 814 * @param len 815 * @param parser 816 * @param check_signature 817 * @param must_exist 818 * @param allow_glob 819 * @param priority 820 * @return 821 */ 822 static bool 823 ucl_include_file_single (const unsigned char *data, size_t len, 824 struct ucl_parser *parser, bool check_signature, bool must_exist, 825 unsigned priority) 826 { 827 bool res; 828 struct ucl_chunk *chunk; 829 unsigned char *buf = NULL; 830 char *old_curfile; 831 size_t buflen; 832 char filebuf[PATH_MAX], realbuf[PATH_MAX]; 833 int prev_state; 834 struct ucl_variable *cur_var, *tmp_var, *old_curdir = NULL, 835 *old_filename = NULL; 836 837 snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data); 838 if (ucl_realpath (filebuf, realbuf) == NULL) { 839 if (!must_exist) { 840 return true; 841 } 842 ucl_create_err (&parser->err, "cannot open file %s: %s", 843 filebuf, 844 strerror (errno)); 845 return false; 846 } 847 848 if (parser->cur_file && strcmp (realbuf, parser->cur_file) == 0) { 849 /* We are likely including the file itself */ 850 ucl_create_err (&parser->err, "trying to include the file %s from itself", 851 realbuf); 852 return false; 853 } 854 855 if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, must_exist)) { 856 return (!must_exist || false); 857 } 858 859 if (check_signature) { 860 #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 861 unsigned char *sigbuf = NULL; 862 size_t siglen = 0; 863 /* We need to check signature first */ 864 snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf); 865 if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) { 866 return false; 867 } 868 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { 869 ucl_create_err (&parser->err, "cannot verify file %s: %s", 870 filebuf, 871 ERR_error_string (ERR_get_error (), NULL)); 872 if (siglen > 0) { 873 ucl_munmap (sigbuf, siglen); 874 } 875 return false; 876 } 877 if (siglen > 0) { 878 ucl_munmap (sigbuf, siglen); 879 } 880 #endif 881 } 882 883 old_curfile = parser->cur_file; 884 parser->cur_file = strdup (realbuf); 885 886 /* Store old file vars */ 887 DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) { 888 if (strcmp (cur_var->var, "CURDIR") == 0) { 889 old_curdir = cur_var; 890 DL_DELETE (parser->variables, cur_var); 891 } 892 else if (strcmp (cur_var->var, "FILENAME") == 0) { 893 old_filename = cur_var; 894 DL_DELETE (parser->variables, cur_var); 895 } 896 } 897 898 ucl_parser_set_filevars (parser, realbuf, false); 899 900 prev_state = parser->state; 901 parser->state = UCL_STATE_INIT; 902 903 res = ucl_parser_add_chunk_priority (parser, buf, buflen, priority); 904 if (!res && !must_exist) { 905 /* Free error */ 906 utstring_free (parser->err); 907 parser->err = NULL; 908 parser->state = UCL_STATE_AFTER_VALUE; 909 } 910 911 /* Remove chunk from the stack */ 912 chunk = parser->chunks; 913 if (chunk != NULL) { 914 parser->chunks = chunk->next; 915 UCL_FREE (sizeof (struct ucl_chunk), chunk); 916 parser->recursion --; 917 } 918 919 /* Restore old file vars */ 920 parser->cur_file = old_curfile; 921 DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) { 922 if (strcmp (cur_var->var, "CURDIR") == 0 && old_curdir) { 923 DL_DELETE (parser->variables, cur_var); 924 free (cur_var->var); 925 free (cur_var->value); 926 UCL_FREE (sizeof (struct ucl_variable), cur_var); 927 } 928 else if (strcmp (cur_var->var, "FILENAME") == 0 && old_filename) { 929 DL_DELETE (parser->variables, cur_var); 930 free (cur_var->var); 931 free (cur_var->value); 932 UCL_FREE (sizeof (struct ucl_variable), cur_var); 933 } 934 } 935 if (old_filename) { 936 DL_APPEND (parser->variables, old_filename); 937 } 938 if (old_curdir) { 939 DL_APPEND (parser->variables, old_curdir); 940 } 941 if (old_curfile) { 942 free (old_curfile); 943 } 944 945 parser->state = prev_state; 946 947 if (buflen > 0) { 948 ucl_munmap (buf, buflen); 949 } 950 951 return res; 952 } 953 954 /** 955 * Include a file to configuration 956 * @param data 957 * @param len 958 * @param parser 959 * @param err 960 * @return 961 */ 962 static bool 963 ucl_include_file (const unsigned char *data, size_t len, 964 struct ucl_parser *parser, bool check_signature, bool must_exist, 965 bool allow_glob, unsigned priority) 966 { 967 const unsigned char *p = data, *end = data + len; 968 bool need_glob = false; 969 int cnt = 0; 970 char glob_pattern[PATH_MAX]; 971 size_t i; 972 973 #ifndef _WIN32 974 if (!allow_glob) { 975 return ucl_include_file_single (data, len, parser, check_signature, 976 must_exist, priority); 977 } 978 else { 979 /* Check for special symbols in a filename */ 980 while (p != end) { 981 if (*p == '*' || *p == '?') { 982 need_glob = true; 983 break; 984 } 985 p ++; 986 } 987 if (need_glob) { 988 glob_t globbuf; 989 memset (&globbuf, 0, sizeof (globbuf)); 990 ucl_strlcpy (glob_pattern, (const char *)data, sizeof (glob_pattern)); 991 if (glob (glob_pattern, 0, NULL, &globbuf) != 0) { 992 return (!must_exist || false); 993 } 994 for (i = 0; i < globbuf.gl_pathc; i ++) { 995 if (!ucl_include_file_single ((unsigned char *)globbuf.gl_pathv[i], 996 strlen (globbuf.gl_pathv[i]), parser, check_signature, 997 must_exist, priority)) { 998 globfree (&globbuf); 999 return false; 1000 } 1001 cnt ++; 1002 } 1003 globfree (&globbuf); 1004 1005 if (cnt == 0 && must_exist) { 1006 ucl_create_err (&parser->err, "cannot match any files for pattern %s", 1007 glob_pattern); 1008 return false; 1009 } 1010 } 1011 else { 1012 return ucl_include_file_single (data, len, parser, check_signature, 1013 must_exist, priority); 1014 } 1015 } 1016 #else 1017 /* Win32 compilers do not support globbing. Therefore, for Win32, 1018 treat allow_glob/need_glob as a NOOP and just return */ 1019 return ucl_include_file_single (data, len, parser, check_signature, 1020 must_exist, priority); 1021 #endif 1022 1023 return true; 1024 } 1025 1026 /** 1027 * Common function to handle .*include* macros 1028 * @param data 1029 * @param len 1030 * @param args 1031 * @param parser 1032 * @param default_try 1033 * @param default_sign 1034 * @return 1035 */ 1036 static bool 1037 ucl_include_common (const unsigned char *data, size_t len, 1038 const ucl_object_t *args, struct ucl_parser *parser, 1039 bool default_try, 1040 bool default_sign) 1041 { 1042 bool try_load, allow_glob, allow_url, need_sign; 1043 unsigned priority; 1044 const ucl_object_t *param; 1045 ucl_object_iter_t it = NULL; 1046 1047 /* Default values */ 1048 try_load = default_try; 1049 allow_glob = false; 1050 allow_url = true; 1051 need_sign = default_sign; 1052 priority = 0; 1053 1054 /* Process arguments */ 1055 if (args != NULL && args->type == UCL_OBJECT) { 1056 while ((param = ucl_iterate_object (args, &it, true)) != NULL) { 1057 if (param->type == UCL_BOOLEAN) { 1058 if (strcmp (param->key, "try") == 0) { 1059 try_load = ucl_object_toboolean (param); 1060 } 1061 else if (strcmp (param->key, "sign") == 0) { 1062 need_sign = ucl_object_toboolean (param); 1063 } 1064 else if (strcmp (param->key, "glob") == 0) { 1065 allow_glob = ucl_object_toboolean (param); 1066 } 1067 else if (strcmp (param->key, "url") == 0) { 1068 allow_url = ucl_object_toboolean (param); 1069 } 1070 } 1071 else if (param->type == UCL_INT) { 1072 if (strcmp (param->key, "priority") == 0) { 1073 priority = ucl_object_toint (param); 1074 } 1075 } 1076 } 1077 } 1078 1079 if (*data == '/' || *data == '.') { 1080 /* Try to load a file */ 1081 return ucl_include_file (data, len, parser, need_sign, !try_load, 1082 allow_glob, priority); 1083 } 1084 else if (allow_url) { 1085 /* Globbing is not used for URL's */ 1086 return ucl_include_url (data, len, parser, need_sign, !try_load, 1087 priority); 1088 } 1089 1090 return false; 1091 } 1092 1093 /** 1094 * Handle include macro 1095 * @param data include data 1096 * @param len length of data 1097 * @param ud user data 1098 * @param err error ptr 1099 * @return 1100 */ 1101 UCL_EXTERN bool 1102 ucl_include_handler (const unsigned char *data, size_t len, 1103 const ucl_object_t *args, void* ud) 1104 { 1105 struct ucl_parser *parser = ud; 1106 1107 return ucl_include_common (data, len, args, parser, false, false); 1108 } 1109 1110 /** 1111 * Handle includes macro 1112 * @param data include data 1113 * @param len length of data 1114 * @param ud user data 1115 * @param err error ptr 1116 * @return 1117 */ 1118 UCL_EXTERN bool 1119 ucl_includes_handler (const unsigned char *data, size_t len, 1120 const ucl_object_t *args, void* ud) 1121 { 1122 struct ucl_parser *parser = ud; 1123 1124 return ucl_include_common (data, len, args, parser, false, true); 1125 } 1126 1127 1128 UCL_EXTERN bool 1129 ucl_try_include_handler (const unsigned char *data, size_t len, 1130 const ucl_object_t *args, void* ud) 1131 { 1132 struct ucl_parser *parser = ud; 1133 1134 return ucl_include_common (data, len, args, parser, true, false); 1135 } 1136 1137 UCL_EXTERN bool 1138 ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand) 1139 { 1140 char realbuf[PATH_MAX], *curdir; 1141 1142 if (filename != NULL) { 1143 if (need_expand) { 1144 if (ucl_realpath (filename, realbuf) == NULL) { 1145 return false; 1146 } 1147 } 1148 else { 1149 ucl_strlcpy (realbuf, filename, sizeof (realbuf)); 1150 } 1151 1152 /* Define variables */ 1153 ucl_parser_register_variable (parser, "FILENAME", realbuf); 1154 curdir = dirname (realbuf); 1155 ucl_parser_register_variable (parser, "CURDIR", curdir); 1156 } 1157 else { 1158 /* Set everything from the current dir */ 1159 curdir = getcwd (realbuf, sizeof (realbuf)); 1160 ucl_parser_register_variable (parser, "FILENAME", "undef"); 1161 ucl_parser_register_variable (parser, "CURDIR", curdir); 1162 } 1163 1164 return true; 1165 } 1166 1167 UCL_EXTERN bool 1168 ucl_parser_add_file (struct ucl_parser *parser, const char *filename) 1169 { 1170 unsigned char *buf; 1171 size_t len; 1172 bool ret; 1173 char realbuf[PATH_MAX]; 1174 1175 if (ucl_realpath (filename, realbuf) == NULL) { 1176 ucl_create_err (&parser->err, "cannot open file %s: %s", 1177 filename, 1178 strerror (errno)); 1179 return false; 1180 } 1181 1182 if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) { 1183 return false; 1184 } 1185 1186 if (parser->cur_file) { 1187 free (parser->cur_file); 1188 } 1189 parser->cur_file = strdup (realbuf); 1190 ucl_parser_set_filevars (parser, realbuf, false); 1191 ret = ucl_parser_add_chunk (parser, buf, len); 1192 1193 if (len > 0) { 1194 ucl_munmap (buf, len); 1195 } 1196 1197 return ret; 1198 } 1199 1200 UCL_EXTERN bool 1201 ucl_parser_add_fd (struct ucl_parser *parser, int fd) 1202 { 1203 unsigned char *buf; 1204 size_t len; 1205 bool ret; 1206 struct stat st; 1207 1208 if (fstat (fd, &st) == -1) { 1209 ucl_create_err (&parser->err, "cannot stat fd %d: %s", 1210 fd, strerror (errno)); 1211 return false; 1212 } 1213 if ((buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 1214 ucl_create_err (&parser->err, "cannot mmap fd %d: %s", 1215 fd, strerror (errno)); 1216 return false; 1217 } 1218 1219 if (parser->cur_file) { 1220 free (parser->cur_file); 1221 } 1222 parser->cur_file = NULL; 1223 len = st.st_size; 1224 ret = ucl_parser_add_chunk (parser, buf, len); 1225 1226 if (len > 0) { 1227 ucl_munmap (buf, len); 1228 } 1229 1230 return ret; 1231 } 1232 1233 size_t 1234 ucl_strlcpy (char *dst, const char *src, size_t siz) 1235 { 1236 char *d = dst; 1237 const char *s = src; 1238 size_t n = siz; 1239 1240 /* Copy as many bytes as will fit */ 1241 if (n != 0) { 1242 while (--n != 0) { 1243 if ((*d++ = *s++) == '\0') { 1244 break; 1245 } 1246 } 1247 } 1248 1249 if (n == 0 && siz != 0) { 1250 *d = '\0'; 1251 } 1252 1253 return (s - src - 1); /* count does not include NUL */ 1254 } 1255 1256 size_t 1257 ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz) 1258 { 1259 memcpy (dst, src, siz - 1); 1260 dst[siz - 1] = '\0'; 1261 1262 return siz - 1; 1263 } 1264 1265 size_t 1266 ucl_strlcpy_tolower (char *dst, const char *src, size_t siz) 1267 { 1268 char *d = dst; 1269 const char *s = src; 1270 size_t n = siz; 1271 1272 /* Copy as many bytes as will fit */ 1273 if (n != 0) { 1274 while (--n != 0) { 1275 if ((*d++ = tolower (*s++)) == '\0') { 1276 break; 1277 } 1278 } 1279 } 1280 1281 if (n == 0 && siz != 0) { 1282 *d = '\0'; 1283 } 1284 1285 return (s - src); /* count does not include NUL */ 1286 } 1287 1288 ucl_object_t * 1289 ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags) 1290 { 1291 ucl_object_t *obj; 1292 const char *start, *end, *p, *pos; 1293 char *dst, *d; 1294 size_t escaped_len; 1295 1296 if (str == NULL) { 1297 return NULL; 1298 } 1299 1300 obj = ucl_object_new (); 1301 if (obj) { 1302 if (len == 0) { 1303 len = strlen (str); 1304 } 1305 if (flags & UCL_STRING_TRIM) { 1306 /* Skip leading spaces */ 1307 for (start = str; (size_t)(start - str) < len; start ++) { 1308 if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) { 1309 break; 1310 } 1311 } 1312 /* Skip trailing spaces */ 1313 for (end = str + len - 1; end > start; end --) { 1314 if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) { 1315 break; 1316 } 1317 } 1318 end ++; 1319 } 1320 else { 1321 start = str; 1322 end = str + len; 1323 } 1324 1325 obj->type = UCL_STRING; 1326 if (flags & UCL_STRING_ESCAPE) { 1327 for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) { 1328 if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { 1329 escaped_len ++; 1330 } 1331 } 1332 dst = malloc (escaped_len + 1); 1333 if (dst != NULL) { 1334 for (p = start, d = dst; p < end; p ++, d ++) { 1335 if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { 1336 switch (*p) { 1337 case '\n': 1338 *d++ = '\\'; 1339 *d = 'n'; 1340 break; 1341 case '\r': 1342 *d++ = '\\'; 1343 *d = 'r'; 1344 break; 1345 case '\b': 1346 *d++ = '\\'; 1347 *d = 'b'; 1348 break; 1349 case '\t': 1350 *d++ = '\\'; 1351 *d = 't'; 1352 break; 1353 case '\f': 1354 *d++ = '\\'; 1355 *d = 'f'; 1356 break; 1357 case '\\': 1358 *d++ = '\\'; 1359 *d = '\\'; 1360 break; 1361 case '"': 1362 *d++ = '\\'; 1363 *d = '"'; 1364 break; 1365 } 1366 } 1367 else { 1368 *d = *p; 1369 } 1370 } 1371 *d = '\0'; 1372 obj->value.sv = dst; 1373 obj->trash_stack[UCL_TRASH_VALUE] = dst; 1374 obj->len = escaped_len; 1375 } 1376 } 1377 else { 1378 dst = malloc (end - start + 1); 1379 if (dst != NULL) { 1380 ucl_strlcpy_unsafe (dst, start, end - start + 1); 1381 obj->value.sv = dst; 1382 obj->trash_stack[UCL_TRASH_VALUE] = dst; 1383 obj->len = end - start; 1384 } 1385 } 1386 if ((flags & UCL_STRING_PARSE) && dst != NULL) { 1387 /* Parse what we have */ 1388 if (flags & UCL_STRING_PARSE_BOOLEAN) { 1389 if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) { 1390 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos, 1391 flags & UCL_STRING_PARSE_DOUBLE, 1392 flags & UCL_STRING_PARSE_BYTES, 1393 flags & UCL_STRING_PARSE_TIME); 1394 } 1395 } 1396 else { 1397 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos, 1398 flags & UCL_STRING_PARSE_DOUBLE, 1399 flags & UCL_STRING_PARSE_BYTES, 1400 flags & UCL_STRING_PARSE_TIME); 1401 } 1402 } 1403 } 1404 1405 return obj; 1406 } 1407 1408 static bool 1409 ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, 1410 const char *key, size_t keylen, bool copy_key, bool merge, bool replace) 1411 { 1412 ucl_object_t *found, *tmp; 1413 const ucl_object_t *cur; 1414 ucl_object_iter_t it = NULL; 1415 const char *p; 1416 int ret = true; 1417 1418 if (elt == NULL || key == NULL) { 1419 return false; 1420 } 1421 1422 if (top == NULL) { 1423 return false; 1424 } 1425 1426 if (top->type != UCL_OBJECT) { 1427 /* It is possible to convert NULL type to an object */ 1428 if (top->type == UCL_NULL) { 1429 top->type = UCL_OBJECT; 1430 } 1431 else { 1432 /* Refuse converting of other object types */ 1433 return false; 1434 } 1435 } 1436 1437 if (top->value.ov == NULL) { 1438 top->value.ov = ucl_hash_create (false); 1439 } 1440 1441 if (keylen == 0) { 1442 keylen = strlen (key); 1443 } 1444 1445 for (p = key; p < key + keylen; p ++) { 1446 if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) { 1447 elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE; 1448 break; 1449 } 1450 } 1451 1452 /* workaround for some use cases */ 1453 if (elt->trash_stack[UCL_TRASH_KEY] != NULL && 1454 key != (const char *)elt->trash_stack[UCL_TRASH_KEY]) { 1455 /* Remove copied key */ 1456 free (elt->trash_stack[UCL_TRASH_KEY]); 1457 elt->trash_stack[UCL_TRASH_KEY] = NULL; 1458 elt->flags &= ~UCL_OBJECT_ALLOCATED_KEY; 1459 } 1460 1461 elt->key = key; 1462 elt->keylen = keylen; 1463 1464 if (copy_key) { 1465 ucl_copy_key_trash (elt); 1466 } 1467 1468 found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt)); 1469 1470 if (found == NULL) { 1471 top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false); 1472 top->len ++; 1473 if (replace) { 1474 ret = false; 1475 } 1476 } 1477 else { 1478 if (replace) { 1479 ucl_hash_replace (top->value.ov, found, elt); 1480 ucl_object_unref (found); 1481 } 1482 else if (merge) { 1483 if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) { 1484 /* Insert old elt to new one */ 1485 ucl_object_insert_key_common (elt, found, found->key, 1486 found->keylen, copy_key, false, false); 1487 ucl_hash_delete (top->value.ov, found); 1488 top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false); 1489 } 1490 else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) { 1491 /* Insert new to old */ 1492 ucl_object_insert_key_common (found, elt, elt->key, 1493 elt->keylen, copy_key, false, false); 1494 } 1495 else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) { 1496 /* Mix two hashes */ 1497 while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) { 1498 tmp = ucl_object_ref (cur); 1499 ucl_object_insert_key_common (found, tmp, cur->key, 1500 cur->keylen, copy_key, false, false); 1501 } 1502 ucl_object_unref (elt); 1503 } 1504 else { 1505 /* Just make a list of scalars */ 1506 DL_APPEND (found, elt); 1507 } 1508 } 1509 else { 1510 DL_APPEND (found, elt); 1511 } 1512 } 1513 1514 return ret; 1515 } 1516 1517 bool 1518 ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen) 1519 { 1520 ucl_object_t *found; 1521 1522 if (top == NULL || key == NULL) { 1523 return false; 1524 } 1525 1526 found = __DECONST (ucl_object_t *, ucl_object_find_keyl (top, key, keylen)); 1527 1528 if (found == NULL) { 1529 return false; 1530 } 1531 1532 ucl_hash_delete (top->value.ov, found); 1533 ucl_object_unref (found); 1534 top->len --; 1535 1536 return true; 1537 } 1538 1539 bool 1540 ucl_object_delete_key (ucl_object_t *top, const char *key) 1541 { 1542 return ucl_object_delete_keyl (top, key, strlen(key)); 1543 } 1544 1545 ucl_object_t* 1546 ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen) 1547 { 1548 const ucl_object_t *found; 1549 1550 if (top == NULL || key == NULL) { 1551 return false; 1552 } 1553 found = ucl_object_find_keyl (top, key, keylen); 1554 1555 if (found == NULL) { 1556 return NULL; 1557 } 1558 ucl_hash_delete (top->value.ov, found); 1559 top->len --; 1560 1561 return __DECONST (ucl_object_t *, found); 1562 } 1563 1564 ucl_object_t* 1565 ucl_object_pop_key (ucl_object_t *top, const char *key) 1566 { 1567 return ucl_object_pop_keyl (top, key, strlen(key)); 1568 } 1569 1570 bool 1571 ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, 1572 const char *key, size_t keylen, bool copy_key) 1573 { 1574 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false); 1575 } 1576 1577 bool 1578 ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, 1579 const char *key, size_t keylen, bool copy_key) 1580 { 1581 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false); 1582 } 1583 1584 bool 1585 ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, 1586 const char *key, size_t keylen, bool copy_key) 1587 { 1588 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true); 1589 } 1590 1591 bool 1592 ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy) 1593 { 1594 ucl_object_t *cur = NULL, *cp = NULL, *found = NULL; 1595 ucl_object_iter_t iter = NULL; 1596 1597 if (top == NULL || top->type != UCL_OBJECT || elt == NULL || elt->type != UCL_OBJECT) { 1598 return false; 1599 } 1600 1601 /* Mix two hashes */ 1602 while ((cur = (ucl_object_t*)ucl_hash_iterate (elt->value.ov, &iter))) { 1603 if (copy) { 1604 cp = ucl_object_copy (cur); 1605 } 1606 else { 1607 cp = ucl_object_ref (cur); 1608 } 1609 found = __DECONST(ucl_object_t *, ucl_hash_search (top->value.ov, cp->key, cp->keylen)); 1610 if (found == NULL) { 1611 /* The key does not exist */ 1612 top->value.ov = ucl_hash_insert_object (top->value.ov, cp, false); 1613 top->len ++; 1614 } 1615 else { 1616 /* The key already exists, replace it */ 1617 ucl_hash_replace (top->value.ov, found, cp); 1618 ucl_object_unref (found); 1619 } 1620 } 1621 1622 return true; 1623 } 1624 1625 const ucl_object_t * 1626 ucl_object_find_keyl (const ucl_object_t *obj, const char *key, size_t klen) 1627 { 1628 const ucl_object_t *ret; 1629 ucl_object_t srch; 1630 1631 if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { 1632 return NULL; 1633 } 1634 1635 srch.key = key; 1636 srch.keylen = klen; 1637 ret = ucl_hash_search_obj (obj->value.ov, &srch); 1638 1639 return ret; 1640 } 1641 1642 const ucl_object_t * 1643 ucl_object_find_key (const ucl_object_t *obj, const char *key) 1644 { 1645 if (key == NULL) 1646 return NULL; 1647 1648 return ucl_object_find_keyl (obj, key, strlen(key)); 1649 } 1650 1651 const ucl_object_t* 1652 ucl_iterate_object (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values) 1653 { 1654 const ucl_object_t *elt = NULL; 1655 1656 if (obj == NULL || iter == NULL) { 1657 return NULL; 1658 } 1659 1660 if (expand_values) { 1661 switch (obj->type) { 1662 case UCL_OBJECT: 1663 return (const ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter); 1664 break; 1665 case UCL_ARRAY: { 1666 unsigned int idx; 1667 UCL_ARRAY_GET (vec, obj); 1668 idx = (unsigned int)(uintptr_t)(*iter); 1669 1670 if (vec != NULL) { 1671 while (idx < kv_size (*vec)) { 1672 if ((elt = kv_A (*vec, idx)) != NULL) { 1673 idx ++; 1674 break; 1675 } 1676 idx ++; 1677 } 1678 *iter = (void *)(uintptr_t)idx; 1679 } 1680 1681 return elt; 1682 break; 1683 } 1684 default: 1685 /* Go to linear iteration */ 1686 break; 1687 } 1688 } 1689 /* Treat everything as a linear list */ 1690 elt = *iter; 1691 if (elt == NULL) { 1692 elt = obj; 1693 } 1694 else if (elt == obj) { 1695 return NULL; 1696 } 1697 *iter = __DECONST (void *, elt->next ? elt->next : obj); 1698 return elt; 1699 1700 /* Not reached */ 1701 return NULL; 1702 } 1703 1704 const char safe_iter_magic[4] = {'u', 'i', 't', 'e'}; 1705 struct ucl_object_safe_iter { 1706 char magic[4]; /* safety check */ 1707 const ucl_object_t *impl_it; /* implicit object iteration */ 1708 ucl_object_iter_t expl_it; /* explicit iteration */ 1709 }; 1710 1711 #define UCL_SAFE_ITER(ptr) (struct ucl_object_safe_iter *)(ptr) 1712 #define UCL_SAFE_ITER_CHECK(it) do { \ 1713 assert (it != NULL); \ 1714 assert (memcmp (it->magic, safe_iter_magic, sizeof (it->magic)) == 0); \ 1715 } while (0) 1716 1717 ucl_object_iter_t 1718 ucl_object_iterate_new (const ucl_object_t *obj) 1719 { 1720 struct ucl_object_safe_iter *it; 1721 1722 it = UCL_ALLOC (sizeof (*it)); 1723 if (it != NULL) { 1724 memcpy (it->magic, safe_iter_magic, sizeof (it->magic)); 1725 it->expl_it = NULL; 1726 it->impl_it = obj; 1727 } 1728 1729 return (ucl_object_iter_t)it; 1730 } 1731 1732 1733 ucl_object_iter_t 1734 ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj) 1735 { 1736 struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it); 1737 1738 UCL_SAFE_ITER_CHECK (rit); 1739 1740 rit->impl_it = obj; 1741 rit->expl_it = NULL; 1742 1743 return it; 1744 } 1745 1746 const ucl_object_t* 1747 ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values) 1748 { 1749 struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it); 1750 const ucl_object_t *ret = NULL; 1751 1752 UCL_SAFE_ITER_CHECK (rit); 1753 1754 if (rit->impl_it == NULL) { 1755 return NULL; 1756 } 1757 1758 if (rit->impl_it->type == UCL_OBJECT || rit->impl_it->type == UCL_ARRAY) { 1759 ret = ucl_iterate_object (rit->impl_it, &rit->expl_it, true); 1760 1761 if (ret == NULL) { 1762 /* Need to switch to another implicit object in chain */ 1763 rit->impl_it = rit->impl_it->next; 1764 rit->expl_it = NULL; 1765 return ucl_object_iterate_safe (it, expand_values); 1766 } 1767 } 1768 else { 1769 /* Just iterate over the implicit array */ 1770 ret = rit->impl_it; 1771 rit->impl_it = rit->impl_it->next; 1772 if (expand_values) { 1773 /* We flatten objects if need to expand values */ 1774 if (ret->type == UCL_OBJECT || ret->type == UCL_ARRAY) { 1775 return ucl_object_iterate_safe (it, expand_values); 1776 } 1777 } 1778 } 1779 1780 return ret; 1781 } 1782 1783 void 1784 ucl_object_iterate_free (ucl_object_iter_t it) 1785 { 1786 struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it); 1787 1788 UCL_SAFE_ITER_CHECK (rit); 1789 1790 UCL_FREE (sizeof (*rit), it); 1791 } 1792 1793 const ucl_object_t * 1794 ucl_lookup_path (const ucl_object_t *top, const char *path_in) { 1795 const ucl_object_t *o = NULL, *found; 1796 const char *p, *c; 1797 char *err_str; 1798 unsigned index; 1799 1800 if (path_in == NULL || top == NULL) { 1801 return NULL; 1802 } 1803 1804 found = NULL; 1805 p = path_in; 1806 1807 /* Skip leading dots */ 1808 while (*p == '.') { 1809 p ++; 1810 } 1811 1812 c = p; 1813 while (*p != '\0') { 1814 p ++; 1815 if (*p == '.' || *p == '\0') { 1816 if (p > c) { 1817 switch (top->type) { 1818 case UCL_ARRAY: 1819 /* Key should be an int */ 1820 index = strtoul (c, &err_str, 10); 1821 if (err_str != NULL && (*err_str != '.' && *err_str != '\0')) { 1822 return NULL; 1823 } 1824 o = ucl_array_find_index (top, index); 1825 break; 1826 default: 1827 o = ucl_object_find_keyl (top, c, p - c); 1828 break; 1829 } 1830 if (o == NULL) { 1831 return NULL; 1832 } 1833 top = o; 1834 } 1835 if (*p != '\0') { 1836 c = p + 1; 1837 } 1838 } 1839 } 1840 found = o; 1841 1842 return found; 1843 } 1844 1845 1846 ucl_object_t * 1847 ucl_object_new (void) 1848 { 1849 return ucl_object_typed_new (UCL_NULL); 1850 } 1851 1852 ucl_object_t * 1853 ucl_object_typed_new (ucl_type_t type) 1854 { 1855 return ucl_object_new_full (type, 0); 1856 } 1857 1858 ucl_object_t * 1859 ucl_object_new_full (ucl_type_t type, unsigned priority) 1860 { 1861 ucl_object_t *new; 1862 1863 if (type != UCL_USERDATA) { 1864 new = UCL_ALLOC (sizeof (ucl_object_t)); 1865 if (new != NULL) { 1866 memset (new, 0, sizeof (ucl_object_t)); 1867 new->ref = 1; 1868 new->type = (type <= UCL_NULL ? type : UCL_NULL); 1869 new->next = NULL; 1870 new->prev = new; 1871 ucl_object_set_priority (new, priority); 1872 1873 if (type == UCL_ARRAY) { 1874 new->value.av = UCL_ALLOC (sizeof (ucl_array_t)); 1875 if (new->value.av) { 1876 memset (new->value.av, 0, sizeof (ucl_array_t)); 1877 UCL_ARRAY_GET (vec, new); 1878 1879 /* Preallocate some space for arrays */ 1880 kv_resize (ucl_object_t *, *vec, 8); 1881 } 1882 } 1883 } 1884 } 1885 else { 1886 new = ucl_object_new_userdata (NULL, NULL); 1887 ucl_object_set_priority (new, priority); 1888 } 1889 1890 return new; 1891 } 1892 1893 ucl_object_t* 1894 ucl_object_new_userdata (ucl_userdata_dtor dtor, ucl_userdata_emitter emitter) 1895 { 1896 struct ucl_object_userdata *new; 1897 size_t nsize = sizeof (*new); 1898 1899 new = UCL_ALLOC (nsize); 1900 if (new != NULL) { 1901 memset (new, 0, nsize); 1902 new->obj.ref = 1; 1903 new->obj.type = UCL_USERDATA; 1904 new->obj.next = NULL; 1905 new->obj.prev = (ucl_object_t *)new; 1906 new->dtor = dtor; 1907 new->emitter = emitter; 1908 } 1909 1910 return (ucl_object_t *)new; 1911 } 1912 1913 ucl_type_t 1914 ucl_object_type (const ucl_object_t *obj) 1915 { 1916 return obj->type; 1917 } 1918 1919 ucl_object_t* 1920 ucl_object_fromstring (const char *str) 1921 { 1922 return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE); 1923 } 1924 1925 ucl_object_t * 1926 ucl_object_fromlstring (const char *str, size_t len) 1927 { 1928 return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE); 1929 } 1930 1931 ucl_object_t * 1932 ucl_object_fromint (int64_t iv) 1933 { 1934 ucl_object_t *obj; 1935 1936 obj = ucl_object_new (); 1937 if (obj != NULL) { 1938 obj->type = UCL_INT; 1939 obj->value.iv = iv; 1940 } 1941 1942 return obj; 1943 } 1944 1945 ucl_object_t * 1946 ucl_object_fromdouble (double dv) 1947 { 1948 ucl_object_t *obj; 1949 1950 obj = ucl_object_new (); 1951 if (obj != NULL) { 1952 obj->type = UCL_FLOAT; 1953 obj->value.dv = dv; 1954 } 1955 1956 return obj; 1957 } 1958 1959 ucl_object_t* 1960 ucl_object_frombool (bool bv) 1961 { 1962 ucl_object_t *obj; 1963 1964 obj = ucl_object_new (); 1965 if (obj != NULL) { 1966 obj->type = UCL_BOOLEAN; 1967 obj->value.iv = bv; 1968 } 1969 1970 return obj; 1971 } 1972 1973 bool 1974 ucl_array_append (ucl_object_t *top, ucl_object_t *elt) 1975 { 1976 UCL_ARRAY_GET (vec, top); 1977 1978 if (elt == NULL || top == NULL) { 1979 return false; 1980 } 1981 1982 if (vec == NULL) { 1983 vec = UCL_ALLOC (sizeof (*vec)); 1984 kv_init (*vec); 1985 top->value.av = (void *)vec; 1986 } 1987 1988 kv_push (ucl_object_t *, *vec, elt); 1989 1990 top->len ++; 1991 1992 return true; 1993 } 1994 1995 bool 1996 ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt) 1997 { 1998 UCL_ARRAY_GET (vec, top); 1999 2000 if (elt == NULL || top == NULL) { 2001 return false; 2002 } 2003 2004 if (vec == NULL) { 2005 vec = UCL_ALLOC (sizeof (*vec)); 2006 kv_init (*vec); 2007 top->value.av = (void *)vec; 2008 kv_push (ucl_object_t *, *vec, elt); 2009 } 2010 else { 2011 /* Slow O(n) algorithm */ 2012 kv_prepend (ucl_object_t *, *vec, elt); 2013 } 2014 2015 top->len ++; 2016 2017 return true; 2018 } 2019 2020 bool 2021 ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy) 2022 { 2023 unsigned i; 2024 ucl_object_t **obj; 2025 UCL_ARRAY_GET (v1, top); 2026 UCL_ARRAY_GET (v2, elt); 2027 2028 if (elt == NULL || top == NULL || top->type != UCL_ARRAY || elt->type != UCL_ARRAY) { 2029 return false; 2030 } 2031 2032 kv_concat (ucl_object_t *, *v1, *v2); 2033 2034 for (i = v2->n; i < v1->n; i ++) { 2035 obj = &kv_A (*v1, i); 2036 if (*obj == NULL) { 2037 continue; 2038 } 2039 2040 top->len ++; 2041 if (copy) { 2042 *obj = ucl_object_copy (*obj); 2043 } 2044 else { 2045 ucl_object_ref (*obj); 2046 } 2047 } 2048 2049 return true; 2050 } 2051 2052 ucl_object_t * 2053 ucl_array_delete (ucl_object_t *top, ucl_object_t *elt) 2054 { 2055 UCL_ARRAY_GET (vec, top); 2056 ucl_object_t *ret = NULL; 2057 unsigned i; 2058 2059 for (i = 0; i < vec->n; i ++) { 2060 if (kv_A (*vec, i) == elt) { 2061 kv_del (ucl_object_t *, *vec, i); 2062 ret = elt; 2063 top->len --; 2064 break; 2065 } 2066 } 2067 2068 return ret; 2069 } 2070 2071 const ucl_object_t * 2072 ucl_array_head (const ucl_object_t *top) 2073 { 2074 UCL_ARRAY_GET (vec, top); 2075 2076 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 2077 return NULL; 2078 } 2079 2080 return (vec->n > 0 ? vec->a[0] : NULL); 2081 } 2082 2083 const ucl_object_t * 2084 ucl_array_tail (const ucl_object_t *top) 2085 { 2086 UCL_ARRAY_GET (vec, top); 2087 2088 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 2089 return NULL; 2090 } 2091 2092 return (vec->n > 0 ? vec->a[vec->n - 1] : NULL); 2093 } 2094 2095 ucl_object_t * 2096 ucl_array_pop_last (ucl_object_t *top) 2097 { 2098 UCL_ARRAY_GET (vec, top); 2099 ucl_object_t **obj, *ret = NULL; 2100 2101 if (vec != NULL && vec->n > 0) { 2102 obj = &kv_A (*vec, vec->n - 1); 2103 ret = *obj; 2104 kv_del (ucl_object_t *, *vec, vec->n - 1); 2105 top->len --; 2106 } 2107 2108 return ret; 2109 } 2110 2111 ucl_object_t * 2112 ucl_array_pop_first (ucl_object_t *top) 2113 { 2114 UCL_ARRAY_GET (vec, top); 2115 ucl_object_t **obj, *ret = NULL; 2116 2117 if (vec != NULL && vec->n > 0) { 2118 obj = &kv_A (*vec, 0); 2119 ret = *obj; 2120 kv_del (ucl_object_t *, *vec, 0); 2121 top->len --; 2122 } 2123 2124 return ret; 2125 } 2126 2127 const ucl_object_t * 2128 ucl_array_find_index (const ucl_object_t *top, unsigned int index) 2129 { 2130 UCL_ARRAY_GET (vec, top); 2131 2132 if (vec != NULL && vec->n > 0 && index < vec->n) { 2133 return kv_A (*vec, index); 2134 } 2135 2136 return NULL; 2137 } 2138 2139 ucl_object_t * 2140 ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt, 2141 unsigned int index) 2142 { 2143 UCL_ARRAY_GET (vec, top); 2144 ucl_object_t *ret = NULL; 2145 2146 if (vec != NULL && vec->n > 0 && index < vec->n) { 2147 ret = kv_A (*vec, index); 2148 kv_A (*vec, index) = elt; 2149 } 2150 2151 return ret; 2152 } 2153 2154 ucl_object_t * 2155 ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) 2156 { 2157 2158 if (head == NULL) { 2159 elt->next = NULL; 2160 elt->prev = elt; 2161 head = elt; 2162 } 2163 else { 2164 elt->prev = head->prev; 2165 head->prev->next = elt; 2166 head->prev = elt; 2167 elt->next = NULL; 2168 } 2169 2170 return head; 2171 } 2172 2173 bool 2174 ucl_object_todouble_safe (const ucl_object_t *obj, double *target) 2175 { 2176 if (obj == NULL || target == NULL) { 2177 return false; 2178 } 2179 switch (obj->type) { 2180 case UCL_INT: 2181 *target = obj->value.iv; /* Probaly could cause overflow */ 2182 break; 2183 case UCL_FLOAT: 2184 case UCL_TIME: 2185 *target = obj->value.dv; 2186 break; 2187 default: 2188 return false; 2189 } 2190 2191 return true; 2192 } 2193 2194 double 2195 ucl_object_todouble (const ucl_object_t *obj) 2196 { 2197 double result = 0.; 2198 2199 ucl_object_todouble_safe (obj, &result); 2200 return result; 2201 } 2202 2203 bool 2204 ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target) 2205 { 2206 if (obj == NULL || target == NULL) { 2207 return false; 2208 } 2209 switch (obj->type) { 2210 case UCL_INT: 2211 *target = obj->value.iv; 2212 break; 2213 case UCL_FLOAT: 2214 case UCL_TIME: 2215 *target = obj->value.dv; /* Loosing of decimal points */ 2216 break; 2217 default: 2218 return false; 2219 } 2220 2221 return true; 2222 } 2223 2224 int64_t 2225 ucl_object_toint (const ucl_object_t *obj) 2226 { 2227 int64_t result = 0; 2228 2229 ucl_object_toint_safe (obj, &result); 2230 return result; 2231 } 2232 2233 bool 2234 ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target) 2235 { 2236 if (obj == NULL || target == NULL) { 2237 return false; 2238 } 2239 switch (obj->type) { 2240 case UCL_BOOLEAN: 2241 *target = (obj->value.iv == true); 2242 break; 2243 default: 2244 return false; 2245 } 2246 2247 return true; 2248 } 2249 2250 bool 2251 ucl_object_toboolean (const ucl_object_t *obj) 2252 { 2253 bool result = false; 2254 2255 ucl_object_toboolean_safe (obj, &result); 2256 return result; 2257 } 2258 2259 bool 2260 ucl_object_tostring_safe (const ucl_object_t *obj, const char **target) 2261 { 2262 if (obj == NULL || target == NULL) { 2263 return false; 2264 } 2265 2266 switch (obj->type) { 2267 case UCL_STRING: 2268 *target = ucl_copy_value_trash (obj); 2269 break; 2270 default: 2271 return false; 2272 } 2273 2274 return true; 2275 } 2276 2277 const char * 2278 ucl_object_tostring (const ucl_object_t *obj) 2279 { 2280 const char *result = NULL; 2281 2282 ucl_object_tostring_safe (obj, &result); 2283 return result; 2284 } 2285 2286 const char * 2287 ucl_object_tostring_forced (const ucl_object_t *obj) 2288 { 2289 return ucl_copy_value_trash (obj); 2290 } 2291 2292 bool 2293 ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen) 2294 { 2295 if (obj == NULL || target == NULL) { 2296 return false; 2297 } 2298 switch (obj->type) { 2299 case UCL_STRING: 2300 *target = obj->value.sv; 2301 if (tlen != NULL) { 2302 *tlen = obj->len; 2303 } 2304 break; 2305 default: 2306 return false; 2307 } 2308 2309 return true; 2310 } 2311 2312 const char * 2313 ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen) 2314 { 2315 const char *result = NULL; 2316 2317 ucl_object_tolstring_safe (obj, &result, tlen); 2318 return result; 2319 } 2320 2321 const char * 2322 ucl_object_key (const ucl_object_t *obj) 2323 { 2324 return ucl_copy_key_trash (obj); 2325 } 2326 2327 const char * 2328 ucl_object_keyl (const ucl_object_t *obj, size_t *len) 2329 { 2330 if (len == NULL || obj == NULL) { 2331 return NULL; 2332 } 2333 *len = obj->keylen; 2334 return obj->key; 2335 } 2336 2337 ucl_object_t * 2338 ucl_object_ref (const ucl_object_t *obj) 2339 { 2340 ucl_object_t *res = NULL; 2341 2342 if (obj != NULL) { 2343 if (obj->flags & UCL_OBJECT_EPHEMERAL) { 2344 /* 2345 * Use deep copy for ephemeral objects, note that its refcount 2346 * is NOT increased, since ephemeral objects does not need refcount 2347 * at all 2348 */ 2349 res = ucl_object_copy (obj); 2350 } 2351 else { 2352 res = __DECONST (ucl_object_t *, obj); 2353 #ifdef HAVE_ATOMIC_BUILTINS 2354 (void)__sync_add_and_fetch (&res->ref, 1); 2355 #else 2356 res->ref ++; 2357 #endif 2358 } 2359 } 2360 return res; 2361 } 2362 2363 static ucl_object_t * 2364 ucl_object_copy_internal (const ucl_object_t *other, bool allow_array) 2365 { 2366 2367 ucl_object_t *new; 2368 ucl_object_iter_t it = NULL; 2369 const ucl_object_t *cur; 2370 2371 new = malloc (sizeof (*new)); 2372 2373 if (new != NULL) { 2374 memcpy (new, other, sizeof (*new)); 2375 if (other->flags & UCL_OBJECT_EPHEMERAL) { 2376 /* Copied object is always non ephemeral */ 2377 new->flags &= ~UCL_OBJECT_EPHEMERAL; 2378 } 2379 new->ref = 1; 2380 /* Unlink from others */ 2381 new->next = NULL; 2382 new->prev = new; 2383 2384 /* deep copy of values stored */ 2385 if (other->trash_stack[UCL_TRASH_KEY] != NULL) { 2386 new->trash_stack[UCL_TRASH_KEY] = 2387 strdup (other->trash_stack[UCL_TRASH_KEY]); 2388 if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) { 2389 new->key = new->trash_stack[UCL_TRASH_KEY]; 2390 } 2391 } 2392 if (other->trash_stack[UCL_TRASH_VALUE] != NULL) { 2393 new->trash_stack[UCL_TRASH_VALUE] = 2394 strdup (other->trash_stack[UCL_TRASH_VALUE]); 2395 if (new->type == UCL_STRING) { 2396 new->value.sv = new->trash_stack[UCL_TRASH_VALUE]; 2397 } 2398 } 2399 2400 if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) { 2401 /* reset old value */ 2402 memset (&new->value, 0, sizeof (new->value)); 2403 2404 while ((cur = ucl_iterate_object (other, &it, true)) != NULL) { 2405 if (other->type == UCL_ARRAY) { 2406 ucl_array_append (new, ucl_object_copy_internal (cur, false)); 2407 } 2408 else { 2409 ucl_object_t *cp = ucl_object_copy_internal (cur, true); 2410 if (cp != NULL) { 2411 ucl_object_insert_key (new, cp, cp->key, cp->keylen, 2412 false); 2413 } 2414 } 2415 } 2416 } 2417 else if (allow_array && other->next != NULL) { 2418 LL_FOREACH (other->next, cur) { 2419 ucl_object_t *cp = ucl_object_copy_internal (cur, false); 2420 if (cp != NULL) { 2421 DL_APPEND (new, cp); 2422 } 2423 } 2424 } 2425 } 2426 2427 return new; 2428 } 2429 2430 ucl_object_t * 2431 ucl_object_copy (const ucl_object_t *other) 2432 { 2433 return ucl_object_copy_internal (other, true); 2434 } 2435 2436 void 2437 ucl_object_unref (ucl_object_t *obj) 2438 { 2439 if (obj != NULL) { 2440 #ifdef HAVE_ATOMIC_BUILTINS 2441 unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1); 2442 if (rc == 0) { 2443 #else 2444 if (--obj->ref == 0) { 2445 #endif 2446 ucl_object_free_internal (obj, true, ucl_object_dtor_unref); 2447 } 2448 } 2449 } 2450 2451 int 2452 ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2) 2453 { 2454 const ucl_object_t *it1, *it2; 2455 ucl_object_iter_t iter = NULL; 2456 int ret = 0; 2457 2458 if (o1->type != o2->type) { 2459 return (o1->type) - (o2->type); 2460 } 2461 2462 switch (o1->type) { 2463 case UCL_STRING: 2464 if (o1->len == o2->len && o1->len > 0) { 2465 ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2)); 2466 } 2467 else { 2468 ret = o1->len - o2->len; 2469 } 2470 break; 2471 case UCL_FLOAT: 2472 case UCL_INT: 2473 case UCL_TIME: 2474 ret = ucl_object_todouble (o1) - ucl_object_todouble (o2); 2475 break; 2476 case UCL_BOOLEAN: 2477 ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2); 2478 break; 2479 case UCL_ARRAY: 2480 if (o1->len == o2->len && o1->len > 0) { 2481 UCL_ARRAY_GET (vec1, o1); 2482 UCL_ARRAY_GET (vec2, o2); 2483 unsigned i; 2484 2485 /* Compare all elements in both arrays */ 2486 for (i = 0; i < vec1->n; i ++) { 2487 it1 = kv_A (*vec1, i); 2488 it2 = kv_A (*vec2, i); 2489 2490 if (it1 == NULL && it2 != NULL) { 2491 return -1; 2492 } 2493 else if (it2 == NULL && it1 != NULL) { 2494 return 1; 2495 } 2496 else if (it1 != NULL && it2 != NULL) { 2497 ret = ucl_object_compare (it1, it2); 2498 if (ret != 0) { 2499 break; 2500 } 2501 } 2502 } 2503 } 2504 else { 2505 ret = o1->len - o2->len; 2506 } 2507 break; 2508 case UCL_OBJECT: 2509 if (o1->len == o2->len && o1->len > 0) { 2510 while ((it1 = ucl_iterate_object (o1, &iter, true)) != NULL) { 2511 it2 = ucl_object_find_key (o2, ucl_object_key (it1)); 2512 if (it2 == NULL) { 2513 ret = 1; 2514 break; 2515 } 2516 ret = ucl_object_compare (it1, it2); 2517 if (ret != 0) { 2518 break; 2519 } 2520 } 2521 } 2522 else { 2523 ret = o1->len - o2->len; 2524 } 2525 break; 2526 default: 2527 ret = 0; 2528 break; 2529 } 2530 2531 return ret; 2532 } 2533 2534 void 2535 ucl_object_array_sort (ucl_object_t *ar, 2536 int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2)) 2537 { 2538 UCL_ARRAY_GET (vec, ar); 2539 2540 if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) { 2541 return; 2542 } 2543 2544 qsort (vec->a, vec->n, sizeof (ucl_object_t *), 2545 (int (*)(const void *, const void *))cmp); 2546 } 2547 2548 #define PRIOBITS 4 2549 2550 unsigned int 2551 ucl_object_get_priority (const ucl_object_t *obj) 2552 { 2553 if (obj == NULL) { 2554 return 0; 2555 } 2556 2557 return (obj->flags >> ((sizeof (obj->flags) * NBBY) - PRIOBITS)); 2558 } 2559 2560 void 2561 ucl_object_set_priority (ucl_object_t *obj, 2562 unsigned int priority) 2563 { 2564 if (obj != NULL) { 2565 priority &= (0x1 << PRIOBITS) - 1; 2566 obj->flags |= priority << ((sizeof (obj->flags) * NBBY) - PRIOBITS); 2567 } 2568 } 2569