Deleted Added
full compact
ucl_util.c (263019) ucl_util.c (268896)
1/* Copyright (c) 2013, Vsevolod Stakhov
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 */
23
24#include "ucl.h"
25#include "ucl_internal.h"
26#include "ucl_chartable.h"
27
1/* Copyright (c) 2013, Vsevolod Stakhov
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 */
23
24#include "ucl.h"
25#include "ucl_internal.h"
26#include "ucl_chartable.h"
27
28#ifdef HAVE_LIBGEN_H
28#include <libgen.h> /* For dirname */
29#include <libgen.h> /* For dirname */
30#endif
29
30#ifdef HAVE_OPENSSL
31#include <openssl/err.h>
32#include <openssl/sha.h>
33#include <openssl/rsa.h>
34#include <openssl/ssl.h>
35#include <openssl/evp.h>
36#endif
37
31
32#ifdef HAVE_OPENSSL
33#include <openssl/err.h>
34#include <openssl/sha.h>
35#include <openssl/rsa.h>
36#include <openssl/ssl.h>
37#include <openssl/evp.h>
38#endif
39
40#ifdef CURL_FOUND
41#include <curl/curl.h>
42#endif
43#ifdef HAVE_FETCH_H
44#include <fetch.h>
45#endif
46
38#ifdef _WIN32
39#include <windows.h>
40
47#ifdef _WIN32
48#include <windows.h>
49
50#ifndef PROT_READ
41#define PROT_READ 1
51#define PROT_READ 1
52#endif
53#ifndef PROT_WRITE
42#define PROT_WRITE 2
54#define PROT_WRITE 2
55#endif
56#ifndef PROT_READWRITE
43#define PROT_READWRITE 3
57#define PROT_READWRITE 3
58#endif
59#ifndef MAP_SHARED
44#define MAP_SHARED 1
60#define MAP_SHARED 1
61#endif
62#ifndef MAP_PRIVATE
45#define MAP_PRIVATE 2
63#define MAP_PRIVATE 2
64#endif
65#ifndef MAP_FAILED
46#define MAP_FAILED ((void *) -1)
66#define MAP_FAILED ((void *) -1)
67#endif
47
68
48static void *mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
69static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
49{
50 void *map = NULL;
51 HANDLE handle = INVALID_HANDLE_VALUE;
52
53 switch (prot) {
54 default:
55 case PROT_READ:
56 {

--- 21 unchanged lines hidden (view full) ---

78 }
79 }
80 if (map == (void *) NULL) {
81 return (void *) MAP_FAILED;
82 }
83 return (void *) ((char *) map + offset);
84}
85
70{
71 void *map = NULL;
72 HANDLE handle = INVALID_HANDLE_VALUE;
73
74 switch (prot) {
75 default:
76 case PROT_READ:
77 {

--- 21 unchanged lines hidden (view full) ---

99 }
100 }
101 if (map == (void *) NULL) {
102 return (void *) MAP_FAILED;
103 }
104 return (void *) ((char *) map + offset);
105}
106
86static int munmap(void *map,size_t length)
107static int ucl_munmap(void *map,size_t length)
87{
88 if (!UnmapViewOfFile(map)) {
89 return(-1);
90 }
91 return(0);
92}
93
108{
109 if (!UnmapViewOfFile(map)) {
110 return(-1);
111 }
112 return(0);
113}
114
94static char* realpath(const char *path, char *resolved_path) {
115static char* ucl_realpath(const char *path, char *resolved_path) {
95 char *p;
96 char tmp[MAX_PATH + 1];
97 strncpy(tmp, path, sizeof(tmp)-1);
98 p = tmp;
99 while(*p) {
100 if (*p == '/') *p = '\\';
101 p++;
102 }
103 return _fullpath(resolved_path, tmp, MAX_PATH);
104}
116 char *p;
117 char tmp[MAX_PATH + 1];
118 strncpy(tmp, path, sizeof(tmp)-1);
119 p = tmp;
120 while(*p) {
121 if (*p == '/') *p = '\\';
122 p++;
123 }
124 return _fullpath(resolved_path, tmp, MAX_PATH);
125}
126#else
127#define ucl_mmap mmap
128#define ucl_munmap munmap
129#define ucl_realpath realpath
105#endif
106
107/**
108 * @file rcl_util.c
109 * Utilities for rcl parsing
110 */
111
130#endif
131
132/**
133 * @file rcl_util.c
134 * Utilities for rcl parsing
135 */
136
137typedef void (*ucl_object_dtor) (ucl_object_t *obj);
138static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec,
139 ucl_object_dtor dtor);
140static void ucl_object_dtor_unref (ucl_object_t *obj);
112
113static void
141
142static void
114ucl_object_free_internal (ucl_object_t *obj, bool allow_rec)
143ucl_object_dtor_free (ucl_object_t *obj)
115{
144{
116 ucl_object_t *sub, *tmp;
145 if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
146 UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
147 }
148 if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
149 UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
150 }
151 UCL_FREE (sizeof (ucl_object_t), obj);
152}
117
153
118 while (obj != NULL) {
119 if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
120 UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
154/*
155 * This is a helper function that performs exactly the same as
156 * `ucl_object_unref` but it doesn't iterate over elements allowing
157 * to use it for individual elements of arrays and multiple values
158 */
159static void
160ucl_object_dtor_unref_single (ucl_object_t *obj)
161{
162 if (obj != NULL) {
163#ifdef HAVE_ATOMIC_BUILTINS
164 unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
165 if (rc == 0) {
166#else
167 if (--obj->ref == 0) {
168#endif
169 ucl_object_free_internal (obj, false, ucl_object_dtor_unref);
121 }
170 }
122 if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
123 UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
124 }
171 }
172}
125
173
174static void
175ucl_object_dtor_unref (ucl_object_t *obj)
176{
177 if (obj->ref == 0) {
178 ucl_object_dtor_free (obj);
179 }
180 else {
181 /* This may cause dtor unref being called one more time */
182 ucl_object_dtor_unref_single (obj);
183 }
184}
185
186static void
187ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor)
188{
189 ucl_object_t *sub, *tmp;
190
191 while (obj != NULL) {
126 if (obj->type == UCL_ARRAY) {
127 sub = obj->value.av;
128 while (sub != NULL) {
129 tmp = sub->next;
192 if (obj->type == UCL_ARRAY) {
193 sub = obj->value.av;
194 while (sub != NULL) {
195 tmp = sub->next;
130 ucl_object_free_internal (sub, false);
196 dtor (sub);
131 sub = tmp;
132 }
133 }
134 else if (obj->type == UCL_OBJECT) {
135 if (obj->value.ov != NULL) {
197 sub = tmp;
198 }
199 }
200 else if (obj->type == UCL_OBJECT) {
201 if (obj->value.ov != NULL) {
136 ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref);
202 ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)dtor);
137 }
138 }
139 tmp = obj->next;
203 }
204 }
205 tmp = obj->next;
140 UCL_FREE (sizeof (ucl_object_t), obj);
206 dtor (obj);
141 obj = tmp;
142
143 if (!allow_rec) {
144 break;
145 }
146 }
147}
148
149void
150ucl_object_free (ucl_object_t *obj)
151{
207 obj = tmp;
208
209 if (!allow_rec) {
210 break;
211 }
212 }
213}
214
215void
216ucl_object_free (ucl_object_t *obj)
217{
152 ucl_object_free_internal (obj, true);
218 ucl_object_free_internal (obj, true, ucl_object_dtor_free);
153}
154
155size_t
156ucl_unescape_json_string (char *str, size_t len)
157{
158 char *t = str, *h = str;
159 int i, uval;
160
219}
220
221size_t
222ucl_unescape_json_string (char *str, size_t len)
223{
224 char *t = str, *h = str;
225 int i, uval;
226
227 if (len <= 1) {
228 return len;
229 }
161 /* t is target (tortoise), h is source (hare) */
162
163 while (len) {
164 if (*h == '\\') {
165 h ++;
166 switch (*h) {
167 case 'n':
168 *t++ = '\n';

--- 14 unchanged lines hidden (view full) ---

183 *t++ = '\\';
184 break;
185 case '"':
186 *t++ = '"';
187 break;
188 case 'u':
189 /* Unicode escape */
190 uval = 0;
230 /* t is target (tortoise), h is source (hare) */
231
232 while (len) {
233 if (*h == '\\') {
234 h ++;
235 switch (*h) {
236 case 'n':
237 *t++ = '\n';

--- 14 unchanged lines hidden (view full) ---

252 *t++ = '\\';
253 break;
254 case '"':
255 *t++ = '"';
256 break;
257 case 'u':
258 /* Unicode escape */
259 uval = 0;
191 for (i = 0; i < 4; i++) {
192 uval <<= 4;
193 if (isdigit (h[i])) {
194 uval += h[i] - '0';
260 if (len > 3) {
261 for (i = 0; i < 4; i++) {
262 uval <<= 4;
263 if (isdigit (h[i])) {
264 uval += h[i] - '0';
265 }
266 else if (h[i] >= 'a' && h[i] <= 'f') {
267 uval += h[i] - 'a' + 10;
268 }
269 else if (h[i] >= 'A' && h[i] <= 'F') {
270 uval += h[i] - 'A' + 10;
271 }
272 else {
273 break;
274 }
195 }
275 }
196 else if (h[i] >= 'a' && h[i] <= 'f') {
197 uval += h[i] - 'a' + 10;
276 h += 3;
277 len -= 3;
278 /* Encode */
279 if(uval < 0x80) {
280 t[0] = (char)uval;
281 t ++;
198 }
282 }
199 else if (h[i] >= 'A' && h[i] <= 'F') {
200 uval += h[i] - 'A' + 10;
283 else if(uval < 0x800) {
284 t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
285 t[1] = 0x80 + ((uval & 0x03F));
286 t += 2;
201 }
287 }
288 else if(uval < 0x10000) {
289 t[0] = 0xE0 + ((uval & 0xF000) >> 12);
290 t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
291 t[2] = 0x80 + ((uval & 0x003F));
292 t += 3;
293 }
294 else if(uval <= 0x10FFFF) {
295 t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
296 t[1] = 0x80 + ((uval & 0x03F000) >> 12);
297 t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
298 t[3] = 0x80 + ((uval & 0x00003F));
299 t += 4;
300 }
301 else {
302 *t++ = '?';
303 }
202 }
304 }
203 h += 3;
204 len -= 3;
205 /* Encode */
206 if(uval < 0x80) {
207 t[0] = (char)uval;
208 t ++;
209 }
210 else if(uval < 0x800) {
211 t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
212 t[1] = 0x80 + ((uval & 0x03F));
213 t += 2;
214 }
215 else if(uval < 0x10000) {
216 t[0] = 0xE0 + ((uval & 0xF000) >> 12);
217 t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
218 t[2] = 0x80 + ((uval & 0x003F));
219 t += 3;
220 }
221 else if(uval <= 0x10FFFF) {
222 t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
223 t[1] = 0x80 + ((uval & 0x03F000) >> 12);
224 t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
225 t[3] = 0x80 + ((uval & 0x00003F));
226 t += 4;
227 }
228 else {
305 else {
229 *t++ = '?';
306 *t++ = 'u';
230 }
231 break;
232 default:
233 *t++ = *h;
234 break;
235 }
236 h ++;
237 len --;
238 }
239 else {
240 *t++ = *h++;
241 }
242 len --;
243 }
244 *t = '\0';
245
246 return (t - str);
247}
248
307 }
308 break;
309 default:
310 *t++ = *h;
311 break;
312 }
313 h ++;
314 len --;
315 }
316 else {
317 *t++ = *h++;
318 }
319 len --;
320 }
321 *t = '\0';
322
323 return (t - str);
324}
325
249UCL_EXTERN char *
250ucl_copy_key_trash (ucl_object_t *obj)
326char *
327ucl_copy_key_trash (const ucl_object_t *obj)
251{
328{
329 ucl_object_t *deconst;
330
331 if (obj == NULL) {
332 return NULL;
333 }
252 if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
334 if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
253 obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
254 if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
255 memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
256 obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
335 deconst = __DECONST (ucl_object_t *, obj);
336 deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
337 if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) {
338 memcpy (deconst->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
339 deconst->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
257 }
340 }
258 obj->key = obj->trash_stack[UCL_TRASH_KEY];
259 obj->flags |= UCL_OBJECT_ALLOCATED_KEY;
341 deconst->key = obj->trash_stack[UCL_TRASH_KEY];
342 deconst->flags |= UCL_OBJECT_ALLOCATED_KEY;
260 }
261
262 return obj->trash_stack[UCL_TRASH_KEY];
263}
264
343 }
344
345 return obj->trash_stack[UCL_TRASH_KEY];
346}
347
265UCL_EXTERN char *
266ucl_copy_value_trash (ucl_object_t *obj)
348char *
349ucl_copy_value_trash (const ucl_object_t *obj)
267{
350{
351 ucl_object_t *deconst;
352
353 if (obj == NULL) {
354 return NULL;
355 }
268 if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
356 if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
357 deconst = __DECONST (ucl_object_t *, obj);
269 if (obj->type == UCL_STRING) {
358 if (obj->type == UCL_STRING) {
359
270 /* Special case for strings */
360 /* Special case for strings */
271 obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
272 if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
273 memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
274 obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
275 obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
361 deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
362 if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
363 memcpy (deconst->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
364 deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
365 deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
276 }
277 }
278 else {
279 /* Just emit value in json notation */
366 }
367 }
368 else {
369 /* Just emit value in json notation */
280 obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
281 obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
370 deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
371 deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
282 }
372 }
283 obj->flags |= UCL_OBJECT_ALLOCATED_VALUE;
373 deconst->flags |= UCL_OBJECT_ALLOCATED_VALUE;
284 }
285 return obj->trash_stack[UCL_TRASH_VALUE];
286}
287
288UCL_EXTERN ucl_object_t*
289ucl_parser_get_object (struct ucl_parser *parser)
290{
291 if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {

--- 7 unchanged lines hidden (view full) ---

299ucl_parser_free (struct ucl_parser *parser)
300{
301 struct ucl_stack *stack, *stmp;
302 struct ucl_macro *macro, *mtmp;
303 struct ucl_chunk *chunk, *ctmp;
304 struct ucl_pubkey *key, *ktmp;
305 struct ucl_variable *var, *vtmp;
306
374 }
375 return obj->trash_stack[UCL_TRASH_VALUE];
376}
377
378UCL_EXTERN ucl_object_t*
379ucl_parser_get_object (struct ucl_parser *parser)
380{
381 if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {

--- 7 unchanged lines hidden (view full) ---

389ucl_parser_free (struct ucl_parser *parser)
390{
391 struct ucl_stack *stack, *stmp;
392 struct ucl_macro *macro, *mtmp;
393 struct ucl_chunk *chunk, *ctmp;
394 struct ucl_pubkey *key, *ktmp;
395 struct ucl_variable *var, *vtmp;
396
397 if (parser == NULL) {
398 return;
399 }
400
307 if (parser->top_obj != NULL) {
308 ucl_object_unref (parser->top_obj);
309 }
310
311 LL_FOREACH_SAFE (parser->stack, stack, stmp) {
312 free (stack);
313 }
314 HASH_ITER (hh, parser->macroes, macro, mtmp) {

--- 18 unchanged lines hidden (view full) ---

333 }
334
335 UCL_FREE (sizeof (struct ucl_parser), parser);
336}
337
338UCL_EXTERN const char *
339ucl_parser_get_error(struct ucl_parser *parser)
340{
401 if (parser->top_obj != NULL) {
402 ucl_object_unref (parser->top_obj);
403 }
404
405 LL_FOREACH_SAFE (parser->stack, stack, stmp) {
406 free (stack);
407 }
408 HASH_ITER (hh, parser->macroes, macro, mtmp) {

--- 18 unchanged lines hidden (view full) ---

427 }
428
429 UCL_FREE (sizeof (struct ucl_parser), parser);
430}
431
432UCL_EXTERN const char *
433ucl_parser_get_error(struct ucl_parser *parser)
434{
435 if (parser == NULL) {
436 return NULL;
437 }
438
341 if (parser->err == NULL)
342 return NULL;
343
344 return utstring_body(parser->err);
345}
346
347UCL_EXTERN bool
348ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)

--- 6 unchanged lines hidden (view full) ---

355 ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
356 return EXIT_FAILURE;
357# else
358 struct ucl_pubkey *nkey;
359 BIO *mem;
360
361 mem = BIO_new_mem_buf ((void *)key, len);
362 nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
439 if (parser->err == NULL)
440 return NULL;
441
442 return utstring_body(parser->err);
443}
444
445UCL_EXTERN bool
446ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)

