1c99fb5f9SBaptiste Daroussin /* Copyright (c) 2013, Vsevolod Stakhov 239ee7a7aSBaptiste Daroussin * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org> 3c99fb5f9SBaptiste Daroussin * All rights reserved. 4c99fb5f9SBaptiste Daroussin * 5c99fb5f9SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 6c99fb5f9SBaptiste Daroussin * modification, are permitted provided that the following conditions are met: 7c99fb5f9SBaptiste Daroussin * * Redistributions of source code must retain the above copyright 8c99fb5f9SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 9c99fb5f9SBaptiste Daroussin * * Redistributions in binary form must reproduce the above copyright 10c99fb5f9SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 11c99fb5f9SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 12c99fb5f9SBaptiste Daroussin * 13c99fb5f9SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 14c99fb5f9SBaptiste Daroussin * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15c99fb5f9SBaptiste Daroussin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16c99fb5f9SBaptiste Daroussin * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 17c99fb5f9SBaptiste Daroussin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18c99fb5f9SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19c99fb5f9SBaptiste Daroussin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20c99fb5f9SBaptiste Daroussin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21c99fb5f9SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22c99fb5f9SBaptiste Daroussin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23c99fb5f9SBaptiste Daroussin */ 24c99fb5f9SBaptiste Daroussin 25c99fb5f9SBaptiste Daroussin #include "ucl.h" 26c99fb5f9SBaptiste Daroussin #include "ucl_internal.h" 27c99fb5f9SBaptiste Daroussin #include "ucl_chartable.h" 288e3b1ab2SBaptiste Daroussin #include "kvec.h" 29*11dd9ed6SBaptiste Daroussin #include <limits.h> 3039ee7a7aSBaptiste Daroussin #include <stdarg.h> 31d9f0ce31SBaptiste Daroussin #include <stdio.h> /* for snprintf */ 32c99fb5f9SBaptiste Daroussin 338e3b1ab2SBaptiste Daroussin #ifndef _WIN32 344bf54857SBaptiste Daroussin #include <glob.h> 35*11dd9ed6SBaptiste Daroussin #include <sys/param.h> 36*11dd9ed6SBaptiste Daroussin #else 37*11dd9ed6SBaptiste Daroussin #ifndef NBBY 38*11dd9ed6SBaptiste Daroussin #define NBBY 8 39*11dd9ed6SBaptiste Daroussin #endif 408e3b1ab2SBaptiste Daroussin #endif 414bf54857SBaptiste Daroussin 4297bd480fSBaptiste Daroussin #ifdef HAVE_LIBGEN_H 43c99fb5f9SBaptiste Daroussin #include <libgen.h> /* For dirname */ 4497bd480fSBaptiste Daroussin #endif 45c99fb5f9SBaptiste Daroussin 468e3b1ab2SBaptiste Daroussin typedef kvec_t(ucl_object_t *) ucl_array_t; 478e3b1ab2SBaptiste Daroussin 488e3b1ab2SBaptiste Daroussin #define UCL_ARRAY_GET(ar, obj) ucl_array_t *ar = \ 498e3b1ab2SBaptiste Daroussin (ucl_array_t *)((obj) != NULL ? (obj)->value.av : NULL) 508e3b1ab2SBaptiste Daroussin 51c99fb5f9SBaptiste Daroussin #ifdef HAVE_OPENSSL 52c99fb5f9SBaptiste Daroussin #include <openssl/err.h> 53c99fb5f9SBaptiste Daroussin #include <openssl/sha.h> 54c99fb5f9SBaptiste Daroussin #include <openssl/rsa.h> 55c99fb5f9SBaptiste Daroussin #include <openssl/ssl.h> 56c99fb5f9SBaptiste Daroussin #include <openssl/evp.h> 57c99fb5f9SBaptiste Daroussin #endif 58c99fb5f9SBaptiste Daroussin 5997bd480fSBaptiste Daroussin #ifdef CURL_FOUND 60d9f0ce31SBaptiste Daroussin /* Seems to be broken */ 61d9f0ce31SBaptiste Daroussin #define CURL_DISABLE_TYPECHECK 1 6297bd480fSBaptiste Daroussin #include <curl/curl.h> 6397bd480fSBaptiste Daroussin #endif 6497bd480fSBaptiste Daroussin #ifdef HAVE_FETCH_H 6597bd480fSBaptiste Daroussin #include <fetch.h> 6697bd480fSBaptiste Daroussin #endif 6797bd480fSBaptiste Daroussin 6836c53d67SBaptiste Daroussin #ifdef _WIN32 6936c53d67SBaptiste Daroussin #include <windows.h> 7036c53d67SBaptiste Daroussin 7197bd480fSBaptiste Daroussin #ifndef PROT_READ 7236c53d67SBaptiste Daroussin #define PROT_READ 1 7397bd480fSBaptiste Daroussin #endif 7497bd480fSBaptiste Daroussin #ifndef PROT_WRITE 7536c53d67SBaptiste Daroussin #define PROT_WRITE 2 7697bd480fSBaptiste Daroussin #endif 7797bd480fSBaptiste Daroussin #ifndef PROT_READWRITE 7836c53d67SBaptiste Daroussin #define PROT_READWRITE 3 7997bd480fSBaptiste Daroussin #endif 8097bd480fSBaptiste Daroussin #ifndef MAP_SHARED 8136c53d67SBaptiste Daroussin #define MAP_SHARED 1 8297bd480fSBaptiste Daroussin #endif 8397bd480fSBaptiste Daroussin #ifndef MAP_PRIVATE 8436c53d67SBaptiste Daroussin #define MAP_PRIVATE 2 8597bd480fSBaptiste Daroussin #endif 8697bd480fSBaptiste Daroussin #ifndef MAP_FAILED 8736c53d67SBaptiste Daroussin #define MAP_FAILED ((void *) -1) 8897bd480fSBaptiste Daroussin #endif 8936c53d67SBaptiste Daroussin 9097bd480fSBaptiste Daroussin static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset) 9136c53d67SBaptiste Daroussin { 9236c53d67SBaptiste Daroussin void *map = NULL; 9336c53d67SBaptiste Daroussin HANDLE handle = INVALID_HANDLE_VALUE; 9436c53d67SBaptiste Daroussin 9536c53d67SBaptiste Daroussin switch (prot) { 9636c53d67SBaptiste Daroussin default: 9736c53d67SBaptiste Daroussin case PROT_READ: 9836c53d67SBaptiste Daroussin { 9936c53d67SBaptiste Daroussin handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0); 10036c53d67SBaptiste Daroussin if (!handle) break; 10136c53d67SBaptiste Daroussin map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length); 10236c53d67SBaptiste Daroussin CloseHandle(handle); 10336c53d67SBaptiste Daroussin break; 10436c53d67SBaptiste Daroussin } 10536c53d67SBaptiste Daroussin case PROT_WRITE: 10636c53d67SBaptiste Daroussin { 10736c53d67SBaptiste Daroussin handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0); 10836c53d67SBaptiste Daroussin if (!handle) break; 10936c53d67SBaptiste Daroussin map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length); 11036c53d67SBaptiste Daroussin CloseHandle(handle); 11136c53d67SBaptiste Daroussin break; 11236c53d67SBaptiste Daroussin } 11336c53d67SBaptiste Daroussin case PROT_READWRITE: 11436c53d67SBaptiste Daroussin { 11536c53d67SBaptiste Daroussin handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0); 11636c53d67SBaptiste Daroussin if (!handle) break; 11736c53d67SBaptiste Daroussin map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length); 11836c53d67SBaptiste Daroussin CloseHandle(handle); 11936c53d67SBaptiste Daroussin break; 12036c53d67SBaptiste Daroussin } 12136c53d67SBaptiste Daroussin } 12236c53d67SBaptiste Daroussin if (map == (void *) NULL) { 12336c53d67SBaptiste Daroussin return (void *) MAP_FAILED; 12436c53d67SBaptiste Daroussin } 12536c53d67SBaptiste Daroussin return (void *) ((char *) map + offset); 12636c53d67SBaptiste Daroussin } 12736c53d67SBaptiste Daroussin 12897bd480fSBaptiste Daroussin static int ucl_munmap(void *map,size_t length) 12936c53d67SBaptiste Daroussin { 13036c53d67SBaptiste Daroussin if (!UnmapViewOfFile(map)) { 13136c53d67SBaptiste Daroussin return(-1); 13236c53d67SBaptiste Daroussin } 13336c53d67SBaptiste Daroussin return(0); 13436c53d67SBaptiste Daroussin } 13536c53d67SBaptiste Daroussin 13697bd480fSBaptiste Daroussin static char* ucl_realpath(const char *path, char *resolved_path) { 13736c53d67SBaptiste Daroussin char *p; 13836c53d67SBaptiste Daroussin char tmp[MAX_PATH + 1]; 13936c53d67SBaptiste Daroussin strncpy(tmp, path, sizeof(tmp)-1); 14036c53d67SBaptiste Daroussin p = tmp; 14136c53d67SBaptiste Daroussin while(*p) { 14236c53d67SBaptiste Daroussin if (*p == '/') *p = '\\'; 14336c53d67SBaptiste Daroussin p++; 14436c53d67SBaptiste Daroussin } 14536c53d67SBaptiste Daroussin return _fullpath(resolved_path, tmp, MAX_PATH); 14636c53d67SBaptiste Daroussin } 14797bd480fSBaptiste Daroussin #else 14897bd480fSBaptiste Daroussin #define ucl_mmap mmap 14997bd480fSBaptiste Daroussin #define ucl_munmap munmap 15097bd480fSBaptiste Daroussin #define ucl_realpath realpath 15136c53d67SBaptiste Daroussin #endif 15236c53d67SBaptiste Daroussin 153b04a7a0bSBaptiste Daroussin typedef void (*ucl_object_dtor) (ucl_object_t *obj); 154b04a7a0bSBaptiste Daroussin static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, 155b04a7a0bSBaptiste Daroussin ucl_object_dtor dtor); 156b04a7a0bSBaptiste Daroussin static void ucl_object_dtor_unref (ucl_object_t *obj); 157c99fb5f9SBaptiste Daroussin 158c99fb5f9SBaptiste Daroussin static void 159b04a7a0bSBaptiste Daroussin ucl_object_dtor_free (ucl_object_t *obj) 160c99fb5f9SBaptiste Daroussin { 161c99fb5f9SBaptiste Daroussin if (obj->trash_stack[UCL_TRASH_KEY] != NULL) { 162c99fb5f9SBaptiste Daroussin UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]); 163c99fb5f9SBaptiste Daroussin } 164c99fb5f9SBaptiste Daroussin if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { 165c99fb5f9SBaptiste Daroussin UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]); 166c99fb5f9SBaptiste Daroussin } 1674bf54857SBaptiste Daroussin /* Do not free ephemeral objects */ 1684bf54857SBaptiste Daroussin if ((obj->flags & UCL_OBJECT_EPHEMERAL) == 0) { 1694bf54857SBaptiste Daroussin if (obj->type != UCL_USERDATA) { 170b04a7a0bSBaptiste Daroussin UCL_FREE (sizeof (ucl_object_t), obj); 171b04a7a0bSBaptiste Daroussin } 1724bf54857SBaptiste Daroussin else { 1734bf54857SBaptiste Daroussin struct ucl_object_userdata *ud = (struct ucl_object_userdata *)obj; 1744bf54857SBaptiste Daroussin if (ud->dtor) { 1754bf54857SBaptiste Daroussin ud->dtor (obj->value.ud); 1764bf54857SBaptiste Daroussin } 1774bf54857SBaptiste Daroussin UCL_FREE (sizeof (*ud), obj); 1784bf54857SBaptiste Daroussin } 1794bf54857SBaptiste Daroussin } 1804bf54857SBaptiste Daroussin } 181c99fb5f9SBaptiste Daroussin 182b04a7a0bSBaptiste Daroussin /* 183b04a7a0bSBaptiste Daroussin * This is a helper function that performs exactly the same as 184b04a7a0bSBaptiste Daroussin * `ucl_object_unref` but it doesn't iterate over elements allowing 185b04a7a0bSBaptiste Daroussin * to use it for individual elements of arrays and multiple values 186b04a7a0bSBaptiste Daroussin */ 187b04a7a0bSBaptiste Daroussin static void 188b04a7a0bSBaptiste Daroussin ucl_object_dtor_unref_single (ucl_object_t *obj) 189b04a7a0bSBaptiste Daroussin { 190b04a7a0bSBaptiste Daroussin if (obj != NULL) { 191b04a7a0bSBaptiste Daroussin #ifdef HAVE_ATOMIC_BUILTINS 192b04a7a0bSBaptiste Daroussin unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1); 193b04a7a0bSBaptiste Daroussin if (rc == 0) { 194b04a7a0bSBaptiste Daroussin #else 195b04a7a0bSBaptiste Daroussin if (--obj->ref == 0) { 196b04a7a0bSBaptiste Daroussin #endif 197b04a7a0bSBaptiste Daroussin ucl_object_free_internal (obj, false, ucl_object_dtor_unref); 198b04a7a0bSBaptiste Daroussin } 199b04a7a0bSBaptiste Daroussin } 200b04a7a0bSBaptiste Daroussin } 201b04a7a0bSBaptiste Daroussin 202b04a7a0bSBaptiste Daroussin static void 203b04a7a0bSBaptiste Daroussin ucl_object_dtor_unref (ucl_object_t *obj) 204b04a7a0bSBaptiste Daroussin { 205b04a7a0bSBaptiste Daroussin if (obj->ref == 0) { 206b04a7a0bSBaptiste Daroussin ucl_object_dtor_free (obj); 207b04a7a0bSBaptiste Daroussin } 208b04a7a0bSBaptiste Daroussin else { 209b04a7a0bSBaptiste Daroussin /* This may cause dtor unref being called one more time */ 210b04a7a0bSBaptiste Daroussin ucl_object_dtor_unref_single (obj); 211b04a7a0bSBaptiste Daroussin } 212b04a7a0bSBaptiste Daroussin } 213b04a7a0bSBaptiste Daroussin 214b04a7a0bSBaptiste Daroussin static void 215b04a7a0bSBaptiste Daroussin ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor) 216b04a7a0bSBaptiste Daroussin { 2178e3b1ab2SBaptiste Daroussin ucl_object_t *tmp, *sub; 218b04a7a0bSBaptiste Daroussin 219b04a7a0bSBaptiste Daroussin while (obj != NULL) { 220c99fb5f9SBaptiste Daroussin if (obj->type == UCL_ARRAY) { 2218e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, obj); 2228e3b1ab2SBaptiste Daroussin unsigned int i; 2238e3b1ab2SBaptiste Daroussin 2248e3b1ab2SBaptiste Daroussin if (vec != NULL) { 2258e3b1ab2SBaptiste Daroussin for (i = 0; i < vec->n; i ++) { 2268e3b1ab2SBaptiste Daroussin sub = kv_A (*vec, i); 2278e3b1ab2SBaptiste Daroussin if (sub != NULL) { 2288e3b1ab2SBaptiste Daroussin tmp = sub; 2298e3b1ab2SBaptiste Daroussin while (sub) { 230c99fb5f9SBaptiste Daroussin tmp = sub->next; 231b04a7a0bSBaptiste Daroussin dtor (sub); 232c99fb5f9SBaptiste Daroussin sub = tmp; 233c99fb5f9SBaptiste Daroussin } 234c99fb5f9SBaptiste Daroussin } 2358e3b1ab2SBaptiste Daroussin } 2368e3b1ab2SBaptiste Daroussin kv_destroy (*vec); 2378e3b1ab2SBaptiste Daroussin UCL_FREE (sizeof (*vec), vec); 2388e3b1ab2SBaptiste Daroussin } 23939ee7a7aSBaptiste Daroussin obj->value.av = NULL; 2408e3b1ab2SBaptiste Daroussin } 241c99fb5f9SBaptiste Daroussin else if (obj->type == UCL_OBJECT) { 242c99fb5f9SBaptiste Daroussin if (obj->value.ov != NULL) { 243d9f0ce31SBaptiste Daroussin ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func)dtor); 244c99fb5f9SBaptiste Daroussin } 24539ee7a7aSBaptiste Daroussin obj->value.ov = NULL; 246c99fb5f9SBaptiste Daroussin } 247c99fb5f9SBaptiste Daroussin tmp = obj->next; 248b04a7a0bSBaptiste Daroussin dtor (obj); 249c99fb5f9SBaptiste Daroussin obj = tmp; 250c99fb5f9SBaptiste Daroussin 251c99fb5f9SBaptiste Daroussin if (!allow_rec) { 252c99fb5f9SBaptiste Daroussin break; 253c99fb5f9SBaptiste Daroussin } 254c99fb5f9SBaptiste Daroussin } 255c99fb5f9SBaptiste Daroussin } 256c99fb5f9SBaptiste Daroussin 257c99fb5f9SBaptiste Daroussin void 258c99fb5f9SBaptiste Daroussin ucl_object_free (ucl_object_t *obj) 259c99fb5f9SBaptiste Daroussin { 260b04a7a0bSBaptiste Daroussin ucl_object_free_internal (obj, true, ucl_object_dtor_free); 261c99fb5f9SBaptiste Daroussin } 262c99fb5f9SBaptiste Daroussin 263c99fb5f9SBaptiste Daroussin size_t 264c99fb5f9SBaptiste Daroussin ucl_unescape_json_string (char *str, size_t len) 265c99fb5f9SBaptiste Daroussin { 266c99fb5f9SBaptiste Daroussin char *t = str, *h = str; 267c99fb5f9SBaptiste Daroussin int i, uval; 268c99fb5f9SBaptiste Daroussin 26997bd480fSBaptiste Daroussin if (len <= 1) { 27097bd480fSBaptiste Daroussin return len; 27197bd480fSBaptiste Daroussin } 272c99fb5f9SBaptiste Daroussin /* t is target (tortoise), h is source (hare) */ 273c99fb5f9SBaptiste Daroussin 274c99fb5f9SBaptiste Daroussin while (len) { 275c99fb5f9SBaptiste Daroussin if (*h == '\\') { 276c99fb5f9SBaptiste Daroussin h ++; 27739ee7a7aSBaptiste Daroussin 27839ee7a7aSBaptiste Daroussin if (len == 1) { 27939ee7a7aSBaptiste Daroussin /* 28039ee7a7aSBaptiste Daroussin * If \ is last, then do not try to go further 28139ee7a7aSBaptiste Daroussin * Issue: #74 28239ee7a7aSBaptiste Daroussin */ 28339ee7a7aSBaptiste Daroussin len --; 28439ee7a7aSBaptiste Daroussin *t++ = '\\'; 28539ee7a7aSBaptiste Daroussin continue; 28639ee7a7aSBaptiste Daroussin } 28739ee7a7aSBaptiste Daroussin 288c99fb5f9SBaptiste Daroussin switch (*h) { 289c99fb5f9SBaptiste Daroussin case 'n': 290c99fb5f9SBaptiste Daroussin *t++ = '\n'; 291c99fb5f9SBaptiste Daroussin break; 292c99fb5f9SBaptiste Daroussin case 'r': 293c99fb5f9SBaptiste Daroussin *t++ = '\r'; 294c99fb5f9SBaptiste Daroussin break; 295c99fb5f9SBaptiste Daroussin case 'b': 296c99fb5f9SBaptiste Daroussin *t++ = '\b'; 297c99fb5f9SBaptiste Daroussin break; 298c99fb5f9SBaptiste Daroussin case 't': 299c99fb5f9SBaptiste Daroussin *t++ = '\t'; 300c99fb5f9SBaptiste Daroussin break; 301c99fb5f9SBaptiste Daroussin case 'f': 302c99fb5f9SBaptiste Daroussin *t++ = '\f'; 303c99fb5f9SBaptiste Daroussin break; 304c99fb5f9SBaptiste Daroussin case '\\': 305c99fb5f9SBaptiste Daroussin *t++ = '\\'; 306c99fb5f9SBaptiste Daroussin break; 307c99fb5f9SBaptiste Daroussin case '"': 308c99fb5f9SBaptiste Daroussin *t++ = '"'; 309c99fb5f9SBaptiste Daroussin break; 310c99fb5f9SBaptiste Daroussin case 'u': 311c99fb5f9SBaptiste Daroussin /* Unicode escape */ 312c99fb5f9SBaptiste Daroussin uval = 0; 313d9f0ce31SBaptiste Daroussin h ++; /* u character */ 314d9f0ce31SBaptiste Daroussin len --; 315d9f0ce31SBaptiste Daroussin 31697bd480fSBaptiste Daroussin if (len > 3) { 317c99fb5f9SBaptiste Daroussin for (i = 0; i < 4; i++) { 318c99fb5f9SBaptiste Daroussin uval <<= 4; 319c99fb5f9SBaptiste Daroussin if (isdigit (h[i])) { 320c99fb5f9SBaptiste Daroussin uval += h[i] - '0'; 321c99fb5f9SBaptiste Daroussin } 322c99fb5f9SBaptiste Daroussin else if (h[i] >= 'a' && h[i] <= 'f') { 323c99fb5f9SBaptiste Daroussin uval += h[i] - 'a' + 10; 324c99fb5f9SBaptiste Daroussin } 325c99fb5f9SBaptiste Daroussin else if (h[i] >= 'A' && h[i] <= 'F') { 326c99fb5f9SBaptiste Daroussin uval += h[i] - 'A' + 10; 327c99fb5f9SBaptiste Daroussin } 32897bd480fSBaptiste Daroussin else { 32997bd480fSBaptiste Daroussin break; 33097bd480fSBaptiste Daroussin } 331c99fb5f9SBaptiste Daroussin } 332d9f0ce31SBaptiste Daroussin 333c99fb5f9SBaptiste Daroussin /* Encode */ 334c99fb5f9SBaptiste Daroussin if(uval < 0x80) { 335c99fb5f9SBaptiste Daroussin t[0] = (char)uval; 336c99fb5f9SBaptiste Daroussin t ++; 337c99fb5f9SBaptiste Daroussin } 338c99fb5f9SBaptiste Daroussin else if(uval < 0x800) { 339c99fb5f9SBaptiste Daroussin t[0] = 0xC0 + ((uval & 0x7C0) >> 6); 340c99fb5f9SBaptiste Daroussin t[1] = 0x80 + ((uval & 0x03F)); 341c99fb5f9SBaptiste Daroussin t += 2; 342c99fb5f9SBaptiste Daroussin } 343c99fb5f9SBaptiste Daroussin else if(uval < 0x10000) { 344c99fb5f9SBaptiste Daroussin t[0] = 0xE0 + ((uval & 0xF000) >> 12); 345c99fb5f9SBaptiste Daroussin t[1] = 0x80 + ((uval & 0x0FC0) >> 6); 346c99fb5f9SBaptiste Daroussin t[2] = 0x80 + ((uval & 0x003F)); 347c99fb5f9SBaptiste Daroussin t += 3; 348c99fb5f9SBaptiste Daroussin } 349d9f0ce31SBaptiste Daroussin #if 0 350d9f0ce31SBaptiste Daroussin /* It's not actually supported now */ 351c99fb5f9SBaptiste Daroussin else if(uval <= 0x10FFFF) { 352c99fb5f9SBaptiste Daroussin t[0] = 0xF0 + ((uval & 0x1C0000) >> 18); 353c99fb5f9SBaptiste Daroussin t[1] = 0x80 + ((uval & 0x03F000) >> 12); 354c99fb5f9SBaptiste Daroussin t[2] = 0x80 + ((uval & 0x000FC0) >> 6); 355c99fb5f9SBaptiste Daroussin t[3] = 0x80 + ((uval & 0x00003F)); 356c99fb5f9SBaptiste Daroussin t += 4; 357c99fb5f9SBaptiste Daroussin } 358d9f0ce31SBaptiste Daroussin #endif 359c99fb5f9SBaptiste Daroussin else { 360c99fb5f9SBaptiste Daroussin *t++ = '?'; 361c99fb5f9SBaptiste Daroussin } 362d9f0ce31SBaptiste Daroussin 363d9f0ce31SBaptiste Daroussin /* Consume 4 characters of source */ 364d9f0ce31SBaptiste Daroussin h += 4; 365d9f0ce31SBaptiste Daroussin len -= 4; 366d9f0ce31SBaptiste Daroussin 367d9f0ce31SBaptiste Daroussin if (len > 0) { 368d9f0ce31SBaptiste Daroussin len --; /* for '\' character */ 369d9f0ce31SBaptiste Daroussin } 370d9f0ce31SBaptiste Daroussin continue; 37197bd480fSBaptiste Daroussin } 37297bd480fSBaptiste Daroussin else { 37397bd480fSBaptiste Daroussin *t++ = 'u'; 37497bd480fSBaptiste Daroussin } 375c99fb5f9SBaptiste Daroussin break; 376c99fb5f9SBaptiste Daroussin default: 377c99fb5f9SBaptiste Daroussin *t++ = *h; 378c99fb5f9SBaptiste Daroussin break; 379c99fb5f9SBaptiste Daroussin } 380c99fb5f9SBaptiste Daroussin h ++; 381c99fb5f9SBaptiste Daroussin len --; 382c99fb5f9SBaptiste Daroussin } 383c99fb5f9SBaptiste Daroussin else { 384c99fb5f9SBaptiste Daroussin *t++ = *h++; 385c99fb5f9SBaptiste Daroussin } 38639ee7a7aSBaptiste Daroussin 38739ee7a7aSBaptiste Daroussin if (len > 0) { 388c99fb5f9SBaptiste Daroussin len --; 389c99fb5f9SBaptiste Daroussin } 39039ee7a7aSBaptiste Daroussin } 391c99fb5f9SBaptiste Daroussin *t = '\0'; 392c99fb5f9SBaptiste Daroussin 393c99fb5f9SBaptiste Daroussin return (t - str); 394c99fb5f9SBaptiste Daroussin } 395c99fb5f9SBaptiste Daroussin 396b04a7a0bSBaptiste Daroussin char * 397b04a7a0bSBaptiste Daroussin ucl_copy_key_trash (const ucl_object_t *obj) 398c99fb5f9SBaptiste Daroussin { 399b04a7a0bSBaptiste Daroussin ucl_object_t *deconst; 400b04a7a0bSBaptiste Daroussin 40197bd480fSBaptiste Daroussin if (obj == NULL) { 40297bd480fSBaptiste Daroussin return NULL; 40397bd480fSBaptiste Daroussin } 404c99fb5f9SBaptiste Daroussin if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) { 405b04a7a0bSBaptiste Daroussin deconst = __DECONST (ucl_object_t *, obj); 406b04a7a0bSBaptiste Daroussin deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1); 407b04a7a0bSBaptiste Daroussin if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) { 408b04a7a0bSBaptiste Daroussin memcpy (deconst->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen); 409b04a7a0bSBaptiste Daroussin deconst->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0'; 410c99fb5f9SBaptiste Daroussin } 411b04a7a0bSBaptiste Daroussin deconst->key = obj->trash_stack[UCL_TRASH_KEY]; 412b04a7a0bSBaptiste Daroussin deconst->flags |= UCL_OBJECT_ALLOCATED_KEY; 413c99fb5f9SBaptiste Daroussin } 414c99fb5f9SBaptiste Daroussin 415c99fb5f9SBaptiste Daroussin return obj->trash_stack[UCL_TRASH_KEY]; 416c99fb5f9SBaptiste Daroussin } 417c99fb5f9SBaptiste Daroussin 418b04a7a0bSBaptiste Daroussin char * 419b04a7a0bSBaptiste Daroussin ucl_copy_value_trash (const ucl_object_t *obj) 420c99fb5f9SBaptiste Daroussin { 421b04a7a0bSBaptiste Daroussin ucl_object_t *deconst; 422b04a7a0bSBaptiste Daroussin 42397bd480fSBaptiste Daroussin if (obj == NULL) { 42497bd480fSBaptiste Daroussin return NULL; 42597bd480fSBaptiste Daroussin } 426c99fb5f9SBaptiste Daroussin if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) { 427b04a7a0bSBaptiste Daroussin deconst = __DECONST (ucl_object_t *, obj); 428c99fb5f9SBaptiste Daroussin if (obj->type == UCL_STRING) { 429b04a7a0bSBaptiste Daroussin 430c99fb5f9SBaptiste Daroussin /* Special case for strings */ 43139ee7a7aSBaptiste Daroussin if (obj->flags & UCL_OBJECT_BINARY) { 43239ee7a7aSBaptiste Daroussin deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len); 43339ee7a7aSBaptiste Daroussin if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) { 43439ee7a7aSBaptiste Daroussin memcpy (deconst->trash_stack[UCL_TRASH_VALUE], 43539ee7a7aSBaptiste Daroussin obj->value.sv, 43639ee7a7aSBaptiste Daroussin obj->len); 43739ee7a7aSBaptiste Daroussin deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE]; 43839ee7a7aSBaptiste Daroussin } 43939ee7a7aSBaptiste Daroussin } 44039ee7a7aSBaptiste Daroussin else { 441b04a7a0bSBaptiste Daroussin deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1); 442b04a7a0bSBaptiste Daroussin if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) { 44339ee7a7aSBaptiste Daroussin memcpy (deconst->trash_stack[UCL_TRASH_VALUE], 44439ee7a7aSBaptiste Daroussin obj->value.sv, 44539ee7a7aSBaptiste Daroussin obj->len); 446b04a7a0bSBaptiste Daroussin deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0'; 447b04a7a0bSBaptiste Daroussin deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE]; 448c99fb5f9SBaptiste Daroussin } 449c99fb5f9SBaptiste Daroussin } 45039ee7a7aSBaptiste Daroussin } 451c99fb5f9SBaptiste Daroussin else { 452c99fb5f9SBaptiste Daroussin /* Just emit value in json notation */ 453b04a7a0bSBaptiste Daroussin deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj); 454b04a7a0bSBaptiste Daroussin deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]); 455c99fb5f9SBaptiste Daroussin } 456b04a7a0bSBaptiste Daroussin deconst->flags |= UCL_OBJECT_ALLOCATED_VALUE; 457c99fb5f9SBaptiste Daroussin } 45839ee7a7aSBaptiste Daroussin 459c99fb5f9SBaptiste Daroussin return obj->trash_stack[UCL_TRASH_VALUE]; 460c99fb5f9SBaptiste Daroussin } 461c99fb5f9SBaptiste Daroussin 46239ee7a7aSBaptiste Daroussin ucl_object_t* 463c99fb5f9SBaptiste Daroussin ucl_parser_get_object (struct ucl_parser *parser) 464c99fb5f9SBaptiste Daroussin { 465c99fb5f9SBaptiste Daroussin if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) { 466c99fb5f9SBaptiste Daroussin return ucl_object_ref (parser->top_obj); 467c99fb5f9SBaptiste Daroussin } 468c99fb5f9SBaptiste Daroussin 469c99fb5f9SBaptiste Daroussin return NULL; 470c99fb5f9SBaptiste Daroussin } 471c99fb5f9SBaptiste Daroussin 47239ee7a7aSBaptiste Daroussin void 473c99fb5f9SBaptiste Daroussin ucl_parser_free (struct ucl_parser *parser) 474c99fb5f9SBaptiste Daroussin { 475c99fb5f9SBaptiste Daroussin struct ucl_stack *stack, *stmp; 476c99fb5f9SBaptiste Daroussin struct ucl_macro *macro, *mtmp; 477c99fb5f9SBaptiste Daroussin struct ucl_chunk *chunk, *ctmp; 478c99fb5f9SBaptiste Daroussin struct ucl_pubkey *key, *ktmp; 479c99fb5f9SBaptiste Daroussin struct ucl_variable *var, *vtmp; 48039ee7a7aSBaptiste Daroussin ucl_object_t *tr, *trtmp; 481c99fb5f9SBaptiste Daroussin 48297bd480fSBaptiste Daroussin if (parser == NULL) { 48397bd480fSBaptiste Daroussin return; 48497bd480fSBaptiste Daroussin } 48597bd480fSBaptiste Daroussin 486c99fb5f9SBaptiste Daroussin if (parser->top_obj != NULL) { 487c99fb5f9SBaptiste Daroussin ucl_object_unref (parser->top_obj); 488c99fb5f9SBaptiste Daroussin } 489c99fb5f9SBaptiste Daroussin 49039ee7a7aSBaptiste Daroussin if (parser->includepaths != NULL) { 49139ee7a7aSBaptiste Daroussin ucl_object_unref (parser->includepaths); 49239ee7a7aSBaptiste Daroussin } 49339ee7a7aSBaptiste Daroussin 494c99fb5f9SBaptiste Daroussin LL_FOREACH_SAFE (parser->stack, stack, stmp) { 495c99fb5f9SBaptiste Daroussin free (stack); 496c99fb5f9SBaptiste Daroussin } 497c99fb5f9SBaptiste Daroussin HASH_ITER (hh, parser->macroes, macro, mtmp) { 498c99fb5f9SBaptiste Daroussin free (macro->name); 499c99fb5f9SBaptiste Daroussin HASH_DEL (parser->macroes, macro); 500c99fb5f9SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_macro), macro); 501c99fb5f9SBaptiste Daroussin } 502c99fb5f9SBaptiste Daroussin LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) { 503c99fb5f9SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_chunk), chunk); 504c99fb5f9SBaptiste Daroussin } 505c99fb5f9SBaptiste Daroussin LL_FOREACH_SAFE (parser->keys, key, ktmp) { 506c99fb5f9SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_pubkey), key); 507c99fb5f9SBaptiste Daroussin } 508c99fb5f9SBaptiste Daroussin LL_FOREACH_SAFE (parser->variables, var, vtmp) { 509c99fb5f9SBaptiste Daroussin free (var->value); 510c99fb5f9SBaptiste Daroussin free (var->var); 511c99fb5f9SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_variable), var); 512c99fb5f9SBaptiste Daroussin } 51339ee7a7aSBaptiste Daroussin LL_FOREACH_SAFE (parser->trash_objs, tr, trtmp) { 51439ee7a7aSBaptiste Daroussin ucl_object_free_internal (tr, false, ucl_object_dtor_free); 51539ee7a7aSBaptiste Daroussin } 516c99fb5f9SBaptiste Daroussin 517c99fb5f9SBaptiste Daroussin if (parser->err != NULL) { 518c99fb5f9SBaptiste Daroussin utstring_free (parser->err); 519c99fb5f9SBaptiste Daroussin } 520c99fb5f9SBaptiste Daroussin 5214bf54857SBaptiste Daroussin if (parser->cur_file) { 5224bf54857SBaptiste Daroussin free (parser->cur_file); 5234bf54857SBaptiste Daroussin } 5244bf54857SBaptiste Daroussin 525d9f0ce31SBaptiste Daroussin if (parser->comments) { 526d9f0ce31SBaptiste Daroussin ucl_object_unref (parser->comments); 527d9f0ce31SBaptiste Daroussin } 528d9f0ce31SBaptiste Daroussin 529c99fb5f9SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_parser), parser); 530c99fb5f9SBaptiste Daroussin } 531c99fb5f9SBaptiste Daroussin 53239ee7a7aSBaptiste Daroussin const char * 533c99fb5f9SBaptiste Daroussin ucl_parser_get_error(struct ucl_parser *parser) 534c99fb5f9SBaptiste Daroussin { 53597bd480fSBaptiste Daroussin if (parser == NULL) { 53697bd480fSBaptiste Daroussin return NULL; 53797bd480fSBaptiste Daroussin } 53897bd480fSBaptiste Daroussin 53939ee7a7aSBaptiste Daroussin if (parser->err == NULL) { 540c99fb5f9SBaptiste Daroussin return NULL; 54139ee7a7aSBaptiste Daroussin } 542c99fb5f9SBaptiste Daroussin 543c99fb5f9SBaptiste Daroussin return utstring_body (parser->err); 544c99fb5f9SBaptiste Daroussin } 545c99fb5f9SBaptiste Daroussin 54639ee7a7aSBaptiste Daroussin int 54739ee7a7aSBaptiste Daroussin ucl_parser_get_error_code(struct ucl_parser *parser) 54839ee7a7aSBaptiste Daroussin { 54939ee7a7aSBaptiste Daroussin if (parser == NULL) { 55039ee7a7aSBaptiste Daroussin return 0; 55139ee7a7aSBaptiste Daroussin } 55239ee7a7aSBaptiste Daroussin 55339ee7a7aSBaptiste Daroussin return parser->err_code; 55439ee7a7aSBaptiste Daroussin } 55539ee7a7aSBaptiste Daroussin 55639ee7a7aSBaptiste Daroussin unsigned 55739ee7a7aSBaptiste Daroussin ucl_parser_get_column(struct ucl_parser *parser) 55839ee7a7aSBaptiste Daroussin { 55939ee7a7aSBaptiste Daroussin if (parser == NULL || parser->chunks == NULL) { 56039ee7a7aSBaptiste Daroussin return 0; 56139ee7a7aSBaptiste Daroussin } 56239ee7a7aSBaptiste Daroussin 56339ee7a7aSBaptiste Daroussin return parser->chunks->column; 56439ee7a7aSBaptiste Daroussin } 56539ee7a7aSBaptiste Daroussin 56639ee7a7aSBaptiste Daroussin unsigned 56739ee7a7aSBaptiste Daroussin ucl_parser_get_linenum(struct ucl_parser *parser) 56839ee7a7aSBaptiste Daroussin { 56939ee7a7aSBaptiste Daroussin if (parser == NULL || parser->chunks == NULL) { 57039ee7a7aSBaptiste Daroussin return 0; 57139ee7a7aSBaptiste Daroussin } 57239ee7a7aSBaptiste Daroussin 57339ee7a7aSBaptiste Daroussin return parser->chunks->line; 57439ee7a7aSBaptiste Daroussin } 57539ee7a7aSBaptiste Daroussin 57639ee7a7aSBaptiste Daroussin void 5778e3b1ab2SBaptiste Daroussin ucl_parser_clear_error(struct ucl_parser *parser) 5788e3b1ab2SBaptiste Daroussin { 5798e3b1ab2SBaptiste Daroussin if (parser != NULL && parser->err != NULL) { 5808e3b1ab2SBaptiste Daroussin utstring_free(parser->err); 5818e3b1ab2SBaptiste Daroussin parser->err = NULL; 58239ee7a7aSBaptiste Daroussin parser->err_code = 0; 5838e3b1ab2SBaptiste Daroussin } 5848e3b1ab2SBaptiste Daroussin } 5858e3b1ab2SBaptiste Daroussin 58639ee7a7aSBaptiste Daroussin bool 587c99fb5f9SBaptiste Daroussin ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) 588c99fb5f9SBaptiste Daroussin { 589c99fb5f9SBaptiste Daroussin #ifndef HAVE_OPENSSL 590c99fb5f9SBaptiste Daroussin ucl_create_err (&parser->err, "cannot check signatures without openssl"); 591c99fb5f9SBaptiste Daroussin return false; 592c99fb5f9SBaptiste Daroussin #else 593c99fb5f9SBaptiste Daroussin # if (OPENSSL_VERSION_NUMBER < 0x10000000L) 594c99fb5f9SBaptiste Daroussin ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported"); 595c99fb5f9SBaptiste Daroussin return EXIT_FAILURE; 596c99fb5f9SBaptiste Daroussin # else 597c99fb5f9SBaptiste Daroussin struct ucl_pubkey *nkey; 598c99fb5f9SBaptiste Daroussin BIO *mem; 599c99fb5f9SBaptiste Daroussin 600c99fb5f9SBaptiste Daroussin mem = BIO_new_mem_buf ((void *)key, len); 601c99fb5f9SBaptiste Daroussin nkey = UCL_ALLOC (sizeof (struct ucl_pubkey)); 60297bd480fSBaptiste Daroussin if (nkey == NULL) { 60397bd480fSBaptiste Daroussin ucl_create_err (&parser->err, "cannot allocate memory for key"); 60497bd480fSBaptiste Daroussin return false; 60597bd480fSBaptiste Daroussin } 606c99fb5f9SBaptiste Daroussin nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL); 607c99fb5f9SBaptiste Daroussin BIO_free (mem); 608c99fb5f9SBaptiste Daroussin if (nkey->key == NULL) { 609c99fb5f9SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_pubkey), nkey); 610c99fb5f9SBaptiste Daroussin ucl_create_err (&parser->err, "%s", 611c99fb5f9SBaptiste Daroussin ERR_error_string (ERR_get_error (), NULL)); 612c99fb5f9SBaptiste Daroussin return false; 613c99fb5f9SBaptiste Daroussin } 614c99fb5f9SBaptiste Daroussin LL_PREPEND (parser->keys, nkey); 615c99fb5f9SBaptiste Daroussin # endif 616c99fb5f9SBaptiste Daroussin #endif 617c99fb5f9SBaptiste Daroussin return true; 618c99fb5f9SBaptiste Daroussin } 619c99fb5f9SBaptiste Daroussin 620c99fb5f9SBaptiste Daroussin #ifdef CURL_FOUND 621c99fb5f9SBaptiste Daroussin struct ucl_curl_cbdata { 622c99fb5f9SBaptiste Daroussin unsigned char *buf; 623c99fb5f9SBaptiste Daroussin size_t buflen; 624c99fb5f9SBaptiste Daroussin }; 625c99fb5f9SBaptiste Daroussin 626c99fb5f9SBaptiste Daroussin static size_t 627c99fb5f9SBaptiste Daroussin ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud) 628c99fb5f9SBaptiste Daroussin { 629c99fb5f9SBaptiste Daroussin struct ucl_curl_cbdata *cbdata = ud; 630c99fb5f9SBaptiste Daroussin size_t realsize = size * nmemb; 631c99fb5f9SBaptiste Daroussin 632c99fb5f9SBaptiste Daroussin cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1); 633c99fb5f9SBaptiste Daroussin if (cbdata->buf == NULL) { 634c99fb5f9SBaptiste Daroussin return 0; 635c99fb5f9SBaptiste Daroussin } 636c99fb5f9SBaptiste Daroussin 637c99fb5f9SBaptiste Daroussin memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize); 638c99fb5f9SBaptiste Daroussin cbdata->buflen += realsize; 639c99fb5f9SBaptiste Daroussin cbdata->buf[cbdata->buflen] = 0; 640c99fb5f9SBaptiste Daroussin 641c99fb5f9SBaptiste Daroussin return realsize; 642c99fb5f9SBaptiste Daroussin } 643c99fb5f9SBaptiste Daroussin #endif 644c99fb5f9SBaptiste Daroussin 645c99fb5f9SBaptiste Daroussin /** 646c99fb5f9SBaptiste Daroussin * Fetch a url and save results to the memory buffer 647c99fb5f9SBaptiste Daroussin * @param url url to fetch 648c99fb5f9SBaptiste Daroussin * @param len length of url 649c99fb5f9SBaptiste Daroussin * @param buf target buffer 650c99fb5f9SBaptiste Daroussin * @param buflen target length 651c99fb5f9SBaptiste Daroussin * @return 652c99fb5f9SBaptiste Daroussin */ 653d9f0ce31SBaptiste Daroussin bool 654c99fb5f9SBaptiste Daroussin ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen, 655c99fb5f9SBaptiste Daroussin UT_string **err, bool must_exist) 656c99fb5f9SBaptiste Daroussin { 657c99fb5f9SBaptiste Daroussin 658c99fb5f9SBaptiste Daroussin #ifdef HAVE_FETCH_H 659c99fb5f9SBaptiste Daroussin struct url *fetch_url; 660c99fb5f9SBaptiste Daroussin struct url_stat us; 661c99fb5f9SBaptiste Daroussin FILE *in; 662c99fb5f9SBaptiste Daroussin 663c99fb5f9SBaptiste Daroussin fetch_url = fetchParseURL (url); 664c99fb5f9SBaptiste Daroussin if (fetch_url == NULL) { 665c99fb5f9SBaptiste Daroussin ucl_create_err (err, "invalid URL %s: %s", 666c99fb5f9SBaptiste Daroussin url, strerror (errno)); 667c99fb5f9SBaptiste Daroussin return false; 668c99fb5f9SBaptiste Daroussin } 669c99fb5f9SBaptiste Daroussin if ((in = fetchXGet (fetch_url, &us, "")) == NULL) { 670c99fb5f9SBaptiste Daroussin if (!must_exist) { 671c99fb5f9SBaptiste Daroussin ucl_create_err (err, "cannot fetch URL %s: %s", 672c99fb5f9SBaptiste Daroussin url, strerror (errno)); 673c99fb5f9SBaptiste Daroussin } 674c99fb5f9SBaptiste Daroussin fetchFreeURL (fetch_url); 675c99fb5f9SBaptiste Daroussin return false; 676c99fb5f9SBaptiste Daroussin } 677c99fb5f9SBaptiste Daroussin 678c99fb5f9SBaptiste Daroussin *buflen = us.size; 679c99fb5f9SBaptiste Daroussin *buf = malloc (*buflen); 680c99fb5f9SBaptiste Daroussin if (*buf == NULL) { 681c99fb5f9SBaptiste Daroussin ucl_create_err (err, "cannot allocate buffer for URL %s: %s", 682c99fb5f9SBaptiste Daroussin url, strerror (errno)); 683c99fb5f9SBaptiste Daroussin fclose (in); 684c99fb5f9SBaptiste Daroussin fetchFreeURL (fetch_url); 685c99fb5f9SBaptiste Daroussin return false; 686c99fb5f9SBaptiste Daroussin } 687c99fb5f9SBaptiste Daroussin 688c99fb5f9SBaptiste Daroussin if (fread (*buf, *buflen, 1, in) != 1) { 689c99fb5f9SBaptiste Daroussin ucl_create_err (err, "cannot read URL %s: %s", 690c99fb5f9SBaptiste Daroussin url, strerror (errno)); 691c99fb5f9SBaptiste Daroussin fclose (in); 692c99fb5f9SBaptiste Daroussin fetchFreeURL (fetch_url); 693c99fb5f9SBaptiste Daroussin return false; 694c99fb5f9SBaptiste Daroussin } 695c99fb5f9SBaptiste Daroussin 696c99fb5f9SBaptiste Daroussin fetchFreeURL (fetch_url); 697c99fb5f9SBaptiste Daroussin return true; 698c99fb5f9SBaptiste Daroussin #elif defined(CURL_FOUND) 699c99fb5f9SBaptiste Daroussin CURL *curl; 700c99fb5f9SBaptiste Daroussin int r; 701c99fb5f9SBaptiste Daroussin struct ucl_curl_cbdata cbdata; 702c99fb5f9SBaptiste Daroussin 703c99fb5f9SBaptiste Daroussin curl = curl_easy_init (); 704c99fb5f9SBaptiste Daroussin if (curl == NULL) { 705c99fb5f9SBaptiste Daroussin ucl_create_err (err, "CURL interface is broken"); 706c99fb5f9SBaptiste Daroussin return false; 707c99fb5f9SBaptiste Daroussin } 708c99fb5f9SBaptiste Daroussin if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) { 709c99fb5f9SBaptiste Daroussin ucl_create_err (err, "invalid URL %s: %s", 710c99fb5f9SBaptiste Daroussin url, curl_easy_strerror (r)); 711c99fb5f9SBaptiste Daroussin curl_easy_cleanup (curl); 712c99fb5f9SBaptiste Daroussin return false; 713c99fb5f9SBaptiste Daroussin } 714c99fb5f9SBaptiste Daroussin curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback); 715d9f0ce31SBaptiste Daroussin cbdata.buf = NULL; 716d9f0ce31SBaptiste Daroussin cbdata.buflen = 0; 717c99fb5f9SBaptiste Daroussin curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata); 718c99fb5f9SBaptiste Daroussin 719c99fb5f9SBaptiste Daroussin if ((r = curl_easy_perform (curl)) != CURLE_OK) { 720c99fb5f9SBaptiste Daroussin if (!must_exist) { 721c99fb5f9SBaptiste Daroussin ucl_create_err (err, "error fetching URL %s: %s", 722c99fb5f9SBaptiste Daroussin url, curl_easy_strerror (r)); 723c99fb5f9SBaptiste Daroussin } 724c99fb5f9SBaptiste Daroussin curl_easy_cleanup (curl); 725c99fb5f9SBaptiste Daroussin if (cbdata.buf) { 726c99fb5f9SBaptiste Daroussin free (cbdata.buf); 727c99fb5f9SBaptiste Daroussin } 728c99fb5f9SBaptiste Daroussin return false; 729c99fb5f9SBaptiste Daroussin } 730c99fb5f9SBaptiste Daroussin *buf = cbdata.buf; 731c99fb5f9SBaptiste Daroussin *buflen = cbdata.buflen; 732c99fb5f9SBaptiste Daroussin 733c99fb5f9SBaptiste Daroussin return true; 734c99fb5f9SBaptiste Daroussin #else 735c99fb5f9SBaptiste Daroussin ucl_create_err (err, "URL support is disabled"); 736c99fb5f9SBaptiste Daroussin return false; 737c99fb5f9SBaptiste Daroussin #endif 738c99fb5f9SBaptiste Daroussin } 739c99fb5f9SBaptiste Daroussin 740c99fb5f9SBaptiste Daroussin /** 741c99fb5f9SBaptiste Daroussin * Fetch a file and save results to the memory buffer 742c99fb5f9SBaptiste Daroussin * @param filename filename to fetch 743c99fb5f9SBaptiste Daroussin * @param len length of filename 744c99fb5f9SBaptiste Daroussin * @param buf target buffer 745c99fb5f9SBaptiste Daroussin * @param buflen target length 746c99fb5f9SBaptiste Daroussin * @return 747c99fb5f9SBaptiste Daroussin */ 748d9f0ce31SBaptiste Daroussin bool 749c99fb5f9SBaptiste Daroussin ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen, 750c99fb5f9SBaptiste Daroussin UT_string **err, bool must_exist) 751c99fb5f9SBaptiste Daroussin { 752c99fb5f9SBaptiste Daroussin int fd; 753c99fb5f9SBaptiste Daroussin struct stat st; 754c99fb5f9SBaptiste Daroussin 755c99fb5f9SBaptiste Daroussin if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) { 756c99fb5f9SBaptiste Daroussin if (must_exist) { 757c99fb5f9SBaptiste Daroussin ucl_create_err (err, "cannot stat file %s: %s", 758c99fb5f9SBaptiste Daroussin filename, strerror (errno)); 759c99fb5f9SBaptiste Daroussin } 760c99fb5f9SBaptiste Daroussin return false; 761c99fb5f9SBaptiste Daroussin } 762c99fb5f9SBaptiste Daroussin if (st.st_size == 0) { 763c99fb5f9SBaptiste Daroussin /* Do not map empty files */ 764d9f0ce31SBaptiste Daroussin *buf = NULL; 765c99fb5f9SBaptiste Daroussin *buflen = 0; 766c99fb5f9SBaptiste Daroussin } 767c99fb5f9SBaptiste Daroussin else { 768c99fb5f9SBaptiste Daroussin if ((fd = open (filename, O_RDONLY)) == -1) { 769c99fb5f9SBaptiste Daroussin ucl_create_err (err, "cannot open file %s: %s", 770c99fb5f9SBaptiste Daroussin filename, strerror (errno)); 771c99fb5f9SBaptiste Daroussin return false; 772c99fb5f9SBaptiste Daroussin } 77397bd480fSBaptiste Daroussin if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 774c99fb5f9SBaptiste Daroussin close (fd); 775c99fb5f9SBaptiste Daroussin ucl_create_err (err, "cannot mmap file %s: %s", 776c99fb5f9SBaptiste Daroussin filename, strerror (errno)); 777d9f0ce31SBaptiste Daroussin *buf = NULL; 778d9f0ce31SBaptiste Daroussin 779c99fb5f9SBaptiste Daroussin return false; 780c99fb5f9SBaptiste Daroussin } 781c99fb5f9SBaptiste Daroussin *buflen = st.st_size; 782c99fb5f9SBaptiste Daroussin close (fd); 783c99fb5f9SBaptiste Daroussin } 784c99fb5f9SBaptiste Daroussin 785c99fb5f9SBaptiste Daroussin return true; 786c99fb5f9SBaptiste Daroussin } 787c99fb5f9SBaptiste Daroussin 788c99fb5f9SBaptiste Daroussin 789c99fb5f9SBaptiste Daroussin #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 790c99fb5f9SBaptiste Daroussin static inline bool 791c99fb5f9SBaptiste Daroussin ucl_sig_check (const unsigned char *data, size_t datalen, 792c99fb5f9SBaptiste Daroussin const unsigned char *sig, size_t siglen, struct ucl_parser *parser) 793c99fb5f9SBaptiste Daroussin { 794c99fb5f9SBaptiste Daroussin struct ucl_pubkey *key; 795c99fb5f9SBaptiste Daroussin char dig[EVP_MAX_MD_SIZE]; 796c99fb5f9SBaptiste Daroussin unsigned int diglen; 797c99fb5f9SBaptiste Daroussin EVP_PKEY_CTX *key_ctx; 798c99fb5f9SBaptiste Daroussin EVP_MD_CTX *sign_ctx = NULL; 799c99fb5f9SBaptiste Daroussin 800c99fb5f9SBaptiste Daroussin sign_ctx = EVP_MD_CTX_create (); 801c99fb5f9SBaptiste Daroussin 802c99fb5f9SBaptiste Daroussin LL_FOREACH (parser->keys, key) { 803c99fb5f9SBaptiste Daroussin key_ctx = EVP_PKEY_CTX_new (key->key, NULL); 804c99fb5f9SBaptiste Daroussin if (key_ctx != NULL) { 805c99fb5f9SBaptiste Daroussin if (EVP_PKEY_verify_init (key_ctx) <= 0) { 806c99fb5f9SBaptiste Daroussin EVP_PKEY_CTX_free (key_ctx); 807c99fb5f9SBaptiste Daroussin continue; 808c99fb5f9SBaptiste Daroussin } 809c99fb5f9SBaptiste Daroussin if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) { 810c99fb5f9SBaptiste Daroussin EVP_PKEY_CTX_free (key_ctx); 811c99fb5f9SBaptiste Daroussin continue; 812c99fb5f9SBaptiste Daroussin } 813c99fb5f9SBaptiste Daroussin if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) { 814c99fb5f9SBaptiste Daroussin EVP_PKEY_CTX_free (key_ctx); 815c99fb5f9SBaptiste Daroussin continue; 816c99fb5f9SBaptiste Daroussin } 817c99fb5f9SBaptiste Daroussin EVP_DigestInit (sign_ctx, EVP_sha256 ()); 818c99fb5f9SBaptiste Daroussin EVP_DigestUpdate (sign_ctx, data, datalen); 819c99fb5f9SBaptiste Daroussin EVP_DigestFinal (sign_ctx, dig, &diglen); 820c99fb5f9SBaptiste Daroussin 821c99fb5f9SBaptiste Daroussin if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) { 822c99fb5f9SBaptiste Daroussin EVP_MD_CTX_destroy (sign_ctx); 823c99fb5f9SBaptiste Daroussin EVP_PKEY_CTX_free (key_ctx); 824c99fb5f9SBaptiste Daroussin return true; 825c99fb5f9SBaptiste Daroussin } 826c99fb5f9SBaptiste Daroussin 827c99fb5f9SBaptiste Daroussin EVP_PKEY_CTX_free (key_ctx); 828c99fb5f9SBaptiste Daroussin } 829c99fb5f9SBaptiste Daroussin } 830c99fb5f9SBaptiste Daroussin 831c99fb5f9SBaptiste Daroussin EVP_MD_CTX_destroy (sign_ctx); 832c99fb5f9SBaptiste Daroussin 833c99fb5f9SBaptiste Daroussin return false; 834c99fb5f9SBaptiste Daroussin } 835c99fb5f9SBaptiste Daroussin #endif 836c99fb5f9SBaptiste Daroussin 83739ee7a7aSBaptiste Daroussin struct ucl_include_params { 83839ee7a7aSBaptiste Daroussin bool check_signature; 83939ee7a7aSBaptiste Daroussin bool must_exist; 84039ee7a7aSBaptiste Daroussin bool use_glob; 84139ee7a7aSBaptiste Daroussin bool use_prefix; 84239ee7a7aSBaptiste Daroussin bool soft_fail; 84339ee7a7aSBaptiste Daroussin bool allow_glob; 84439ee7a7aSBaptiste Daroussin unsigned priority; 84539ee7a7aSBaptiste Daroussin enum ucl_duplicate_strategy strat; 84639ee7a7aSBaptiste Daroussin enum ucl_parse_type parse_type; 84739ee7a7aSBaptiste Daroussin const char *prefix; 84839ee7a7aSBaptiste Daroussin const char *target; 84939ee7a7aSBaptiste Daroussin }; 85039ee7a7aSBaptiste Daroussin 851c99fb5f9SBaptiste Daroussin /** 852c99fb5f9SBaptiste Daroussin * Include an url to configuration 853c99fb5f9SBaptiste Daroussin * @param data 854c99fb5f9SBaptiste Daroussin * @param len 855c99fb5f9SBaptiste Daroussin * @param parser 856c99fb5f9SBaptiste Daroussin * @param err 857c99fb5f9SBaptiste Daroussin * @return 858c99fb5f9SBaptiste Daroussin */ 859c99fb5f9SBaptiste Daroussin static bool 860c99fb5f9SBaptiste Daroussin ucl_include_url (const unsigned char *data, size_t len, 86139ee7a7aSBaptiste Daroussin struct ucl_parser *parser, 86239ee7a7aSBaptiste Daroussin struct ucl_include_params *params) 863c99fb5f9SBaptiste Daroussin { 864c99fb5f9SBaptiste Daroussin 865c99fb5f9SBaptiste Daroussin bool res; 866c99fb5f9SBaptiste Daroussin unsigned char *buf = NULL; 867c99fb5f9SBaptiste Daroussin size_t buflen = 0; 868c99fb5f9SBaptiste Daroussin struct ucl_chunk *chunk; 869c99fb5f9SBaptiste Daroussin char urlbuf[PATH_MAX]; 870c99fb5f9SBaptiste Daroussin int prev_state; 871c99fb5f9SBaptiste Daroussin 872c99fb5f9SBaptiste Daroussin snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data); 873c99fb5f9SBaptiste Daroussin 87439ee7a7aSBaptiste Daroussin if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, params->must_exist)) { 875d9f0ce31SBaptiste Daroussin return !params->must_exist; 876c99fb5f9SBaptiste Daroussin } 877c99fb5f9SBaptiste Daroussin 87839ee7a7aSBaptiste Daroussin if (params->check_signature) { 879c99fb5f9SBaptiste Daroussin #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 880c99fb5f9SBaptiste Daroussin unsigned char *sigbuf = NULL; 881c99fb5f9SBaptiste Daroussin size_t siglen = 0; 882c99fb5f9SBaptiste Daroussin /* We need to check signature first */ 883c99fb5f9SBaptiste Daroussin snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data); 884c99fb5f9SBaptiste Daroussin if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) { 885c99fb5f9SBaptiste Daroussin return false; 886c99fb5f9SBaptiste Daroussin } 887c99fb5f9SBaptiste Daroussin if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { 888c99fb5f9SBaptiste Daroussin ucl_create_err (&parser->err, "cannot verify url %s: %s", 889c99fb5f9SBaptiste Daroussin urlbuf, 890c99fb5f9SBaptiste Daroussin ERR_error_string (ERR_get_error (), NULL)); 891c99fb5f9SBaptiste Daroussin if (siglen > 0) { 89297bd480fSBaptiste Daroussin ucl_munmap (sigbuf, siglen); 893c99fb5f9SBaptiste Daroussin } 894c99fb5f9SBaptiste Daroussin return false; 895c99fb5f9SBaptiste Daroussin } 896c99fb5f9SBaptiste Daroussin if (siglen > 0) { 89797bd480fSBaptiste Daroussin ucl_munmap (sigbuf, siglen); 898c99fb5f9SBaptiste Daroussin } 899c99fb5f9SBaptiste Daroussin #endif 900c99fb5f9SBaptiste Daroussin } 901c99fb5f9SBaptiste Daroussin 902c99fb5f9SBaptiste Daroussin prev_state = parser->state; 903c99fb5f9SBaptiste Daroussin parser->state = UCL_STATE_INIT; 904c99fb5f9SBaptiste Daroussin 90539ee7a7aSBaptiste Daroussin res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority, 90639ee7a7aSBaptiste Daroussin params->strat, params->parse_type); 907c99fb5f9SBaptiste Daroussin if (res == true) { 908c99fb5f9SBaptiste Daroussin /* Remove chunk from the stack */ 909c99fb5f9SBaptiste Daroussin chunk = parser->chunks; 910c99fb5f9SBaptiste Daroussin if (chunk != NULL) { 911c99fb5f9SBaptiste Daroussin parser->chunks = chunk->next; 912c99fb5f9SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_chunk), chunk); 913c99fb5f9SBaptiste Daroussin } 914c99fb5f9SBaptiste Daroussin } 915c99fb5f9SBaptiste Daroussin 916c99fb5f9SBaptiste Daroussin parser->state = prev_state; 917c99fb5f9SBaptiste Daroussin free (buf); 918c99fb5f9SBaptiste Daroussin 919c99fb5f9SBaptiste Daroussin return res; 920c99fb5f9SBaptiste Daroussin } 921c99fb5f9SBaptiste Daroussin 922c99fb5f9SBaptiste Daroussin /** 9234bf54857SBaptiste Daroussin * Include a single file to the parser 924c99fb5f9SBaptiste Daroussin * @param data 925c99fb5f9SBaptiste Daroussin * @param len 926c99fb5f9SBaptiste Daroussin * @param parser 9274bf54857SBaptiste Daroussin * @param check_signature 9284bf54857SBaptiste Daroussin * @param must_exist 9294bf54857SBaptiste Daroussin * @param allow_glob 9304bf54857SBaptiste Daroussin * @param priority 931c99fb5f9SBaptiste Daroussin * @return 932c99fb5f9SBaptiste Daroussin */ 933c99fb5f9SBaptiste Daroussin static bool 9344bf54857SBaptiste Daroussin ucl_include_file_single (const unsigned char *data, size_t len, 93539ee7a7aSBaptiste Daroussin struct ucl_parser *parser, struct ucl_include_params *params) 936c99fb5f9SBaptiste Daroussin { 937c99fb5f9SBaptiste Daroussin bool res; 938c99fb5f9SBaptiste Daroussin struct ucl_chunk *chunk; 939c99fb5f9SBaptiste Daroussin unsigned char *buf = NULL; 94039ee7a7aSBaptiste Daroussin char *old_curfile, *ext; 94139ee7a7aSBaptiste Daroussin size_t buflen = 0; 942c99fb5f9SBaptiste Daroussin char filebuf[PATH_MAX], realbuf[PATH_MAX]; 943c99fb5f9SBaptiste Daroussin int prev_state; 9444bf54857SBaptiste Daroussin struct ucl_variable *cur_var, *tmp_var, *old_curdir = NULL, 9454bf54857SBaptiste Daroussin *old_filename = NULL; 94639ee7a7aSBaptiste Daroussin ucl_object_t *nest_obj = NULL, *old_obj = NULL, *new_obj = NULL; 94739ee7a7aSBaptiste Daroussin ucl_hash_t *container = NULL; 94839ee7a7aSBaptiste Daroussin struct ucl_stack *st = NULL; 949c99fb5f9SBaptiste Daroussin 950c99fb5f9SBaptiste Daroussin snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data); 95197bd480fSBaptiste Daroussin if (ucl_realpath (filebuf, realbuf) == NULL) { 95239ee7a7aSBaptiste Daroussin if (params->soft_fail) { 95339ee7a7aSBaptiste Daroussin return false; 95439ee7a7aSBaptiste Daroussin } 95539ee7a7aSBaptiste Daroussin if (!params->must_exist) { 956c99fb5f9SBaptiste Daroussin return true; 957c99fb5f9SBaptiste Daroussin } 958c99fb5f9SBaptiste Daroussin ucl_create_err (&parser->err, "cannot open file %s: %s", 959c99fb5f9SBaptiste Daroussin filebuf, 960c99fb5f9SBaptiste Daroussin strerror (errno)); 961c99fb5f9SBaptiste Daroussin return false; 962c99fb5f9SBaptiste Daroussin } 963c99fb5f9SBaptiste Daroussin 9644bf54857SBaptiste Daroussin if (parser->cur_file && strcmp (realbuf, parser->cur_file) == 0) { 9654bf54857SBaptiste Daroussin /* We are likely including the file itself */ 96639ee7a7aSBaptiste Daroussin if (params->soft_fail) { 96739ee7a7aSBaptiste Daroussin return false; 96839ee7a7aSBaptiste Daroussin } 96939ee7a7aSBaptiste Daroussin 9704bf54857SBaptiste Daroussin ucl_create_err (&parser->err, "trying to include the file %s from itself", 9714bf54857SBaptiste Daroussin realbuf); 9724bf54857SBaptiste Daroussin return false; 9734bf54857SBaptiste Daroussin } 9744bf54857SBaptiste Daroussin 97539ee7a7aSBaptiste Daroussin if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, params->must_exist)) { 97639ee7a7aSBaptiste Daroussin if (params->soft_fail) { 97739ee7a7aSBaptiste Daroussin return false; 97839ee7a7aSBaptiste Daroussin } 9796525738fSBaptiste Daroussin 98039ee7a7aSBaptiste Daroussin return (!params->must_exist || false); 981c99fb5f9SBaptiste Daroussin } 982c99fb5f9SBaptiste Daroussin 98339ee7a7aSBaptiste Daroussin if (params->check_signature) { 984c99fb5f9SBaptiste Daroussin #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L) 985c99fb5f9SBaptiste Daroussin unsigned char *sigbuf = NULL; 986c99fb5f9SBaptiste Daroussin size_t siglen = 0; 987c99fb5f9SBaptiste Daroussin /* We need to check signature first */ 988c99fb5f9SBaptiste Daroussin snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf); 989c99fb5f9SBaptiste Daroussin if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) { 990c99fb5f9SBaptiste Daroussin return false; 991c99fb5f9SBaptiste Daroussin } 992c99fb5f9SBaptiste Daroussin if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { 993c99fb5f9SBaptiste Daroussin ucl_create_err (&parser->err, "cannot verify file %s: %s", 994c99fb5f9SBaptiste Daroussin filebuf, 995c99fb5f9SBaptiste Daroussin ERR_error_string (ERR_get_error (), NULL)); 996d9f0ce31SBaptiste Daroussin if (sigbuf) { 99797bd480fSBaptiste Daroussin ucl_munmap (sigbuf, siglen); 998c99fb5f9SBaptiste Daroussin } 999c99fb5f9SBaptiste Daroussin return false; 1000c99fb5f9SBaptiste Daroussin } 1001d9f0ce31SBaptiste Daroussin if (sigbuf) { 100297bd480fSBaptiste Daroussin ucl_munmap (sigbuf, siglen); 1003c99fb5f9SBaptiste Daroussin } 1004c99fb5f9SBaptiste Daroussin #endif 1005c99fb5f9SBaptiste Daroussin } 1006c99fb5f9SBaptiste Daroussin 10074bf54857SBaptiste Daroussin old_curfile = parser->cur_file; 10084bf54857SBaptiste Daroussin parser->cur_file = strdup (realbuf); 10094bf54857SBaptiste Daroussin 10104bf54857SBaptiste Daroussin /* Store old file vars */ 10114bf54857SBaptiste Daroussin DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) { 10124bf54857SBaptiste Daroussin if (strcmp (cur_var->var, "CURDIR") == 0) { 10134bf54857SBaptiste Daroussin old_curdir = cur_var; 10144bf54857SBaptiste Daroussin DL_DELETE (parser->variables, cur_var); 10154bf54857SBaptiste Daroussin } 10164bf54857SBaptiste Daroussin else if (strcmp (cur_var->var, "FILENAME") == 0) { 10174bf54857SBaptiste Daroussin old_filename = cur_var; 10184bf54857SBaptiste Daroussin DL_DELETE (parser->variables, cur_var); 10194bf54857SBaptiste Daroussin } 10204bf54857SBaptiste Daroussin } 10214bf54857SBaptiste Daroussin 1022c99fb5f9SBaptiste Daroussin ucl_parser_set_filevars (parser, realbuf, false); 1023c99fb5f9SBaptiste Daroussin 1024c99fb5f9SBaptiste Daroussin prev_state = parser->state; 1025c99fb5f9SBaptiste Daroussin parser->state = UCL_STATE_INIT; 1026c99fb5f9SBaptiste Daroussin 102739ee7a7aSBaptiste Daroussin if (params->use_prefix && params->prefix == NULL) { 102839ee7a7aSBaptiste Daroussin /* Auto generate a key name based on the included filename */ 102939ee7a7aSBaptiste Daroussin params->prefix = basename (realbuf); 103039ee7a7aSBaptiste Daroussin ext = strrchr (params->prefix, '.'); 103139ee7a7aSBaptiste Daroussin if (ext != NULL && (strcmp (ext, ".conf") == 0 || strcmp (ext, ".ucl") == 0)) { 103239ee7a7aSBaptiste Daroussin /* Strip off .conf or .ucl */ 103339ee7a7aSBaptiste Daroussin *ext = '\0'; 103439ee7a7aSBaptiste Daroussin } 103539ee7a7aSBaptiste Daroussin } 103639ee7a7aSBaptiste Daroussin if (params->prefix != NULL) { 103739ee7a7aSBaptiste Daroussin /* This is a prefixed include */ 103839ee7a7aSBaptiste Daroussin container = parser->stack->obj->value.ov; 103939ee7a7aSBaptiste Daroussin 104039ee7a7aSBaptiste Daroussin old_obj = __DECONST (ucl_object_t *, ucl_hash_search (container, 104139ee7a7aSBaptiste Daroussin params->prefix, strlen (params->prefix))); 104239ee7a7aSBaptiste Daroussin 104339ee7a7aSBaptiste Daroussin if (strcasecmp (params->target, "array") == 0 && old_obj == NULL) { 104439ee7a7aSBaptiste Daroussin /* Create an array with key: prefix */ 104539ee7a7aSBaptiste Daroussin old_obj = ucl_object_new_full (UCL_ARRAY, params->priority); 104639ee7a7aSBaptiste Daroussin old_obj->key = params->prefix; 104739ee7a7aSBaptiste Daroussin old_obj->keylen = strlen (params->prefix); 104839ee7a7aSBaptiste Daroussin ucl_copy_key_trash(old_obj); 104939ee7a7aSBaptiste Daroussin old_obj->prev = old_obj; 105039ee7a7aSBaptiste Daroussin old_obj->next = NULL; 105139ee7a7aSBaptiste Daroussin 105239ee7a7aSBaptiste Daroussin container = ucl_hash_insert_object (container, old_obj, 105339ee7a7aSBaptiste Daroussin parser->flags & UCL_PARSER_KEY_LOWERCASE); 105439ee7a7aSBaptiste Daroussin parser->stack->obj->len ++; 105539ee7a7aSBaptiste Daroussin 105639ee7a7aSBaptiste Daroussin nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority); 105739ee7a7aSBaptiste Daroussin nest_obj->prev = nest_obj; 105839ee7a7aSBaptiste Daroussin nest_obj->next = NULL; 105939ee7a7aSBaptiste Daroussin 106039ee7a7aSBaptiste Daroussin ucl_array_append (old_obj, nest_obj); 106139ee7a7aSBaptiste Daroussin } 106239ee7a7aSBaptiste Daroussin else if (old_obj == NULL) { 106339ee7a7aSBaptiste Daroussin /* Create an object with key: prefix */ 106439ee7a7aSBaptiste Daroussin nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority); 1065d9f0ce31SBaptiste Daroussin 1066d9f0ce31SBaptiste Daroussin if (nest_obj == NULL) { 1067d9f0ce31SBaptiste Daroussin ucl_create_err (&parser->err, "cannot allocate memory for an object"); 1068d9f0ce31SBaptiste Daroussin if (buf) { 1069d9f0ce31SBaptiste Daroussin ucl_munmap (buf, buflen); 1070d9f0ce31SBaptiste Daroussin } 1071d9f0ce31SBaptiste Daroussin 1072d9f0ce31SBaptiste Daroussin return false; 1073d9f0ce31SBaptiste Daroussin } 1074d9f0ce31SBaptiste Daroussin 107539ee7a7aSBaptiste Daroussin nest_obj->key = params->prefix; 107639ee7a7aSBaptiste Daroussin nest_obj->keylen = strlen (params->prefix); 107739ee7a7aSBaptiste Daroussin ucl_copy_key_trash(nest_obj); 107839ee7a7aSBaptiste Daroussin nest_obj->prev = nest_obj; 107939ee7a7aSBaptiste Daroussin nest_obj->next = NULL; 108039ee7a7aSBaptiste Daroussin 108139ee7a7aSBaptiste Daroussin container = ucl_hash_insert_object (container, nest_obj, 108239ee7a7aSBaptiste Daroussin parser->flags & UCL_PARSER_KEY_LOWERCASE); 108339ee7a7aSBaptiste Daroussin parser->stack->obj->len ++; 108439ee7a7aSBaptiste Daroussin } 108539ee7a7aSBaptiste Daroussin else if (strcasecmp (params->target, "array") == 0 || 108639ee7a7aSBaptiste Daroussin ucl_object_type(old_obj) == UCL_ARRAY) { 108739ee7a7aSBaptiste Daroussin if (ucl_object_type(old_obj) == UCL_ARRAY) { 108839ee7a7aSBaptiste Daroussin /* Append to the existing array */ 108939ee7a7aSBaptiste Daroussin nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority); 1090d9f0ce31SBaptiste Daroussin if (nest_obj == NULL) { 1091d9f0ce31SBaptiste Daroussin ucl_create_err (&parser->err, "cannot allocate memory for an object"); 1092d9f0ce31SBaptiste Daroussin if (buf) { 1093d9f0ce31SBaptiste Daroussin ucl_munmap (buf, buflen); 1094d9f0ce31SBaptiste Daroussin } 1095d9f0ce31SBaptiste Daroussin 1096d9f0ce31SBaptiste Daroussin return false; 1097d9f0ce31SBaptiste Daroussin } 109839ee7a7aSBaptiste Daroussin nest_obj->prev = nest_obj; 109939ee7a7aSBaptiste Daroussin nest_obj->next = NULL; 110039ee7a7aSBaptiste Daroussin 110139ee7a7aSBaptiste Daroussin ucl_array_append (old_obj, nest_obj); 110239ee7a7aSBaptiste Daroussin } 110339ee7a7aSBaptiste Daroussin else { 110439ee7a7aSBaptiste Daroussin /* Convert the object to an array */ 110539ee7a7aSBaptiste Daroussin new_obj = ucl_object_typed_new (UCL_ARRAY); 1106d9f0ce31SBaptiste Daroussin if (new_obj == NULL) { 1107d9f0ce31SBaptiste Daroussin ucl_create_err (&parser->err, "cannot allocate memory for an object"); 1108d9f0ce31SBaptiste Daroussin if (buf) { 1109d9f0ce31SBaptiste Daroussin ucl_munmap (buf, buflen); 1110d9f0ce31SBaptiste Daroussin } 1111d9f0ce31SBaptiste Daroussin 1112d9f0ce31SBaptiste Daroussin return false; 1113d9f0ce31SBaptiste Daroussin } 111439ee7a7aSBaptiste Daroussin new_obj->key = old_obj->key; 111539ee7a7aSBaptiste Daroussin new_obj->keylen = old_obj->keylen; 111639ee7a7aSBaptiste Daroussin new_obj->flags |= UCL_OBJECT_MULTIVALUE; 111739ee7a7aSBaptiste Daroussin new_obj->prev = new_obj; 111839ee7a7aSBaptiste Daroussin new_obj->next = NULL; 111939ee7a7aSBaptiste Daroussin 112039ee7a7aSBaptiste Daroussin nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority); 1121d9f0ce31SBaptiste Daroussin if (nest_obj == NULL) { 1122d9f0ce31SBaptiste Daroussin ucl_create_err (&parser->err, "cannot allocate memory for an object"); 1123d9f0ce31SBaptiste Daroussin if (buf) { 1124d9f0ce31SBaptiste Daroussin ucl_munmap (buf, buflen); 1125d9f0ce31SBaptiste Daroussin } 1126d9f0ce31SBaptiste Daroussin 1127d9f0ce31SBaptiste Daroussin return false; 1128d9f0ce31SBaptiste Daroussin } 112939ee7a7aSBaptiste Daroussin nest_obj->prev = nest_obj; 113039ee7a7aSBaptiste Daroussin nest_obj->next = NULL; 113139ee7a7aSBaptiste Daroussin 113239ee7a7aSBaptiste Daroussin ucl_array_append (new_obj, old_obj); 113339ee7a7aSBaptiste Daroussin ucl_array_append (new_obj, nest_obj); 113439ee7a7aSBaptiste Daroussin ucl_hash_replace (container, old_obj, new_obj); 113539ee7a7aSBaptiste Daroussin } 113639ee7a7aSBaptiste Daroussin } 113739ee7a7aSBaptiste Daroussin else { 113839ee7a7aSBaptiste Daroussin if (ucl_object_type (old_obj) == UCL_OBJECT) { 113939ee7a7aSBaptiste Daroussin /* Append to existing Object*/ 114039ee7a7aSBaptiste Daroussin nest_obj = old_obj; 114139ee7a7aSBaptiste Daroussin } 114239ee7a7aSBaptiste Daroussin else { 114339ee7a7aSBaptiste Daroussin /* The key is not an object */ 114439ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, 114539ee7a7aSBaptiste Daroussin "Conflicting type for key: %s", 114639ee7a7aSBaptiste Daroussin params->prefix); 1147d9f0ce31SBaptiste Daroussin if (buf) { 1148d9f0ce31SBaptiste Daroussin ucl_munmap (buf, buflen); 1149d9f0ce31SBaptiste Daroussin } 1150d9f0ce31SBaptiste Daroussin 115139ee7a7aSBaptiste Daroussin return false; 115239ee7a7aSBaptiste Daroussin } 115339ee7a7aSBaptiste Daroussin } 115439ee7a7aSBaptiste Daroussin 115539ee7a7aSBaptiste Daroussin /* Put all of the content of the include inside that object */ 115639ee7a7aSBaptiste Daroussin parser->stack->obj->value.ov = container; 115739ee7a7aSBaptiste Daroussin 115839ee7a7aSBaptiste Daroussin st = UCL_ALLOC (sizeof (struct ucl_stack)); 115939ee7a7aSBaptiste Daroussin if (st == NULL) { 116039ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, "cannot allocate memory for an object"); 116139ee7a7aSBaptiste Daroussin ucl_object_unref (nest_obj); 1162d9f0ce31SBaptiste Daroussin 1163d9f0ce31SBaptiste Daroussin if (buf) { 1164d9f0ce31SBaptiste Daroussin ucl_munmap (buf, buflen); 1165d9f0ce31SBaptiste Daroussin } 1166d9f0ce31SBaptiste Daroussin 1167d9f0ce31SBaptiste Daroussin return false; 116839ee7a7aSBaptiste Daroussin } 116939ee7a7aSBaptiste Daroussin st->obj = nest_obj; 117039ee7a7aSBaptiste Daroussin st->level = parser->stack->level; 117139ee7a7aSBaptiste Daroussin LL_PREPEND (parser->stack, st); 117239ee7a7aSBaptiste Daroussin parser->cur_obj = nest_obj; 117339ee7a7aSBaptiste Daroussin } 117439ee7a7aSBaptiste Daroussin 117539ee7a7aSBaptiste Daroussin res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority, 117639ee7a7aSBaptiste Daroussin params->strat, params->parse_type); 11776525738fSBaptiste Daroussin 11786525738fSBaptiste Daroussin if (!res) { 11796525738fSBaptiste Daroussin if (!params->must_exist) { 11804bf54857SBaptiste Daroussin /* Free error */ 11814bf54857SBaptiste Daroussin utstring_free (parser->err); 11824bf54857SBaptiste Daroussin parser->err = NULL; 11836525738fSBaptiste Daroussin res = true; 11846525738fSBaptiste Daroussin } 11854bf54857SBaptiste Daroussin } 11864bf54857SBaptiste Daroussin 118739ee7a7aSBaptiste Daroussin /* Stop nesting the include, take 1 level off the stack */ 118839ee7a7aSBaptiste Daroussin if (params->prefix != NULL && nest_obj != NULL) { 118939ee7a7aSBaptiste Daroussin parser->stack = st->next; 119039ee7a7aSBaptiste Daroussin UCL_FREE (sizeof (struct ucl_stack), st); 119139ee7a7aSBaptiste Daroussin } 119239ee7a7aSBaptiste Daroussin 1193c99fb5f9SBaptiste Daroussin /* Remove chunk from the stack */ 1194c99fb5f9SBaptiste Daroussin chunk = parser->chunks; 1195c99fb5f9SBaptiste Daroussin if (chunk != NULL) { 1196c99fb5f9SBaptiste Daroussin parser->chunks = chunk->next; 1197c99fb5f9SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_chunk), chunk); 11984bf54857SBaptiste Daroussin parser->recursion --; 1199c99fb5f9SBaptiste Daroussin } 12004bf54857SBaptiste Daroussin 12014bf54857SBaptiste Daroussin /* Restore old file vars */ 120239ee7a7aSBaptiste Daroussin if (parser->cur_file) { 120339ee7a7aSBaptiste Daroussin free (parser->cur_file); 120439ee7a7aSBaptiste Daroussin } 120539ee7a7aSBaptiste Daroussin 12064bf54857SBaptiste Daroussin parser->cur_file = old_curfile; 12074bf54857SBaptiste Daroussin DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) { 12084bf54857SBaptiste Daroussin if (strcmp (cur_var->var, "CURDIR") == 0 && old_curdir) { 12094bf54857SBaptiste Daroussin DL_DELETE (parser->variables, cur_var); 12104bf54857SBaptiste Daroussin free (cur_var->var); 12114bf54857SBaptiste Daroussin free (cur_var->value); 12124bf54857SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_variable), cur_var); 12134bf54857SBaptiste Daroussin } 12144bf54857SBaptiste Daroussin else if (strcmp (cur_var->var, "FILENAME") == 0 && old_filename) { 12154bf54857SBaptiste Daroussin DL_DELETE (parser->variables, cur_var); 12164bf54857SBaptiste Daroussin free (cur_var->var); 12174bf54857SBaptiste Daroussin free (cur_var->value); 12184bf54857SBaptiste Daroussin UCL_FREE (sizeof (struct ucl_variable), cur_var); 12194bf54857SBaptiste Daroussin } 12204bf54857SBaptiste Daroussin } 12214bf54857SBaptiste Daroussin if (old_filename) { 12224bf54857SBaptiste Daroussin DL_APPEND (parser->variables, old_filename); 12234bf54857SBaptiste Daroussin } 12244bf54857SBaptiste Daroussin if (old_curdir) { 12254bf54857SBaptiste Daroussin DL_APPEND (parser->variables, old_curdir); 12264bf54857SBaptiste Daroussin } 1227c99fb5f9SBaptiste Daroussin 1228c99fb5f9SBaptiste Daroussin parser->state = prev_state; 1229c99fb5f9SBaptiste Daroussin 1230c99fb5f9SBaptiste Daroussin if (buflen > 0) { 123197bd480fSBaptiste Daroussin ucl_munmap (buf, buflen); 1232c99fb5f9SBaptiste Daroussin } 1233c99fb5f9SBaptiste Daroussin 1234c99fb5f9SBaptiste Daroussin return res; 1235c99fb5f9SBaptiste Daroussin } 1236c99fb5f9SBaptiste Daroussin 1237c99fb5f9SBaptiste Daroussin /** 12384bf54857SBaptiste Daroussin * Include a file to configuration 12394bf54857SBaptiste Daroussin * @param data 12404bf54857SBaptiste Daroussin * @param len 12414bf54857SBaptiste Daroussin * @param parser 12424bf54857SBaptiste Daroussin * @param err 12434bf54857SBaptiste Daroussin * @return 12444bf54857SBaptiste Daroussin */ 12454bf54857SBaptiste Daroussin static bool 12464bf54857SBaptiste Daroussin ucl_include_file (const unsigned char *data, size_t len, 124739ee7a7aSBaptiste Daroussin struct ucl_parser *parser, struct ucl_include_params *params) 12484bf54857SBaptiste Daroussin { 12494bf54857SBaptiste Daroussin const unsigned char *p = data, *end = data + len; 12504bf54857SBaptiste Daroussin bool need_glob = false; 12514bf54857SBaptiste Daroussin int cnt = 0; 12524bf54857SBaptiste Daroussin char glob_pattern[PATH_MAX]; 12534bf54857SBaptiste Daroussin size_t i; 12544bf54857SBaptiste Daroussin 12558e3b1ab2SBaptiste Daroussin #ifndef _WIN32 125639ee7a7aSBaptiste Daroussin if (!params->allow_glob) { 125739ee7a7aSBaptiste Daroussin return ucl_include_file_single (data, len, parser, params); 12584bf54857SBaptiste Daroussin } 12594bf54857SBaptiste Daroussin else { 12604bf54857SBaptiste Daroussin /* Check for special symbols in a filename */ 12614bf54857SBaptiste Daroussin while (p != end) { 12624bf54857SBaptiste Daroussin if (*p == '*' || *p == '?') { 12634bf54857SBaptiste Daroussin need_glob = true; 12644bf54857SBaptiste Daroussin break; 12654bf54857SBaptiste Daroussin } 12664bf54857SBaptiste Daroussin p ++; 12674bf54857SBaptiste Daroussin } 12684bf54857SBaptiste Daroussin if (need_glob) { 12698e3b1ab2SBaptiste Daroussin glob_t globbuf; 12704bf54857SBaptiste Daroussin memset (&globbuf, 0, sizeof (globbuf)); 127139ee7a7aSBaptiste Daroussin ucl_strlcpy (glob_pattern, (const char *)data, 127239ee7a7aSBaptiste Daroussin (len + 1 < sizeof (glob_pattern) ? len + 1 : sizeof (glob_pattern))); 12734bf54857SBaptiste Daroussin if (glob (glob_pattern, 0, NULL, &globbuf) != 0) { 127439ee7a7aSBaptiste Daroussin return (!params->must_exist || false); 12754bf54857SBaptiste Daroussin } 12764bf54857SBaptiste Daroussin for (i = 0; i < globbuf.gl_pathc; i ++) { 12774bf54857SBaptiste Daroussin if (!ucl_include_file_single ((unsigned char *)globbuf.gl_pathv[i], 127839ee7a7aSBaptiste Daroussin strlen (globbuf.gl_pathv[i]), parser, params)) { 127939ee7a7aSBaptiste Daroussin if (params->soft_fail) { 128039ee7a7aSBaptiste Daroussin continue; 128139ee7a7aSBaptiste Daroussin } 12824bf54857SBaptiste Daroussin globfree (&globbuf); 12834bf54857SBaptiste Daroussin return false; 12844bf54857SBaptiste Daroussin } 12854bf54857SBaptiste Daroussin cnt ++; 12864bf54857SBaptiste Daroussin } 12874bf54857SBaptiste Daroussin globfree (&globbuf); 12884bf54857SBaptiste Daroussin 128939ee7a7aSBaptiste Daroussin if (cnt == 0 && params->must_exist) { 12904bf54857SBaptiste Daroussin ucl_create_err (&parser->err, "cannot match any files for pattern %s", 12914bf54857SBaptiste Daroussin glob_pattern); 12924bf54857SBaptiste Daroussin return false; 12934bf54857SBaptiste Daroussin } 12944bf54857SBaptiste Daroussin } 12954bf54857SBaptiste Daroussin else { 129639ee7a7aSBaptiste Daroussin return ucl_include_file_single (data, len, parser, params); 12974bf54857SBaptiste Daroussin } 12984bf54857SBaptiste Daroussin } 12998e3b1ab2SBaptiste Daroussin #else 13008e3b1ab2SBaptiste Daroussin /* Win32 compilers do not support globbing. Therefore, for Win32, 13018e3b1ab2SBaptiste Daroussin treat allow_glob/need_glob as a NOOP and just return */ 130239ee7a7aSBaptiste Daroussin return ucl_include_file_single (data, len, parser, params); 13038e3b1ab2SBaptiste Daroussin #endif 13044bf54857SBaptiste Daroussin 13054bf54857SBaptiste Daroussin return true; 13064bf54857SBaptiste Daroussin } 13074bf54857SBaptiste Daroussin 13084bf54857SBaptiste Daroussin /** 13094bf54857SBaptiste Daroussin * Common function to handle .*include* macros 13104bf54857SBaptiste Daroussin * @param data 13114bf54857SBaptiste Daroussin * @param len 13124bf54857SBaptiste Daroussin * @param args 13134bf54857SBaptiste Daroussin * @param parser 13144bf54857SBaptiste Daroussin * @param default_try 13154bf54857SBaptiste Daroussin * @param default_sign 13164bf54857SBaptiste Daroussin * @return 13174bf54857SBaptiste Daroussin */ 13184bf54857SBaptiste Daroussin static bool 13194bf54857SBaptiste Daroussin ucl_include_common (const unsigned char *data, size_t len, 13204bf54857SBaptiste Daroussin const ucl_object_t *args, struct ucl_parser *parser, 13214bf54857SBaptiste Daroussin bool default_try, 13224bf54857SBaptiste Daroussin bool default_sign) 13234bf54857SBaptiste Daroussin { 1324d9f0ce31SBaptiste Daroussin bool allow_url = false, search = false; 132539ee7a7aSBaptiste Daroussin const char *duplicate; 13264bf54857SBaptiste Daroussin const ucl_object_t *param; 132739ee7a7aSBaptiste Daroussin ucl_object_iter_t it = NULL, ip = NULL; 132839ee7a7aSBaptiste Daroussin char ipath[PATH_MAX]; 132939ee7a7aSBaptiste Daroussin struct ucl_include_params params; 13304bf54857SBaptiste Daroussin 13314bf54857SBaptiste Daroussin /* Default values */ 133239ee7a7aSBaptiste Daroussin params.soft_fail = default_try; 133339ee7a7aSBaptiste Daroussin params.allow_glob = false; 133439ee7a7aSBaptiste Daroussin params.check_signature = default_sign; 133539ee7a7aSBaptiste Daroussin params.use_prefix = false; 133639ee7a7aSBaptiste Daroussin params.target = "object"; 133739ee7a7aSBaptiste Daroussin params.prefix = NULL; 133839ee7a7aSBaptiste Daroussin params.priority = 0; 133939ee7a7aSBaptiste Daroussin params.parse_type = UCL_PARSE_UCL; 134039ee7a7aSBaptiste Daroussin params.strat = UCL_DUPLICATE_APPEND; 134139ee7a7aSBaptiste Daroussin params.must_exist = !default_try; 134239ee7a7aSBaptiste Daroussin 13434bf54857SBaptiste Daroussin /* Process arguments */ 13444bf54857SBaptiste Daroussin if (args != NULL && args->type == UCL_OBJECT) { 1345d9f0ce31SBaptiste Daroussin while ((param = ucl_object_iterate (args, &it, true)) != NULL) { 13464bf54857SBaptiste Daroussin if (param->type == UCL_BOOLEAN) { 134739ee7a7aSBaptiste Daroussin if (strncmp (param->key, "try", param->keylen) == 0) { 134839ee7a7aSBaptiste Daroussin params.must_exist = !ucl_object_toboolean (param); 13494bf54857SBaptiste Daroussin } 135039ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "sign", param->keylen) == 0) { 135139ee7a7aSBaptiste Daroussin params.check_signature = ucl_object_toboolean (param); 13524bf54857SBaptiste Daroussin } 135339ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "glob", param->keylen) == 0) { 135439ee7a7aSBaptiste Daroussin params.allow_glob = ucl_object_toboolean (param); 13554bf54857SBaptiste Daroussin } 135639ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "url", param->keylen) == 0) { 13574bf54857SBaptiste Daroussin allow_url = ucl_object_toboolean (param); 13584bf54857SBaptiste Daroussin } 135939ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "prefix", param->keylen) == 0) { 136039ee7a7aSBaptiste Daroussin params.use_prefix = ucl_object_toboolean (param); 136139ee7a7aSBaptiste Daroussin } 136239ee7a7aSBaptiste Daroussin } 136339ee7a7aSBaptiste Daroussin else if (param->type == UCL_STRING) { 136439ee7a7aSBaptiste Daroussin if (strncmp (param->key, "key", param->keylen) == 0) { 136539ee7a7aSBaptiste Daroussin params.prefix = ucl_object_tostring (param); 136639ee7a7aSBaptiste Daroussin } 136739ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "target", param->keylen) == 0) { 136839ee7a7aSBaptiste Daroussin params.target = ucl_object_tostring (param); 136939ee7a7aSBaptiste Daroussin } 137039ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "duplicate", param->keylen) == 0) { 137139ee7a7aSBaptiste Daroussin duplicate = ucl_object_tostring (param); 137239ee7a7aSBaptiste Daroussin 137339ee7a7aSBaptiste Daroussin if (strcmp (duplicate, "append") == 0) { 137439ee7a7aSBaptiste Daroussin params.strat = UCL_DUPLICATE_APPEND; 137539ee7a7aSBaptiste Daroussin } 137639ee7a7aSBaptiste Daroussin else if (strcmp (duplicate, "merge") == 0) { 137739ee7a7aSBaptiste Daroussin params.strat = UCL_DUPLICATE_MERGE; 137839ee7a7aSBaptiste Daroussin } 137939ee7a7aSBaptiste Daroussin else if (strcmp (duplicate, "rewrite") == 0) { 138039ee7a7aSBaptiste Daroussin params.strat = UCL_DUPLICATE_REWRITE; 138139ee7a7aSBaptiste Daroussin } 138239ee7a7aSBaptiste Daroussin else if (strcmp (duplicate, "error") == 0) { 138339ee7a7aSBaptiste Daroussin params.strat = UCL_DUPLICATE_ERROR; 138439ee7a7aSBaptiste Daroussin } 138539ee7a7aSBaptiste Daroussin } 138639ee7a7aSBaptiste Daroussin } 138739ee7a7aSBaptiste Daroussin else if (param->type == UCL_ARRAY) { 138839ee7a7aSBaptiste Daroussin if (strncmp (param->key, "path", param->keylen) == 0) { 138939ee7a7aSBaptiste Daroussin ucl_set_include_path (parser, __DECONST(ucl_object_t *, param)); 139039ee7a7aSBaptiste Daroussin } 13914bf54857SBaptiste Daroussin } 13924bf54857SBaptiste Daroussin else if (param->type == UCL_INT) { 139339ee7a7aSBaptiste Daroussin if (strncmp (param->key, "priority", param->keylen) == 0) { 139439ee7a7aSBaptiste Daroussin params.priority = ucl_object_toint (param); 13954bf54857SBaptiste Daroussin } 13964bf54857SBaptiste Daroussin } 13974bf54857SBaptiste Daroussin } 13984bf54857SBaptiste Daroussin } 13994bf54857SBaptiste Daroussin 140039ee7a7aSBaptiste Daroussin if (parser->includepaths == NULL) { 140139ee7a7aSBaptiste Daroussin if (allow_url && ucl_strnstr (data, "://", len) != NULL) { 14024bf54857SBaptiste Daroussin /* Globbing is not used for URL's */ 140339ee7a7aSBaptiste Daroussin return ucl_include_url (data, len, parser, ¶ms); 140439ee7a7aSBaptiste Daroussin } 140539ee7a7aSBaptiste Daroussin else if (data != NULL) { 140639ee7a7aSBaptiste Daroussin /* Try to load a file */ 140739ee7a7aSBaptiste Daroussin return ucl_include_file (data, len, parser, ¶ms); 140839ee7a7aSBaptiste Daroussin } 140939ee7a7aSBaptiste Daroussin } 141039ee7a7aSBaptiste Daroussin else { 141139ee7a7aSBaptiste Daroussin if (allow_url && ucl_strnstr (data, "://", len) != NULL) { 141239ee7a7aSBaptiste Daroussin /* Globbing is not used for URL's */ 141339ee7a7aSBaptiste Daroussin return ucl_include_url (data, len, parser, ¶ms); 141439ee7a7aSBaptiste Daroussin } 141539ee7a7aSBaptiste Daroussin 141639ee7a7aSBaptiste Daroussin ip = ucl_object_iterate_new (parser->includepaths); 141739ee7a7aSBaptiste Daroussin while ((param = ucl_object_iterate_safe (ip, true)) != NULL) { 141839ee7a7aSBaptiste Daroussin if (ucl_object_type(param) == UCL_STRING) { 141939ee7a7aSBaptiste Daroussin snprintf (ipath, sizeof (ipath), "%s/%.*s", ucl_object_tostring(param), 142039ee7a7aSBaptiste Daroussin (int)len, data); 142139ee7a7aSBaptiste Daroussin if ((search = ucl_include_file (ipath, strlen (ipath), 142239ee7a7aSBaptiste Daroussin parser, ¶ms))) { 142339ee7a7aSBaptiste Daroussin if (!params.allow_glob) { 142439ee7a7aSBaptiste Daroussin break; 142539ee7a7aSBaptiste Daroussin } 142639ee7a7aSBaptiste Daroussin } 142739ee7a7aSBaptiste Daroussin } 142839ee7a7aSBaptiste Daroussin } 142939ee7a7aSBaptiste Daroussin ucl_object_iterate_free (ip); 143039ee7a7aSBaptiste Daroussin if (search == true) { 143139ee7a7aSBaptiste Daroussin return true; 143239ee7a7aSBaptiste Daroussin } 143339ee7a7aSBaptiste Daroussin else { 143439ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, 143539ee7a7aSBaptiste Daroussin "cannot find file: %.*s in search path", 143639ee7a7aSBaptiste Daroussin (int)len, data); 143739ee7a7aSBaptiste Daroussin return false; 143839ee7a7aSBaptiste Daroussin } 14394bf54857SBaptiste Daroussin } 14404bf54857SBaptiste Daroussin 14414bf54857SBaptiste Daroussin return false; 14424bf54857SBaptiste Daroussin } 14434bf54857SBaptiste Daroussin 14444bf54857SBaptiste Daroussin /** 1445c99fb5f9SBaptiste Daroussin * Handle include macro 1446c99fb5f9SBaptiste Daroussin * @param data include data 1447c99fb5f9SBaptiste Daroussin * @param len length of data 144839ee7a7aSBaptiste Daroussin * @param args UCL object representing arguments to the macro 1449c99fb5f9SBaptiste Daroussin * @param ud user data 1450c99fb5f9SBaptiste Daroussin * @return 1451c99fb5f9SBaptiste Daroussin */ 145239ee7a7aSBaptiste Daroussin bool 14534bf54857SBaptiste Daroussin ucl_include_handler (const unsigned char *data, size_t len, 14544bf54857SBaptiste Daroussin const ucl_object_t *args, void* ud) 1455c99fb5f9SBaptiste Daroussin { 1456c99fb5f9SBaptiste Daroussin struct ucl_parser *parser = ud; 1457c99fb5f9SBaptiste Daroussin 14584bf54857SBaptiste Daroussin return ucl_include_common (data, len, args, parser, false, false); 1459c99fb5f9SBaptiste Daroussin } 1460c99fb5f9SBaptiste Daroussin 1461c99fb5f9SBaptiste Daroussin /** 1462c99fb5f9SBaptiste Daroussin * Handle includes macro 1463c99fb5f9SBaptiste Daroussin * @param data include data 1464c99fb5f9SBaptiste Daroussin * @param len length of data 146539ee7a7aSBaptiste Daroussin * @param args UCL object representing arguments to the macro 1466c99fb5f9SBaptiste Daroussin * @param ud user data 1467c99fb5f9SBaptiste Daroussin * @return 1468c99fb5f9SBaptiste Daroussin */ 146939ee7a7aSBaptiste Daroussin bool 14704bf54857SBaptiste Daroussin ucl_includes_handler (const unsigned char *data, size_t len, 14714bf54857SBaptiste Daroussin const ucl_object_t *args, void* ud) 1472c99fb5f9SBaptiste Daroussin { 1473c99fb5f9SBaptiste Daroussin struct ucl_parser *parser = ud; 1474c99fb5f9SBaptiste Daroussin 14754bf54857SBaptiste Daroussin return ucl_include_common (data, len, args, parser, false, true); 1476c99fb5f9SBaptiste Daroussin } 1477c99fb5f9SBaptiste Daroussin 147839ee7a7aSBaptiste Daroussin /** 147939ee7a7aSBaptiste Daroussin * Handle tryinclude macro 148039ee7a7aSBaptiste Daroussin * @param data include data 148139ee7a7aSBaptiste Daroussin * @param len length of data 148239ee7a7aSBaptiste Daroussin * @param args UCL object representing arguments to the macro 148339ee7a7aSBaptiste Daroussin * @param ud user data 148439ee7a7aSBaptiste Daroussin * @return 148539ee7a7aSBaptiste Daroussin */ 148639ee7a7aSBaptiste Daroussin bool 14874bf54857SBaptiste Daroussin ucl_try_include_handler (const unsigned char *data, size_t len, 14884bf54857SBaptiste Daroussin const ucl_object_t *args, void* ud) 1489c99fb5f9SBaptiste Daroussin { 1490c99fb5f9SBaptiste Daroussin struct ucl_parser *parser = ud; 1491c99fb5f9SBaptiste Daroussin 14924bf54857SBaptiste Daroussin return ucl_include_common (data, len, args, parser, true, false); 1493c99fb5f9SBaptiste Daroussin } 1494c99fb5f9SBaptiste Daroussin 149539ee7a7aSBaptiste Daroussin /** 149639ee7a7aSBaptiste Daroussin * Handle priority macro 149739ee7a7aSBaptiste Daroussin * @param data include data 149839ee7a7aSBaptiste Daroussin * @param len length of data 149939ee7a7aSBaptiste Daroussin * @param args UCL object representing arguments to the macro 150039ee7a7aSBaptiste Daroussin * @param ud user data 150139ee7a7aSBaptiste Daroussin * @return 150239ee7a7aSBaptiste Daroussin */ 150339ee7a7aSBaptiste Daroussin bool 150439ee7a7aSBaptiste Daroussin ucl_priority_handler (const unsigned char *data, size_t len, 150539ee7a7aSBaptiste Daroussin const ucl_object_t *args, void* ud) 150639ee7a7aSBaptiste Daroussin { 150739ee7a7aSBaptiste Daroussin struct ucl_parser *parser = ud; 150839ee7a7aSBaptiste Daroussin unsigned priority = 255; 150939ee7a7aSBaptiste Daroussin const ucl_object_t *param; 151039ee7a7aSBaptiste Daroussin bool found = false; 151139ee7a7aSBaptiste Daroussin char *value = NULL, *leftover = NULL; 151239ee7a7aSBaptiste Daroussin ucl_object_iter_t it = NULL; 151339ee7a7aSBaptiste Daroussin 151439ee7a7aSBaptiste Daroussin if (parser == NULL) { 151539ee7a7aSBaptiste Daroussin return false; 151639ee7a7aSBaptiste Daroussin } 151739ee7a7aSBaptiste Daroussin 151839ee7a7aSBaptiste Daroussin /* Process arguments */ 151939ee7a7aSBaptiste Daroussin if (args != NULL && args->type == UCL_OBJECT) { 1520d9f0ce31SBaptiste Daroussin while ((param = ucl_object_iterate (args, &it, true)) != NULL) { 152139ee7a7aSBaptiste Daroussin if (param->type == UCL_INT) { 152239ee7a7aSBaptiste Daroussin if (strncmp (param->key, "priority", param->keylen) == 0) { 152339ee7a7aSBaptiste Daroussin priority = ucl_object_toint (param); 152439ee7a7aSBaptiste Daroussin found = true; 152539ee7a7aSBaptiste Daroussin } 152639ee7a7aSBaptiste Daroussin } 152739ee7a7aSBaptiste Daroussin } 152839ee7a7aSBaptiste Daroussin } 152939ee7a7aSBaptiste Daroussin 153039ee7a7aSBaptiste Daroussin if (len > 0) { 153139ee7a7aSBaptiste Daroussin value = malloc(len + 1); 153239ee7a7aSBaptiste Daroussin ucl_strlcpy(value, (const char *)data, len + 1); 153339ee7a7aSBaptiste Daroussin priority = strtol(value, &leftover, 10); 153439ee7a7aSBaptiste Daroussin if (*leftover != '\0') { 153539ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, "Invalid priority value in macro: %s", 153639ee7a7aSBaptiste Daroussin value); 153739ee7a7aSBaptiste Daroussin free(value); 153839ee7a7aSBaptiste Daroussin return false; 153939ee7a7aSBaptiste Daroussin } 154039ee7a7aSBaptiste Daroussin free(value); 154139ee7a7aSBaptiste Daroussin found = true; 154239ee7a7aSBaptiste Daroussin } 154339ee7a7aSBaptiste Daroussin 154439ee7a7aSBaptiste Daroussin if (found == true) { 154539ee7a7aSBaptiste Daroussin parser->chunks->priority = priority; 154639ee7a7aSBaptiste Daroussin return true; 154739ee7a7aSBaptiste Daroussin } 154839ee7a7aSBaptiste Daroussin 154939ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, "Unable to parse priority macro"); 155039ee7a7aSBaptiste Daroussin return false; 155139ee7a7aSBaptiste Daroussin } 155239ee7a7aSBaptiste Daroussin 155339ee7a7aSBaptiste Daroussin /** 155439ee7a7aSBaptiste Daroussin * Handle load macro 155539ee7a7aSBaptiste Daroussin * @param data include data 155639ee7a7aSBaptiste Daroussin * @param len length of data 155739ee7a7aSBaptiste Daroussin * @param args UCL object representing arguments to the macro 155839ee7a7aSBaptiste Daroussin * @param ud user data 155939ee7a7aSBaptiste Daroussin * @return 156039ee7a7aSBaptiste Daroussin */ 156139ee7a7aSBaptiste Daroussin bool 156239ee7a7aSBaptiste Daroussin ucl_load_handler (const unsigned char *data, size_t len, 156339ee7a7aSBaptiste Daroussin const ucl_object_t *args, void* ud) 156439ee7a7aSBaptiste Daroussin { 156539ee7a7aSBaptiste Daroussin struct ucl_parser *parser = ud; 156639ee7a7aSBaptiste Daroussin const ucl_object_t *param; 156739ee7a7aSBaptiste Daroussin ucl_object_t *obj, *old_obj; 156839ee7a7aSBaptiste Daroussin ucl_object_iter_t it = NULL; 156939ee7a7aSBaptiste Daroussin bool try_load, multiline, test; 157039ee7a7aSBaptiste Daroussin const char *target, *prefix; 157139ee7a7aSBaptiste Daroussin char *load_file, *tmp; 157239ee7a7aSBaptiste Daroussin unsigned char *buf; 157339ee7a7aSBaptiste Daroussin size_t buflen; 157439ee7a7aSBaptiste Daroussin unsigned priority; 157539ee7a7aSBaptiste Daroussin int64_t iv; 1576d9f0ce31SBaptiste Daroussin ucl_object_t *container = NULL; 157739ee7a7aSBaptiste Daroussin enum ucl_string_flags flags; 157839ee7a7aSBaptiste Daroussin 157939ee7a7aSBaptiste Daroussin /* Default values */ 158039ee7a7aSBaptiste Daroussin try_load = false; 158139ee7a7aSBaptiste Daroussin multiline = false; 158239ee7a7aSBaptiste Daroussin test = false; 158339ee7a7aSBaptiste Daroussin target = "string"; 158439ee7a7aSBaptiste Daroussin prefix = NULL; 158539ee7a7aSBaptiste Daroussin load_file = NULL; 158639ee7a7aSBaptiste Daroussin buf = NULL; 158739ee7a7aSBaptiste Daroussin buflen = 0; 158839ee7a7aSBaptiste Daroussin priority = 0; 158939ee7a7aSBaptiste Daroussin obj = NULL; 159039ee7a7aSBaptiste Daroussin old_obj = NULL; 159139ee7a7aSBaptiste Daroussin flags = 0; 159239ee7a7aSBaptiste Daroussin 159339ee7a7aSBaptiste Daroussin if (parser == NULL) { 159439ee7a7aSBaptiste Daroussin return false; 159539ee7a7aSBaptiste Daroussin } 159639ee7a7aSBaptiste Daroussin 159739ee7a7aSBaptiste Daroussin /* Process arguments */ 159839ee7a7aSBaptiste Daroussin if (args != NULL && args->type == UCL_OBJECT) { 1599d9f0ce31SBaptiste Daroussin while ((param = ucl_object_iterate (args, &it, true)) != NULL) { 160039ee7a7aSBaptiste Daroussin if (param->type == UCL_BOOLEAN) { 160139ee7a7aSBaptiste Daroussin if (strncmp (param->key, "try", param->keylen) == 0) { 160239ee7a7aSBaptiste Daroussin try_load = ucl_object_toboolean (param); 160339ee7a7aSBaptiste Daroussin } 160439ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "multiline", param->keylen) == 0) { 160539ee7a7aSBaptiste Daroussin multiline = ucl_object_toboolean (param); 160639ee7a7aSBaptiste Daroussin } 160739ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "escape", param->keylen) == 0) { 160839ee7a7aSBaptiste Daroussin test = ucl_object_toboolean (param); 160939ee7a7aSBaptiste Daroussin if (test) { 161039ee7a7aSBaptiste Daroussin flags |= UCL_STRING_ESCAPE; 161139ee7a7aSBaptiste Daroussin } 161239ee7a7aSBaptiste Daroussin } 161339ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "trim", param->keylen) == 0) { 161439ee7a7aSBaptiste Daroussin test = ucl_object_toboolean (param); 161539ee7a7aSBaptiste Daroussin if (test) { 161639ee7a7aSBaptiste Daroussin flags |= UCL_STRING_TRIM; 161739ee7a7aSBaptiste Daroussin } 161839ee7a7aSBaptiste Daroussin } 161939ee7a7aSBaptiste Daroussin } 162039ee7a7aSBaptiste Daroussin else if (param->type == UCL_STRING) { 162139ee7a7aSBaptiste Daroussin if (strncmp (param->key, "key", param->keylen) == 0) { 162239ee7a7aSBaptiste Daroussin prefix = ucl_object_tostring (param); 162339ee7a7aSBaptiste Daroussin } 162439ee7a7aSBaptiste Daroussin else if (strncmp (param->key, "target", param->keylen) == 0) { 162539ee7a7aSBaptiste Daroussin target = ucl_object_tostring (param); 162639ee7a7aSBaptiste Daroussin } 162739ee7a7aSBaptiste Daroussin } 162839ee7a7aSBaptiste Daroussin else if (param->type == UCL_INT) { 162939ee7a7aSBaptiste Daroussin if (strncmp (param->key, "priority", param->keylen) == 0) { 163039ee7a7aSBaptiste Daroussin priority = ucl_object_toint (param); 163139ee7a7aSBaptiste Daroussin } 163239ee7a7aSBaptiste Daroussin } 163339ee7a7aSBaptiste Daroussin } 163439ee7a7aSBaptiste Daroussin } 163539ee7a7aSBaptiste Daroussin 163639ee7a7aSBaptiste Daroussin if (prefix == NULL || strlen (prefix) == 0) { 163739ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, "No Key specified in load macro"); 163839ee7a7aSBaptiste Daroussin return false; 163939ee7a7aSBaptiste Daroussin } 164039ee7a7aSBaptiste Daroussin 164139ee7a7aSBaptiste Daroussin if (len > 0) { 1642d9f0ce31SBaptiste Daroussin load_file = malloc (len + 1); 1643d9f0ce31SBaptiste Daroussin if (!load_file) { 1644d9f0ce31SBaptiste Daroussin ucl_create_err (&parser->err, "cannot allocate memory for suffix"); 1645d9f0ce31SBaptiste Daroussin 1646d9f0ce31SBaptiste Daroussin return false; 1647d9f0ce31SBaptiste Daroussin } 1648d9f0ce31SBaptiste Daroussin 1649d9f0ce31SBaptiste Daroussin snprintf (load_file, len + 1, "%.*s", (int)len, data); 1650d9f0ce31SBaptiste Daroussin 1651d9f0ce31SBaptiste Daroussin if (!ucl_fetch_file (load_file, &buf, &buflen, &parser->err, 1652d9f0ce31SBaptiste Daroussin !try_load)) { 1653d9f0ce31SBaptiste Daroussin free (load_file); 1654d9f0ce31SBaptiste Daroussin 165539ee7a7aSBaptiste Daroussin return (try_load || false); 165639ee7a7aSBaptiste Daroussin } 165739ee7a7aSBaptiste Daroussin 1658d9f0ce31SBaptiste Daroussin free (load_file); 1659d9f0ce31SBaptiste Daroussin container = parser->stack->obj; 1660d9f0ce31SBaptiste Daroussin old_obj = __DECONST (ucl_object_t *, ucl_object_lookup (container, 1661d9f0ce31SBaptiste Daroussin prefix)); 1662d9f0ce31SBaptiste Daroussin 166339ee7a7aSBaptiste Daroussin if (old_obj != NULL) { 166439ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, "Key %s already exists", prefix); 1665d9f0ce31SBaptiste Daroussin if (buf) { 1666d9f0ce31SBaptiste Daroussin ucl_munmap (buf, buflen); 1667d9f0ce31SBaptiste Daroussin } 1668d9f0ce31SBaptiste Daroussin 166939ee7a7aSBaptiste Daroussin return false; 167039ee7a7aSBaptiste Daroussin } 167139ee7a7aSBaptiste Daroussin 167239ee7a7aSBaptiste Daroussin if (strcasecmp (target, "string") == 0) { 167339ee7a7aSBaptiste Daroussin obj = ucl_object_fromstring_common (buf, buflen, flags); 167439ee7a7aSBaptiste Daroussin ucl_copy_value_trash (obj); 167539ee7a7aSBaptiste Daroussin if (multiline) { 167639ee7a7aSBaptiste Daroussin obj->flags |= UCL_OBJECT_MULTILINE; 167739ee7a7aSBaptiste Daroussin } 167839ee7a7aSBaptiste Daroussin } 167939ee7a7aSBaptiste Daroussin else if (strcasecmp (target, "int") == 0) { 1680d9f0ce31SBaptiste Daroussin tmp = malloc (buflen + 1); 1681d9f0ce31SBaptiste Daroussin 1682d9f0ce31SBaptiste Daroussin if (tmp == NULL) { 1683d9f0ce31SBaptiste Daroussin ucl_create_err (&parser->err, "Memory allocation failed"); 1684d9f0ce31SBaptiste Daroussin if (buf) { 1685d9f0ce31SBaptiste Daroussin ucl_munmap (buf, buflen); 168639ee7a7aSBaptiste Daroussin } 168739ee7a7aSBaptiste Daroussin 1688d9f0ce31SBaptiste Daroussin return false; 1689d9f0ce31SBaptiste Daroussin } 1690d9f0ce31SBaptiste Daroussin 1691d9f0ce31SBaptiste Daroussin snprintf (tmp, buflen + 1, "%.*s", (int)buflen, buf); 1692d9f0ce31SBaptiste Daroussin iv = strtoll (tmp, NULL, 10); 1693d9f0ce31SBaptiste Daroussin obj = ucl_object_fromint (iv); 1694d9f0ce31SBaptiste Daroussin free (tmp); 1695d9f0ce31SBaptiste Daroussin } 1696d9f0ce31SBaptiste Daroussin 1697d9f0ce31SBaptiste Daroussin if (buf) { 169839ee7a7aSBaptiste Daroussin ucl_munmap (buf, buflen); 169939ee7a7aSBaptiste Daroussin } 170039ee7a7aSBaptiste Daroussin 170139ee7a7aSBaptiste Daroussin if (obj != NULL) { 170239ee7a7aSBaptiste Daroussin obj->key = prefix; 170339ee7a7aSBaptiste Daroussin obj->keylen = strlen (prefix); 170439ee7a7aSBaptiste Daroussin ucl_copy_key_trash (obj); 170539ee7a7aSBaptiste Daroussin obj->prev = obj; 170639ee7a7aSBaptiste Daroussin obj->next = NULL; 170739ee7a7aSBaptiste Daroussin ucl_object_set_priority (obj, priority); 1708d9f0ce31SBaptiste Daroussin ucl_object_insert_key (container, obj, obj->key, obj->keylen, false); 170939ee7a7aSBaptiste Daroussin } 1710d9f0ce31SBaptiste Daroussin 171139ee7a7aSBaptiste Daroussin return true; 171239ee7a7aSBaptiste Daroussin } 171339ee7a7aSBaptiste Daroussin 171439ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, "Unable to parse load macro"); 171539ee7a7aSBaptiste Daroussin return false; 171639ee7a7aSBaptiste Daroussin } 171739ee7a7aSBaptiste Daroussin 171839ee7a7aSBaptiste Daroussin bool 171939ee7a7aSBaptiste Daroussin ucl_inherit_handler (const unsigned char *data, size_t len, 172039ee7a7aSBaptiste Daroussin const ucl_object_t *args, const ucl_object_t *ctx, void* ud) 172139ee7a7aSBaptiste Daroussin { 172239ee7a7aSBaptiste Daroussin const ucl_object_t *parent, *cur; 172339ee7a7aSBaptiste Daroussin ucl_object_t *target, *copy; 172439ee7a7aSBaptiste Daroussin ucl_object_iter_t it = NULL; 172539ee7a7aSBaptiste Daroussin bool replace = false; 172639ee7a7aSBaptiste Daroussin struct ucl_parser *parser = ud; 172739ee7a7aSBaptiste Daroussin 1728d9f0ce31SBaptiste Daroussin parent = ucl_object_lookup_len (ctx, data, len); 172939ee7a7aSBaptiste Daroussin 173039ee7a7aSBaptiste Daroussin /* Some sanity checks */ 173139ee7a7aSBaptiste Daroussin if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) { 173239ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, "Unable to find inherited object %*.s", 173339ee7a7aSBaptiste Daroussin (int)len, data); 173439ee7a7aSBaptiste Daroussin return false; 173539ee7a7aSBaptiste Daroussin } 173639ee7a7aSBaptiste Daroussin 173739ee7a7aSBaptiste Daroussin if (parser->stack == NULL || parser->stack->obj == NULL || 173839ee7a7aSBaptiste Daroussin ucl_object_type (parser->stack->obj) != UCL_OBJECT) { 173939ee7a7aSBaptiste Daroussin ucl_create_err (&parser->err, "Invalid inherit context"); 174039ee7a7aSBaptiste Daroussin return false; 174139ee7a7aSBaptiste Daroussin } 174239ee7a7aSBaptiste Daroussin 174339ee7a7aSBaptiste Daroussin target = parser->stack->obj; 174439ee7a7aSBaptiste Daroussin 1745d9f0ce31SBaptiste Daroussin if (args && (cur = ucl_object_lookup (args, "replace")) != NULL) { 174639ee7a7aSBaptiste Daroussin replace = ucl_object_toboolean (cur); 174739ee7a7aSBaptiste Daroussin } 174839ee7a7aSBaptiste Daroussin 1749d9f0ce31SBaptiste Daroussin while ((cur = ucl_object_iterate (parent, &it, true))) { 175039ee7a7aSBaptiste Daroussin /* We do not replace existing keys */ 1751d9f0ce31SBaptiste Daroussin if (!replace && ucl_object_lookup_len (target, cur->key, cur->keylen)) { 175239ee7a7aSBaptiste Daroussin continue; 175339ee7a7aSBaptiste Daroussin } 175439ee7a7aSBaptiste Daroussin 175539ee7a7aSBaptiste Daroussin copy = ucl_object_copy (cur); 175639ee7a7aSBaptiste Daroussin 175739ee7a7aSBaptiste Daroussin if (!replace) { 175839ee7a7aSBaptiste Daroussin copy->flags |= UCL_OBJECT_INHERITED; 175939ee7a7aSBaptiste Daroussin } 176039ee7a7aSBaptiste Daroussin 176139ee7a7aSBaptiste Daroussin ucl_object_insert_key (target, copy, copy->key, 176239ee7a7aSBaptiste Daroussin copy->keylen, false); 176339ee7a7aSBaptiste Daroussin } 176439ee7a7aSBaptiste Daroussin 176539ee7a7aSBaptiste Daroussin return true; 176639ee7a7aSBaptiste Daroussin } 176739ee7a7aSBaptiste Daroussin 176839ee7a7aSBaptiste Daroussin bool 1769c99fb5f9SBaptiste Daroussin ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand) 1770c99fb5f9SBaptiste Daroussin { 1771c99fb5f9SBaptiste Daroussin char realbuf[PATH_MAX], *curdir; 1772c99fb5f9SBaptiste Daroussin 1773c99fb5f9SBaptiste Daroussin if (filename != NULL) { 1774c99fb5f9SBaptiste Daroussin if (need_expand) { 177597bd480fSBaptiste Daroussin if (ucl_realpath (filename, realbuf) == NULL) { 1776c99fb5f9SBaptiste Daroussin return false; 1777c99fb5f9SBaptiste Daroussin } 1778c99fb5f9SBaptiste Daroussin } 1779c99fb5f9SBaptiste Daroussin else { 1780c99fb5f9SBaptiste Daroussin ucl_strlcpy (realbuf, filename, sizeof (realbuf)); 1781c99fb5f9SBaptiste Daroussin } 1782c99fb5f9SBaptiste Daroussin 1783c99fb5f9SBaptiste Daroussin /* Define variables */ 1784c99fb5f9SBaptiste Daroussin ucl_parser_register_variable (parser, "FILENAME", realbuf); 1785c99fb5f9SBaptiste Daroussin curdir = dirname (realbuf); 1786c99fb5f9SBaptiste Daroussin ucl_parser_register_variable (parser, "CURDIR", curdir); 1787c99fb5f9SBaptiste Daroussin } 1788c99fb5f9SBaptiste Daroussin else { 1789c99fb5f9SBaptiste Daroussin /* Set everything from the current dir */ 1790c99fb5f9SBaptiste Daroussin curdir = getcwd (realbuf, sizeof (realbuf)); 1791c99fb5f9SBaptiste Daroussin ucl_parser_register_variable (parser, "FILENAME", "undef"); 1792c99fb5f9SBaptiste Daroussin ucl_parser_register_variable (parser, "CURDIR", curdir); 1793c99fb5f9SBaptiste Daroussin } 1794c99fb5f9SBaptiste Daroussin 1795c99fb5f9SBaptiste Daroussin return true; 1796c99fb5f9SBaptiste Daroussin } 1797c99fb5f9SBaptiste Daroussin 179839ee7a7aSBaptiste Daroussin bool 1799273c26a3SBaptiste Daroussin ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename, 1800273c26a3SBaptiste Daroussin unsigned priority, enum ucl_duplicate_strategy strat, 1801273c26a3SBaptiste Daroussin enum ucl_parse_type parse_type) 1802c99fb5f9SBaptiste Daroussin { 1803c99fb5f9SBaptiste Daroussin unsigned char *buf; 1804c99fb5f9SBaptiste Daroussin size_t len; 1805c99fb5f9SBaptiste Daroussin bool ret; 1806c99fb5f9SBaptiste Daroussin char realbuf[PATH_MAX]; 1807c99fb5f9SBaptiste Daroussin 180897bd480fSBaptiste Daroussin if (ucl_realpath (filename, realbuf) == NULL) { 1809c99fb5f9SBaptiste Daroussin ucl_create_err (&parser->err, "cannot open file %s: %s", 1810c99fb5f9SBaptiste Daroussin filename, 1811c99fb5f9SBaptiste Daroussin strerror (errno)); 1812c99fb5f9SBaptiste Daroussin return false; 1813c99fb5f9SBaptiste Daroussin } 1814c99fb5f9SBaptiste Daroussin 1815c99fb5f9SBaptiste Daroussin if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) { 1816c99fb5f9SBaptiste Daroussin return false; 1817c99fb5f9SBaptiste Daroussin } 1818c99fb5f9SBaptiste Daroussin 18194bf54857SBaptiste Daroussin if (parser->cur_file) { 18204bf54857SBaptiste Daroussin free (parser->cur_file); 18214bf54857SBaptiste Daroussin } 18224bf54857SBaptiste Daroussin parser->cur_file = strdup (realbuf); 1823c99fb5f9SBaptiste Daroussin ucl_parser_set_filevars (parser, realbuf, false); 1824273c26a3SBaptiste Daroussin ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat, 1825273c26a3SBaptiste Daroussin parse_type); 1826c99fb5f9SBaptiste Daroussin 1827c99fb5f9SBaptiste Daroussin if (len > 0) { 182897bd480fSBaptiste Daroussin ucl_munmap (buf, len); 1829c99fb5f9SBaptiste Daroussin } 1830c99fb5f9SBaptiste Daroussin 1831c99fb5f9SBaptiste Daroussin return ret; 1832c99fb5f9SBaptiste Daroussin } 1833c99fb5f9SBaptiste Daroussin 183439ee7a7aSBaptiste Daroussin bool 1835273c26a3SBaptiste Daroussin ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename, 1836273c26a3SBaptiste Daroussin unsigned priority) 1837273c26a3SBaptiste Daroussin { 1838273c26a3SBaptiste Daroussin if (parser == NULL) { 1839273c26a3SBaptiste Daroussin return false; 1840273c26a3SBaptiste Daroussin } 1841273c26a3SBaptiste Daroussin 1842273c26a3SBaptiste Daroussin return ucl_parser_add_file_full(parser, filename, priority, 1843273c26a3SBaptiste Daroussin UCL_DUPLICATE_APPEND, UCL_PARSE_UCL); 1844273c26a3SBaptiste Daroussin } 1845273c26a3SBaptiste Daroussin 1846273c26a3SBaptiste Daroussin bool 184739ee7a7aSBaptiste Daroussin ucl_parser_add_file (struct ucl_parser *parser, const char *filename) 184839ee7a7aSBaptiste Daroussin { 184939ee7a7aSBaptiste Daroussin if (parser == NULL) { 185039ee7a7aSBaptiste Daroussin return false; 185139ee7a7aSBaptiste Daroussin } 185239ee7a7aSBaptiste Daroussin 1853273c26a3SBaptiste Daroussin return ucl_parser_add_file_full(parser, filename, 1854273c26a3SBaptiste Daroussin parser->default_priority, UCL_DUPLICATE_APPEND, 1855273c26a3SBaptiste Daroussin UCL_PARSE_UCL); 185639ee7a7aSBaptiste Daroussin } 185739ee7a7aSBaptiste Daroussin 1858*11dd9ed6SBaptiste Daroussin 185939ee7a7aSBaptiste Daroussin bool 1860*11dd9ed6SBaptiste Daroussin ucl_parser_add_fd_full (struct ucl_parser *parser, int fd, 1861*11dd9ed6SBaptiste Daroussin unsigned priority, enum ucl_duplicate_strategy strat, 1862*11dd9ed6SBaptiste Daroussin enum ucl_parse_type parse_type) 18634bf54857SBaptiste Daroussin { 18644bf54857SBaptiste Daroussin unsigned char *buf; 18654bf54857SBaptiste Daroussin size_t len; 18664bf54857SBaptiste Daroussin bool ret; 18674bf54857SBaptiste Daroussin struct stat st; 18684bf54857SBaptiste Daroussin 18694bf54857SBaptiste Daroussin if (fstat (fd, &st) == -1) { 18704bf54857SBaptiste Daroussin ucl_create_err (&parser->err, "cannot stat fd %d: %s", 18714bf54857SBaptiste Daroussin fd, strerror (errno)); 18724bf54857SBaptiste Daroussin return false; 18734bf54857SBaptiste Daroussin } 18746525738fSBaptiste Daroussin if (st.st_size == 0) { 18756525738fSBaptiste Daroussin return true; 18766525738fSBaptiste Daroussin } 18774bf54857SBaptiste Daroussin if ((buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 18784bf54857SBaptiste Daroussin ucl_create_err (&parser->err, "cannot mmap fd %d: %s", 18794bf54857SBaptiste Daroussin fd, strerror (errno)); 18804bf54857SBaptiste Daroussin return false; 18814bf54857SBaptiste Daroussin } 18824bf54857SBaptiste Daroussin 18834bf54857SBaptiste Daroussin if (parser->cur_file) { 18844bf54857SBaptiste Daroussin free (parser->cur_file); 18854bf54857SBaptiste Daroussin } 18864bf54857SBaptiste Daroussin parser->cur_file = NULL; 18874bf54857SBaptiste Daroussin len = st.st_size; 1888*11dd9ed6SBaptiste Daroussin ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat, 1889*11dd9ed6SBaptiste Daroussin parse_type); 18904bf54857SBaptiste Daroussin 18914bf54857SBaptiste Daroussin if (len > 0) { 18924bf54857SBaptiste Daroussin ucl_munmap (buf, len); 18934bf54857SBaptiste Daroussin } 18944bf54857SBaptiste Daroussin 18954bf54857SBaptiste Daroussin return ret; 18964bf54857SBaptiste Daroussin } 18974bf54857SBaptiste Daroussin 189839ee7a7aSBaptiste Daroussin bool 1899*11dd9ed6SBaptiste Daroussin ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd, 1900*11dd9ed6SBaptiste Daroussin unsigned priority) 1901*11dd9ed6SBaptiste Daroussin { 1902*11dd9ed6SBaptiste Daroussin if (parser == NULL) { 1903*11dd9ed6SBaptiste Daroussin return false; 1904*11dd9ed6SBaptiste Daroussin } 1905*11dd9ed6SBaptiste Daroussin 1906*11dd9ed6SBaptiste Daroussin return ucl_parser_add_fd_full(parser, fd, parser->default_priority, 1907*11dd9ed6SBaptiste Daroussin UCL_DUPLICATE_APPEND, UCL_PARSE_UCL); 1908*11dd9ed6SBaptiste Daroussin } 1909*11dd9ed6SBaptiste Daroussin 1910*11dd9ed6SBaptiste Daroussin bool 191139ee7a7aSBaptiste Daroussin ucl_parser_add_fd (struct ucl_parser *parser, int fd) 191239ee7a7aSBaptiste Daroussin { 191339ee7a7aSBaptiste Daroussin if (parser == NULL) { 191439ee7a7aSBaptiste Daroussin return false; 191539ee7a7aSBaptiste Daroussin } 191639ee7a7aSBaptiste Daroussin 191739ee7a7aSBaptiste Daroussin return ucl_parser_add_fd_priority(parser, fd, parser->default_priority); 191839ee7a7aSBaptiste Daroussin } 191939ee7a7aSBaptiste Daroussin 1920c99fb5f9SBaptiste Daroussin size_t 1921c99fb5f9SBaptiste Daroussin ucl_strlcpy (char *dst, const char *src, size_t siz) 1922c99fb5f9SBaptiste Daroussin { 1923c99fb5f9SBaptiste Daroussin char *d = dst; 1924c99fb5f9SBaptiste Daroussin const char *s = src; 1925c99fb5f9SBaptiste Daroussin size_t n = siz; 1926c99fb5f9SBaptiste Daroussin 1927c99fb5f9SBaptiste Daroussin /* Copy as many bytes as will fit */ 1928c99fb5f9SBaptiste Daroussin if (n != 0) { 1929c99fb5f9SBaptiste Daroussin while (--n != 0) { 1930c99fb5f9SBaptiste Daroussin if ((*d++ = *s++) == '\0') { 1931c99fb5f9SBaptiste Daroussin break; 1932c99fb5f9SBaptiste Daroussin } 1933c99fb5f9SBaptiste Daroussin } 1934c99fb5f9SBaptiste Daroussin } 1935c99fb5f9SBaptiste Daroussin 1936c99fb5f9SBaptiste Daroussin if (n == 0 && siz != 0) { 1937c99fb5f9SBaptiste Daroussin *d = '\0'; 1938c99fb5f9SBaptiste Daroussin } 1939c99fb5f9SBaptiste Daroussin 1940c99fb5f9SBaptiste Daroussin return (s - src - 1); /* count does not include NUL */ 1941c99fb5f9SBaptiste Daroussin } 1942c99fb5f9SBaptiste Daroussin 1943c99fb5f9SBaptiste Daroussin size_t 1944c99fb5f9SBaptiste Daroussin ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz) 1945c99fb5f9SBaptiste Daroussin { 1946c99fb5f9SBaptiste Daroussin memcpy (dst, src, siz - 1); 1947c99fb5f9SBaptiste Daroussin dst[siz - 1] = '\0'; 1948c99fb5f9SBaptiste Daroussin 1949c99fb5f9SBaptiste Daroussin return siz - 1; 1950c99fb5f9SBaptiste Daroussin } 1951c99fb5f9SBaptiste Daroussin 1952c99fb5f9SBaptiste Daroussin size_t 1953c99fb5f9SBaptiste Daroussin ucl_strlcpy_tolower (char *dst, const char *src, size_t siz) 1954c99fb5f9SBaptiste Daroussin { 1955c99fb5f9SBaptiste Daroussin char *d = dst; 1956c99fb5f9SBaptiste Daroussin const char *s = src; 1957c99fb5f9SBaptiste Daroussin size_t n = siz; 1958c99fb5f9SBaptiste Daroussin 1959c99fb5f9SBaptiste Daroussin /* Copy as many bytes as will fit */ 1960c99fb5f9SBaptiste Daroussin if (n != 0) { 1961c99fb5f9SBaptiste Daroussin while (--n != 0) { 1962c99fb5f9SBaptiste Daroussin if ((*d++ = tolower (*s++)) == '\0') { 1963c99fb5f9SBaptiste Daroussin break; 1964c99fb5f9SBaptiste Daroussin } 1965c99fb5f9SBaptiste Daroussin } 1966c99fb5f9SBaptiste Daroussin } 1967c99fb5f9SBaptiste Daroussin 1968c99fb5f9SBaptiste Daroussin if (n == 0 && siz != 0) { 1969c99fb5f9SBaptiste Daroussin *d = '\0'; 1970c99fb5f9SBaptiste Daroussin } 1971c99fb5f9SBaptiste Daroussin 1972c99fb5f9SBaptiste Daroussin return (s - src); /* count does not include NUL */ 1973c99fb5f9SBaptiste Daroussin } 1974c99fb5f9SBaptiste Daroussin 197539ee7a7aSBaptiste Daroussin /* 197639ee7a7aSBaptiste Daroussin * Find the first occurrence of find in s 197739ee7a7aSBaptiste Daroussin */ 197839ee7a7aSBaptiste Daroussin char * 197939ee7a7aSBaptiste Daroussin ucl_strnstr (const char *s, const char *find, int len) 198039ee7a7aSBaptiste Daroussin { 198139ee7a7aSBaptiste Daroussin char c, sc; 198239ee7a7aSBaptiste Daroussin int mlen; 198339ee7a7aSBaptiste Daroussin 198439ee7a7aSBaptiste Daroussin if ((c = *find++) != 0) { 198539ee7a7aSBaptiste Daroussin mlen = strlen (find); 198639ee7a7aSBaptiste Daroussin do { 198739ee7a7aSBaptiste Daroussin do { 198839ee7a7aSBaptiste Daroussin if ((sc = *s++) == 0 || len-- == 0) 198939ee7a7aSBaptiste Daroussin return (NULL); 199039ee7a7aSBaptiste Daroussin } while (sc != c); 199139ee7a7aSBaptiste Daroussin } while (strncmp (s, find, mlen) != 0); 199239ee7a7aSBaptiste Daroussin s--; 199339ee7a7aSBaptiste Daroussin } 199439ee7a7aSBaptiste Daroussin return ((char *)s); 199539ee7a7aSBaptiste Daroussin } 199639ee7a7aSBaptiste Daroussin 199739ee7a7aSBaptiste Daroussin /* 199839ee7a7aSBaptiste Daroussin * Find the first occurrence of find in s, ignore case. 199939ee7a7aSBaptiste Daroussin */ 200039ee7a7aSBaptiste Daroussin char * 200139ee7a7aSBaptiste Daroussin ucl_strncasestr (const char *s, const char *find, int len) 200239ee7a7aSBaptiste Daroussin { 200339ee7a7aSBaptiste Daroussin char c, sc; 200439ee7a7aSBaptiste Daroussin int mlen; 200539ee7a7aSBaptiste Daroussin 200639ee7a7aSBaptiste Daroussin if ((c = *find++) != 0) { 200739ee7a7aSBaptiste Daroussin c = tolower (c); 200839ee7a7aSBaptiste Daroussin mlen = strlen (find); 200939ee7a7aSBaptiste Daroussin do { 201039ee7a7aSBaptiste Daroussin do { 201139ee7a7aSBaptiste Daroussin if ((sc = *s++) == 0 || len-- == 0) 201239ee7a7aSBaptiste Daroussin return (NULL); 201339ee7a7aSBaptiste Daroussin } while (tolower (sc) != c); 201439ee7a7aSBaptiste Daroussin } while (strncasecmp (s, find, mlen) != 0); 201539ee7a7aSBaptiste Daroussin s--; 201639ee7a7aSBaptiste Daroussin } 201739ee7a7aSBaptiste Daroussin return ((char *)s); 201839ee7a7aSBaptiste Daroussin } 201939ee7a7aSBaptiste Daroussin 2020c99fb5f9SBaptiste Daroussin ucl_object_t * 2021c99fb5f9SBaptiste Daroussin ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags) 2022c99fb5f9SBaptiste Daroussin { 2023c99fb5f9SBaptiste Daroussin ucl_object_t *obj; 2024c99fb5f9SBaptiste Daroussin const char *start, *end, *p, *pos; 2025c99fb5f9SBaptiste Daroussin char *dst, *d; 2026c99fb5f9SBaptiste Daroussin size_t escaped_len; 2027c99fb5f9SBaptiste Daroussin 2028c99fb5f9SBaptiste Daroussin if (str == NULL) { 2029c99fb5f9SBaptiste Daroussin return NULL; 2030c99fb5f9SBaptiste Daroussin } 2031c99fb5f9SBaptiste Daroussin 2032c99fb5f9SBaptiste Daroussin obj = ucl_object_new (); 2033c99fb5f9SBaptiste Daroussin if (obj) { 2034c99fb5f9SBaptiste Daroussin if (len == 0) { 2035c99fb5f9SBaptiste Daroussin len = strlen (str); 2036c99fb5f9SBaptiste Daroussin } 2037c99fb5f9SBaptiste Daroussin if (flags & UCL_STRING_TRIM) { 2038c99fb5f9SBaptiste Daroussin /* Skip leading spaces */ 2039c99fb5f9SBaptiste Daroussin for (start = str; (size_t)(start - str) < len; start ++) { 2040c99fb5f9SBaptiste Daroussin if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) { 2041c99fb5f9SBaptiste Daroussin break; 2042c99fb5f9SBaptiste Daroussin } 2043c99fb5f9SBaptiste Daroussin } 2044c99fb5f9SBaptiste Daroussin /* Skip trailing spaces */ 2045c99fb5f9SBaptiste Daroussin for (end = str + len - 1; end > start; end --) { 2046c99fb5f9SBaptiste Daroussin if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) { 2047c99fb5f9SBaptiste Daroussin break; 2048c99fb5f9SBaptiste Daroussin } 2049c99fb5f9SBaptiste Daroussin } 2050c99fb5f9SBaptiste Daroussin end ++; 2051c99fb5f9SBaptiste Daroussin } 2052c99fb5f9SBaptiste Daroussin else { 2053c99fb5f9SBaptiste Daroussin start = str; 2054c99fb5f9SBaptiste Daroussin end = str + len; 2055c99fb5f9SBaptiste Daroussin } 2056c99fb5f9SBaptiste Daroussin 2057c99fb5f9SBaptiste Daroussin obj->type = UCL_STRING; 2058c99fb5f9SBaptiste Daroussin if (flags & UCL_STRING_ESCAPE) { 2059c99fb5f9SBaptiste Daroussin for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) { 2060c99fb5f9SBaptiste Daroussin if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { 2061c99fb5f9SBaptiste Daroussin escaped_len ++; 2062c99fb5f9SBaptiste Daroussin } 2063c99fb5f9SBaptiste Daroussin } 2064c99fb5f9SBaptiste Daroussin dst = malloc (escaped_len + 1); 2065c99fb5f9SBaptiste Daroussin if (dst != NULL) { 2066c99fb5f9SBaptiste Daroussin for (p = start, d = dst; p < end; p ++, d ++) { 2067c99fb5f9SBaptiste Daroussin if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { 2068c99fb5f9SBaptiste Daroussin switch (*p) { 2069c99fb5f9SBaptiste Daroussin case '\n': 2070c99fb5f9SBaptiste Daroussin *d++ = '\\'; 2071c99fb5f9SBaptiste Daroussin *d = 'n'; 2072c99fb5f9SBaptiste Daroussin break; 2073c99fb5f9SBaptiste Daroussin case '\r': 2074c99fb5f9SBaptiste Daroussin *d++ = '\\'; 2075c99fb5f9SBaptiste Daroussin *d = 'r'; 2076c99fb5f9SBaptiste Daroussin break; 2077c99fb5f9SBaptiste Daroussin case '\b': 2078c99fb5f9SBaptiste Daroussin *d++ = '\\'; 2079c99fb5f9SBaptiste Daroussin *d = 'b'; 2080c99fb5f9SBaptiste Daroussin break; 2081c99fb5f9SBaptiste Daroussin case '\t': 2082c99fb5f9SBaptiste Daroussin *d++ = '\\'; 2083c99fb5f9SBaptiste Daroussin *d = 't'; 2084c99fb5f9SBaptiste Daroussin break; 2085c99fb5f9SBaptiste Daroussin case '\f': 2086c99fb5f9SBaptiste Daroussin *d++ = '\\'; 2087c99fb5f9SBaptiste Daroussin *d = 'f'; 2088c99fb5f9SBaptiste Daroussin break; 2089c99fb5f9SBaptiste Daroussin case '\\': 2090c99fb5f9SBaptiste Daroussin *d++ = '\\'; 2091c99fb5f9SBaptiste Daroussin *d = '\\'; 2092c99fb5f9SBaptiste Daroussin break; 2093c99fb5f9SBaptiste Daroussin case '"': 2094c99fb5f9SBaptiste Daroussin *d++ = '\\'; 2095c99fb5f9SBaptiste Daroussin *d = '"'; 2096c99fb5f9SBaptiste Daroussin break; 2097c99fb5f9SBaptiste Daroussin } 2098c99fb5f9SBaptiste Daroussin } 2099c99fb5f9SBaptiste Daroussin else { 2100c99fb5f9SBaptiste Daroussin *d = *p; 2101c99fb5f9SBaptiste Daroussin } 2102c99fb5f9SBaptiste Daroussin } 2103c99fb5f9SBaptiste Daroussin *d = '\0'; 2104c99fb5f9SBaptiste Daroussin obj->value.sv = dst; 2105c99fb5f9SBaptiste Daroussin obj->trash_stack[UCL_TRASH_VALUE] = dst; 2106c99fb5f9SBaptiste Daroussin obj->len = escaped_len; 2107c99fb5f9SBaptiste Daroussin } 2108c99fb5f9SBaptiste Daroussin } 2109c99fb5f9SBaptiste Daroussin else { 2110c99fb5f9SBaptiste Daroussin dst = malloc (end - start + 1); 2111c99fb5f9SBaptiste Daroussin if (dst != NULL) { 2112c99fb5f9SBaptiste Daroussin ucl_strlcpy_unsafe (dst, start, end - start + 1); 2113c99fb5f9SBaptiste Daroussin obj->value.sv = dst; 2114c99fb5f9SBaptiste Daroussin obj->trash_stack[UCL_TRASH_VALUE] = dst; 2115c99fb5f9SBaptiste Daroussin obj->len = end - start; 2116c99fb5f9SBaptiste Daroussin } 2117c99fb5f9SBaptiste Daroussin } 2118c99fb5f9SBaptiste Daroussin if ((flags & UCL_STRING_PARSE) && dst != NULL) { 2119c99fb5f9SBaptiste Daroussin /* Parse what we have */ 2120c99fb5f9SBaptiste Daroussin if (flags & UCL_STRING_PARSE_BOOLEAN) { 2121c99fb5f9SBaptiste Daroussin if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) { 2122c99fb5f9SBaptiste Daroussin ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos, 2123c99fb5f9SBaptiste Daroussin flags & UCL_STRING_PARSE_DOUBLE, 212497bd480fSBaptiste Daroussin flags & UCL_STRING_PARSE_BYTES, 212597bd480fSBaptiste Daroussin flags & UCL_STRING_PARSE_TIME); 2126c99fb5f9SBaptiste Daroussin } 2127c99fb5f9SBaptiste Daroussin } 2128c99fb5f9SBaptiste Daroussin else { 2129c99fb5f9SBaptiste Daroussin ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos, 2130c99fb5f9SBaptiste Daroussin flags & UCL_STRING_PARSE_DOUBLE, 213197bd480fSBaptiste Daroussin flags & UCL_STRING_PARSE_BYTES, 213297bd480fSBaptiste Daroussin flags & UCL_STRING_PARSE_TIME); 2133c99fb5f9SBaptiste Daroussin } 2134c99fb5f9SBaptiste Daroussin } 2135c99fb5f9SBaptiste Daroussin } 2136c99fb5f9SBaptiste Daroussin 2137c99fb5f9SBaptiste Daroussin return obj; 2138c99fb5f9SBaptiste Daroussin } 2139c99fb5f9SBaptiste Daroussin 2140b04a7a0bSBaptiste Daroussin static bool 2141c99fb5f9SBaptiste Daroussin ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, 2142c99fb5f9SBaptiste Daroussin const char *key, size_t keylen, bool copy_key, bool merge, bool replace) 2143c99fb5f9SBaptiste Daroussin { 2144b04a7a0bSBaptiste Daroussin ucl_object_t *found, *tmp; 2145b04a7a0bSBaptiste Daroussin const ucl_object_t *cur; 2146c99fb5f9SBaptiste Daroussin ucl_object_iter_t it = NULL; 2147c99fb5f9SBaptiste Daroussin const char *p; 2148b04a7a0bSBaptiste Daroussin int ret = true; 2149c99fb5f9SBaptiste Daroussin 2150c99fb5f9SBaptiste Daroussin if (elt == NULL || key == NULL) { 2151b04a7a0bSBaptiste Daroussin return false; 2152c99fb5f9SBaptiste Daroussin } 2153c99fb5f9SBaptiste Daroussin 2154c99fb5f9SBaptiste Daroussin if (top == NULL) { 2155b04a7a0bSBaptiste Daroussin return false; 2156c99fb5f9SBaptiste Daroussin } 2157c99fb5f9SBaptiste Daroussin 2158c99fb5f9SBaptiste Daroussin if (top->type != UCL_OBJECT) { 2159c99fb5f9SBaptiste Daroussin /* It is possible to convert NULL type to an object */ 2160c99fb5f9SBaptiste Daroussin if (top->type == UCL_NULL) { 2161c99fb5f9SBaptiste Daroussin top->type = UCL_OBJECT; 2162c99fb5f9SBaptiste Daroussin } 2163c99fb5f9SBaptiste Daroussin else { 2164c99fb5f9SBaptiste Daroussin /* Refuse converting of other object types */ 2165b04a7a0bSBaptiste Daroussin return false; 2166c99fb5f9SBaptiste Daroussin } 2167c99fb5f9SBaptiste Daroussin } 2168c99fb5f9SBaptiste Daroussin 2169c99fb5f9SBaptiste Daroussin if (top->value.ov == NULL) { 21708e3b1ab2SBaptiste Daroussin top->value.ov = ucl_hash_create (false); 2171c99fb5f9SBaptiste Daroussin } 2172c99fb5f9SBaptiste Daroussin 2173c99fb5f9SBaptiste Daroussin if (keylen == 0) { 2174c99fb5f9SBaptiste Daroussin keylen = strlen (key); 2175c99fb5f9SBaptiste Daroussin } 2176c99fb5f9SBaptiste Daroussin 2177c99fb5f9SBaptiste Daroussin for (p = key; p < key + keylen; p ++) { 2178c99fb5f9SBaptiste Daroussin if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) { 2179c99fb5f9SBaptiste Daroussin elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE; 2180c99fb5f9SBaptiste Daroussin break; 2181c99fb5f9SBaptiste Daroussin } 2182c99fb5f9SBaptiste Daroussin } 2183c99fb5f9SBaptiste Daroussin 21844bf54857SBaptiste Daroussin /* workaround for some use cases */ 21854bf54857SBaptiste Daroussin if (elt->trash_stack[UCL_TRASH_KEY] != NULL && 21864bf54857SBaptiste Daroussin key != (const char *)elt->trash_stack[UCL_TRASH_KEY]) { 21874bf54857SBaptiste Daroussin /* Remove copied key */ 21884bf54857SBaptiste Daroussin free (elt->trash_stack[UCL_TRASH_KEY]); 21894bf54857SBaptiste Daroussin elt->trash_stack[UCL_TRASH_KEY] = NULL; 21904bf54857SBaptiste Daroussin elt->flags &= ~UCL_OBJECT_ALLOCATED_KEY; 21914bf54857SBaptiste Daroussin } 21924bf54857SBaptiste Daroussin 2193c99fb5f9SBaptiste Daroussin elt->key = key; 2194c99fb5f9SBaptiste Daroussin elt->keylen = keylen; 2195c99fb5f9SBaptiste Daroussin 2196c99fb5f9SBaptiste Daroussin if (copy_key) { 2197c99fb5f9SBaptiste Daroussin ucl_copy_key_trash (elt); 2198c99fb5f9SBaptiste Daroussin } 2199c99fb5f9SBaptiste Daroussin 2200b04a7a0bSBaptiste Daroussin found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt)); 2201c99fb5f9SBaptiste Daroussin 22024bf54857SBaptiste Daroussin if (found == NULL) { 22038e3b1ab2SBaptiste Daroussin top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false); 220497bd480fSBaptiste Daroussin top->len ++; 2205b04a7a0bSBaptiste Daroussin if (replace) { 2206b04a7a0bSBaptiste Daroussin ret = false; 2207b04a7a0bSBaptiste Daroussin } 2208c99fb5f9SBaptiste Daroussin } 2209c99fb5f9SBaptiste Daroussin else { 2210c99fb5f9SBaptiste Daroussin if (replace) { 22114bf54857SBaptiste Daroussin ucl_hash_replace (top->value.ov, found, elt); 2212c99fb5f9SBaptiste Daroussin ucl_object_unref (found); 2213c99fb5f9SBaptiste Daroussin } 2214c99fb5f9SBaptiste Daroussin else if (merge) { 2215c99fb5f9SBaptiste Daroussin if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) { 2216c99fb5f9SBaptiste Daroussin /* Insert old elt to new one */ 2217b04a7a0bSBaptiste Daroussin ucl_object_insert_key_common (elt, found, found->key, 2218b04a7a0bSBaptiste Daroussin found->keylen, copy_key, false, false); 2219c99fb5f9SBaptiste Daroussin ucl_hash_delete (top->value.ov, found); 22208e3b1ab2SBaptiste Daroussin top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false); 2221c99fb5f9SBaptiste Daroussin } 2222c99fb5f9SBaptiste Daroussin else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) { 2223c99fb5f9SBaptiste Daroussin /* Insert new to old */ 2224b04a7a0bSBaptiste Daroussin ucl_object_insert_key_common (found, elt, elt->key, 2225b04a7a0bSBaptiste Daroussin elt->keylen, copy_key, false, false); 2226c99fb5f9SBaptiste Daroussin } 2227c99fb5f9SBaptiste Daroussin else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) { 2228c99fb5f9SBaptiste Daroussin /* Mix two hashes */ 2229d9f0ce31SBaptiste Daroussin while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) { 2230b04a7a0bSBaptiste Daroussin tmp = ucl_object_ref (cur); 2231b04a7a0bSBaptiste Daroussin ucl_object_insert_key_common (found, tmp, cur->key, 2232b04a7a0bSBaptiste Daroussin cur->keylen, copy_key, false, false); 2233c99fb5f9SBaptiste Daroussin } 2234c99fb5f9SBaptiste Daroussin ucl_object_unref (elt); 2235c99fb5f9SBaptiste Daroussin } 2236c99fb5f9SBaptiste Daroussin else { 2237c99fb5f9SBaptiste Daroussin /* Just make a list of scalars */ 2238c99fb5f9SBaptiste Daroussin DL_APPEND (found, elt); 2239c99fb5f9SBaptiste Daroussin } 2240c99fb5f9SBaptiste Daroussin } 2241c99fb5f9SBaptiste Daroussin else { 2242c99fb5f9SBaptiste Daroussin DL_APPEND (found, elt); 2243c99fb5f9SBaptiste Daroussin } 2244c99fb5f9SBaptiste Daroussin } 2245c99fb5f9SBaptiste Daroussin 2246b04a7a0bSBaptiste Daroussin return ret; 2247c99fb5f9SBaptiste Daroussin } 2248c99fb5f9SBaptiste Daroussin 224936c53d67SBaptiste Daroussin bool 225036c53d67SBaptiste Daroussin ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen) 225136c53d67SBaptiste Daroussin { 225236c53d67SBaptiste Daroussin ucl_object_t *found; 225336c53d67SBaptiste Daroussin 225497bd480fSBaptiste Daroussin if (top == NULL || key == NULL) { 225597bd480fSBaptiste Daroussin return false; 225697bd480fSBaptiste Daroussin } 225797bd480fSBaptiste Daroussin 2258d9f0ce31SBaptiste Daroussin found = __DECONST (ucl_object_t *, ucl_object_lookup_len (top, key, keylen)); 225936c53d67SBaptiste Daroussin 226097bd480fSBaptiste Daroussin if (found == NULL) { 226136c53d67SBaptiste Daroussin return false; 226297bd480fSBaptiste Daroussin } 226336c53d67SBaptiste Daroussin 226436c53d67SBaptiste Daroussin ucl_hash_delete (top->value.ov, found); 226536c53d67SBaptiste Daroussin ucl_object_unref (found); 226636c53d67SBaptiste Daroussin top->len --; 226736c53d67SBaptiste Daroussin 226836c53d67SBaptiste Daroussin return true; 226936c53d67SBaptiste Daroussin } 227036c53d67SBaptiste Daroussin 227136c53d67SBaptiste Daroussin bool 227236c53d67SBaptiste Daroussin ucl_object_delete_key (ucl_object_t *top, const char *key) 227336c53d67SBaptiste Daroussin { 2274b04a7a0bSBaptiste Daroussin return ucl_object_delete_keyl (top, key, strlen (key)); 227536c53d67SBaptiste Daroussin } 227636c53d67SBaptiste Daroussin 2277c99fb5f9SBaptiste Daroussin ucl_object_t* 227897bd480fSBaptiste Daroussin ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen) 227997bd480fSBaptiste Daroussin { 2280b04a7a0bSBaptiste Daroussin const ucl_object_t *found; 228197bd480fSBaptiste Daroussin 228297bd480fSBaptiste Daroussin if (top == NULL || key == NULL) { 228397bd480fSBaptiste Daroussin return false; 228497bd480fSBaptiste Daroussin } 2285d9f0ce31SBaptiste Daroussin found = ucl_object_lookup_len (top, key, keylen); 228697bd480fSBaptiste Daroussin 228797bd480fSBaptiste Daroussin if (found == NULL) { 228897bd480fSBaptiste Daroussin return NULL; 228997bd480fSBaptiste Daroussin } 229097bd480fSBaptiste Daroussin ucl_hash_delete (top->value.ov, found); 229197bd480fSBaptiste Daroussin top->len --; 229297bd480fSBaptiste Daroussin 2293b04a7a0bSBaptiste Daroussin return __DECONST (ucl_object_t *, found); 229497bd480fSBaptiste Daroussin } 229597bd480fSBaptiste Daroussin 229697bd480fSBaptiste Daroussin ucl_object_t* 229797bd480fSBaptiste Daroussin ucl_object_pop_key (ucl_object_t *top, const char *key) 229897bd480fSBaptiste Daroussin { 2299b04a7a0bSBaptiste Daroussin return ucl_object_pop_keyl (top, key, strlen (key)); 230097bd480fSBaptiste Daroussin } 230197bd480fSBaptiste Daroussin 2302b04a7a0bSBaptiste Daroussin bool 2303c99fb5f9SBaptiste Daroussin ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, 2304c99fb5f9SBaptiste Daroussin const char *key, size_t keylen, bool copy_key) 2305c99fb5f9SBaptiste Daroussin { 2306c99fb5f9SBaptiste Daroussin return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false); 2307c99fb5f9SBaptiste Daroussin } 2308c99fb5f9SBaptiste Daroussin 2309b04a7a0bSBaptiste Daroussin bool 2310c99fb5f9SBaptiste Daroussin ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, 2311c99fb5f9SBaptiste Daroussin const char *key, size_t keylen, bool copy_key) 2312c99fb5f9SBaptiste Daroussin { 2313c99fb5f9SBaptiste Daroussin return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false); 2314c99fb5f9SBaptiste Daroussin } 2315c99fb5f9SBaptiste Daroussin 2316b04a7a0bSBaptiste Daroussin bool 2317c99fb5f9SBaptiste Daroussin ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, 2318c99fb5f9SBaptiste Daroussin const char *key, size_t keylen, bool copy_key) 2319c99fb5f9SBaptiste Daroussin { 2320c99fb5f9SBaptiste Daroussin return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true); 2321c99fb5f9SBaptiste Daroussin } 2322c99fb5f9SBaptiste Daroussin 23234bf54857SBaptiste Daroussin bool 23244bf54857SBaptiste Daroussin ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy) 23254bf54857SBaptiste Daroussin { 23264bf54857SBaptiste Daroussin ucl_object_t *cur = NULL, *cp = NULL, *found = NULL; 23274bf54857SBaptiste Daroussin ucl_object_iter_t iter = NULL; 23284bf54857SBaptiste Daroussin 23294bf54857SBaptiste Daroussin if (top == NULL || top->type != UCL_OBJECT || elt == NULL || elt->type != UCL_OBJECT) { 23304bf54857SBaptiste Daroussin return false; 23314bf54857SBaptiste Daroussin } 23324bf54857SBaptiste Daroussin 23334bf54857SBaptiste Daroussin /* Mix two hashes */ 23344bf54857SBaptiste Daroussin while ((cur = (ucl_object_t*)ucl_hash_iterate (elt->value.ov, &iter))) { 23354bf54857SBaptiste Daroussin if (copy) { 23364bf54857SBaptiste Daroussin cp = ucl_object_copy (cur); 23374bf54857SBaptiste Daroussin } 23384bf54857SBaptiste Daroussin else { 23394bf54857SBaptiste Daroussin cp = ucl_object_ref (cur); 23404bf54857SBaptiste Daroussin } 23414bf54857SBaptiste Daroussin found = __DECONST(ucl_object_t *, ucl_hash_search (top->value.ov, cp->key, cp->keylen)); 23424bf54857SBaptiste Daroussin if (found == NULL) { 23434bf54857SBaptiste Daroussin /* The key does not exist */ 23448e3b1ab2SBaptiste Daroussin top->value.ov = ucl_hash_insert_object (top->value.ov, cp, false); 23454bf54857SBaptiste Daroussin top->len ++; 23464bf54857SBaptiste Daroussin } 23474bf54857SBaptiste Daroussin else { 23484bf54857SBaptiste Daroussin /* The key already exists, replace it */ 23494bf54857SBaptiste Daroussin ucl_hash_replace (top->value.ov, found, cp); 23504bf54857SBaptiste Daroussin ucl_object_unref (found); 23514bf54857SBaptiste Daroussin } 23524bf54857SBaptiste Daroussin } 23534bf54857SBaptiste Daroussin 23544bf54857SBaptiste Daroussin return true; 23554bf54857SBaptiste Daroussin } 23564bf54857SBaptiste Daroussin 2357b04a7a0bSBaptiste Daroussin const ucl_object_t * 2358d9f0ce31SBaptiste Daroussin ucl_object_lookup_len (const ucl_object_t *obj, const char *key, size_t klen) 2359c99fb5f9SBaptiste Daroussin { 2360b04a7a0bSBaptiste Daroussin const ucl_object_t *ret; 2361b04a7a0bSBaptiste Daroussin ucl_object_t srch; 2362c99fb5f9SBaptiste Daroussin 2363c99fb5f9SBaptiste Daroussin if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) { 2364c99fb5f9SBaptiste Daroussin return NULL; 2365c99fb5f9SBaptiste Daroussin } 2366c99fb5f9SBaptiste Daroussin 2367c99fb5f9SBaptiste Daroussin srch.key = key; 2368c99fb5f9SBaptiste Daroussin srch.keylen = klen; 2369c99fb5f9SBaptiste Daroussin ret = ucl_hash_search_obj (obj->value.ov, &srch); 2370c99fb5f9SBaptiste Daroussin 2371c99fb5f9SBaptiste Daroussin return ret; 2372c99fb5f9SBaptiste Daroussin } 2373c99fb5f9SBaptiste Daroussin 2374b04a7a0bSBaptiste Daroussin const ucl_object_t * 2375d9f0ce31SBaptiste Daroussin ucl_object_lookup (const ucl_object_t *obj, const char *key) 2376c99fb5f9SBaptiste Daroussin { 237739ee7a7aSBaptiste Daroussin if (key == NULL) { 2378c99fb5f9SBaptiste Daroussin return NULL; 237939ee7a7aSBaptiste Daroussin } 2380c99fb5f9SBaptiste Daroussin 2381d9f0ce31SBaptiste Daroussin return ucl_object_lookup_len (obj, key, strlen (key)); 2382c99fb5f9SBaptiste Daroussin } 2383c99fb5f9SBaptiste Daroussin 2384b04a7a0bSBaptiste Daroussin const ucl_object_t* 2385d9f0ce31SBaptiste Daroussin ucl_object_lookup_any (const ucl_object_t *obj, 238639ee7a7aSBaptiste Daroussin const char *key, ...) 238739ee7a7aSBaptiste Daroussin { 238839ee7a7aSBaptiste Daroussin va_list ap; 238939ee7a7aSBaptiste Daroussin const ucl_object_t *ret = NULL; 239039ee7a7aSBaptiste Daroussin const char *nk = NULL; 239139ee7a7aSBaptiste Daroussin 239239ee7a7aSBaptiste Daroussin if (obj == NULL || key == NULL) { 239339ee7a7aSBaptiste Daroussin return NULL; 239439ee7a7aSBaptiste Daroussin } 239539ee7a7aSBaptiste Daroussin 2396d9f0ce31SBaptiste Daroussin ret = ucl_object_lookup_len (obj, key, strlen (key)); 239739ee7a7aSBaptiste Daroussin 239839ee7a7aSBaptiste Daroussin if (ret == NULL) { 239939ee7a7aSBaptiste Daroussin va_start (ap, key); 240039ee7a7aSBaptiste Daroussin 240139ee7a7aSBaptiste Daroussin while (ret == NULL) { 240239ee7a7aSBaptiste Daroussin nk = va_arg (ap, const char *); 240339ee7a7aSBaptiste Daroussin 240439ee7a7aSBaptiste Daroussin if (nk == NULL) { 240539ee7a7aSBaptiste Daroussin break; 240639ee7a7aSBaptiste Daroussin } 240739ee7a7aSBaptiste Daroussin else { 2408d9f0ce31SBaptiste Daroussin ret = ucl_object_lookup_len (obj, nk, strlen (nk)); 240939ee7a7aSBaptiste Daroussin } 241039ee7a7aSBaptiste Daroussin } 241139ee7a7aSBaptiste Daroussin 241239ee7a7aSBaptiste Daroussin va_end (ap); 241339ee7a7aSBaptiste Daroussin } 241439ee7a7aSBaptiste Daroussin 241539ee7a7aSBaptiste Daroussin return ret; 241639ee7a7aSBaptiste Daroussin } 241739ee7a7aSBaptiste Daroussin 241839ee7a7aSBaptiste Daroussin const ucl_object_t* 2419d9f0ce31SBaptiste Daroussin ucl_object_iterate (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values) 2420c99fb5f9SBaptiste Daroussin { 24218e3b1ab2SBaptiste Daroussin const ucl_object_t *elt = NULL; 2422c99fb5f9SBaptiste Daroussin 242397bd480fSBaptiste Daroussin if (obj == NULL || iter == NULL) { 242497bd480fSBaptiste Daroussin return NULL; 242597bd480fSBaptiste Daroussin } 242697bd480fSBaptiste Daroussin 2427c99fb5f9SBaptiste Daroussin if (expand_values) { 2428c99fb5f9SBaptiste Daroussin switch (obj->type) { 2429c99fb5f9SBaptiste Daroussin case UCL_OBJECT: 2430b04a7a0bSBaptiste Daroussin return (const ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter); 2431c99fb5f9SBaptiste Daroussin break; 24328e3b1ab2SBaptiste Daroussin case UCL_ARRAY: { 24338e3b1ab2SBaptiste Daroussin unsigned int idx; 24348e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, obj); 24358e3b1ab2SBaptiste Daroussin idx = (unsigned int)(uintptr_t)(*iter); 24368e3b1ab2SBaptiste Daroussin 24378e3b1ab2SBaptiste Daroussin if (vec != NULL) { 24388e3b1ab2SBaptiste Daroussin while (idx < kv_size (*vec)) { 24398e3b1ab2SBaptiste Daroussin if ((elt = kv_A (*vec, idx)) != NULL) { 24408e3b1ab2SBaptiste Daroussin idx ++; 24418e3b1ab2SBaptiste Daroussin break; 2442c99fb5f9SBaptiste Daroussin } 24438e3b1ab2SBaptiste Daroussin idx ++; 2444c99fb5f9SBaptiste Daroussin } 24458e3b1ab2SBaptiste Daroussin *iter = (void *)(uintptr_t)idx; 2446c99fb5f9SBaptiste Daroussin } 24478e3b1ab2SBaptiste Daroussin 2448c99fb5f9SBaptiste Daroussin return elt; 24498e3b1ab2SBaptiste Daroussin break; 24508e3b1ab2SBaptiste Daroussin } 2451c99fb5f9SBaptiste Daroussin default: 2452c99fb5f9SBaptiste Daroussin /* Go to linear iteration */ 2453c99fb5f9SBaptiste Daroussin break; 2454c99fb5f9SBaptiste Daroussin } 2455c99fb5f9SBaptiste Daroussin } 2456c99fb5f9SBaptiste Daroussin /* Treat everything as a linear list */ 2457c99fb5f9SBaptiste Daroussin elt = *iter; 2458c99fb5f9SBaptiste Daroussin if (elt == NULL) { 2459c99fb5f9SBaptiste Daroussin elt = obj; 2460c99fb5f9SBaptiste Daroussin } 2461c99fb5f9SBaptiste Daroussin else if (elt == obj) { 2462c99fb5f9SBaptiste Daroussin return NULL; 2463c99fb5f9SBaptiste Daroussin } 2464b04a7a0bSBaptiste Daroussin *iter = __DECONST (void *, elt->next ? elt->next : obj); 2465c99fb5f9SBaptiste Daroussin return elt; 2466c99fb5f9SBaptiste Daroussin 2467c99fb5f9SBaptiste Daroussin /* Not reached */ 2468c99fb5f9SBaptiste Daroussin return NULL; 2469c99fb5f9SBaptiste Daroussin } 247097bd480fSBaptiste Daroussin 24718e3b1ab2SBaptiste Daroussin const char safe_iter_magic[4] = {'u', 'i', 't', 'e'}; 24728e3b1ab2SBaptiste Daroussin struct ucl_object_safe_iter { 24738e3b1ab2SBaptiste Daroussin char magic[4]; /* safety check */ 24748e3b1ab2SBaptiste Daroussin const ucl_object_t *impl_it; /* implicit object iteration */ 24758e3b1ab2SBaptiste Daroussin ucl_object_iter_t expl_it; /* explicit iteration */ 24768e3b1ab2SBaptiste Daroussin }; 24778e3b1ab2SBaptiste Daroussin 24788e3b1ab2SBaptiste Daroussin #define UCL_SAFE_ITER(ptr) (struct ucl_object_safe_iter *)(ptr) 24798e3b1ab2SBaptiste Daroussin #define UCL_SAFE_ITER_CHECK(it) do { \ 24808e3b1ab2SBaptiste Daroussin assert (it != NULL); \ 24818e3b1ab2SBaptiste Daroussin assert (memcmp (it->magic, safe_iter_magic, sizeof (it->magic)) == 0); \ 24828e3b1ab2SBaptiste Daroussin } while (0) 24838e3b1ab2SBaptiste Daroussin 24848e3b1ab2SBaptiste Daroussin ucl_object_iter_t 24858e3b1ab2SBaptiste Daroussin ucl_object_iterate_new (const ucl_object_t *obj) 24868e3b1ab2SBaptiste Daroussin { 24878e3b1ab2SBaptiste Daroussin struct ucl_object_safe_iter *it; 24888e3b1ab2SBaptiste Daroussin 24898e3b1ab2SBaptiste Daroussin it = UCL_ALLOC (sizeof (*it)); 24908e3b1ab2SBaptiste Daroussin if (it != NULL) { 24918e3b1ab2SBaptiste Daroussin memcpy (it->magic, safe_iter_magic, sizeof (it->magic)); 24928e3b1ab2SBaptiste Daroussin it->expl_it = NULL; 24938e3b1ab2SBaptiste Daroussin it->impl_it = obj; 24948e3b1ab2SBaptiste Daroussin } 24958e3b1ab2SBaptiste Daroussin 24968e3b1ab2SBaptiste Daroussin return (ucl_object_iter_t)it; 24978e3b1ab2SBaptiste Daroussin } 24988e3b1ab2SBaptiste Daroussin 24998e3b1ab2SBaptiste Daroussin 25008e3b1ab2SBaptiste Daroussin ucl_object_iter_t 25018e3b1ab2SBaptiste Daroussin ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj) 25028e3b1ab2SBaptiste Daroussin { 25038e3b1ab2SBaptiste Daroussin struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it); 25048e3b1ab2SBaptiste Daroussin 25058e3b1ab2SBaptiste Daroussin UCL_SAFE_ITER_CHECK (rit); 25068e3b1ab2SBaptiste Daroussin 2507*11dd9ed6SBaptiste Daroussin if (rit->expl_it != NULL) { 2508*11dd9ed6SBaptiste Daroussin UCL_FREE (sizeof (*rit->expl_it), rit->expl_it); 2509*11dd9ed6SBaptiste Daroussin } 2510*11dd9ed6SBaptiste Daroussin 25118e3b1ab2SBaptiste Daroussin rit->impl_it = obj; 25128e3b1ab2SBaptiste Daroussin rit->expl_it = NULL; 25138e3b1ab2SBaptiste Daroussin 25148e3b1ab2SBaptiste Daroussin return it; 25158e3b1ab2SBaptiste Daroussin } 25168e3b1ab2SBaptiste Daroussin 25178e3b1ab2SBaptiste Daroussin const ucl_object_t* 25188e3b1ab2SBaptiste Daroussin ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values) 25198e3b1ab2SBaptiste Daroussin { 2520*11dd9ed6SBaptiste Daroussin return ucl_object_iterate_full (it, expand_values ? UCL_ITERATE_BOTH : 2521*11dd9ed6SBaptiste Daroussin UCL_ITERATE_IMPLICIT); 2522*11dd9ed6SBaptiste Daroussin } 2523*11dd9ed6SBaptiste Daroussin 2524*11dd9ed6SBaptiste Daroussin const ucl_object_t* 2525*11dd9ed6SBaptiste Daroussin ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type) 2526*11dd9ed6SBaptiste Daroussin { 25278e3b1ab2SBaptiste Daroussin struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it); 25288e3b1ab2SBaptiste Daroussin const ucl_object_t *ret = NULL; 25298e3b1ab2SBaptiste Daroussin 25308e3b1ab2SBaptiste Daroussin UCL_SAFE_ITER_CHECK (rit); 25318e3b1ab2SBaptiste Daroussin 25328e3b1ab2SBaptiste Daroussin if (rit->impl_it == NULL) { 25338e3b1ab2SBaptiste Daroussin return NULL; 25348e3b1ab2SBaptiste Daroussin } 25358e3b1ab2SBaptiste Daroussin 25368e3b1ab2SBaptiste Daroussin if (rit->impl_it->type == UCL_OBJECT || rit->impl_it->type == UCL_ARRAY) { 2537d9f0ce31SBaptiste Daroussin ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true); 25388e3b1ab2SBaptiste Daroussin 2539*11dd9ed6SBaptiste Daroussin if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) { 25408e3b1ab2SBaptiste Daroussin /* Need to switch to another implicit object in chain */ 25418e3b1ab2SBaptiste Daroussin rit->impl_it = rit->impl_it->next; 25428e3b1ab2SBaptiste Daroussin rit->expl_it = NULL; 2543*11dd9ed6SBaptiste Daroussin 2544*11dd9ed6SBaptiste Daroussin return ucl_object_iterate_safe (it, type); 25458e3b1ab2SBaptiste Daroussin } 25468e3b1ab2SBaptiste Daroussin } 25478e3b1ab2SBaptiste Daroussin else { 25488e3b1ab2SBaptiste Daroussin /* Just iterate over the implicit array */ 25498e3b1ab2SBaptiste Daroussin ret = rit->impl_it; 25508e3b1ab2SBaptiste Daroussin rit->impl_it = rit->impl_it->next; 2551*11dd9ed6SBaptiste Daroussin 2552*11dd9ed6SBaptiste Daroussin if (type & UCL_ITERATE_EXPLICIT) { 25538e3b1ab2SBaptiste Daroussin /* We flatten objects if need to expand values */ 25548e3b1ab2SBaptiste Daroussin if (ret->type == UCL_OBJECT || ret->type == UCL_ARRAY) { 2555*11dd9ed6SBaptiste Daroussin return ucl_object_iterate_safe (it, type); 25568e3b1ab2SBaptiste Daroussin } 25578e3b1ab2SBaptiste Daroussin } 25588e3b1ab2SBaptiste Daroussin } 25598e3b1ab2SBaptiste Daroussin 25608e3b1ab2SBaptiste Daroussin return ret; 25618e3b1ab2SBaptiste Daroussin } 25628e3b1ab2SBaptiste Daroussin 25638e3b1ab2SBaptiste Daroussin void 25648e3b1ab2SBaptiste Daroussin ucl_object_iterate_free (ucl_object_iter_t it) 25658e3b1ab2SBaptiste Daroussin { 25668e3b1ab2SBaptiste Daroussin struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it); 25678e3b1ab2SBaptiste Daroussin 25688e3b1ab2SBaptiste Daroussin UCL_SAFE_ITER_CHECK (rit); 25698e3b1ab2SBaptiste Daroussin 2570*11dd9ed6SBaptiste Daroussin if (rit->expl_it != NULL) { 2571*11dd9ed6SBaptiste Daroussin UCL_FREE (sizeof (*rit->expl_it), rit->expl_it); 2572*11dd9ed6SBaptiste Daroussin } 2573*11dd9ed6SBaptiste Daroussin 25748e3b1ab2SBaptiste Daroussin UCL_FREE (sizeof (*rit), it); 25758e3b1ab2SBaptiste Daroussin } 25768e3b1ab2SBaptiste Daroussin 25772e8ed2b8SBaptiste Daroussin const ucl_object_t * 2578d9f0ce31SBaptiste Daroussin ucl_object_lookup_path (const ucl_object_t *top, const char *path_in) { 2579d9f0ce31SBaptiste Daroussin return ucl_object_lookup_path_char (top, path_in, '.'); 258039ee7a7aSBaptiste Daroussin } 258139ee7a7aSBaptiste Daroussin 258239ee7a7aSBaptiste Daroussin 258339ee7a7aSBaptiste Daroussin const ucl_object_t * 2584d9f0ce31SBaptiste Daroussin ucl_object_lookup_path_char (const ucl_object_t *top, const char *path_in, const char sep) { 25852e8ed2b8SBaptiste Daroussin const ucl_object_t *o = NULL, *found; 25862e8ed2b8SBaptiste Daroussin const char *p, *c; 25872e8ed2b8SBaptiste Daroussin char *err_str; 25882e8ed2b8SBaptiste Daroussin unsigned index; 25892e8ed2b8SBaptiste Daroussin 25902e8ed2b8SBaptiste Daroussin if (path_in == NULL || top == NULL) { 25912e8ed2b8SBaptiste Daroussin return NULL; 25922e8ed2b8SBaptiste Daroussin } 25932e8ed2b8SBaptiste Daroussin 25942e8ed2b8SBaptiste Daroussin found = NULL; 25952e8ed2b8SBaptiste Daroussin p = path_in; 25962e8ed2b8SBaptiste Daroussin 25972e8ed2b8SBaptiste Daroussin /* Skip leading dots */ 259839ee7a7aSBaptiste Daroussin while (*p == sep) { 25992e8ed2b8SBaptiste Daroussin p ++; 26002e8ed2b8SBaptiste Daroussin } 26012e8ed2b8SBaptiste Daroussin 26022e8ed2b8SBaptiste Daroussin c = p; 26032e8ed2b8SBaptiste Daroussin while (*p != '\0') { 26042e8ed2b8SBaptiste Daroussin p ++; 260539ee7a7aSBaptiste Daroussin if (*p == sep || *p == '\0') { 26062e8ed2b8SBaptiste Daroussin if (p > c) { 26072e8ed2b8SBaptiste Daroussin switch (top->type) { 26082e8ed2b8SBaptiste Daroussin case UCL_ARRAY: 26092e8ed2b8SBaptiste Daroussin /* Key should be an int */ 26102e8ed2b8SBaptiste Daroussin index = strtoul (c, &err_str, 10); 261139ee7a7aSBaptiste Daroussin if (err_str != NULL && (*err_str != sep && *err_str != '\0')) { 26122e8ed2b8SBaptiste Daroussin return NULL; 26132e8ed2b8SBaptiste Daroussin } 26142e8ed2b8SBaptiste Daroussin o = ucl_array_find_index (top, index); 26152e8ed2b8SBaptiste Daroussin break; 26162e8ed2b8SBaptiste Daroussin default: 2617d9f0ce31SBaptiste Daroussin o = ucl_object_lookup_len (top, c, p - c); 26182e8ed2b8SBaptiste Daroussin break; 26192e8ed2b8SBaptiste Daroussin } 26202e8ed2b8SBaptiste Daroussin if (o == NULL) { 26212e8ed2b8SBaptiste Daroussin return NULL; 26222e8ed2b8SBaptiste Daroussin } 26232e8ed2b8SBaptiste Daroussin top = o; 26242e8ed2b8SBaptiste Daroussin } 26252e8ed2b8SBaptiste Daroussin if (*p != '\0') { 26262e8ed2b8SBaptiste Daroussin c = p + 1; 26272e8ed2b8SBaptiste Daroussin } 26282e8ed2b8SBaptiste Daroussin } 26292e8ed2b8SBaptiste Daroussin } 26302e8ed2b8SBaptiste Daroussin found = o; 26312e8ed2b8SBaptiste Daroussin 26322e8ed2b8SBaptiste Daroussin return found; 26332e8ed2b8SBaptiste Daroussin } 26342e8ed2b8SBaptiste Daroussin 263597bd480fSBaptiste Daroussin 263697bd480fSBaptiste Daroussin ucl_object_t * 263797bd480fSBaptiste Daroussin ucl_object_new (void) 263897bd480fSBaptiste Daroussin { 26394bf54857SBaptiste Daroussin return ucl_object_typed_new (UCL_NULL); 264097bd480fSBaptiste Daroussin } 264197bd480fSBaptiste Daroussin 264297bd480fSBaptiste Daroussin ucl_object_t * 26432e8ed2b8SBaptiste Daroussin ucl_object_typed_new (ucl_type_t type) 264497bd480fSBaptiste Daroussin { 26454bf54857SBaptiste Daroussin return ucl_object_new_full (type, 0); 26464bf54857SBaptiste Daroussin } 26474bf54857SBaptiste Daroussin 26484bf54857SBaptiste Daroussin ucl_object_t * 26494bf54857SBaptiste Daroussin ucl_object_new_full (ucl_type_t type, unsigned priority) 26504bf54857SBaptiste Daroussin { 265197bd480fSBaptiste Daroussin ucl_object_t *new; 26524bf54857SBaptiste Daroussin 26534bf54857SBaptiste Daroussin if (type != UCL_USERDATA) { 26544bf54857SBaptiste Daroussin new = UCL_ALLOC (sizeof (ucl_object_t)); 265597bd480fSBaptiste Daroussin if (new != NULL) { 265697bd480fSBaptiste Daroussin memset (new, 0, sizeof (ucl_object_t)); 265797bd480fSBaptiste Daroussin new->ref = 1; 265897bd480fSBaptiste Daroussin new->type = (type <= UCL_NULL ? type : UCL_NULL); 26594bf54857SBaptiste Daroussin new->next = NULL; 26604bf54857SBaptiste Daroussin new->prev = new; 26614bf54857SBaptiste Daroussin ucl_object_set_priority (new, priority); 26628e3b1ab2SBaptiste Daroussin 26638e3b1ab2SBaptiste Daroussin if (type == UCL_ARRAY) { 26648e3b1ab2SBaptiste Daroussin new->value.av = UCL_ALLOC (sizeof (ucl_array_t)); 26658e3b1ab2SBaptiste Daroussin if (new->value.av) { 26668e3b1ab2SBaptiste Daroussin memset (new->value.av, 0, sizeof (ucl_array_t)); 26678e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, new); 26688e3b1ab2SBaptiste Daroussin 26698e3b1ab2SBaptiste Daroussin /* Preallocate some space for arrays */ 26708e3b1ab2SBaptiste Daroussin kv_resize (ucl_object_t *, *vec, 8); 26718e3b1ab2SBaptiste Daroussin } 26728e3b1ab2SBaptiste Daroussin } 267397bd480fSBaptiste Daroussin } 26744bf54857SBaptiste Daroussin } 26754bf54857SBaptiste Daroussin else { 2676d9f0ce31SBaptiste Daroussin new = ucl_object_new_userdata (NULL, NULL, NULL); 26774bf54857SBaptiste Daroussin ucl_object_set_priority (new, priority); 26784bf54857SBaptiste Daroussin } 26794bf54857SBaptiste Daroussin 268097bd480fSBaptiste Daroussin return new; 268197bd480fSBaptiste Daroussin } 268297bd480fSBaptiste Daroussin 26834bf54857SBaptiste Daroussin ucl_object_t* 2684d9f0ce31SBaptiste Daroussin ucl_object_new_userdata (ucl_userdata_dtor dtor, 2685d9f0ce31SBaptiste Daroussin ucl_userdata_emitter emitter, 2686d9f0ce31SBaptiste Daroussin void *ptr) 26874bf54857SBaptiste Daroussin { 26884bf54857SBaptiste Daroussin struct ucl_object_userdata *new; 26894bf54857SBaptiste Daroussin size_t nsize = sizeof (*new); 26904bf54857SBaptiste Daroussin 26914bf54857SBaptiste Daroussin new = UCL_ALLOC (nsize); 26924bf54857SBaptiste Daroussin if (new != NULL) { 26934bf54857SBaptiste Daroussin memset (new, 0, nsize); 26944bf54857SBaptiste Daroussin new->obj.ref = 1; 26954bf54857SBaptiste Daroussin new->obj.type = UCL_USERDATA; 26964bf54857SBaptiste Daroussin new->obj.next = NULL; 26974bf54857SBaptiste Daroussin new->obj.prev = (ucl_object_t *)new; 26984bf54857SBaptiste Daroussin new->dtor = dtor; 26994bf54857SBaptiste Daroussin new->emitter = emitter; 2700d9f0ce31SBaptiste Daroussin new->obj.value.ud = ptr; 27014bf54857SBaptiste Daroussin } 27024bf54857SBaptiste Daroussin 27034bf54857SBaptiste Daroussin return (ucl_object_t *)new; 27044bf54857SBaptiste Daroussin } 27054bf54857SBaptiste Daroussin 27062e8ed2b8SBaptiste Daroussin ucl_type_t 27072e8ed2b8SBaptiste Daroussin ucl_object_type (const ucl_object_t *obj) 27082e8ed2b8SBaptiste Daroussin { 270939ee7a7aSBaptiste Daroussin if (obj == NULL) { 271039ee7a7aSBaptiste Daroussin return UCL_NULL; 271139ee7a7aSBaptiste Daroussin } 271239ee7a7aSBaptiste Daroussin 27132e8ed2b8SBaptiste Daroussin return obj->type; 27142e8ed2b8SBaptiste Daroussin } 27152e8ed2b8SBaptiste Daroussin 271697bd480fSBaptiste Daroussin ucl_object_t* 271797bd480fSBaptiste Daroussin ucl_object_fromstring (const char *str) 271897bd480fSBaptiste Daroussin { 271997bd480fSBaptiste Daroussin return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE); 272097bd480fSBaptiste Daroussin } 272197bd480fSBaptiste Daroussin 272297bd480fSBaptiste Daroussin ucl_object_t * 272397bd480fSBaptiste Daroussin ucl_object_fromlstring (const char *str, size_t len) 272497bd480fSBaptiste Daroussin { 272597bd480fSBaptiste Daroussin return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE); 272697bd480fSBaptiste Daroussin } 272797bd480fSBaptiste Daroussin 272897bd480fSBaptiste Daroussin ucl_object_t * 272997bd480fSBaptiste Daroussin ucl_object_fromint (int64_t iv) 273097bd480fSBaptiste Daroussin { 273197bd480fSBaptiste Daroussin ucl_object_t *obj; 273297bd480fSBaptiste Daroussin 273397bd480fSBaptiste Daroussin obj = ucl_object_new (); 273497bd480fSBaptiste Daroussin if (obj != NULL) { 273597bd480fSBaptiste Daroussin obj->type = UCL_INT; 273697bd480fSBaptiste Daroussin obj->value.iv = iv; 273797bd480fSBaptiste Daroussin } 273897bd480fSBaptiste Daroussin 273997bd480fSBaptiste Daroussin return obj; 274097bd480fSBaptiste Daroussin } 274197bd480fSBaptiste Daroussin 274297bd480fSBaptiste Daroussin ucl_object_t * 274397bd480fSBaptiste Daroussin ucl_object_fromdouble (double dv) 274497bd480fSBaptiste Daroussin { 274597bd480fSBaptiste Daroussin ucl_object_t *obj; 274697bd480fSBaptiste Daroussin 274797bd480fSBaptiste Daroussin obj = ucl_object_new (); 274897bd480fSBaptiste Daroussin if (obj != NULL) { 274997bd480fSBaptiste Daroussin obj->type = UCL_FLOAT; 275097bd480fSBaptiste Daroussin obj->value.dv = dv; 275197bd480fSBaptiste Daroussin } 275297bd480fSBaptiste Daroussin 275397bd480fSBaptiste Daroussin return obj; 275497bd480fSBaptiste Daroussin } 275597bd480fSBaptiste Daroussin 275697bd480fSBaptiste Daroussin ucl_object_t* 275797bd480fSBaptiste Daroussin ucl_object_frombool (bool bv) 275897bd480fSBaptiste Daroussin { 275997bd480fSBaptiste Daroussin ucl_object_t *obj; 276097bd480fSBaptiste Daroussin 276197bd480fSBaptiste Daroussin obj = ucl_object_new (); 276297bd480fSBaptiste Daroussin if (obj != NULL) { 276397bd480fSBaptiste Daroussin obj->type = UCL_BOOLEAN; 276497bd480fSBaptiste Daroussin obj->value.iv = bv; 276597bd480fSBaptiste Daroussin } 276697bd480fSBaptiste Daroussin 276797bd480fSBaptiste Daroussin return obj; 276897bd480fSBaptiste Daroussin } 276997bd480fSBaptiste Daroussin 2770b04a7a0bSBaptiste Daroussin bool 277197bd480fSBaptiste Daroussin ucl_array_append (ucl_object_t *top, ucl_object_t *elt) 277297bd480fSBaptiste Daroussin { 27738e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 277497bd480fSBaptiste Daroussin 2775b04a7a0bSBaptiste Daroussin if (elt == NULL || top == NULL) { 2776b04a7a0bSBaptiste Daroussin return false; 277797bd480fSBaptiste Daroussin } 277897bd480fSBaptiste Daroussin 27798e3b1ab2SBaptiste Daroussin if (vec == NULL) { 27808e3b1ab2SBaptiste Daroussin vec = UCL_ALLOC (sizeof (*vec)); 278139ee7a7aSBaptiste Daroussin 278239ee7a7aSBaptiste Daroussin if (vec == NULL) { 278339ee7a7aSBaptiste Daroussin return false; 278439ee7a7aSBaptiste Daroussin } 278539ee7a7aSBaptiste Daroussin 27868e3b1ab2SBaptiste Daroussin kv_init (*vec); 27878e3b1ab2SBaptiste Daroussin top->value.av = (void *)vec; 278897bd480fSBaptiste Daroussin } 27898e3b1ab2SBaptiste Daroussin 27908e3b1ab2SBaptiste Daroussin kv_push (ucl_object_t *, *vec, elt); 27918e3b1ab2SBaptiste Daroussin 279297bd480fSBaptiste Daroussin top->len ++; 2793b04a7a0bSBaptiste Daroussin 2794b04a7a0bSBaptiste Daroussin return true; 279597bd480fSBaptiste Daroussin } 279697bd480fSBaptiste Daroussin 2797b04a7a0bSBaptiste Daroussin bool 279897bd480fSBaptiste Daroussin ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt) 279997bd480fSBaptiste Daroussin { 28008e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 280197bd480fSBaptiste Daroussin 2802b04a7a0bSBaptiste Daroussin if (elt == NULL || top == NULL) { 2803b04a7a0bSBaptiste Daroussin return false; 280497bd480fSBaptiste Daroussin } 280597bd480fSBaptiste Daroussin 28068e3b1ab2SBaptiste Daroussin if (vec == NULL) { 28078e3b1ab2SBaptiste Daroussin vec = UCL_ALLOC (sizeof (*vec)); 28088e3b1ab2SBaptiste Daroussin kv_init (*vec); 28098e3b1ab2SBaptiste Daroussin top->value.av = (void *)vec; 28108e3b1ab2SBaptiste Daroussin kv_push (ucl_object_t *, *vec, elt); 281197bd480fSBaptiste Daroussin } 281297bd480fSBaptiste Daroussin else { 28138e3b1ab2SBaptiste Daroussin /* Slow O(n) algorithm */ 28148e3b1ab2SBaptiste Daroussin kv_prepend (ucl_object_t *, *vec, elt); 281597bd480fSBaptiste Daroussin } 28168e3b1ab2SBaptiste Daroussin 281797bd480fSBaptiste Daroussin top->len ++; 281897bd480fSBaptiste Daroussin 2819b04a7a0bSBaptiste Daroussin return true; 282097bd480fSBaptiste Daroussin } 282197bd480fSBaptiste Daroussin 28224bf54857SBaptiste Daroussin bool 28234bf54857SBaptiste Daroussin ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy) 28244bf54857SBaptiste Daroussin { 28258e3b1ab2SBaptiste Daroussin unsigned i; 282639ee7a7aSBaptiste Daroussin ucl_object_t *cp = NULL; 28278e3b1ab2SBaptiste Daroussin ucl_object_t **obj; 28284bf54857SBaptiste Daroussin 28294bf54857SBaptiste Daroussin if (elt == NULL || top == NULL || top->type != UCL_ARRAY || elt->type != UCL_ARRAY) { 28304bf54857SBaptiste Daroussin return false; 28314bf54857SBaptiste Daroussin } 28324bf54857SBaptiste Daroussin 283339ee7a7aSBaptiste Daroussin if (copy) { 283439ee7a7aSBaptiste Daroussin cp = ucl_object_copy (elt); 283539ee7a7aSBaptiste Daroussin } 283639ee7a7aSBaptiste Daroussin else { 283739ee7a7aSBaptiste Daroussin cp = ucl_object_ref (elt); 283839ee7a7aSBaptiste Daroussin } 283939ee7a7aSBaptiste Daroussin 284039ee7a7aSBaptiste Daroussin UCL_ARRAY_GET (v1, top); 284139ee7a7aSBaptiste Daroussin UCL_ARRAY_GET (v2, cp); 284239ee7a7aSBaptiste Daroussin 2843d9f0ce31SBaptiste Daroussin if (v1 && v2) { 28448e3b1ab2SBaptiste Daroussin kv_concat (ucl_object_t *, *v1, *v2); 28458e3b1ab2SBaptiste Daroussin 28468e3b1ab2SBaptiste Daroussin for (i = v2->n; i < v1->n; i ++) { 28478e3b1ab2SBaptiste Daroussin obj = &kv_A (*v1, i); 28488e3b1ab2SBaptiste Daroussin if (*obj == NULL) { 28498e3b1ab2SBaptiste Daroussin continue; 28508e3b1ab2SBaptiste Daroussin } 28518e3b1ab2SBaptiste Daroussin top->len ++; 28524bf54857SBaptiste Daroussin } 2853d9f0ce31SBaptiste Daroussin } 28544bf54857SBaptiste Daroussin 28554bf54857SBaptiste Daroussin return true; 28564bf54857SBaptiste Daroussin } 28574bf54857SBaptiste Daroussin 285897bd480fSBaptiste Daroussin ucl_object_t * 285997bd480fSBaptiste Daroussin ucl_array_delete (ucl_object_t *top, ucl_object_t *elt) 286097bd480fSBaptiste Daroussin { 28618e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 28628e3b1ab2SBaptiste Daroussin ucl_object_t *ret = NULL; 28638e3b1ab2SBaptiste Daroussin unsigned i; 286497bd480fSBaptiste Daroussin 286539ee7a7aSBaptiste Daroussin if (vec == NULL) { 286639ee7a7aSBaptiste Daroussin return NULL; 286739ee7a7aSBaptiste Daroussin } 286839ee7a7aSBaptiste Daroussin 28698e3b1ab2SBaptiste Daroussin for (i = 0; i < vec->n; i ++) { 28708e3b1ab2SBaptiste Daroussin if (kv_A (*vec, i) == elt) { 28718e3b1ab2SBaptiste Daroussin kv_del (ucl_object_t *, *vec, i); 28728e3b1ab2SBaptiste Daroussin ret = elt; 287397bd480fSBaptiste Daroussin top->len --; 28748e3b1ab2SBaptiste Daroussin break; 28758e3b1ab2SBaptiste Daroussin } 28768e3b1ab2SBaptiste Daroussin } 287797bd480fSBaptiste Daroussin 28788e3b1ab2SBaptiste Daroussin return ret; 287997bd480fSBaptiste Daroussin } 288097bd480fSBaptiste Daroussin 2881b04a7a0bSBaptiste Daroussin const ucl_object_t * 2882b04a7a0bSBaptiste Daroussin ucl_array_head (const ucl_object_t *top) 288397bd480fSBaptiste Daroussin { 28848e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 28858e3b1ab2SBaptiste Daroussin 288639ee7a7aSBaptiste Daroussin if (vec == NULL || top == NULL || top->type != UCL_ARRAY || 288739ee7a7aSBaptiste Daroussin top->value.av == NULL) { 288897bd480fSBaptiste Daroussin return NULL; 288997bd480fSBaptiste Daroussin } 28908e3b1ab2SBaptiste Daroussin 28918e3b1ab2SBaptiste Daroussin return (vec->n > 0 ? vec->a[0] : NULL); 289297bd480fSBaptiste Daroussin } 289397bd480fSBaptiste Daroussin 2894b04a7a0bSBaptiste Daroussin const ucl_object_t * 2895b04a7a0bSBaptiste Daroussin ucl_array_tail (const ucl_object_t *top) 289697bd480fSBaptiste Daroussin { 28978e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 28988e3b1ab2SBaptiste Daroussin 289997bd480fSBaptiste Daroussin if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 290097bd480fSBaptiste Daroussin return NULL; 290197bd480fSBaptiste Daroussin } 29028e3b1ab2SBaptiste Daroussin 29038e3b1ab2SBaptiste Daroussin return (vec->n > 0 ? vec->a[vec->n - 1] : NULL); 290497bd480fSBaptiste Daroussin } 290597bd480fSBaptiste Daroussin 290697bd480fSBaptiste Daroussin ucl_object_t * 290797bd480fSBaptiste Daroussin ucl_array_pop_last (ucl_object_t *top) 290897bd480fSBaptiste Daroussin { 29098e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 29108e3b1ab2SBaptiste Daroussin ucl_object_t **obj, *ret = NULL; 29118e3b1ab2SBaptiste Daroussin 29128e3b1ab2SBaptiste Daroussin if (vec != NULL && vec->n > 0) { 29138e3b1ab2SBaptiste Daroussin obj = &kv_A (*vec, vec->n - 1); 29148e3b1ab2SBaptiste Daroussin ret = *obj; 29158e3b1ab2SBaptiste Daroussin kv_del (ucl_object_t *, *vec, vec->n - 1); 29168e3b1ab2SBaptiste Daroussin top->len --; 29178e3b1ab2SBaptiste Daroussin } 29188e3b1ab2SBaptiste Daroussin 29198e3b1ab2SBaptiste Daroussin return ret; 292097bd480fSBaptiste Daroussin } 292197bd480fSBaptiste Daroussin 292297bd480fSBaptiste Daroussin ucl_object_t * 292397bd480fSBaptiste Daroussin ucl_array_pop_first (ucl_object_t *top) 292497bd480fSBaptiste Daroussin { 29258e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 29268e3b1ab2SBaptiste Daroussin ucl_object_t **obj, *ret = NULL; 29278e3b1ab2SBaptiste Daroussin 29288e3b1ab2SBaptiste Daroussin if (vec != NULL && vec->n > 0) { 29298e3b1ab2SBaptiste Daroussin obj = &kv_A (*vec, 0); 29308e3b1ab2SBaptiste Daroussin ret = *obj; 29318e3b1ab2SBaptiste Daroussin kv_del (ucl_object_t *, *vec, 0); 29328e3b1ab2SBaptiste Daroussin top->len --; 29338e3b1ab2SBaptiste Daroussin } 29348e3b1ab2SBaptiste Daroussin 29358e3b1ab2SBaptiste Daroussin return ret; 293697bd480fSBaptiste Daroussin } 293797bd480fSBaptiste Daroussin 29382e8ed2b8SBaptiste Daroussin const ucl_object_t * 29392e8ed2b8SBaptiste Daroussin ucl_array_find_index (const ucl_object_t *top, unsigned int index) 29402e8ed2b8SBaptiste Daroussin { 29418e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 29422e8ed2b8SBaptiste Daroussin 29438e3b1ab2SBaptiste Daroussin if (vec != NULL && vec->n > 0 && index < vec->n) { 29448e3b1ab2SBaptiste Daroussin return kv_A (*vec, index); 29452e8ed2b8SBaptiste Daroussin } 29462e8ed2b8SBaptiste Daroussin 29472e8ed2b8SBaptiste Daroussin return NULL; 29482e8ed2b8SBaptiste Daroussin } 29492e8ed2b8SBaptiste Daroussin 295039ee7a7aSBaptiste Daroussin unsigned int 295139ee7a7aSBaptiste Daroussin ucl_array_index_of (ucl_object_t *top, ucl_object_t *elt) 295239ee7a7aSBaptiste Daroussin { 295339ee7a7aSBaptiste Daroussin UCL_ARRAY_GET (vec, top); 295439ee7a7aSBaptiste Daroussin unsigned i; 295539ee7a7aSBaptiste Daroussin 295639ee7a7aSBaptiste Daroussin if (vec == NULL) { 295739ee7a7aSBaptiste Daroussin return (unsigned int)(-1); 295839ee7a7aSBaptiste Daroussin } 295939ee7a7aSBaptiste Daroussin 296039ee7a7aSBaptiste Daroussin for (i = 0; i < vec->n; i ++) { 296139ee7a7aSBaptiste Daroussin if (kv_A (*vec, i) == elt) { 296239ee7a7aSBaptiste Daroussin return i; 296339ee7a7aSBaptiste Daroussin } 296439ee7a7aSBaptiste Daroussin } 296539ee7a7aSBaptiste Daroussin 296639ee7a7aSBaptiste Daroussin return (unsigned int)(-1); 296739ee7a7aSBaptiste Daroussin } 296839ee7a7aSBaptiste Daroussin 296997bd480fSBaptiste Daroussin ucl_object_t * 29704bf54857SBaptiste Daroussin ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt, 29714bf54857SBaptiste Daroussin unsigned int index) 29724bf54857SBaptiste Daroussin { 29738e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, top); 29748e3b1ab2SBaptiste Daroussin ucl_object_t *ret = NULL; 29754bf54857SBaptiste Daroussin 29768e3b1ab2SBaptiste Daroussin if (vec != NULL && vec->n > 0 && index < vec->n) { 29778e3b1ab2SBaptiste Daroussin ret = kv_A (*vec, index); 29788e3b1ab2SBaptiste Daroussin kv_A (*vec, index) = elt; 29794bf54857SBaptiste Daroussin } 29804bf54857SBaptiste Daroussin 29818e3b1ab2SBaptiste Daroussin return ret; 29824bf54857SBaptiste Daroussin } 29834bf54857SBaptiste Daroussin 29844bf54857SBaptiste Daroussin ucl_object_t * 298597bd480fSBaptiste Daroussin ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) 298697bd480fSBaptiste Daroussin { 298797bd480fSBaptiste Daroussin 298897bd480fSBaptiste Daroussin if (head == NULL) { 298997bd480fSBaptiste Daroussin elt->next = NULL; 299097bd480fSBaptiste Daroussin elt->prev = elt; 299197bd480fSBaptiste Daroussin head = elt; 299297bd480fSBaptiste Daroussin } 299397bd480fSBaptiste Daroussin else { 299497bd480fSBaptiste Daroussin elt->prev = head->prev; 299597bd480fSBaptiste Daroussin head->prev->next = elt; 299697bd480fSBaptiste Daroussin head->prev = elt; 299797bd480fSBaptiste Daroussin elt->next = NULL; 299897bd480fSBaptiste Daroussin } 299997bd480fSBaptiste Daroussin 300097bd480fSBaptiste Daroussin return head; 300197bd480fSBaptiste Daroussin } 300297bd480fSBaptiste Daroussin 300397bd480fSBaptiste Daroussin bool 3004b04a7a0bSBaptiste Daroussin ucl_object_todouble_safe (const ucl_object_t *obj, double *target) 300597bd480fSBaptiste Daroussin { 300697bd480fSBaptiste Daroussin if (obj == NULL || target == NULL) { 300797bd480fSBaptiste Daroussin return false; 300897bd480fSBaptiste Daroussin } 300997bd480fSBaptiste Daroussin switch (obj->type) { 301097bd480fSBaptiste Daroussin case UCL_INT: 301197bd480fSBaptiste Daroussin *target = obj->value.iv; /* Probaly could cause overflow */ 301297bd480fSBaptiste Daroussin break; 301397bd480fSBaptiste Daroussin case UCL_FLOAT: 301497bd480fSBaptiste Daroussin case UCL_TIME: 301597bd480fSBaptiste Daroussin *target = obj->value.dv; 301697bd480fSBaptiste Daroussin break; 301797bd480fSBaptiste Daroussin default: 301897bd480fSBaptiste Daroussin return false; 301997bd480fSBaptiste Daroussin } 302097bd480fSBaptiste Daroussin 302197bd480fSBaptiste Daroussin return true; 302297bd480fSBaptiste Daroussin } 302397bd480fSBaptiste Daroussin 302497bd480fSBaptiste Daroussin double 3025b04a7a0bSBaptiste Daroussin ucl_object_todouble (const ucl_object_t *obj) 302697bd480fSBaptiste Daroussin { 302797bd480fSBaptiste Daroussin double result = 0.; 302897bd480fSBaptiste Daroussin 302997bd480fSBaptiste Daroussin ucl_object_todouble_safe (obj, &result); 303097bd480fSBaptiste Daroussin return result; 303197bd480fSBaptiste Daroussin } 303297bd480fSBaptiste Daroussin 303397bd480fSBaptiste Daroussin bool 3034b04a7a0bSBaptiste Daroussin ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target) 303597bd480fSBaptiste Daroussin { 303697bd480fSBaptiste Daroussin if (obj == NULL || target == NULL) { 303797bd480fSBaptiste Daroussin return false; 303897bd480fSBaptiste Daroussin } 303997bd480fSBaptiste Daroussin switch (obj->type) { 304097bd480fSBaptiste Daroussin case UCL_INT: 304197bd480fSBaptiste Daroussin *target = obj->value.iv; 304297bd480fSBaptiste Daroussin break; 304397bd480fSBaptiste Daroussin case UCL_FLOAT: 304497bd480fSBaptiste Daroussin case UCL_TIME: 304597bd480fSBaptiste Daroussin *target = obj->value.dv; /* Loosing of decimal points */ 304697bd480fSBaptiste Daroussin break; 304797bd480fSBaptiste Daroussin default: 304897bd480fSBaptiste Daroussin return false; 304997bd480fSBaptiste Daroussin } 305097bd480fSBaptiste Daroussin 305197bd480fSBaptiste Daroussin return true; 305297bd480fSBaptiste Daroussin } 305397bd480fSBaptiste Daroussin 305497bd480fSBaptiste Daroussin int64_t 3055b04a7a0bSBaptiste Daroussin ucl_object_toint (const ucl_object_t *obj) 305697bd480fSBaptiste Daroussin { 305797bd480fSBaptiste Daroussin int64_t result = 0; 305897bd480fSBaptiste Daroussin 305997bd480fSBaptiste Daroussin ucl_object_toint_safe (obj, &result); 306097bd480fSBaptiste Daroussin return result; 306197bd480fSBaptiste Daroussin } 306297bd480fSBaptiste Daroussin 306397bd480fSBaptiste Daroussin bool 3064b04a7a0bSBaptiste Daroussin ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target) 306597bd480fSBaptiste Daroussin { 306697bd480fSBaptiste Daroussin if (obj == NULL || target == NULL) { 306797bd480fSBaptiste Daroussin return false; 306897bd480fSBaptiste Daroussin } 306997bd480fSBaptiste Daroussin switch (obj->type) { 307097bd480fSBaptiste Daroussin case UCL_BOOLEAN: 307197bd480fSBaptiste Daroussin *target = (obj->value.iv == true); 307297bd480fSBaptiste Daroussin break; 307397bd480fSBaptiste Daroussin default: 307497bd480fSBaptiste Daroussin return false; 307597bd480fSBaptiste Daroussin } 307697bd480fSBaptiste Daroussin 307797bd480fSBaptiste Daroussin return true; 307897bd480fSBaptiste Daroussin } 307997bd480fSBaptiste Daroussin 308097bd480fSBaptiste Daroussin bool 3081b04a7a0bSBaptiste Daroussin ucl_object_toboolean (const ucl_object_t *obj) 308297bd480fSBaptiste Daroussin { 308397bd480fSBaptiste Daroussin bool result = false; 308497bd480fSBaptiste Daroussin 308597bd480fSBaptiste Daroussin ucl_object_toboolean_safe (obj, &result); 308697bd480fSBaptiste Daroussin return result; 308797bd480fSBaptiste Daroussin } 308897bd480fSBaptiste Daroussin 308997bd480fSBaptiste Daroussin bool 3090b04a7a0bSBaptiste Daroussin ucl_object_tostring_safe (const ucl_object_t *obj, const char **target) 309197bd480fSBaptiste Daroussin { 309297bd480fSBaptiste Daroussin if (obj == NULL || target == NULL) { 309397bd480fSBaptiste Daroussin return false; 309497bd480fSBaptiste Daroussin } 309597bd480fSBaptiste Daroussin 309697bd480fSBaptiste Daroussin switch (obj->type) { 309797bd480fSBaptiste Daroussin case UCL_STRING: 309839ee7a7aSBaptiste Daroussin if (!(obj->flags & UCL_OBJECT_BINARY)) { 309997bd480fSBaptiste Daroussin *target = ucl_copy_value_trash (obj); 310039ee7a7aSBaptiste Daroussin } 310197bd480fSBaptiste Daroussin break; 310297bd480fSBaptiste Daroussin default: 310397bd480fSBaptiste Daroussin return false; 310497bd480fSBaptiste Daroussin } 310597bd480fSBaptiste Daroussin 310697bd480fSBaptiste Daroussin return true; 310797bd480fSBaptiste Daroussin } 310897bd480fSBaptiste Daroussin 310997bd480fSBaptiste Daroussin const char * 3110b04a7a0bSBaptiste Daroussin ucl_object_tostring (const ucl_object_t *obj) 311197bd480fSBaptiste Daroussin { 311297bd480fSBaptiste Daroussin const char *result = NULL; 311397bd480fSBaptiste Daroussin 311497bd480fSBaptiste Daroussin ucl_object_tostring_safe (obj, &result); 311597bd480fSBaptiste Daroussin return result; 311697bd480fSBaptiste Daroussin } 311797bd480fSBaptiste Daroussin 311897bd480fSBaptiste Daroussin const char * 3119b04a7a0bSBaptiste Daroussin ucl_object_tostring_forced (const ucl_object_t *obj) 312097bd480fSBaptiste Daroussin { 312139ee7a7aSBaptiste Daroussin /* TODO: For binary strings we might encode string here */ 312239ee7a7aSBaptiste Daroussin if (!(obj->flags & UCL_OBJECT_BINARY)) { 312397bd480fSBaptiste Daroussin return ucl_copy_value_trash (obj); 312497bd480fSBaptiste Daroussin } 312597bd480fSBaptiste Daroussin 312639ee7a7aSBaptiste Daroussin return NULL; 312739ee7a7aSBaptiste Daroussin } 312839ee7a7aSBaptiste Daroussin 312997bd480fSBaptiste Daroussin bool 3130b04a7a0bSBaptiste Daroussin ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen) 313197bd480fSBaptiste Daroussin { 313297bd480fSBaptiste Daroussin if (obj == NULL || target == NULL) { 313397bd480fSBaptiste Daroussin return false; 313497bd480fSBaptiste Daroussin } 313597bd480fSBaptiste Daroussin switch (obj->type) { 313697bd480fSBaptiste Daroussin case UCL_STRING: 313797bd480fSBaptiste Daroussin *target = obj->value.sv; 313897bd480fSBaptiste Daroussin if (tlen != NULL) { 313997bd480fSBaptiste Daroussin *tlen = obj->len; 314097bd480fSBaptiste Daroussin } 314197bd480fSBaptiste Daroussin break; 314297bd480fSBaptiste Daroussin default: 314397bd480fSBaptiste Daroussin return false; 314497bd480fSBaptiste Daroussin } 314597bd480fSBaptiste Daroussin 314697bd480fSBaptiste Daroussin return true; 314797bd480fSBaptiste Daroussin } 314897bd480fSBaptiste Daroussin 314997bd480fSBaptiste Daroussin const char * 3150b04a7a0bSBaptiste Daroussin ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen) 315197bd480fSBaptiste Daroussin { 315297bd480fSBaptiste Daroussin const char *result = NULL; 315397bd480fSBaptiste Daroussin 315497bd480fSBaptiste Daroussin ucl_object_tolstring_safe (obj, &result, tlen); 315597bd480fSBaptiste Daroussin return result; 315697bd480fSBaptiste Daroussin } 315797bd480fSBaptiste Daroussin 315897bd480fSBaptiste Daroussin const char * 3159b04a7a0bSBaptiste Daroussin ucl_object_key (const ucl_object_t *obj) 316097bd480fSBaptiste Daroussin { 316197bd480fSBaptiste Daroussin return ucl_copy_key_trash (obj); 316297bd480fSBaptiste Daroussin } 316397bd480fSBaptiste Daroussin 316497bd480fSBaptiste Daroussin const char * 3165b04a7a0bSBaptiste Daroussin ucl_object_keyl (const ucl_object_t *obj, size_t *len) 316697bd480fSBaptiste Daroussin { 316797bd480fSBaptiste Daroussin if (len == NULL || obj == NULL) { 316897bd480fSBaptiste Daroussin return NULL; 316997bd480fSBaptiste Daroussin } 317097bd480fSBaptiste Daroussin *len = obj->keylen; 317197bd480fSBaptiste Daroussin return obj->key; 317297bd480fSBaptiste Daroussin } 317397bd480fSBaptiste Daroussin 317497bd480fSBaptiste Daroussin ucl_object_t * 3175b04a7a0bSBaptiste Daroussin ucl_object_ref (const ucl_object_t *obj) 317697bd480fSBaptiste Daroussin { 3177b04a7a0bSBaptiste Daroussin ucl_object_t *res = NULL; 3178b04a7a0bSBaptiste Daroussin 317997bd480fSBaptiste Daroussin if (obj != NULL) { 31804bf54857SBaptiste Daroussin if (obj->flags & UCL_OBJECT_EPHEMERAL) { 31814bf54857SBaptiste Daroussin /* 31824bf54857SBaptiste Daroussin * Use deep copy for ephemeral objects, note that its refcount 31834bf54857SBaptiste Daroussin * is NOT increased, since ephemeral objects does not need refcount 31844bf54857SBaptiste Daroussin * at all 31854bf54857SBaptiste Daroussin */ 31864bf54857SBaptiste Daroussin res = ucl_object_copy (obj); 31874bf54857SBaptiste Daroussin } 31884bf54857SBaptiste Daroussin else { 3189b04a7a0bSBaptiste Daroussin res = __DECONST (ucl_object_t *, obj); 3190b04a7a0bSBaptiste Daroussin #ifdef HAVE_ATOMIC_BUILTINS 3191b04a7a0bSBaptiste Daroussin (void)__sync_add_and_fetch (&res->ref, 1); 3192b04a7a0bSBaptiste Daroussin #else 3193b04a7a0bSBaptiste Daroussin res->ref ++; 3194b04a7a0bSBaptiste Daroussin #endif 319597bd480fSBaptiste Daroussin } 31964bf54857SBaptiste Daroussin } 3197b04a7a0bSBaptiste Daroussin return res; 319897bd480fSBaptiste Daroussin } 319997bd480fSBaptiste Daroussin 32004bf54857SBaptiste Daroussin static ucl_object_t * 32014bf54857SBaptiste Daroussin ucl_object_copy_internal (const ucl_object_t *other, bool allow_array) 32024bf54857SBaptiste Daroussin { 32034bf54857SBaptiste Daroussin 32044bf54857SBaptiste Daroussin ucl_object_t *new; 32054bf54857SBaptiste Daroussin ucl_object_iter_t it = NULL; 32064bf54857SBaptiste Daroussin const ucl_object_t *cur; 32074bf54857SBaptiste Daroussin 32084bf54857SBaptiste Daroussin new = malloc (sizeof (*new)); 32094bf54857SBaptiste Daroussin 32104bf54857SBaptiste Daroussin if (new != NULL) { 32114bf54857SBaptiste Daroussin memcpy (new, other, sizeof (*new)); 32124bf54857SBaptiste Daroussin if (other->flags & UCL_OBJECT_EPHEMERAL) { 32134bf54857SBaptiste Daroussin /* Copied object is always non ephemeral */ 32144bf54857SBaptiste Daroussin new->flags &= ~UCL_OBJECT_EPHEMERAL; 32154bf54857SBaptiste Daroussin } 32164bf54857SBaptiste Daroussin new->ref = 1; 32174bf54857SBaptiste Daroussin /* Unlink from others */ 32184bf54857SBaptiste Daroussin new->next = NULL; 32194bf54857SBaptiste Daroussin new->prev = new; 32204bf54857SBaptiste Daroussin 32214bf54857SBaptiste Daroussin /* deep copy of values stored */ 32224bf54857SBaptiste Daroussin if (other->trash_stack[UCL_TRASH_KEY] != NULL) { 32234bf54857SBaptiste Daroussin new->trash_stack[UCL_TRASH_KEY] = 32244bf54857SBaptiste Daroussin strdup (other->trash_stack[UCL_TRASH_KEY]); 32254bf54857SBaptiste Daroussin if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) { 32264bf54857SBaptiste Daroussin new->key = new->trash_stack[UCL_TRASH_KEY]; 32274bf54857SBaptiste Daroussin } 32284bf54857SBaptiste Daroussin } 32294bf54857SBaptiste Daroussin if (other->trash_stack[UCL_TRASH_VALUE] != NULL) { 32304bf54857SBaptiste Daroussin new->trash_stack[UCL_TRASH_VALUE] = 32314bf54857SBaptiste Daroussin strdup (other->trash_stack[UCL_TRASH_VALUE]); 32324bf54857SBaptiste Daroussin if (new->type == UCL_STRING) { 32334bf54857SBaptiste Daroussin new->value.sv = new->trash_stack[UCL_TRASH_VALUE]; 32344bf54857SBaptiste Daroussin } 32354bf54857SBaptiste Daroussin } 32364bf54857SBaptiste Daroussin 32374bf54857SBaptiste Daroussin if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) { 32384bf54857SBaptiste Daroussin /* reset old value */ 32394bf54857SBaptiste Daroussin memset (&new->value, 0, sizeof (new->value)); 32404bf54857SBaptiste Daroussin 3241d9f0ce31SBaptiste Daroussin while ((cur = ucl_object_iterate (other, &it, true)) != NULL) { 32424bf54857SBaptiste Daroussin if (other->type == UCL_ARRAY) { 32434bf54857SBaptiste Daroussin ucl_array_append (new, ucl_object_copy_internal (cur, false)); 32444bf54857SBaptiste Daroussin } 32454bf54857SBaptiste Daroussin else { 32464bf54857SBaptiste Daroussin ucl_object_t *cp = ucl_object_copy_internal (cur, true); 32474bf54857SBaptiste Daroussin if (cp != NULL) { 32484bf54857SBaptiste Daroussin ucl_object_insert_key (new, cp, cp->key, cp->keylen, 32494bf54857SBaptiste Daroussin false); 32504bf54857SBaptiste Daroussin } 32514bf54857SBaptiste Daroussin } 32524bf54857SBaptiste Daroussin } 32534bf54857SBaptiste Daroussin } 32544bf54857SBaptiste Daroussin else if (allow_array && other->next != NULL) { 32554bf54857SBaptiste Daroussin LL_FOREACH (other->next, cur) { 32564bf54857SBaptiste Daroussin ucl_object_t *cp = ucl_object_copy_internal (cur, false); 32574bf54857SBaptiste Daroussin if (cp != NULL) { 32584bf54857SBaptiste Daroussin DL_APPEND (new, cp); 32594bf54857SBaptiste Daroussin } 32604bf54857SBaptiste Daroussin } 32614bf54857SBaptiste Daroussin } 32624bf54857SBaptiste Daroussin } 32634bf54857SBaptiste Daroussin 32644bf54857SBaptiste Daroussin return new; 32654bf54857SBaptiste Daroussin } 32664bf54857SBaptiste Daroussin 32674bf54857SBaptiste Daroussin ucl_object_t * 32684bf54857SBaptiste Daroussin ucl_object_copy (const ucl_object_t *other) 32694bf54857SBaptiste Daroussin { 32704bf54857SBaptiste Daroussin return ucl_object_copy_internal (other, true); 32714bf54857SBaptiste Daroussin } 32724bf54857SBaptiste Daroussin 327397bd480fSBaptiste Daroussin void 327497bd480fSBaptiste Daroussin ucl_object_unref (ucl_object_t *obj) 327597bd480fSBaptiste Daroussin { 3276b04a7a0bSBaptiste Daroussin if (obj != NULL) { 3277b04a7a0bSBaptiste Daroussin #ifdef HAVE_ATOMIC_BUILTINS 3278b04a7a0bSBaptiste Daroussin unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1); 3279b04a7a0bSBaptiste Daroussin if (rc == 0) { 3280b04a7a0bSBaptiste Daroussin #else 3281b04a7a0bSBaptiste Daroussin if (--obj->ref == 0) { 3282b04a7a0bSBaptiste Daroussin #endif 3283b04a7a0bSBaptiste Daroussin ucl_object_free_internal (obj, true, ucl_object_dtor_unref); 3284b04a7a0bSBaptiste Daroussin } 328597bd480fSBaptiste Daroussin } 328697bd480fSBaptiste Daroussin } 328797bd480fSBaptiste Daroussin 328897bd480fSBaptiste Daroussin int 3289b04a7a0bSBaptiste Daroussin ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2) 329097bd480fSBaptiste Daroussin { 3291b04a7a0bSBaptiste Daroussin const ucl_object_t *it1, *it2; 329297bd480fSBaptiste Daroussin ucl_object_iter_t iter = NULL; 329397bd480fSBaptiste Daroussin int ret = 0; 329497bd480fSBaptiste Daroussin 329597bd480fSBaptiste Daroussin if (o1->type != o2->type) { 329697bd480fSBaptiste Daroussin return (o1->type) - (o2->type); 329797bd480fSBaptiste Daroussin } 329897bd480fSBaptiste Daroussin 329997bd480fSBaptiste Daroussin switch (o1->type) { 330097bd480fSBaptiste Daroussin case UCL_STRING: 33018e3b1ab2SBaptiste Daroussin if (o1->len == o2->len && o1->len > 0) { 330297bd480fSBaptiste Daroussin ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2)); 330397bd480fSBaptiste Daroussin } 330497bd480fSBaptiste Daroussin else { 330597bd480fSBaptiste Daroussin ret = o1->len - o2->len; 330697bd480fSBaptiste Daroussin } 330797bd480fSBaptiste Daroussin break; 330897bd480fSBaptiste Daroussin case UCL_FLOAT: 330997bd480fSBaptiste Daroussin case UCL_INT: 331097bd480fSBaptiste Daroussin case UCL_TIME: 331197bd480fSBaptiste Daroussin ret = ucl_object_todouble (o1) - ucl_object_todouble (o2); 331297bd480fSBaptiste Daroussin break; 331397bd480fSBaptiste Daroussin case UCL_BOOLEAN: 331497bd480fSBaptiste Daroussin ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2); 331597bd480fSBaptiste Daroussin break; 331697bd480fSBaptiste Daroussin case UCL_ARRAY: 33178e3b1ab2SBaptiste Daroussin if (o1->len == o2->len && o1->len > 0) { 33188e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec1, o1); 33198e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec2, o2); 33208e3b1ab2SBaptiste Daroussin unsigned i; 33218e3b1ab2SBaptiste Daroussin 332297bd480fSBaptiste Daroussin /* Compare all elements in both arrays */ 33238e3b1ab2SBaptiste Daroussin for (i = 0; i < vec1->n; i ++) { 33248e3b1ab2SBaptiste Daroussin it1 = kv_A (*vec1, i); 33258e3b1ab2SBaptiste Daroussin it2 = kv_A (*vec2, i); 33268e3b1ab2SBaptiste Daroussin 33278e3b1ab2SBaptiste Daroussin if (it1 == NULL && it2 != NULL) { 33288e3b1ab2SBaptiste Daroussin return -1; 33298e3b1ab2SBaptiste Daroussin } 33308e3b1ab2SBaptiste Daroussin else if (it2 == NULL && it1 != NULL) { 33318e3b1ab2SBaptiste Daroussin return 1; 33328e3b1ab2SBaptiste Daroussin } 33338e3b1ab2SBaptiste Daroussin else if (it1 != NULL && it2 != NULL) { 333497bd480fSBaptiste Daroussin ret = ucl_object_compare (it1, it2); 333597bd480fSBaptiste Daroussin if (ret != 0) { 333697bd480fSBaptiste Daroussin break; 333797bd480fSBaptiste Daroussin } 33388e3b1ab2SBaptiste Daroussin } 333997bd480fSBaptiste Daroussin } 334097bd480fSBaptiste Daroussin } 334197bd480fSBaptiste Daroussin else { 334297bd480fSBaptiste Daroussin ret = o1->len - o2->len; 334397bd480fSBaptiste Daroussin } 334497bd480fSBaptiste Daroussin break; 334597bd480fSBaptiste Daroussin case UCL_OBJECT: 33468e3b1ab2SBaptiste Daroussin if (o1->len == o2->len && o1->len > 0) { 3347d9f0ce31SBaptiste Daroussin while ((it1 = ucl_object_iterate (o1, &iter, true)) != NULL) { 3348d9f0ce31SBaptiste Daroussin it2 = ucl_object_lookup (o2, ucl_object_key (it1)); 334997bd480fSBaptiste Daroussin if (it2 == NULL) { 335097bd480fSBaptiste Daroussin ret = 1; 335197bd480fSBaptiste Daroussin break; 335297bd480fSBaptiste Daroussin } 335397bd480fSBaptiste Daroussin ret = ucl_object_compare (it1, it2); 335497bd480fSBaptiste Daroussin if (ret != 0) { 335597bd480fSBaptiste Daroussin break; 335697bd480fSBaptiste Daroussin } 335797bd480fSBaptiste Daroussin } 335897bd480fSBaptiste Daroussin } 335997bd480fSBaptiste Daroussin else { 336097bd480fSBaptiste Daroussin ret = o1->len - o2->len; 336197bd480fSBaptiste Daroussin } 336297bd480fSBaptiste Daroussin break; 336397bd480fSBaptiste Daroussin default: 336497bd480fSBaptiste Daroussin ret = 0; 336597bd480fSBaptiste Daroussin break; 336697bd480fSBaptiste Daroussin } 336797bd480fSBaptiste Daroussin 336897bd480fSBaptiste Daroussin return ret; 336997bd480fSBaptiste Daroussin } 337097bd480fSBaptiste Daroussin 3371d9f0ce31SBaptiste Daroussin int 3372d9f0ce31SBaptiste Daroussin ucl_object_compare_qsort (const ucl_object_t **o1, 3373d9f0ce31SBaptiste Daroussin const ucl_object_t **o2) 3374d9f0ce31SBaptiste Daroussin { 3375d9f0ce31SBaptiste Daroussin return ucl_object_compare (*o1, *o2); 3376d9f0ce31SBaptiste Daroussin } 3377d9f0ce31SBaptiste Daroussin 337897bd480fSBaptiste Daroussin void 337997bd480fSBaptiste Daroussin ucl_object_array_sort (ucl_object_t *ar, 338039ee7a7aSBaptiste Daroussin int (*cmp)(const ucl_object_t **o1, const ucl_object_t **o2)) 338197bd480fSBaptiste Daroussin { 33828e3b1ab2SBaptiste Daroussin UCL_ARRAY_GET (vec, ar); 33838e3b1ab2SBaptiste Daroussin 338497bd480fSBaptiste Daroussin if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) { 338597bd480fSBaptiste Daroussin return; 338697bd480fSBaptiste Daroussin } 338797bd480fSBaptiste Daroussin 33888e3b1ab2SBaptiste Daroussin qsort (vec->a, vec->n, sizeof (ucl_object_t *), 33898e3b1ab2SBaptiste Daroussin (int (*)(const void *, const void *))cmp); 339097bd480fSBaptiste Daroussin } 33914bf54857SBaptiste Daroussin 33924bf54857SBaptiste Daroussin #define PRIOBITS 4 33934bf54857SBaptiste Daroussin 33944bf54857SBaptiste Daroussin unsigned int 33954bf54857SBaptiste Daroussin ucl_object_get_priority (const ucl_object_t *obj) 33964bf54857SBaptiste Daroussin { 33974bf54857SBaptiste Daroussin if (obj == NULL) { 33984bf54857SBaptiste Daroussin return 0; 33994bf54857SBaptiste Daroussin } 34004bf54857SBaptiste Daroussin 34014bf54857SBaptiste Daroussin return (obj->flags >> ((sizeof (obj->flags) * NBBY) - PRIOBITS)); 34024bf54857SBaptiste Daroussin } 34034bf54857SBaptiste Daroussin 34044bf54857SBaptiste Daroussin void 34054bf54857SBaptiste Daroussin ucl_object_set_priority (ucl_object_t *obj, 34064bf54857SBaptiste Daroussin unsigned int priority) 34074bf54857SBaptiste Daroussin { 34084bf54857SBaptiste Daroussin if (obj != NULL) { 34094bf54857SBaptiste Daroussin priority &= (0x1 << PRIOBITS) - 1; 341039ee7a7aSBaptiste Daroussin priority <<= ((sizeof (obj->flags) * NBBY) - PRIOBITS); 341139ee7a7aSBaptiste Daroussin priority |= obj->flags & ((1 << ((sizeof (obj->flags) * NBBY) - 341239ee7a7aSBaptiste Daroussin PRIOBITS)) - 1); 341339ee7a7aSBaptiste Daroussin obj->flags = priority; 34144bf54857SBaptiste Daroussin } 34154bf54857SBaptiste Daroussin } 3416d9f0ce31SBaptiste Daroussin 3417d9f0ce31SBaptiste Daroussin bool 3418d9f0ce31SBaptiste Daroussin ucl_object_string_to_type (const char *input, ucl_type_t *res) 3419d9f0ce31SBaptiste Daroussin { 3420d9f0ce31SBaptiste Daroussin if (strcasecmp (input, "object") == 0) { 3421d9f0ce31SBaptiste Daroussin *res = UCL_OBJECT; 3422d9f0ce31SBaptiste Daroussin } 3423d9f0ce31SBaptiste Daroussin else if (strcasecmp (input, "array") == 0) { 3424d9f0ce31SBaptiste Daroussin *res = UCL_ARRAY; 3425d9f0ce31SBaptiste Daroussin } 3426d9f0ce31SBaptiste Daroussin else if (strcasecmp (input, "integer") == 0) { 3427d9f0ce31SBaptiste Daroussin *res = UCL_INT; 3428d9f0ce31SBaptiste Daroussin } 3429d9f0ce31SBaptiste Daroussin else if (strcasecmp (input, "number") == 0) { 3430d9f0ce31SBaptiste Daroussin *res = UCL_FLOAT; 3431d9f0ce31SBaptiste Daroussin } 3432d9f0ce31SBaptiste Daroussin else if (strcasecmp (input, "string") == 0) { 3433d9f0ce31SBaptiste Daroussin *res = UCL_STRING; 3434d9f0ce31SBaptiste Daroussin } 3435d9f0ce31SBaptiste Daroussin else if (strcasecmp (input, "boolean") == 0) { 3436d9f0ce31SBaptiste Daroussin *res = UCL_BOOLEAN; 3437d9f0ce31SBaptiste Daroussin } 3438d9f0ce31SBaptiste Daroussin else if (strcasecmp (input, "null") == 0) { 3439d9f0ce31SBaptiste Daroussin *res = UCL_NULL; 3440d9f0ce31SBaptiste Daroussin } 3441d9f0ce31SBaptiste Daroussin else if (strcasecmp (input, "userdata") == 0) { 3442d9f0ce31SBaptiste Daroussin *res = UCL_USERDATA; 3443d9f0ce31SBaptiste Daroussin } 3444d9f0ce31SBaptiste Daroussin else { 3445d9f0ce31SBaptiste Daroussin return false; 3446d9f0ce31SBaptiste Daroussin } 3447d9f0ce31SBaptiste Daroussin 3448d9f0ce31SBaptiste Daroussin return true; 3449d9f0ce31SBaptiste Daroussin } 3450d9f0ce31SBaptiste Daroussin 3451d9f0ce31SBaptiste Daroussin const char * 3452d9f0ce31SBaptiste Daroussin ucl_object_type_to_string (ucl_type_t type) 3453d9f0ce31SBaptiste Daroussin { 3454d9f0ce31SBaptiste Daroussin const char *res = "unknown"; 3455d9f0ce31SBaptiste Daroussin 3456d9f0ce31SBaptiste Daroussin switch (type) { 3457d9f0ce31SBaptiste Daroussin case UCL_OBJECT: 3458d9f0ce31SBaptiste Daroussin res = "object"; 3459d9f0ce31SBaptiste Daroussin break; 3460d9f0ce31SBaptiste Daroussin case UCL_ARRAY: 3461d9f0ce31SBaptiste Daroussin res = "array"; 3462d9f0ce31SBaptiste Daroussin break; 3463d9f0ce31SBaptiste Daroussin case UCL_INT: 3464d9f0ce31SBaptiste Daroussin res = "integer"; 3465d9f0ce31SBaptiste Daroussin break; 3466d9f0ce31SBaptiste Daroussin case UCL_FLOAT: 3467d9f0ce31SBaptiste Daroussin case UCL_TIME: 3468d9f0ce31SBaptiste Daroussin res = "number"; 3469d9f0ce31SBaptiste Daroussin break; 3470d9f0ce31SBaptiste Daroussin case UCL_STRING: 3471d9f0ce31SBaptiste Daroussin res = "string"; 3472d9f0ce31SBaptiste Daroussin break; 3473d9f0ce31SBaptiste Daroussin case UCL_BOOLEAN: 3474d9f0ce31SBaptiste Daroussin res = "boolean"; 3475d9f0ce31SBaptiste Daroussin break; 3476d9f0ce31SBaptiste Daroussin case UCL_USERDATA: 3477d9f0ce31SBaptiste Daroussin res = "userdata"; 3478d9f0ce31SBaptiste Daroussin break; 3479d9f0ce31SBaptiste Daroussin case UCL_NULL: 3480d9f0ce31SBaptiste Daroussin res = "null"; 3481d9f0ce31SBaptiste Daroussin break; 3482d9f0ce31SBaptiste Daroussin } 3483d9f0ce31SBaptiste Daroussin 3484d9f0ce31SBaptiste Daroussin return res; 3485d9f0ce31SBaptiste Daroussin } 3486d9f0ce31SBaptiste Daroussin 3487d9f0ce31SBaptiste Daroussin const ucl_object_t * 3488d9f0ce31SBaptiste Daroussin ucl_parser_get_comments (struct ucl_parser *parser) 3489d9f0ce31SBaptiste Daroussin { 3490d9f0ce31SBaptiste Daroussin if (parser && parser->comments) { 3491d9f0ce31SBaptiste Daroussin return parser->comments; 3492d9f0ce31SBaptiste Daroussin } 3493d9f0ce31SBaptiste Daroussin 3494d9f0ce31SBaptiste Daroussin return NULL; 3495d9f0ce31SBaptiste Daroussin } 3496d9f0ce31SBaptiste Daroussin 3497d9f0ce31SBaptiste Daroussin const ucl_object_t * 3498d9f0ce31SBaptiste Daroussin ucl_comments_find (const ucl_object_t *comments, 3499d9f0ce31SBaptiste Daroussin const ucl_object_t *srch) 3500d9f0ce31SBaptiste Daroussin { 3501d9f0ce31SBaptiste Daroussin if (comments && srch) { 3502d9f0ce31SBaptiste Daroussin return ucl_object_lookup_len (comments, (const char *)&srch, 3503d9f0ce31SBaptiste Daroussin sizeof (void *)); 3504d9f0ce31SBaptiste Daroussin } 3505d9f0ce31SBaptiste Daroussin 3506d9f0ce31SBaptiste Daroussin return NULL; 3507d9f0ce31SBaptiste Daroussin } 3508d9f0ce31SBaptiste Daroussin 3509d9f0ce31SBaptiste Daroussin bool 3510d9f0ce31SBaptiste Daroussin ucl_comments_move (ucl_object_t *comments, 3511d9f0ce31SBaptiste Daroussin const ucl_object_t *from, const ucl_object_t *to) 3512d9f0ce31SBaptiste Daroussin { 3513d9f0ce31SBaptiste Daroussin const ucl_object_t *found; 3514d9f0ce31SBaptiste Daroussin ucl_object_t *obj; 3515d9f0ce31SBaptiste Daroussin 3516d9f0ce31SBaptiste Daroussin if (comments && from && to) { 3517d9f0ce31SBaptiste Daroussin found = ucl_object_lookup_len (comments, 3518d9f0ce31SBaptiste Daroussin (const char *)&from, sizeof (void *)); 3519d9f0ce31SBaptiste Daroussin 3520d9f0ce31SBaptiste Daroussin if (found) { 3521d9f0ce31SBaptiste Daroussin /* Replace key */ 3522d9f0ce31SBaptiste Daroussin obj = ucl_object_ref (found); 3523d9f0ce31SBaptiste Daroussin ucl_object_delete_keyl (comments, (const char *)&from, 3524d9f0ce31SBaptiste Daroussin sizeof (void *)); 3525d9f0ce31SBaptiste Daroussin ucl_object_insert_key (comments, obj, (const char *)&to, 3526d9f0ce31SBaptiste Daroussin sizeof (void *), true); 3527d9f0ce31SBaptiste Daroussin 3528d9f0ce31SBaptiste Daroussin return true; 3529d9f0ce31SBaptiste Daroussin } 3530d9f0ce31SBaptiste Daroussin } 3531d9f0ce31SBaptiste Daroussin 3532d9f0ce31SBaptiste Daroussin return false; 3533d9f0ce31SBaptiste Daroussin } 3534d9f0ce31SBaptiste Daroussin 3535d9f0ce31SBaptiste Daroussin void 3536d9f0ce31SBaptiste Daroussin ucl_comments_add (ucl_object_t *comments, const ucl_object_t *obj, 3537d9f0ce31SBaptiste Daroussin const char *comment) 3538d9f0ce31SBaptiste Daroussin { 3539d9f0ce31SBaptiste Daroussin if (comments && obj && comment) { 3540d9f0ce31SBaptiste Daroussin ucl_object_insert_key (comments, ucl_object_fromstring (comment), 3541d9f0ce31SBaptiste Daroussin (const char *)&obj, sizeof (void *), true); 3542d9f0ce31SBaptiste Daroussin } 3543d9f0ce31SBaptiste Daroussin } 3544