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
29#include <libgen.h> /* For dirname */
30#endif
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
47#ifdef _WIN32
48#include <windows.h>
49
50#ifndef PROT_READ
51#define PROT_READ 1
52#endif
53#ifndef PROT_WRITE
54#define PROT_WRITE 2
55#endif
56#ifndef PROT_READWRITE
57#define PROT_READWRITE 3
58#endif
59#ifndef MAP_SHARED
60#define MAP_SHARED 1
61#endif
62#ifndef MAP_PRIVATE
63#define MAP_PRIVATE 2
64#endif
65#ifndef MAP_FAILED
66#define MAP_FAILED ((void *) -1)
67#endif
68
69static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
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
107static int ucl_munmap(void *map,size_t length)
108{
109 if (!UnmapViewOfFile(map)) {
110 return(-1);
111 }
112 return(0);
113}
114
115static char* ucl_realpath(const char *path, char *resolved_path) {
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
130#endif
131
132/**
133 * @file rcl_util.c
134 * Utilities for rcl parsing
135 */
136
137
--- 40 unchanged lines hidden (view full) ---
178}
179
180size_t
181ucl_unescape_json_string (char *str, size_t len)
182{
183 char *t = str, *h = str;
184 int i, uval;
185
186 if (len <= 1) {
187 return len;
188 }
189 /* t is target (tortoise), h is source (hare) */
190
191 while (len) {
192 if (*h == '\\') {
193 h ++;
194 switch (*h) {
195 case 'n':
196 *t++ = '\n';
--- 14 unchanged lines hidden (view full) ---
211 *t++ = '\\';
212 break;
213 case '"':
214 *t++ = '"';
215 break;
216 case 'u':
217 /* Unicode escape */
218 uval = 0;
219 if (len > 3) {
220 for (i = 0; i < 4; i++) {
221 uval <<= 4;
222 if (isdigit (h[i])) {
223 uval += h[i] - '0';
224 }
225 else if (h[i] >= 'a' && h[i] <= 'f') {
226 uval += h[i] - 'a' + 10;
227 }
228 else if (h[i] >= 'A' && h[i] <= 'F') {
229 uval += h[i] - 'A' + 10;
230 }
231 else {
232 break;
233 }
234 }
235 h += 3;
236 len -= 3;
237 /* Encode */
238 if(uval < 0x80) {
239 t[0] = (char)uval;
240 t ++;
241 }
242 else if(uval < 0x800) {
243 t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
244 t[1] = 0x80 + ((uval & 0x03F));
245 t += 2;
246 }
247 else if(uval < 0x10000) {
248 t[0] = 0xE0 + ((uval & 0xF000) >> 12);
249 t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
250 t[2] = 0x80 + ((uval & 0x003F));
251 t += 3;
252 }
253 else if(uval <= 0x10FFFF) {
254 t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
255 t[1] = 0x80 + ((uval & 0x03F000) >> 12);
256 t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
257 t[3] = 0x80 + ((uval & 0x00003F));
258 t += 4;
259 }
260 else {
261 *t++ = '?';
262 }
263 }
264 else {
265 *t++ = 'u';
266 }
267 break;
268 default:
269 *t++ = *h;
270 break;
271 }
272 h ++;
273 len --;
--- 6 unchanged lines hidden (view full) ---
280 *t = '\0';
281
282 return (t - str);
283}
284
285UCL_EXTERN char *
286ucl_copy_key_trash (ucl_object_t *obj)
287{
288 if (obj == NULL) {
289 return NULL;
290 }
291 if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
292 obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
293 if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
294 memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
295 obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
296 }
297 obj->key = obj->trash_stack[UCL_TRASH_KEY];
298 obj->flags |= UCL_OBJECT_ALLOCATED_KEY;
299 }
300
301 return obj->trash_stack[UCL_TRASH_KEY];
302}
303
304UCL_EXTERN char *
305ucl_copy_value_trash (ucl_object_t *obj)
306{
307 if (obj == NULL) {
308 return NULL;
309 }
310 if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
311 if (obj->type == UCL_STRING) {
312 /* Special case for strings */
313 obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
314 if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
315 memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
316 obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
317 obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
--- 23 unchanged lines hidden (view full) ---
341ucl_parser_free (struct ucl_parser *parser)
342{
343 struct ucl_stack *stack, *stmp;
344 struct ucl_macro *macro, *mtmp;
345 struct ucl_chunk *chunk, *ctmp;
346 struct ucl_pubkey *key, *ktmp;
347 struct ucl_variable *var, *vtmp;
348
349 if (parser == NULL) {
350 return;
351 }
352
353 if (parser->top_obj != NULL) {
354 ucl_object_unref (parser->top_obj);
355 }
356
357 LL_FOREACH_SAFE (parser->stack, stack, stmp) {
358 free (stack);
359 }
360 HASH_ITER (hh, parser->macroes, macro, mtmp) {
--- 18 unchanged lines hidden (view full) ---
379 }
380
381 UCL_FREE (sizeof (struct ucl_parser), parser);
382}
383
384UCL_EXTERN const char *
385ucl_parser_get_error(struct ucl_parser *parser)
386{
387 if (parser == NULL) {
388 return NULL;
389 }
390
391 if (parser->err == NULL)
392 return NULL;
393
394 return utstring_body(parser->err);
395}
396
397UCL_EXTERN bool
398ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
--- 6 unchanged lines hidden (view full) ---
405 ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
406 return EXIT_FAILURE;
407# else
408 struct ucl_pubkey *nkey;
409 BIO *mem;
410
411 mem = BIO_new_mem_buf ((void *)key, len);
412 nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
413 if (nkey == NULL) {
414 ucl_create_err (&parser->err, "cannot allocate memory for key");
415 return false;
416 }
417 nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
418 BIO_free (mem);
419 if (nkey->key == NULL) {
420 UCL_FREE (sizeof (struct ucl_pubkey), nkey);
421 ucl_create_err (&parser->err, "%s",
422 ERR_error_string (ERR_get_error (), NULL));
423 return false;
424 }
--- 151 unchanged lines hidden (view full) ---
576 *buflen = 0;
577 }
578 else {
579 if ((fd = open (filename, O_RDONLY)) == -1) {
580 ucl_create_err (err, "cannot open file %s: %s",
581 filename, strerror (errno));
582 return false;
583 }
584 if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
585 close (fd);
586 ucl_create_err (err, "cannot mmap file %s: %s",
587 filename, strerror (errno));
588 return false;
589 }
590 *buflen = st.st_size;
591 close (fd);
592 }
--- 85 unchanged lines hidden (view full) ---
678 if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
679 return false;
680 }
681 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
682 ucl_create_err (&parser->err, "cannot verify url %s: %s",
683 urlbuf,
684 ERR_error_string (ERR_get_error (), NULL));
685 if (siglen > 0) {
686 ucl_munmap (sigbuf, siglen);
687 }
688 return false;
689 }
690 if (siglen > 0) {
691 ucl_munmap (sigbuf, siglen);
692 }
693#endif
694 }
695
696 prev_state = parser->state;
697 parser->state = UCL_STATE_INIT;
698
699 res = ucl_parser_add_chunk (parser, buf, buflen);
--- 27 unchanged lines hidden (view full) ---
727 bool res;
728 struct ucl_chunk *chunk;
729 unsigned char *buf = NULL;
730 size_t buflen;
731 char filebuf[PATH_MAX], realbuf[PATH_MAX];
732 int prev_state;
733
734 snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
735 if (ucl_realpath (filebuf, realbuf) == NULL) {
736 if (!must_exist) {
737 return true;
738 }
739 ucl_create_err (&parser->err, "cannot open file %s: %s",
740 filebuf,
741 strerror (errno));
742 return false;
743 }
--- 11 unchanged lines hidden (view full) ---
755 if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
756 return false;
757 }
758 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
759 ucl_create_err (&parser->err, "cannot verify file %s: %s",
760 filebuf,
761 ERR_error_string (ERR_get_error (), NULL));
762 if (siglen > 0) {
763 ucl_munmap (sigbuf, siglen);
764 }
765 return false;
766 }
767 if (siglen > 0) {
768 ucl_munmap (sigbuf, siglen);
769 }
770#endif
771 }
772
773 ucl_parser_set_filevars (parser, realbuf, false);
774
775 prev_state = parser->state;
776 parser->state = UCL_STATE_INIT;
--- 6 unchanged lines hidden (view full) ---
783 parser->chunks = chunk->next;
784 UCL_FREE (sizeof (struct ucl_chunk), chunk);
785 }
786 }
787
788 parser->state = prev_state;
789
790 if (buflen > 0) {
791 ucl_munmap (buf, buflen);
792 }
793
794 return res;
795}
796
797/**
798 * Handle include macro
799 * @param data include data
--- 52 unchanged lines hidden (view full) ---
852
853UCL_EXTERN bool
854ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
855{
856 char realbuf[PATH_MAX], *curdir;
857
858 if (filename != NULL) {
859 if (need_expand) {
860 if (ucl_realpath (filename, realbuf) == NULL) {
861 return false;
862 }
863 }
864 else {
865 ucl_strlcpy (realbuf, filename, sizeof (realbuf));
866 }
867
868 /* Define variables */
--- 14 unchanged lines hidden (view full) ---
883UCL_EXTERN bool
884ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
885{
886 unsigned char *buf;
887 size_t len;
888 bool ret;
889 char realbuf[PATH_MAX];
890
891 if (ucl_realpath (filename, realbuf) == NULL) {
892 ucl_create_err (&parser->err, "cannot open file %s: %s",
893 filename,
894 strerror (errno));
895 return false;
896 }
897
898 if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
899 return false;
900 }
901
902 ucl_parser_set_filevars (parser, realbuf, false);
903 ret = ucl_parser_add_chunk (parser, buf, len);
904
905 if (len > 0) {
906 ucl_munmap (buf, len);
907 }
908
909 return ret;
910}
911
912size_t
913ucl_strlcpy (char *dst, const char *src, size_t siz)
914{
--- 148 unchanged lines hidden (view full) ---
1063 }
1064 }
1065 if ((flags & UCL_STRING_PARSE) && dst != NULL) {
1066 /* Parse what we have */
1067 if (flags & UCL_STRING_PARSE_BOOLEAN) {
1068 if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
1069 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1070 flags & UCL_STRING_PARSE_DOUBLE,
1071 flags & UCL_STRING_PARSE_BYTES,
1072 flags & UCL_STRING_PARSE_TIME);
1073 }
1074 }
1075 else {
1076 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1077 flags & UCL_STRING_PARSE_DOUBLE,
1078 flags & UCL_STRING_PARSE_BYTES,
1079 flags & UCL_STRING_PARSE_TIME);
1080 }
1081 }
1082 }
1083
1084 return obj;
1085}
1086
1087static ucl_object_t *
--- 46 unchanged lines hidden (view full) ---
1134 ucl_copy_key_trash (elt);
1135 }
1136
1137 found = ucl_hash_search_obj (top->value.ov, elt);
1138
1139 if (!found) {
1140 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1141 DL_APPEND (found, elt);
1142 top->len ++;
1143 }
1144 else {
1145 if (replace) {
1146 ucl_hash_delete (top->value.ov, found);
1147 ucl_object_unref (found);
1148 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1149 found = NULL;
1150 DL_APPEND (found, elt);
--- 30 unchanged lines hidden (view full) ---
1181 return top;
1182}
1183
1184bool
1185ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
1186{
1187 ucl_object_t *found;
1188
1189 if (top == NULL || key == NULL) {
1190 return false;
1191 }
1192
1193 found = ucl_object_find_keyl(top, key, keylen);
1194
1195 if (found == NULL) {
1196 return false;
1197 }
1198
1199 ucl_hash_delete(top->value.ov, found);
1200 ucl_object_unref (found);
1201 top->len --;
1202
1203 return true;
1204}
1205
1206bool
1207ucl_object_delete_key(ucl_object_t *top, const char *key)
1208{
1209 return ucl_object_delete_keyl(top, key, 0);
1210}
1211
1212ucl_object_t*
1213ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
1214{
1215 ucl_object_t *found;
1216
1217 if (top == NULL || key == NULL) {
1218 return false;
1219 }
1220 found = ucl_object_find_keyl(top, key, keylen);
1221
1222 if (found == NULL) {
1223 return NULL;
1224 }
1225 ucl_hash_delete(top->value.ov, found);
1226 top->len --;
1227
1228 return found;
1229}
1230
1231ucl_object_t*
1232ucl_object_pop_key (ucl_object_t *top, const char *key)
1233{
1234 return ucl_object_pop_keyl (top, key, 0);
1235}
1236
1237ucl_object_t *
1238ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
1239 const char *key, size_t keylen, bool copy_key)
1240{
1241 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
1242}
1243
1244ucl_object_t *
--- 44 unchanged lines hidden (view full) ---
1289 return ret;
1290}
1291
1292ucl_object_t*
1293ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
1294{
1295 ucl_object_t *elt;
1296
1297 if (obj == NULL || iter == NULL) {
1298 return NULL;
1299 }
1300
1301 if (expand_values) {
1302 switch (obj->type) {
1303 case UCL_OBJECT:
1304 return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
1305 break;
1306 case UCL_ARRAY:
1307 elt = *iter;
1308 if (elt == NULL) {
--- 24 unchanged lines hidden (view full) ---
1333 return NULL;
1334 }
1335 *iter = elt->next ? elt->next : obj;
1336 return elt;
1337
1338 /* Not reached */
1339 return NULL;
1340}
1341
1342
1343ucl_object_t *
1344ucl_object_new (void)
1345{
1346 ucl_object_t *new;
1347 new = malloc (sizeof (ucl_object_t));
1348 if (new != NULL) {
1349 memset (new, 0, sizeof (ucl_object_t));
1350 new->ref = 1;
1351 new->type = UCL_NULL;
1352 }
1353 return new;
1354}
1355
1356ucl_object_t *
1357ucl_object_typed_new (unsigned int type)
1358{
1359 ucl_object_t *new;
1360 new = malloc (sizeof (ucl_object_t));
1361 if (new != NULL) {
1362 memset (new, 0, sizeof (ucl_object_t));
1363 new->ref = 1;
1364 new->type = (type <= UCL_NULL ? type : UCL_NULL);
1365 }
1366 return new;
1367}
1368
1369ucl_object_t*
1370ucl_object_fromstring (const char *str)
1371{
1372 return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
1373}
1374
1375ucl_object_t *
1376ucl_object_fromlstring (const char *str, size_t len)
1377{
1378 return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
1379}
1380
1381ucl_object_t *
1382ucl_object_fromint (int64_t iv)
1383{
1384 ucl_object_t *obj;
1385
1386 obj = ucl_object_new ();
1387 if (obj != NULL) {
1388 obj->type = UCL_INT;
1389 obj->value.iv = iv;
1390 }
1391
1392 return obj;
1393}
1394
1395ucl_object_t *
1396ucl_object_fromdouble (double dv)
1397{
1398 ucl_object_t *obj;
1399
1400 obj = ucl_object_new ();
1401 if (obj != NULL) {
1402 obj->type = UCL_FLOAT;
1403 obj->value.dv = dv;
1404 }
1405
1406 return obj;
1407}
1408
1409ucl_object_t*
1410ucl_object_frombool (bool bv)
1411{
1412 ucl_object_t *obj;
1413
1414 obj = ucl_object_new ();
1415 if (obj != NULL) {
1416 obj->type = UCL_BOOLEAN;
1417 obj->value.iv = bv;
1418 }
1419
1420 return obj;
1421}
1422
1423ucl_object_t *
1424ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
1425{
1426 ucl_object_t *head;
1427
1428 if (elt == NULL) {
1429 return NULL;
1430 }
1431
1432 if (top == NULL) {
1433 top = ucl_object_typed_new (UCL_ARRAY);
1434 top->value.av = elt;
1435 elt->next = NULL;
1436 elt->prev = elt;
1437 top->len = 1;
1438 }
1439 else {
1440 head = top->value.av;
1441 if (head == NULL) {
1442 top->value.av = elt;
1443 elt->prev = elt;
1444 }
1445 else {
1446 elt->prev = head->prev;
1447 head->prev->next = elt;
1448 head->prev = elt;
1449 }
1450 elt->next = NULL;
1451 top->len ++;
1452 }
1453
1454 return top;
1455}
1456
1457ucl_object_t *
1458ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
1459{
1460 ucl_object_t *head;
1461
1462 if (elt == NULL) {
1463 return NULL;
1464 }
1465
1466 if (top == NULL) {
1467 top = ucl_object_typed_new (UCL_ARRAY);
1468 top->value.av = elt;
1469 elt->next = NULL;
1470 elt->prev = elt;
1471 top->len = 1;
1472 }
1473 else {
1474 head = top->value.av;
1475 if (head == NULL) {
1476 top->value.av = elt;
1477 elt->prev = elt;
1478 }
1479 else {
1480 elt->prev = head->prev;
1481 head->prev = elt;
1482 }
1483 elt->next = head;
1484 top->value.av = elt;
1485 top->len ++;
1486 }
1487
1488 return top;
1489}
1490
1491ucl_object_t *
1492ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
1493{
1494 ucl_object_t *head;
1495
1496 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1497 return NULL;
1498 }
1499 head = top->value.av;
1500
1501 if (elt->prev == elt) {
1502 top->value.av = NULL;
1503 }
1504 else if (elt == head) {
1505 elt->next->prev = elt->prev;
1506 top->value.av = elt->next;
1507 }
1508 else {
1509 elt->prev->next = elt->next;
1510 if (elt->next) {
1511 elt->next->prev = elt->prev;
1512 }
1513 else {
1514 head->prev = elt->prev;
1515 }
1516 }
1517 elt->next = NULL;
1518 elt->prev = elt;
1519 top->len --;
1520
1521 return elt;
1522}
1523
1524ucl_object_t *
1525ucl_array_head (ucl_object_t *top)
1526{
1527 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1528 return NULL;
1529 }
1530 return top->value.av;
1531}
1532
1533ucl_object_t *
1534ucl_array_tail (ucl_object_t *top)
1535{
1536 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1537 return NULL;
1538 }
1539 return top->value.av->prev;
1540}
1541
1542ucl_object_t *
1543ucl_array_pop_last (ucl_object_t *top)
1544{
1545 return ucl_array_delete (top, ucl_array_tail (top));
1546}
1547
1548ucl_object_t *
1549ucl_array_pop_first (ucl_object_t *top)
1550{
1551 return ucl_array_delete (top, ucl_array_head (top));
1552}
1553
1554ucl_object_t *
1555ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
1556{
1557
1558 if (head == NULL) {
1559 elt->next = NULL;
1560 elt->prev = elt;
1561 head = elt;
1562 }
1563 else {
1564 elt->prev = head->prev;
1565 head->prev->next = elt;
1566 head->prev = elt;
1567 elt->next = NULL;
1568 }
1569
1570 return head;
1571}
1572
1573bool
1574ucl_object_todouble_safe (ucl_object_t *obj, double *target)
1575{
1576 if (obj == NULL || target == NULL) {
1577 return false;
1578 }
1579 switch (obj->type) {
1580 case UCL_INT:
1581 *target = obj->value.iv; /* Probaly could cause overflow */
1582 break;
1583 case UCL_FLOAT:
1584 case UCL_TIME:
1585 *target = obj->value.dv;
1586 break;
1587 default:
1588 return false;
1589 }
1590
1591 return true;
1592}
1593
1594double
1595ucl_object_todouble (ucl_object_t *obj)
1596{
1597 double result = 0.;
1598
1599 ucl_object_todouble_safe (obj, &result);
1600 return result;
1601}
1602
1603bool
1604ucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
1605{
1606 if (obj == NULL || target == NULL) {
1607 return false;
1608 }
1609 switch (obj->type) {
1610 case UCL_INT:
1611 *target = obj->value.iv;
1612 break;
1613 case UCL_FLOAT:
1614 case UCL_TIME:
1615 *target = obj->value.dv; /* Loosing of decimal points */
1616 break;
1617 default:
1618 return false;
1619 }
1620
1621 return true;
1622}
1623
1624int64_t
1625ucl_object_toint (ucl_object_t *obj)
1626{
1627 int64_t result = 0;
1628
1629 ucl_object_toint_safe (obj, &result);
1630 return result;
1631}
1632
1633bool
1634ucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
1635{
1636 if (obj == NULL || target == NULL) {
1637 return false;
1638 }
1639 switch (obj->type) {
1640 case UCL_BOOLEAN:
1641 *target = (obj->value.iv == true);
1642 break;
1643 default:
1644 return false;
1645 }
1646
1647 return true;
1648}
1649
1650bool
1651ucl_object_toboolean (ucl_object_t *obj)
1652{
1653 bool result = false;
1654
1655 ucl_object_toboolean_safe (obj, &result);
1656 return result;
1657}
1658
1659bool
1660ucl_object_tostring_safe (ucl_object_t *obj, const char **target)
1661{
1662 if (obj == NULL || target == NULL) {
1663 return false;
1664 }
1665
1666 switch (obj->type) {
1667 case UCL_STRING:
1668 *target = ucl_copy_value_trash (obj);
1669 break;
1670 default:
1671 return false;
1672 }
1673
1674 return true;
1675}
1676
1677const char *
1678ucl_object_tostring (ucl_object_t *obj)
1679{
1680 const char *result = NULL;
1681
1682 ucl_object_tostring_safe (obj, &result);
1683 return result;
1684}
1685
1686const char *
1687ucl_object_tostring_forced (ucl_object_t *obj)
1688{
1689 return ucl_copy_value_trash (obj);
1690}
1691
1692bool
1693ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
1694{
1695 if (obj == NULL || target == NULL) {
1696 return false;
1697 }
1698 switch (obj->type) {
1699 case UCL_STRING:
1700 *target = obj->value.sv;
1701 if (tlen != NULL) {
1702 *tlen = obj->len;
1703 }
1704 break;
1705 default:
1706 return false;
1707 }
1708
1709 return true;
1710}
1711
1712const char *
1713ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
1714{
1715 const char *result = NULL;
1716
1717 ucl_object_tolstring_safe (obj, &result, tlen);
1718 return result;
1719}
1720
1721const char *
1722ucl_object_key (ucl_object_t *obj)
1723{
1724 return ucl_copy_key_trash (obj);
1725}
1726
1727const char *
1728ucl_object_keyl (ucl_object_t *obj, size_t *len)
1729{
1730 if (len == NULL || obj == NULL) {
1731 return NULL;
1732 }
1733 *len = obj->keylen;
1734 return obj->key;
1735}
1736
1737ucl_object_t *
1738ucl_object_ref (ucl_object_t *obj)
1739{
1740 if (obj != NULL) {
1741 obj->ref ++;
1742 }
1743 return obj;
1744}
1745
1746void
1747ucl_object_unref (ucl_object_t *obj)
1748{
1749 if (obj != NULL && --obj->ref <= 0) {
1750 ucl_object_free (obj);
1751 }
1752}
1753
1754int
1755ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2)
1756{
1757 ucl_object_t *it1, *it2;
1758 ucl_object_iter_t iter = NULL;
1759 int ret = 0;
1760
1761 if (o1->type != o2->type) {
1762 return (o1->type) - (o2->type);
1763 }
1764
1765 switch (o1->type) {
1766 case UCL_STRING:
1767 if (o1->len == o2->len) {
1768 ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
1769 }
1770 else {
1771 ret = o1->len - o2->len;
1772 }
1773 break;
1774 case UCL_FLOAT:
1775 case UCL_INT:
1776 case UCL_TIME:
1777 ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
1778 break;
1779 case UCL_BOOLEAN:
1780 ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
1781 break;
1782 case UCL_ARRAY:
1783 if (o1->len == o2->len) {
1784 it1 = o1->value.av;
1785 it2 = o2->value.av;
1786 /* Compare all elements in both arrays */
1787 while (it1 != NULL && it2 != NULL) {
1788 ret = ucl_object_compare (it1, it2);
1789 if (ret != 0) {
1790 break;
1791 }
1792 it1 = it1->next;
1793 it2 = it2->next;
1794 }
1795 }
1796 else {
1797 ret = o1->len - o2->len;
1798 }
1799 break;
1800 case UCL_OBJECT:
1801 if (o1->len == o2->len) {
1802 while ((it1 = ucl_iterate_object (o1, &iter, true)) != NULL) {
1803 it2 = ucl_object_find_key (o2, ucl_object_key (it1));
1804 if (it2 == NULL) {
1805 ret = 1;
1806 break;
1807 }
1808 ret = ucl_object_compare (it1, it2);
1809 if (ret != 0) {
1810 break;
1811 }
1812 }
1813 }
1814 else {
1815 ret = o1->len - o2->len;
1816 }
1817 break;
1818 default:
1819 ret = 0;
1820 break;
1821 }
1822
1823 return ret;
1824}
1825
1826void
1827ucl_object_array_sort (ucl_object_t *ar,
1828 int (*cmp)(ucl_object_t *o1, ucl_object_t *o2))
1829{
1830 if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
1831 return;
1832 }
1833
1834 DL_SORT (ar->value.av, cmp);
1835}
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
29#include <libgen.h> /* For dirname */
30#endif
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
47#ifdef _WIN32
48#include <windows.h>
49
50#ifndef PROT_READ
51#define PROT_READ 1
52#endif
53#ifndef PROT_WRITE
54#define PROT_WRITE 2
55#endif
56#ifndef PROT_READWRITE
57#define PROT_READWRITE 3
58#endif
59#ifndef MAP_SHARED
60#define MAP_SHARED 1
61#endif
62#ifndef MAP_PRIVATE
63#define MAP_PRIVATE 2
64#endif
65#ifndef MAP_FAILED
66#define MAP_FAILED ((void *) -1)
67#endif
68
69static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
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
107static int ucl_munmap(void *map,size_t length)
108{
109 if (!UnmapViewOfFile(map)) {
110 return(-1);
111 }
112 return(0);
113}
114
115static char* ucl_realpath(const char *path, char *resolved_path) {
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
130#endif
131
132/**
133 * @file rcl_util.c
134 * Utilities for rcl parsing
135 */
136
137
--- 40 unchanged lines hidden (view full) ---
178}
179
180size_t
181ucl_unescape_json_string (char *str, size_t len)
182{
183 char *t = str, *h = str;
184 int i, uval;
185
186 if (len <= 1) {
187 return len;
188 }
189 /* t is target (tortoise), h is source (hare) */
190
191 while (len) {
192 if (*h == '\\') {
193 h ++;
194 switch (*h) {
195 case 'n':
196 *t++ = '\n';
--- 14 unchanged lines hidden (view full) ---
211 *t++ = '\\';
212 break;
213 case '"':
214 *t++ = '"';
215 break;
216 case 'u':
217 /* Unicode escape */
218 uval = 0;
219 if (len > 3) {
220 for (i = 0; i < 4; i++) {
221 uval <<= 4;
222 if (isdigit (h[i])) {
223 uval += h[i] - '0';
224 }
225 else if (h[i] >= 'a' && h[i] <= 'f') {
226 uval += h[i] - 'a' + 10;
227 }
228 else if (h[i] >= 'A' && h[i] <= 'F') {
229 uval += h[i] - 'A' + 10;
230 }
231 else {
232 break;
233 }
234 }
235 h += 3;
236 len -= 3;
237 /* Encode */
238 if(uval < 0x80) {
239 t[0] = (char)uval;
240 t ++;
241 }
242 else if(uval < 0x800) {
243 t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
244 t[1] = 0x80 + ((uval & 0x03F));
245 t += 2;
246 }
247 else if(uval < 0x10000) {
248 t[0] = 0xE0 + ((uval & 0xF000) >> 12);
249 t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
250 t[2] = 0x80 + ((uval & 0x003F));
251 t += 3;
252 }
253 else if(uval <= 0x10FFFF) {
254 t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
255 t[1] = 0x80 + ((uval & 0x03F000) >> 12);
256 t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
257 t[3] = 0x80 + ((uval & 0x00003F));
258 t += 4;
259 }
260 else {
261 *t++ = '?';
262 }
263 }
264 else {
265 *t++ = 'u';
266 }
267 break;
268 default:
269 *t++ = *h;
270 break;
271 }
272 h ++;
273 len --;
--- 6 unchanged lines hidden (view full) ---
280 *t = '\0';
281
282 return (t - str);
283}
284
285UCL_EXTERN char *
286ucl_copy_key_trash (ucl_object_t *obj)
287{
288 if (obj == NULL) {
289 return NULL;
290 }
291 if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
292 obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
293 if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
294 memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
295 obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
296 }
297 obj->key = obj->trash_stack[UCL_TRASH_KEY];
298 obj->flags |= UCL_OBJECT_ALLOCATED_KEY;
299 }
300
301 return obj->trash_stack[UCL_TRASH_KEY];
302}
303
304UCL_EXTERN char *
305ucl_copy_value_trash (ucl_object_t *obj)
306{
307 if (obj == NULL) {
308 return NULL;
309 }
310 if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
311 if (obj->type == UCL_STRING) {
312 /* Special case for strings */
313 obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
314 if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
315 memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
316 obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
317 obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
--- 23 unchanged lines hidden (view full) ---
341ucl_parser_free (struct ucl_parser *parser)
342{
343 struct ucl_stack *stack, *stmp;
344 struct ucl_macro *macro, *mtmp;
345 struct ucl_chunk *chunk, *ctmp;
346 struct ucl_pubkey *key, *ktmp;
347 struct ucl_variable *var, *vtmp;
348
349 if (parser == NULL) {
350 return;
351 }
352
353 if (parser->top_obj != NULL) {
354 ucl_object_unref (parser->top_obj);
355 }
356
357 LL_FOREACH_SAFE (parser->stack, stack, stmp) {
358 free (stack);
359 }
360 HASH_ITER (hh, parser->macroes, macro, mtmp) {
--- 18 unchanged lines hidden (view full) ---
379 }
380
381 UCL_FREE (sizeof (struct ucl_parser), parser);
382}
383
384UCL_EXTERN const char *
385ucl_parser_get_error(struct ucl_parser *parser)
386{
387 if (parser == NULL) {
388 return NULL;
389 }
390
391 if (parser->err == NULL)
392 return NULL;
393
394 return utstring_body(parser->err);
395}
396
397UCL_EXTERN bool
398ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
--- 6 unchanged lines hidden (view full) ---
405 ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
406 return EXIT_FAILURE;
407# else
408 struct ucl_pubkey *nkey;
409 BIO *mem;
410
411 mem = BIO_new_mem_buf ((void *)key, len);
412 nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
413 if (nkey == NULL) {
414 ucl_create_err (&parser->err, "cannot allocate memory for key");
415 return false;
416 }
417 nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
418 BIO_free (mem);
419 if (nkey->key == NULL) {
420 UCL_FREE (sizeof (struct ucl_pubkey), nkey);
421 ucl_create_err (&parser->err, "%s",
422 ERR_error_string (ERR_get_error (), NULL));
423 return false;
424 }
--- 151 unchanged lines hidden (view full) ---
576 *buflen = 0;
577 }
578 else {
579 if ((fd = open (filename, O_RDONLY)) == -1) {
580 ucl_create_err (err, "cannot open file %s: %s",
581 filename, strerror (errno));
582 return false;
583 }
584 if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
585 close (fd);
586 ucl_create_err (err, "cannot mmap file %s: %s",
587 filename, strerror (errno));
588 return false;
589 }
590 *buflen = st.st_size;
591 close (fd);
592 }
--- 85 unchanged lines hidden (view full) ---
678 if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
679 return false;
680 }
681 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
682 ucl_create_err (&parser->err, "cannot verify url %s: %s",
683 urlbuf,
684 ERR_error_string (ERR_get_error (), NULL));
685 if (siglen > 0) {
686 ucl_munmap (sigbuf, siglen);
687 }
688 return false;
689 }
690 if (siglen > 0) {
691 ucl_munmap (sigbuf, siglen);
692 }
693#endif
694 }
695
696 prev_state = parser->state;
697 parser->state = UCL_STATE_INIT;
698
699 res = ucl_parser_add_chunk (parser, buf, buflen);
--- 27 unchanged lines hidden (view full) ---
727 bool res;
728 struct ucl_chunk *chunk;
729 unsigned char *buf = NULL;
730 size_t buflen;
731 char filebuf[PATH_MAX], realbuf[PATH_MAX];
732 int prev_state;
733
734 snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
735 if (ucl_realpath (filebuf, realbuf) == NULL) {
736 if (!must_exist) {
737 return true;
738 }
739 ucl_create_err (&parser->err, "cannot open file %s: %s",
740 filebuf,
741 strerror (errno));
742 return false;
743 }
--- 11 unchanged lines hidden (view full) ---
755 if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
756 return false;
757 }
758 if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
759 ucl_create_err (&parser->err, "cannot verify file %s: %s",
760 filebuf,
761 ERR_error_string (ERR_get_error (), NULL));
762 if (siglen > 0) {
763 ucl_munmap (sigbuf, siglen);
764 }
765 return false;
766 }
767 if (siglen > 0) {
768 ucl_munmap (sigbuf, siglen);
769 }
770#endif
771 }
772
773 ucl_parser_set_filevars (parser, realbuf, false);
774
775 prev_state = parser->state;
776 parser->state = UCL_STATE_INIT;
--- 6 unchanged lines hidden (view full) ---
783 parser->chunks = chunk->next;
784 UCL_FREE (sizeof (struct ucl_chunk), chunk);
785 }
786 }
787
788 parser->state = prev_state;
789
790 if (buflen > 0) {
791 ucl_munmap (buf, buflen);
792 }
793
794 return res;
795}
796
797/**
798 * Handle include macro
799 * @param data include data
--- 52 unchanged lines hidden (view full) ---
852
853UCL_EXTERN bool
854ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
855{
856 char realbuf[PATH_MAX], *curdir;
857
858 if (filename != NULL) {
859 if (need_expand) {
860 if (ucl_realpath (filename, realbuf) == NULL) {
861 return false;
862 }
863 }
864 else {
865 ucl_strlcpy (realbuf, filename, sizeof (realbuf));
866 }
867
868 /* Define variables */
--- 14 unchanged lines hidden (view full) ---
883UCL_EXTERN bool
884ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
885{
886 unsigned char *buf;
887 size_t len;
888 bool ret;
889 char realbuf[PATH_MAX];
890
891 if (ucl_realpath (filename, realbuf) == NULL) {
892 ucl_create_err (&parser->err, "cannot open file %s: %s",
893 filename,
894 strerror (errno));
895 return false;
896 }
897
898 if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
899 return false;
900 }
901
902 ucl_parser_set_filevars (parser, realbuf, false);
903 ret = ucl_parser_add_chunk (parser, buf, len);
904
905 if (len > 0) {
906 ucl_munmap (buf, len);
907 }
908
909 return ret;
910}
911
912size_t
913ucl_strlcpy (char *dst, const char *src, size_t siz)
914{
--- 148 unchanged lines hidden (view full) ---
1063 }
1064 }
1065 if ((flags & UCL_STRING_PARSE) && dst != NULL) {
1066 /* Parse what we have */
1067 if (flags & UCL_STRING_PARSE_BOOLEAN) {
1068 if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
1069 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1070 flags & UCL_STRING_PARSE_DOUBLE,
1071 flags & UCL_STRING_PARSE_BYTES,
1072 flags & UCL_STRING_PARSE_TIME);
1073 }
1074 }
1075 else {
1076 ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1077 flags & UCL_STRING_PARSE_DOUBLE,
1078 flags & UCL_STRING_PARSE_BYTES,
1079 flags & UCL_STRING_PARSE_TIME);
1080 }
1081 }
1082 }
1083
1084 return obj;
1085}
1086
1087static ucl_object_t *
--- 46 unchanged lines hidden (view full) ---
1134 ucl_copy_key_trash (elt);
1135 }
1136
1137 found = ucl_hash_search_obj (top->value.ov, elt);
1138
1139 if (!found) {
1140 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1141 DL_APPEND (found, elt);
1142 top->len ++;
1143 }
1144 else {
1145 if (replace) {
1146 ucl_hash_delete (top->value.ov, found);
1147 ucl_object_unref (found);
1148 top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1149 found = NULL;
1150 DL_APPEND (found, elt);
--- 30 unchanged lines hidden (view full) ---
1181 return top;
1182}
1183
1184bool
1185ucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
1186{
1187 ucl_object_t *found;
1188
1189 if (top == NULL || key == NULL) {
1190 return false;
1191 }
1192
1193 found = ucl_object_find_keyl(top, key, keylen);
1194
1195 if (found == NULL) {
1196 return false;
1197 }
1198
1199 ucl_hash_delete(top->value.ov, found);
1200 ucl_object_unref (found);
1201 top->len --;
1202
1203 return true;
1204}
1205
1206bool
1207ucl_object_delete_key(ucl_object_t *top, const char *key)
1208{
1209 return ucl_object_delete_keyl(top, key, 0);
1210}
1211
1212ucl_object_t*
1213ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
1214{
1215 ucl_object_t *found;
1216
1217 if (top == NULL || key == NULL) {
1218 return false;
1219 }
1220 found = ucl_object_find_keyl(top, key, keylen);
1221
1222 if (found == NULL) {
1223 return NULL;
1224 }
1225 ucl_hash_delete(top->value.ov, found);
1226 top->len --;
1227
1228 return found;
1229}
1230
1231ucl_object_t*
1232ucl_object_pop_key (ucl_object_t *top, const char *key)
1233{
1234 return ucl_object_pop_keyl (top, key, 0);
1235}
1236
1237ucl_object_t *
1238ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
1239 const char *key, size_t keylen, bool copy_key)
1240{
1241 return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
1242}
1243
1244ucl_object_t *
--- 44 unchanged lines hidden (view full) ---
1289 return ret;
1290}
1291
1292ucl_object_t*
1293ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
1294{
1295 ucl_object_t *elt;
1296
1297 if (obj == NULL || iter == NULL) {
1298 return NULL;
1299 }
1300
1301 if (expand_values) {
1302 switch (obj->type) {
1303 case UCL_OBJECT:
1304 return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
1305 break;
1306 case UCL_ARRAY:
1307 elt = *iter;
1308 if (elt == NULL) {
--- 24 unchanged lines hidden (view full) ---
1333 return NULL;
1334 }
1335 *iter = elt->next ? elt->next : obj;
1336 return elt;
1337
1338 /* Not reached */
1339 return NULL;
1340}
1341
1342
1343ucl_object_t *
1344ucl_object_new (void)
1345{
1346 ucl_object_t *new;
1347 new = malloc (sizeof (ucl_object_t));
1348 if (new != NULL) {
1349 memset (new, 0, sizeof (ucl_object_t));
1350 new->ref = 1;
1351 new->type = UCL_NULL;
1352 }
1353 return new;
1354}
1355
1356ucl_object_t *
1357ucl_object_typed_new (unsigned int type)
1358{
1359 ucl_object_t *new;
1360 new = malloc (sizeof (ucl_object_t));
1361 if (new != NULL) {
1362 memset (new, 0, sizeof (ucl_object_t));
1363 new->ref = 1;
1364 new->type = (type <= UCL_NULL ? type : UCL_NULL);
1365 }
1366 return new;
1367}
1368
1369ucl_object_t*
1370ucl_object_fromstring (const char *str)
1371{
1372 return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
1373}
1374
1375ucl_object_t *
1376ucl_object_fromlstring (const char *str, size_t len)
1377{
1378 return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
1379}
1380
1381ucl_object_t *
1382ucl_object_fromint (int64_t iv)
1383{
1384 ucl_object_t *obj;
1385
1386 obj = ucl_object_new ();
1387 if (obj != NULL) {
1388 obj->type = UCL_INT;
1389 obj->value.iv = iv;
1390 }
1391
1392 return obj;
1393}
1394
1395ucl_object_t *
1396ucl_object_fromdouble (double dv)
1397{
1398 ucl_object_t *obj;
1399
1400 obj = ucl_object_new ();
1401 if (obj != NULL) {
1402 obj->type = UCL_FLOAT;
1403 obj->value.dv = dv;
1404 }
1405
1406 return obj;
1407}
1408
1409ucl_object_t*
1410ucl_object_frombool (bool bv)
1411{
1412 ucl_object_t *obj;
1413
1414 obj = ucl_object_new ();
1415 if (obj != NULL) {
1416 obj->type = UCL_BOOLEAN;
1417 obj->value.iv = bv;
1418 }
1419
1420 return obj;
1421}
1422
1423ucl_object_t *
1424ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
1425{
1426 ucl_object_t *head;
1427
1428 if (elt == NULL) {
1429 return NULL;
1430 }
1431
1432 if (top == NULL) {
1433 top = ucl_object_typed_new (UCL_ARRAY);
1434 top->value.av = elt;
1435 elt->next = NULL;
1436 elt->prev = elt;
1437 top->len = 1;
1438 }
1439 else {
1440 head = top->value.av;
1441 if (head == NULL) {
1442 top->value.av = elt;
1443 elt->prev = elt;
1444 }
1445 else {
1446 elt->prev = head->prev;
1447 head->prev->next = elt;
1448 head->prev = elt;
1449 }
1450 elt->next = NULL;
1451 top->len ++;
1452 }
1453
1454 return top;
1455}
1456
1457ucl_object_t *
1458ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
1459{
1460 ucl_object_t *head;
1461
1462 if (elt == NULL) {
1463 return NULL;
1464 }
1465
1466 if (top == NULL) {
1467 top = ucl_object_typed_new (UCL_ARRAY);
1468 top->value.av = elt;
1469 elt->next = NULL;
1470 elt->prev = elt;
1471 top->len = 1;
1472 }
1473 else {
1474 head = top->value.av;
1475 if (head == NULL) {
1476 top->value.av = elt;
1477 elt->prev = elt;
1478 }
1479 else {
1480 elt->prev = head->prev;
1481 head->prev = elt;
1482 }
1483 elt->next = head;
1484 top->value.av = elt;
1485 top->len ++;
1486 }
1487
1488 return top;
1489}
1490
1491ucl_object_t *
1492ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
1493{
1494 ucl_object_t *head;
1495
1496 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1497 return NULL;
1498 }
1499 head = top->value.av;
1500
1501 if (elt->prev == elt) {
1502 top->value.av = NULL;
1503 }
1504 else if (elt == head) {
1505 elt->next->prev = elt->prev;
1506 top->value.av = elt->next;
1507 }
1508 else {
1509 elt->prev->next = elt->next;
1510 if (elt->next) {
1511 elt->next->prev = elt->prev;
1512 }
1513 else {
1514 head->prev = elt->prev;
1515 }
1516 }
1517 elt->next = NULL;
1518 elt->prev = elt;
1519 top->len --;
1520
1521 return elt;
1522}
1523
1524ucl_object_t *
1525ucl_array_head (ucl_object_t *top)
1526{
1527 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1528 return NULL;
1529 }
1530 return top->value.av;
1531}
1532
1533ucl_object_t *
1534ucl_array_tail (ucl_object_t *top)
1535{
1536 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1537 return NULL;
1538 }
1539 return top->value.av->prev;
1540}
1541
1542ucl_object_t *
1543ucl_array_pop_last (ucl_object_t *top)
1544{
1545 return ucl_array_delete (top, ucl_array_tail (top));
1546}
1547
1548ucl_object_t *
1549ucl_array_pop_first (ucl_object_t *top)
1550{
1551 return ucl_array_delete (top, ucl_array_head (top));
1552}
1553
1554ucl_object_t *
1555ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
1556{
1557
1558 if (head == NULL) {
1559 elt->next = NULL;
1560 elt->prev = elt;
1561 head = elt;
1562 }
1563 else {
1564 elt->prev = head->prev;
1565 head->prev->next = elt;
1566 head->prev = elt;
1567 elt->next = NULL;
1568 }
1569
1570 return head;
1571}
1572
1573bool
1574ucl_object_todouble_safe (ucl_object_t *obj, double *target)
1575{
1576 if (obj == NULL || target == NULL) {
1577 return false;
1578 }
1579 switch (obj->type) {
1580 case UCL_INT:
1581 *target = obj->value.iv; /* Probaly could cause overflow */
1582 break;
1583 case UCL_FLOAT:
1584 case UCL_TIME:
1585 *target = obj->value.dv;
1586 break;
1587 default:
1588 return false;
1589 }
1590
1591 return true;
1592}
1593
1594double
1595ucl_object_todouble (ucl_object_t *obj)
1596{
1597 double result = 0.;
1598
1599 ucl_object_todouble_safe (obj, &result);
1600 return result;
1601}
1602
1603bool
1604ucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
1605{
1606 if (obj == NULL || target == NULL) {
1607 return false;
1608 }
1609 switch (obj->type) {
1610 case UCL_INT:
1611 *target = obj->value.iv;
1612 break;
1613 case UCL_FLOAT:
1614 case UCL_TIME:
1615 *target = obj->value.dv; /* Loosing of decimal points */
1616 break;
1617 default:
1618 return false;
1619 }
1620
1621 return true;
1622}
1623
1624int64_t
1625ucl_object_toint (ucl_object_t *obj)
1626{
1627 int64_t result = 0;
1628
1629 ucl_object_toint_safe (obj, &result);
1630 return result;
1631}
1632
1633bool
1634ucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
1635{
1636 if (obj == NULL || target == NULL) {
1637 return false;
1638 }
1639 switch (obj->type) {
1640 case UCL_BOOLEAN:
1641 *target = (obj->value.iv == true);
1642 break;
1643 default:
1644 return false;
1645 }
1646
1647 return true;
1648}
1649
1650bool
1651ucl_object_toboolean (ucl_object_t *obj)
1652{
1653 bool result = false;
1654
1655 ucl_object_toboolean_safe (obj, &result);
1656 return result;
1657}
1658
1659bool
1660ucl_object_tostring_safe (ucl_object_t *obj, const char **target)
1661{
1662 if (obj == NULL || target == NULL) {
1663 return false;
1664 }
1665
1666 switch (obj->type) {
1667 case UCL_STRING:
1668 *target = ucl_copy_value_trash (obj);
1669 break;
1670 default:
1671 return false;
1672 }
1673
1674 return true;
1675}
1676
1677const char *
1678ucl_object_tostring (ucl_object_t *obj)
1679{
1680 const char *result = NULL;
1681
1682 ucl_object_tostring_safe (obj, &result);
1683 return result;
1684}
1685
1686const char *
1687ucl_object_tostring_forced (ucl_object_t *obj)
1688{
1689 return ucl_copy_value_trash (obj);
1690}
1691
1692bool
1693ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
1694{
1695 if (obj == NULL || target == NULL) {
1696 return false;
1697 }
1698 switch (obj->type) {
1699 case UCL_STRING:
1700 *target = obj->value.sv;
1701 if (tlen != NULL) {
1702 *tlen = obj->len;
1703 }
1704 break;
1705 default:
1706 return false;
1707 }
1708
1709 return true;
1710}
1711
1712const char *
1713ucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
1714{
1715 const char *result = NULL;
1716
1717 ucl_object_tolstring_safe (obj, &result, tlen);
1718 return result;
1719}
1720
1721const char *
1722ucl_object_key (ucl_object_t *obj)
1723{
1724 return ucl_copy_key_trash (obj);
1725}
1726
1727const char *
1728ucl_object_keyl (ucl_object_t *obj, size_t *len)
1729{
1730 if (len == NULL || obj == NULL) {
1731 return NULL;
1732 }
1733 *len = obj->keylen;
1734 return obj->key;
1735}
1736
1737ucl_object_t *
1738ucl_object_ref (ucl_object_t *obj)
1739{
1740 if (obj != NULL) {
1741 obj->ref ++;
1742 }
1743 return obj;
1744}
1745
1746void
1747ucl_object_unref (ucl_object_t *obj)
1748{
1749 if (obj != NULL && --obj->ref <= 0) {
1750 ucl_object_free (obj);
1751 }
1752}
1753
1754int
1755ucl_object_compare (ucl_object_t *o1, ucl_object_t *o2)
1756{
1757 ucl_object_t *it1, *it2;
1758 ucl_object_iter_t iter = NULL;
1759 int ret = 0;
1760
1761 if (o1->type != o2->type) {
1762 return (o1->type) - (o2->type);
1763 }
1764
1765 switch (o1->type) {
1766 case UCL_STRING:
1767 if (o1->len == o2->len) {
1768 ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
1769 }
1770 else {
1771 ret = o1->len - o2->len;
1772 }
1773 break;
1774 case UCL_FLOAT:
1775 case UCL_INT:
1776 case UCL_TIME:
1777 ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
1778 break;
1779 case UCL_BOOLEAN:
1780 ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
1781 break;
1782 case UCL_ARRAY:
1783 if (o1->len == o2->len) {
1784 it1 = o1->value.av;
1785 it2 = o2->value.av;
1786 /* Compare all elements in both arrays */
1787 while (it1 != NULL && it2 != NULL) {
1788 ret = ucl_object_compare (it1, it2);
1789 if (ret != 0) {
1790 break;
1791 }
1792 it1 = it1->next;
1793 it2 = it2->next;
1794 }
1795 }
1796 else {
1797 ret = o1->len - o2->len;
1798 }
1799 break;
1800 case UCL_OBJECT:
1801 if (o1->len == o2->len) {
1802 while ((it1 = ucl_iterate_object (o1, &iter, true)) != NULL) {
1803 it2 = ucl_object_find_key (o2, ucl_object_key (it1));
1804 if (it2 == NULL) {
1805 ret = 1;
1806 break;
1807 }
1808 ret = ucl_object_compare (it1, it2);
1809 if (ret != 0) {
1810 break;
1811 }
1812 }
1813 }
1814 else {
1815 ret = o1->len - o2->len;
1816 }
1817 break;
1818 default:
1819 ret = 0;
1820 break;
1821 }
1822
1823 return ret;
1824}
1825
1826void
1827ucl_object_array_sort (ucl_object_t *ar,
1828 int (*cmp)(ucl_object_t *o1, ucl_object_t *o2))
1829{
1830 if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
1831 return;
1832 }
1833
1834 DL_SORT (ar->value.av, cmp);
1835}