--- 6 unchanged lines hidden (view full) ---

453 ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
454 return EXIT_FAILURE;
455# else
456 struct ucl_pubkey *nkey;
457 BIO *mem;
458
459 mem = BIO_new_mem_buf ((void *)key, len);
460 nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
461 if (nkey == NULL) {
462 ucl_create_err (&parser->err, "cannot allocate memory for key");
463 return false;
464 }
363 nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
364 BIO_free (mem);
365 if (nkey->key == NULL) {
366 UCL_FREE (sizeof (struct ucl_pubkey), nkey);
367 ucl_create_err (&parser->err, "%s",
368 ERR_error_string (ERR_get_error (), NULL));
369 return false;
370 }

--- 151 unchanged lines hidden (view full) ---

522 *buflen = 0;
523 }
524 else {
525 if ((fd = open (filename, O_RDONLY)) == -1) {
526 ucl_create_err (err, "cannot open file %s: %s",
527 filename, strerror (errno));
528 return false;
529 }
465 nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
466 BIO_free (mem);
467 if (nkey->key == NULL) {
468 UCL_FREE (sizeof (struct ucl_pubkey), nkey);
469 ucl_create_err (&parser->err, "%s",
470 ERR_error_string (ERR_get_error (), NULL));
471 return false;
472 }

--- 151 unchanged lines hidden (view full) ---

624 *buflen = 0;
625 }
626 else {
627 if ((fd = open (filename, O_RDONLY)) == -1) {
628 ucl_create_err (err, "cannot open file %s: %s",
629 filename, strerror (errno));
630 return false;
631 }
530 if ((*buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
632 if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
531 close (fd);
532 ucl_create_err (err, "cannot mmap file %s: %s",
533 filename, strerror (errno));
534 return false;
535 }
536 *buflen = st.st_size;
537 close (fd);
538 }

--- 85 unchanged lines hidden (view full) ---

624 if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
625 return false;
626 }
627 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
628 ucl_create_err (&parser->err, "cannot verify url %s: %s",
629 urlbuf,
630 ERR_error_string (ERR_get_error (), NULL));
631 if (siglen > 0) {
633 close (fd);
634 ucl_create_err (err, "cannot mmap file %s: %s",
635 filename, strerror (errno));
636 return false;
637 }
638 *buflen = st.st_size;
639 close (fd);
640 }

--- 85 unchanged lines hidden (view full) ---

726 if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
727 return false;
728 }
729 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
730 ucl_create_err (&parser->err, "cannot verify url %s: %s",
731 urlbuf,
732 ERR_error_string (ERR_get_error (), NULL));
733 if (siglen > 0) {
632 munmap (sigbuf, siglen);
734 ucl_munmap (sigbuf, siglen);
633 }
634 return false;
635 }
636 if (siglen > 0) {
735 }
736 return false;
737 }
738 if (siglen > 0) {
637 munmap (sigbuf, siglen);
739 ucl_munmap (sigbuf, siglen);
638 }
639#endif
640 }
641
642 prev_state = parser->state;
643 parser->state = UCL_STATE_INIT;
644
645 res = ucl_parser_add_chunk (parser, buf, buflen);

--- 27 unchanged lines hidden (view full) ---

673 bool res;
674 struct ucl_chunk *chunk;
675 unsigned char *buf = NULL;
676 size_t buflen;
677 char filebuf[PATH_MAX], realbuf[PATH_MAX];
678 int prev_state;
679
680 snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
740 }
741#endif
742 }
743
744 prev_state = parser->state;
745 parser->state = UCL_STATE_INIT;
746
747 res = ucl_parser_add_chunk (parser, buf, buflen);

--- 27 unchanged lines hidden (view full) ---

775 bool res;
776 struct ucl_chunk *chunk;
777 unsigned char *buf = NULL;
778 size_t buflen;
779 char filebuf[PATH_MAX], realbuf[PATH_MAX];
780 int prev_state;
781
782 snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
681 if (realpath (filebuf, realbuf) == NULL) {
783 if (ucl_realpath (filebuf, realbuf) == NULL) {
682 if (!must_exist) {
683 return true;
684 }
685 ucl_create_err (&parser->err, "cannot open file %s: %s",
686 filebuf,
687 strerror (errno));
688 return false;
689 }

--- 11 unchanged lines hidden (view full) ---

701 if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
702 return false;
703 }
704 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
705 ucl_create_err (&parser->err, "cannot verify file %s: %s",
706 filebuf,
707 ERR_error_string (ERR_get_error (), NULL));
708 if (siglen > 0) {
784 if (!must_exist) {
785 return true;
786 }
787 ucl_create_err (&parser->err, "cannot open file %s: %s",
788 filebuf,
789 strerror (errno));
790 return false;
791 }

--- 11 unchanged lines hidden (view full) ---

803 if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
804 return false;
805 }
806 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
807 ucl_create_err (&parser->err, "cannot verify file %s: %s",
808 filebuf,
809 ERR_error_string (ERR_get_error (), NULL));
810 if (siglen > 0) {
709 munmap (sigbuf, siglen);
811 ucl_munmap (sigbuf, siglen);
710 }
711 return false;
712 }
713 if (siglen > 0) {
812 }
813 return false;
814 }
815 if (siglen > 0) {
714 munmap (sigbuf, siglen);
816 ucl_munmap (sigbuf, siglen);
715 }
716#endif
717 }
718
719 ucl_parser_set_filevars (parser, realbuf, false);
720
721 prev_state = parser->state;
722 parser->state = UCL_STATE_INIT;

--- 6 unchanged lines hidden (view full) ---

729 parser->chunks = chunk->next;
730 UCL_FREE (sizeof (struct ucl_chunk), chunk);
731 }
732 }
733
734 parser->state = prev_state;
735
736 if (buflen > 0) {
817 }
818#endif
819 }
820
821 ucl_parser_set_filevars (parser, realbuf, false);
822
823 prev_state = parser->state;
824 parser->state = UCL_STATE_INIT;

--- 6 unchanged lines hidden (view full) ---

831 parser->chunks = chunk->next;
832 UCL_FREE (sizeof (struct ucl_chunk), chunk);
833 }
834 }
835
836 parser->state = prev_state;
837
838 if (buflen > 0) {
737 munmap (buf, buflen);
839 ucl_munmap (buf, buflen);
738 }
739
740 return res;
741}
742
743/**
744 * Handle include macro
745 * @param data include data

--- 52 unchanged lines hidden (view full) ---

798
799UCL_EXTERN bool
800ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
801{
802 char realbuf[PATH_MAX], *curdir;
803
804 if (filename != NULL) {
805 if (need_expand) {
840 }
841
842 return res;
843}
844
845/**
846 * Handle include macro
847 * @param data include data

--- 52 unchanged lines hidden (view full) ---

900
901UCL_EXTERN bool
902ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
903{
904 char realbuf[PATH_MAX], *curdir;
905
906 if (filename != NULL) {
907 if (need_expand) {
806 if (realpath (filename, realbuf) == NULL) {
908 if (ucl_realpath (filename, realbuf) == NULL) {
807 return false;
808 }
809 }
810 else {
811 ucl_strlcpy (realbuf, filename, sizeof (realbuf));
812 }
813
814 /* Define variables */

--- 14 unchanged lines hidden (view full) ---

829UCL_EXTERN bool
830ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
831{
832 unsigned char *buf;
833 size_t len;
834 bool ret;
835 char realbuf[PATH_MAX];
836
909 return false;
910 }
911 }
912 else {
913 ucl_strlcpy (realbuf, filename, sizeof (realbuf));
914 }
915
916 /* Define variables */

--- 14 unchanged lines hidden (view full) ---

931UCL_EXTERN bool
932ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
933{
934 unsigned char *buf;
935 size_t len;
936 bool ret;
937 char realbuf[PATH_MAX];
938
837 if (realpath (filename, realbuf) == NULL) {
939 if (ucl_realpath (filename, realbuf) == NULL) {
838 ucl_create_err (&parser->err, "cannot open file %s: %s",
839 filename,
840 strerror (errno));
841 return false;
842 }
843
844 if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
845 return false;
846 }
847
848 ucl_parser_set_filevars (parser, realbuf, false);
849 ret = ucl_parser_add_chunk (parser, buf, len);
850
851 if (len > 0) {
940 ucl_create_err (&parser->err, "cannot open file %s: %s",
941 filename,
942 strerror (errno));
943 return false;
944 }
945
946 if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
947 return false;
948 }
949
950 ucl_parser_set_filevars (parser, realbuf, false);
951 ret = ucl_parser_add_chunk (parser, buf, len);
952
953 if (len > 0) {
852 munmap (buf, len);
954 ucl_munmap (buf, len);
853 }
854
855 return ret;
856}
857
858size_t
859ucl_strlcpy (char *dst, const char *src, size_t siz)
860{

--- 148 unchanged lines hidden (view full) ---

1009 }
1010 }
1011 if ((flags & UCL_STRING_PARSE) && dst != NULL) {
1012 /* Parse what we have */
1013 if (flags & UCL_STRING_PARSE_BOOLEAN) {
1014 if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
1015 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1016 flags & UCL_STRING_PARSE_DOUBLE,
955 }
956
957 return ret;
958}
959
960size_t
961ucl_strlcpy (char *dst, const char *src, size_t siz)
962{

--- 148 unchanged lines hidden (view full) ---

1111 }
1112 }
1113 if ((flags & UCL_STRING_PARSE) && dst != NULL) {
1114 /* Parse what we have */
1115 if (flags & UCL_STRING_PARSE_BOOLEAN) {
1116 if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
1117 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1118 flags & UCL_STRING_PARSE_DOUBLE,
1017 flags & UCL_STRING_PARSE_BYTES);
1119 flags & UCL_STRING_PARSE_BYTES,
1120 flags & UCL_STRING_PARSE_TIME);
1018 }
1019 }
1020 else {
1021 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1022 flags & UCL_STRING_PARSE_DOUBLE,
1121 }
1122 }
1123 else {
1124 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1125 flags & UCL_STRING_PARSE_DOUBLE,
1023 flags & UCL_STRING_PARSE_BYTES);
1126 flags & UCL_STRING_PARSE_BYTES,
1127 flags & UCL_STRING_PARSE_TIME);
1024 }
1025 }
1026 }
1027
1028 return obj;
1029}
1030
1128 }
1129 }
1130 }
1131
1132 return obj;
1133}
1134
1031static ucl_object_t *
1135static bool
1032ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
1033 const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
1034{
1136ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
1137 const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
1138{
1035 ucl_object_t *found, *cur;
1139 ucl_object_t *found, *tmp;
1140 const ucl_object_t *cur;
1036 ucl_object_iter_t it = NULL;
1037 const char *p;
1141 ucl_object_iter_t it = NULL;
1142 const char *p;
1143 int ret = true;
1038
1039 if (elt == NULL || key == NULL) {
1144
1145 if (elt == NULL || key == NULL) {
1040 return NULL;
1146 return false;
1041 }
1042
1043 if (top == NULL) {
1147 }
1148
1149 if (top == NULL) {
1044 top = ucl_object_new ();
1045 top->type = UCL_OBJECT;
1150 return false;
1046 }
1047
1048 if (top->type != UCL_OBJECT) {
1049 /* It is possible to convert NULL type to an object */
1050 if (top->type == UCL_NULL) {
1051 top->type = UCL_OBJECT;
1052 }
1053 else {
1054 /* Refuse converting of other object types */
1151 }
1152
1153 if (top->type != UCL_OBJECT) {
1154 /* It is possible to convert NULL type to an object */
1155 if (top->type == UCL_NULL) {
1156 top->type = UCL_OBJECT;
1157 }
1158 else {
1159 /* Refuse converting of other object types */
1055 return top;
1160 return false;
1056 }
1057 }
1058
1059 if (top->value.ov == NULL) {
1060 top->value.ov = ucl_hash_create ();
1061 }
1062
1063 if (keylen == 0) {

--- 9 unchanged lines hidden (view full) ---

1073
1074 elt->key = key;
1075 elt->keylen = keylen;
1076
1077 if (copy_key) {
1078 ucl_copy_key_trash (elt);
1079 }
1080
1161 }
1162 }
1163
1164 if (top->value.ov == NULL) {
1165 top->value.ov = ucl_hash_create ();
1166 }
1167
1168 if (keylen == 0) {

--- 9 unchanged lines hidden (view full) ---

1178
1179 elt->key = key;
1180 elt->keylen = keylen;
1181
1182 if (copy_key) {
1183 ucl_copy_key_trash (elt);
1184 }
1185
1081 found = ucl_hash_search_obj (top->value.ov, elt);
1186 found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt));
1082
1083 if (!found) {
1084 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1085 DL_APPEND (found, elt);
1187
1188 if (!found) {
1189 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1190 DL_APPEND (found, elt);
1191 top->len ++;
1192 if (replace) {
1193 ret = false;
1194 }
1086 }
1087 else {
1088 if (replace) {
1089 ucl_hash_delete (top->value.ov, found);
1090 ucl_object_unref (found);
1091 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1092 found = NULL;
1093 DL_APPEND (found, elt);
1094 }
1095 else if (merge) {
1096 if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
1097 /* Insert old elt to new one */
1195 }
1196 else {
1197 if (replace) {
1198 ucl_hash_delete (top->value.ov, found);
1199 ucl_object_unref (found);
1200 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1201 found = NULL;
1202 DL_APPEND (found, elt);
1203 }
1204 else if (merge) {
1205 if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
1206 /* Insert old elt to new one */
1098 elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false, false);
1207 ucl_object_insert_key_common (elt, found, found->key,
1208 found->keylen, copy_key, false, false);
1099 ucl_hash_delete (top->value.ov, found);
1100 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1101 }
1102 else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
1103 /* Insert new to old */
1209 ucl_hash_delete (top->value.ov, found);
1210 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1211 }
1212 else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
1213 /* Insert new to old */
1104 found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false, false);
1214 ucl_object_insert_key_common (found, elt, elt->key,
1215 elt->keylen, copy_key, false, false);
1105 }
1106 else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
1107 /* Mix two hashes */
1108 while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) {
1216 }
1217 else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
1218 /* Mix two hashes */
1219 while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) {
1109 ucl_object_ref (cur);
1110 found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false);
1220 tmp = ucl_object_ref (cur);
1221 ucl_object_insert_key_common (found, tmp, cur->key,
1222 cur->keylen, copy_key, false, false);
1111 }
1112 ucl_object_unref (elt);
1113 }
1114 else {
1115 /* Just make a list of scalars */
1116 DL_APPEND (found, elt);
1117 }
1118 }
1119 else {
1120 DL_APPEND (found, elt);
1121 }
1122 }
1123
1223 }
1224 ucl_object_unref (elt);
1225 }
1226 else {
1227 /* Just make a list of scalars */
1228 DL_APPEND (found, elt);
1229 }
1230 }
1231 else {
1232 DL_APPEND (found, elt);
1233 }
1234 }
1235
1124 return top;
1236 return ret;
1125}
1126
1127bool
1237}
1238
1239bool
1128ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
1240ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen)
1129{
1130 ucl_object_t *found;
1131
1241{
1242 ucl_object_t *found;
1243
1132 found = ucl_object_find_keyl(top, key, keylen);
1244 if (top == NULL || key == NULL) {
1245 return false;
1246 }
1133
1247
1134 if (found == NULL)
1248 found = __DECONST (ucl_object_t *, ucl_object_find_keyl (top, key, keylen));
1249
1250 if (found == NULL) {
1135 return false;
1251 return false;
1252 }
1136
1253
1137 ucl_hash_delete(top->value.ov, found);
1254 ucl_hash_delete (top->value.ov, found);
1138 ucl_object_unref (found);
1139 top->len --;
1140
1141 return true;
1142}
1143
1144bool
1255 ucl_object_unref (found);
1256 top->len --;
1257
1258 return true;
1259}
1260
1261bool
1145ucl_object_delete_key(ucl_object_t *top, const char *key)
1262ucl_object_delete_key (ucl_object_t *top, const char *key)
1146{
1263{
1147 return ucl_object_delete_keyl(top, key, 0);
1264 return ucl_object_delete_keyl (top, key, strlen(key));
1148}
1149
1265}
1266
1150ucl_object_t *
1267ucl_object_t*
1268ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
1269{
1270 const ucl_object_t *found;
1271
1272 if (top == NULL || key == NULL) {
1273 return false;
1274 }
1275 found = ucl_object_find_keyl (top, key, keylen);
1276
1277 if (found == NULL) {
1278 return NULL;
1279 }
1280 ucl_hash_delete (top->value.ov, found);
1281 top->len --;
1282
1283 return __DECONST (ucl_object_t *, found);
1284}
1285
1286ucl_object_t*
1287ucl_object_pop_key (ucl_object_t *top, const char *key)
1288{
1289 return ucl_object_pop_keyl (top, key, strlen(key));
1290}
1291
1292bool
1151ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
1152 const char *key, size_t keylen, bool copy_key)
1153{
1154 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
1155}
1156
1293ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
1294 const char *key, size_t keylen, bool copy_key)
1295{
1296 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
1297}
1298
1157ucl_object_t *
1299bool
1158ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
1159 const char *key, size_t keylen, bool copy_key)
1160{
1161 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
1162}
1163
1300ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
1301 const char *key, size_t keylen, bool copy_key)
1302{
1303 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
1304}
1305
1164ucl_object_t *
1306bool
1165ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
1166 const char *key, size_t keylen, bool copy_key)
1167{
1168 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
1169}
1170
1307ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
1308 const char *key, size_t keylen, bool copy_key)
1309{
1310 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
1311}
1312
1171ucl_object_t *
1172ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
1313const ucl_object_t *
1314ucl_object_find_keyl (const ucl_object_t *obj, const char *key, size_t klen)
1173{
1315{
1174 ucl_object_t *ret, srch;
1316 const ucl_object_t *ret;
1317 ucl_object_t srch;
1175
1176 if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1177 return NULL;
1178 }
1179
1180 srch.key = key;
1181 srch.keylen = klen;
1182 ret = ucl_hash_search_obj (obj->value.ov, &srch);
1183
1184 return ret;
1185}
1186
1318
1319 if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1320 return NULL;
1321 }
1322
1323 srch.key = key;
1324 srch.keylen = klen;
1325 ret = ucl_hash_search_obj (obj->value.ov, &srch);
1326
1327 return ret;
1328}
1329
1187ucl_object_t *
1188ucl_object_find_key (ucl_object_t *obj, const char *key)
1330const ucl_object_t *
1331ucl_object_find_key (const ucl_object_t *obj, const char *key)
1189{
1332{
1190 size_t klen;
1191 ucl_object_t *ret, srch;
1192
1193 if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1333 if (key == NULL)
1194 return NULL;
1334 return NULL;
1195 }
1196
1335
1197 klen = strlen (key);
1198 srch.key = key;
1199 srch.keylen = klen;
1200 ret = ucl_hash_search_obj (obj->value.ov, &srch);
1201
1202 return ret;
1336 return ucl_object_find_keyl (obj, key, strlen(key));
1203}
1204
1337}
1338
1205ucl_object_t*
1206ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
1339const ucl_object_t*
1340ucl_iterate_object (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
1207{
1341{
1208 ucl_object_t *elt;
1342 const ucl_object_t *elt;
1209
1343
1344 if (obj == NULL || iter == NULL) {
1345 return NULL;
1346 }
1347
1210 if (expand_values) {
1211 switch (obj->type) {
1212 case UCL_OBJECT:
1348 if (expand_values) {
1349 switch (obj->type) {
1350 case UCL_OBJECT:
1213 return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
1351 return (const ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
1214 break;
1215 case UCL_ARRAY:
1216 elt = *iter;
1217 if (elt == NULL) {
1218 elt = obj->value.av;
1219 if (elt == NULL) {
1220 return NULL;
1221 }

--- 14 unchanged lines hidden (view full) ---

1236 elt = obj;
1237 if (elt == NULL) {
1238 return NULL;
1239 }
1240 }
1241 else if (elt == obj) {
1242 return NULL;
1243 }
1352 break;
1353 case UCL_ARRAY:
1354 elt = *iter;
1355 if (elt == NULL) {
1356 elt = obj->value.av;
1357 if (elt == NULL) {
1358 return NULL;
1359 }

--- 14 unchanged lines hidden (view full) ---

1374 elt = obj;
1375 if (elt == NULL) {
1376 return NULL;
1377 }
1378 }
1379 else if (elt == obj) {
1380 return NULL;
1381 }
1244 *iter = elt->next ? elt->next : obj;
1382 *iter = __DECONST (void *, elt->next ? elt->next : obj);
1245 return elt;
1246
1247 /* Not reached */
1248 return NULL;
1249}
1383 return elt;
1384
1385 /* Not reached */
1386 return NULL;
1387}
1388
1389const ucl_object_t *
1390ucl_lookup_path (const ucl_object_t *top, const char *path_in) {
1391 const ucl_object_t *o = NULL, *found;
1392 const char *p, *c;
1393 char *err_str;
1394 unsigned index;
1395
1396 if (path_in == NULL || top == NULL) {
1397 return NULL;
1398 }
1399
1400 found = NULL;
1401 p = path_in;
1402
1403 /* Skip leading dots */
1404 while (*p == '.') {
1405 p ++;
1406 }
1407
1408 c = p;
1409 while (*p != '\0') {
1410 p ++;
1411 if (*p == '.' || *p == '\0') {
1412 if (p > c) {
1413 switch (top->type) {
1414 case UCL_ARRAY:
1415 /* Key should be an int */
1416 index = strtoul (c, &err_str, 10);
1417 if (err_str != NULL && (*err_str != '.' && *err_str != '\0')) {
1418 return NULL;
1419 }
1420 o = ucl_array_find_index (top, index);
1421 break;
1422 default:
1423 o = ucl_object_find_keyl (top, c, p - c);
1424 break;
1425 }
1426 if (o == NULL) {
1427 return NULL;
1428 }
1429 top = o;
1430 }
1431 if (*p != '\0') {
1432 c = p + 1;
1433 }
1434 }
1435 }
1436 found = o;
1437
1438 return found;
1439}
1440
1441
1442ucl_object_t *
1443ucl_object_new (void)
1444{
1445 ucl_object_t *new;
1446 new = malloc (sizeof (ucl_object_t));
1447 if (new != NULL) {
1448 memset (new, 0, sizeof (ucl_object_t));
1449 new->ref = 1;
1450 new->type = UCL_NULL;
1451 }
1452 return new;
1453}
1454
1455ucl_object_t *
1456ucl_object_typed_new (ucl_type_t type)
1457{
1458 ucl_object_t *new;
1459 new = malloc (sizeof (ucl_object_t));
1460 if (new != NULL) {
1461 memset (new, 0, sizeof (ucl_object_t));
1462 new->ref = 1;
1463 new->type = (type <= UCL_NULL ? type : UCL_NULL);
1464 }
1465 return new;
1466}
1467
1468ucl_type_t
1469ucl_object_type (const ucl_object_t *obj)
1470{
1471 return obj->type;
1472}
1473
1474ucl_object_t*
1475ucl_object_fromstring (const char *str)
1476{
1477 return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
1478}
1479
1480ucl_object_t *
1481ucl_object_fromlstring (const char *str, size_t len)
1482{
1483 return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
1484}
1485
1486ucl_object_t *
1487ucl_object_fromint (int64_t iv)
1488{
1489 ucl_object_t *obj;
1490
1491 obj = ucl_object_new ();
1492 if (obj != NULL) {
1493 obj->type = UCL_INT;
1494 obj->value.iv = iv;
1495 }
1496
1497 return obj;
1498}
1499
1500ucl_object_t *
1501ucl_object_fromdouble (double dv)
1502{
1503 ucl_object_t *obj;
1504
1505 obj = ucl_object_new ();
1506 if (obj != NULL) {
1507 obj->type = UCL_FLOAT;
1508 obj->value.dv = dv;
1509 }
1510
1511 return obj;
1512}
1513
1514ucl_object_t*
1515ucl_object_frombool (bool bv)
1516{
1517 ucl_object_t *obj;
1518
1519 obj = ucl_object_new ();
1520 if (obj != NULL) {
1521 obj->type = UCL_BOOLEAN;
1522 obj->value.iv = bv;
1523 }
1524
1525 return obj;
1526}
1527
1528bool
1529ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
1530{
1531 ucl_object_t *head;
1532
1533 if (elt == NULL || top == NULL) {
1534 return false;
1535 }
1536
1537 head = top->value.av;
1538 if (head == NULL) {
1539 top->value.av = elt;
1540 elt->prev = elt;
1541 }
1542 else {
1543 elt->prev = head->prev;
1544 head->prev->next = elt;
1545 head->prev = elt;
1546 }
1547 elt->next = NULL;
1548 top->len ++;
1549
1550 return true;
1551}
1552
1553bool
1554ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
1555{
1556 ucl_object_t *head;
1557
1558 if (elt == NULL || top == NULL) {
1559 return false;
1560 }
1561
1562
1563 head = top->value.av;
1564 if (head == NULL) {
1565 top->value.av = elt;
1566 elt->prev = elt;
1567 }
1568 else {
1569 elt->prev = head->prev;
1570 head->prev = elt;
1571 }
1572 elt->next = head;
1573 top->value.av = elt;
1574 top->len ++;
1575
1576 return true;
1577}
1578
1579ucl_object_t *
1580ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
1581{
1582 ucl_object_t *head;
1583
1584 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1585 return NULL;
1586 }
1587 head = top->value.av;
1588
1589 if (elt->prev == elt) {
1590 top->value.av = NULL;
1591 }
1592 else if (elt == head) {
1593 elt->next->prev = elt->prev;
1594 top->value.av = elt->next;
1595 }
1596 else {
1597 elt->prev->next = elt->next;
1598 if (elt->next) {
1599 elt->next->prev = elt->prev;
1600 }
1601 else {
1602 head->prev = elt->prev;
1603 }
1604 }
1605 elt->next = NULL;
1606 elt->prev = elt;
1607 top->len --;
1608
1609 return elt;
1610}
1611
1612const ucl_object_t *
1613ucl_array_head (const ucl_object_t *top)
1614{
1615 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1616 return NULL;
1617 }
1618 return top->value.av;
1619}
1620
1621const ucl_object_t *
1622ucl_array_tail (const ucl_object_t *top)
1623{
1624 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1625 return NULL;
1626 }
1627 return top->value.av->prev;
1628}
1629
1630ucl_object_t *
1631ucl_array_pop_last (ucl_object_t *top)
1632{
1633 return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_tail (top)));
1634}
1635
1636ucl_object_t *
1637ucl_array_pop_first (ucl_object_t *top)
1638{
1639 return ucl_array_delete (top, __DECONST(ucl_object_t *, ucl_array_head (top)));
1640}
1641
1642const ucl_object_t *
1643ucl_array_find_index (const ucl_object_t *top, unsigned int index)
1644{
1645 ucl_object_iter_t it = NULL;
1646 const ucl_object_t *ret;
1647
1648 if (top == NULL || top->type != UCL_ARRAY || top->len == 0 ||
1649 (index + 1) > top->len) {
1650 return NULL;
1651 }
1652
1653 while ((ret = ucl_iterate_object (top, &it, true)) != NULL) {
1654 if (index == 0) {
1655 return ret;
1656 }
1657 --index;
1658 }
1659
1660 return NULL;
1661}
1662
1663ucl_object_t *
1664ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
1665{
1666
1667 if (head == NULL) {
1668 elt->next = NULL;
1669 elt->prev = elt;
1670 head = elt;
1671 }
1672 else {
1673 elt->prev = head->prev;
1674 head->prev->next = elt;
1675 head->prev = elt;
1676 elt->next = NULL;
1677 }
1678
1679 return head;
1680}
1681
1682bool
1683ucl_object_todouble_safe (const ucl_object_t *obj, double *target)
1684{
1685 if (obj == NULL || target == NULL) {
1686 return false;
1687 }
1688 switch (obj->type) {
1689 case UCL_INT:
1690 *target = obj->value.iv; /* Probaly could cause overflow */
1691 break;
1692 case UCL_FLOAT:
1693 case UCL_TIME:
1694 *target = obj->value.dv;
1695 break;
1696 default:
1697 return false;
1698 }
1699
1700 return true;
1701}
1702
1703double
1704ucl_object_todouble (const ucl_object_t *obj)
1705{
1706 double result = 0.;
1707
1708 ucl_object_todouble_safe (obj, &result);
1709 return result;
1710}
1711
1712bool
1713ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target)
1714{
1715 if (obj == NULL || target == NULL) {
1716 return false;
1717 }
1718 switch (obj->type) {
1719 case UCL_INT:
1720 *target = obj->value.iv;
1721 break;
1722 case UCL_FLOAT:
1723 case UCL_TIME:
1724 *target = obj->value.dv; /* Loosing of decimal points */
1725 break;
1726 default:
1727 return false;
1728 }
1729
1730 return true;
1731}
1732
1733int64_t
1734ucl_object_toint (const ucl_object_t *obj)
1735{
1736 int64_t result = 0;
1737
1738 ucl_object_toint_safe (obj, &result);
1739 return result;
1740}
1741
1742bool
1743ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target)
1744{
1745 if (obj == NULL || target == NULL) {
1746 return false;
1747 }
1748 switch (obj->type) {
1749 case UCL_BOOLEAN:
1750 *target = (obj->value.iv == true);
1751 break;
1752 default:
1753 return false;
1754 }
1755
1756 return true;
1757}
1758
1759bool
1760ucl_object_toboolean (const ucl_object_t *obj)
1761{
1762 bool result = false;
1763
1764 ucl_object_toboolean_safe (obj, &result);
1765 return result;
1766}
1767
1768bool
1769ucl_object_tostring_safe (const ucl_object_t *obj, const char **target)
1770{
1771 if (obj == NULL || target == NULL) {
1772 return false;
1773 }
1774
1775 switch (obj->type) {
1776 case UCL_STRING:
1777 *target = ucl_copy_value_trash (obj);
1778 break;
1779 default:
1780 return false;
1781 }
1782
1783 return true;
1784}
1785
1786const char *
1787ucl_object_tostring (const ucl_object_t *obj)
1788{
1789 const char *result = NULL;
1790
1791 ucl_object_tostring_safe (obj, &result);
1792 return result;
1793}
1794
1795const char *
1796ucl_object_tostring_forced (const ucl_object_t *obj)
1797{
1798 return ucl_copy_value_trash (obj);
1799}
1800
1801bool
1802ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen)
1803{
1804 if (obj == NULL || target == NULL) {
1805 return false;
1806 }
1807 switch (obj->type) {
1808 case UCL_STRING:
1809 *target = obj->value.sv;
1810 if (tlen != NULL) {
1811 *tlen = obj->len;
1812 }
1813 break;
1814 default:
1815 return false;
1816 }
1817
1818 return true;
1819}
1820
1821const char *
1822ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen)
1823{
1824 const char *result = NULL;
1825
1826 ucl_object_tolstring_safe (obj, &result, tlen);
1827 return result;
1828}
1829
1830const char *
1831ucl_object_key (const ucl_object_t *obj)
1832{
1833 return ucl_copy_key_trash (obj);
1834}
1835
1836const char *
1837ucl_object_keyl (const ucl_object_t *obj, size_t *len)
1838{
1839 if (len == NULL || obj == NULL) {
1840 return NULL;
1841 }
1842 *len = obj->keylen;
1843 return obj->key;
1844}
1845
1846ucl_object_t *
1847ucl_object_ref (const ucl_object_t *obj)
1848{
1849 ucl_object_t *res = NULL;
1850
1851 if (obj != NULL) {
1852 res = __DECONST (ucl_object_t *, obj);
1853#ifdef HAVE_ATOMIC_BUILTINS
1854 (void)__sync_add_and_fetch (&res->ref, 1);
1855#else
1856 res->ref ++;
1857#endif
1858 }
1859 return res;
1860}
1861
1862void
1863ucl_object_unref (ucl_object_t *obj)
1864{
1865 if (obj != NULL) {
1866#ifdef HAVE_ATOMIC_BUILTINS
1867 unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
1868 if (rc == 0) {
1869#else
1870 if (--obj->ref == 0) {
1871#endif
1872 ucl_object_free_internal (obj, true, ucl_object_dtor_unref);
1873 }
1874 }
1875}
1876
1877int
1878ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2)
1879{
1880 const ucl_object_t *it1, *it2;
1881 ucl_object_iter_t iter = NULL;
1882 int ret = 0;
1883
1884 if (o1->type != o2->type) {
1885 return (o1->type) - (o2->type);
1886 }
1887
1888 switch (o1->type) {
1889 case UCL_STRING:
1890 if (o1->len == o2->len) {
1891 ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
1892 }
1893 else {
1894 ret = o1->len - o2->len;
1895 }
1896 break;
1897 case UCL_FLOAT:
1898 case UCL_INT:
1899 case UCL_TIME:
1900 ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
1901 break;
1902 case UCL_BOOLEAN:
1903 ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
1904 break;
1905 case UCL_ARRAY:
1906 if (o1->len == o2->len) {
1907 it1 = o1->value.av;
1908 it2 = o2->value.av;
1909 /* Compare all elements in both arrays */
1910 while (it1 != NULL && it2 != NULL) {
1911 ret = ucl_object_compare (it1, it2);
1912 if (ret != 0) {
1913 break;
1914 }
1915 it1 = it1->next;
1916 it2 = it2->next;
1917 }
1918 }
1919 else {
1920 ret = o1->len - o2->len;
1921 }
1922 break;
1923 case UCL_OBJECT:
1924 if (o1->len == o2->len) {
1925 while ((it1 = ucl_iterate_object (o1, &iter, true)) != NULL) {
1926 it2 = ucl_object_find_key (o2, ucl_object_key (it1));
1927 if (it2 == NULL) {
1928 ret = 1;
1929 break;
1930 }
1931 ret = ucl_object_compare (it1, it2);
1932 if (ret != 0) {
1933 break;
1934 }
1935 }
1936 }
1937 else {
1938 ret = o1->len - o2->len;
1939 }
1940 break;
1941 default:
1942 ret = 0;
1943 break;
1944 }
1945
1946 return ret;
1947}
1948
1949void
1950ucl_object_array_sort (ucl_object_t *ar,
1951 int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2))
1952{
1953 if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
1954 return;
1955 }
1956
1957 DL_SORT (ar->value.av, cmp);
1958}