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 --- 530 unchanged lines hidden (view full) --- 539 } 540 else { 541 obj->type = UCL_ARRAY; 542 } 543 parser->state = UCL_STATE_VALUE; 544 } 545 546 st = UCL_ALLOC (sizeof (struct ucl_stack)); |
547 if (st == NULL) { 548 ucl_set_err (parser->chunks, 0, "cannot allocate memory for an object", &parser->err); 549 return NULL; 550 } |
551 st->obj = obj; 552 st->level = level; 553 LL_PREPEND (parser->stack, st); 554 parser->cur_obj = obj; 555 556 return obj; 557} 558 559int 560ucl_maybe_parse_number (ucl_object_t *obj, |
561 const char *start, const char *end, const char **pos, 562 bool allow_double, bool number_bytes, bool allow_time) |
563{ 564 const char *p = start, *c = start; 565 char *endptr; 566 bool got_dot = false, got_exp = false, need_double = false, |
567 is_time = false, valid_start = false, is_hex = false, |
568 is_neg = false; 569 double dv = 0; 570 int64_t lv = 0; 571 572 if (*p == '-') { 573 is_neg = true; 574 c ++; 575 p ++; --- 81 unchanged lines hidden (view full) --- 657 } 658 } 659 if (errno == ERANGE) { 660 *pos = start; 661 return ERANGE; 662 } 663 664 /* Now check endptr */ |
665 if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0' || 666 ucl_test_character (*endptr, UCL_CHARACTER_WHITESPACE_UNSAFE)) { |
667 p = endptr; 668 goto set_obj; 669 } 670 671 if (endptr < end && endptr != start) { 672 p = endptr; 673 switch (*p) { 674 case 'm': --- 4 unchanged lines hidden (view full) --- 679 case 'K': 680 if (end - p >= 2) { 681 if (p[1] == 's' || p[1] == 'S') { 682 /* Milliseconds */ 683 if (!need_double) { 684 need_double = true; 685 dv = lv; 686 } |
687 is_time = true; |
688 if (p[0] == 'm' || p[0] == 'M') { 689 dv /= 1000.; 690 } 691 else { 692 dv *= ucl_lex_num_multiplier (*p, false); 693 } 694 p += 2; 695 goto set_obj; --- 13 unchanged lines hidden (view full) --- 709 dv *= ucl_lex_num_multiplier (*p, false); 710 } 711 else { 712 lv *= ucl_lex_num_multiplier (*p, number_bytes); 713 } 714 p ++; 715 goto set_obj; 716 } |
717 else if (allow_time && end - p >= 3) { |
718 if (tolower (p[0]) == 'm' && 719 tolower (p[1]) == 'i' && 720 tolower (p[2]) == 'n') { 721 /* Minutes */ 722 if (!need_double) { 723 need_double = true; 724 dv = lv; 725 } |
726 is_time = true; |
727 dv *= 60.; 728 p += 3; 729 goto set_obj; 730 } 731 } 732 } 733 else { 734 if (need_double) { 735 dv *= ucl_lex_num_multiplier (*p, false); 736 } 737 else { 738 lv *= ucl_lex_num_multiplier (*p, number_bytes); 739 } 740 p ++; 741 goto set_obj; 742 } 743 break; 744 case 'S': 745 case 's': |
746 if (allow_time && 747 (p == end - 1 || ucl_lex_is_atom_end (p[1]))) { |
748 if (!need_double) { 749 need_double = true; 750 dv = lv; 751 } 752 p ++; |
753 is_time = true; |
754 goto set_obj; 755 } 756 break; 757 case 'h': 758 case 'H': 759 case 'd': 760 case 'D': 761 case 'w': 762 case 'W': 763 case 'Y': 764 case 'y': |
765 if (allow_time && 766 (p == end - 1 || ucl_lex_is_atom_end (p[1]))) { |
767 if (!need_double) { 768 need_double = true; 769 dv = lv; 770 } |
771 is_time = true; |
772 dv *= ucl_lex_time_multiplier (*p); 773 p ++; 774 goto set_obj; 775 } 776 break; 777 } 778 } 779 780 *pos = c; 781 return EINVAL; 782 783 set_obj: |
784 if (allow_double && (need_double || is_time)) { 785 if (!is_time) { |
786 obj->type = UCL_FLOAT; 787 } 788 else { 789 obj->type = UCL_TIME; 790 } 791 obj->value.dv = is_neg ? (-dv) : dv; 792 } 793 else { --- 12 unchanged lines hidden (view full) --- 806 */ 807static bool 808ucl_lex_number (struct ucl_parser *parser, 809 struct ucl_chunk *chunk, ucl_object_t *obj) 810{ 811 const unsigned char *pos; 812 int ret; 813 |
814 ret = ucl_maybe_parse_number (obj, chunk->pos, chunk->end, (const char **)&pos, 815 true, false, ((parser->flags & UCL_PARSER_NO_TIME) == 0)); |
816 817 if (ret == 0) { 818 chunk->remain -= pos - chunk->pos; 819 chunk->column += pos - chunk->pos; 820 chunk->pos = pos; 821 return true; 822 } 823 else if (ret == ERANGE) { --- 488 unchanged lines hidden (view full) --- 1312 parser->state = UCL_STATE_AFTER_VALUE; 1313 p = chunk->pos; 1314 return true; 1315 break; 1316 case '{': 1317 obj = ucl_get_value_object (parser); 1318 /* We have a new object */ 1319 obj = ucl_add_parser_stack (obj, parser, false, parser->stack->level); |
1320 if (obj == NULL) { 1321 return false; 1322 } |
1323 1324 ucl_chunk_skipc (chunk, p); 1325 return true; 1326 break; 1327 case '[': 1328 obj = ucl_get_value_object (parser); 1329 /* We have a new array */ 1330 obj = ucl_add_parser_stack (obj, parser, true, parser->stack->level); |
1331 if (obj == NULL) { 1332 return false; 1333 } |
1334 1335 ucl_chunk_skipc (chunk, p); 1336 return true; 1337 break; 1338 case ']': 1339 /* We have the array ending */ 1340 if (parser->stack && parser->stack->obj->type == UCL_ARRAY) { 1341 parser->state = UCL_STATE_AFTER_VALUE; --- 276 unchanged lines hidden (view full) --- 1618 1619 if (parser->top_obj == NULL) { 1620 if (*chunk->pos == '[') { 1621 obj = ucl_add_parser_stack (NULL, parser, true, 0); 1622 } 1623 else { 1624 obj = ucl_add_parser_stack (NULL, parser, false, 0); 1625 } |
1626 if (obj == NULL) { 1627 return false; 1628 } |
1629 parser->top_obj = obj; 1630 parser->cur_obj = obj; 1631 parser->state = UCL_STATE_INIT; 1632 } 1633 1634 p = chunk->pos; 1635 while (chunk->pos < chunk->end) { 1636 switch (parser->state) { --- 49 unchanged lines hidden (view full) --- 1686 if (end_of_object) { 1687 p = chunk->pos; 1688 parser->state = UCL_STATE_AFTER_VALUE; 1689 continue; 1690 } 1691 else if (parser->state != UCL_STATE_MACRO_NAME) { 1692 if (next_key && parser->stack->obj->type == UCL_OBJECT) { 1693 /* Parse more keys and nest objects accordingly */ |
1694 obj = ucl_add_parser_stack (parser->cur_obj, parser, false, 1695 parser->stack->level + 1); 1696 if (obj == NULL) { 1697 return false; 1698 } |
1699 } 1700 else { 1701 parser->state = UCL_STATE_VALUE; 1702 } 1703 } 1704 else { 1705 c = chunk->pos; 1706 } --- 97 unchanged lines hidden (view full) --- 1804} 1805 1806struct ucl_parser* 1807ucl_parser_new (int flags) 1808{ 1809 struct ucl_parser *new; 1810 1811 new = UCL_ALLOC (sizeof (struct ucl_parser)); |
1812 if (new == NULL) { 1813 return NULL; 1814 } |
1815 memset (new, 0, sizeof (struct ucl_parser)); 1816 1817 ucl_parser_register_macro (new, "include", ucl_include_handler, new); 1818 ucl_parser_register_macro (new, "try_include", ucl_try_include_handler, new); 1819 ucl_parser_register_macro (new, "includes", ucl_includes_handler, new); 1820 1821 new->flags = flags; 1822 --- 5 unchanged lines hidden (view full) --- 1828 1829 1830void 1831ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, 1832 ucl_macro_handler handler, void* ud) 1833{ 1834 struct ucl_macro *new; 1835 |
1836 if (macro == NULL || handler == NULL) { 1837 return; 1838 } |
1839 new = UCL_ALLOC (sizeof (struct ucl_macro)); |
1840 if (new == NULL) { 1841 return; 1842 } |
1843 memset (new, 0, sizeof (struct ucl_macro)); 1844 new->handler = handler; 1845 new->name = strdup (macro); 1846 new->ud = ud; 1847 HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new); 1848} 1849 1850void --- 26 unchanged lines hidden (view full) --- 1877 else { 1878 /* Do nothing */ 1879 return; 1880 } 1881 } 1882 else { 1883 if (new == NULL) { 1884 new = UCL_ALLOC (sizeof (struct ucl_variable)); |
1885 if (new == NULL) { 1886 return; 1887 } |
1888 memset (new, 0, sizeof (struct ucl_variable)); 1889 new->var = strdup (var); 1890 new->var_len = strlen (var); 1891 new->value = strdup (value); 1892 new->value_len = strlen (value); 1893 1894 LL_PREPEND (parser->variables, new); 1895 } --- 6 unchanged lines hidden (view full) --- 1902} 1903 1904bool 1905ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, 1906 size_t len) 1907{ 1908 struct ucl_chunk *chunk; 1909 |
1910 if (data == NULL || len == 0) { 1911 ucl_create_err (&parser->err, "invalid chunk added"); 1912 return false; 1913 } |
1914 if (parser->state != UCL_STATE_ERROR) { 1915 chunk = UCL_ALLOC (sizeof (struct ucl_chunk)); |
1916 if (chunk == NULL) { 1917 ucl_create_err (&parser->err, "cannot allocate chunk structure"); 1918 return false; 1919 } |
1920 chunk->begin = data; 1921 chunk->remain = len; 1922 chunk->pos = chunk->begin; 1923 chunk->end = chunk->begin + len; 1924 chunk->line = 1; 1925 chunk->column = 0; 1926 LL_PREPEND (parser->chunks, chunk); 1927 parser->recursion ++; --- 4 unchanged lines hidden (view full) --- 1932 } 1933 return ucl_state_machine (parser); 1934 } 1935 1936 ucl_create_err (&parser->err, "a parser is in an invalid state"); 1937 1938 return false; 1939} |
1940 1941bool 1942ucl_parser_add_string (struct ucl_parser *parser, const char *data, 1943 size_t len) 1944{ 1945 if (data == NULL) { 1946 ucl_create_err (&parser->err, "invalid string added"); 1947 return false; 1948 } 1949 if (len == 0) { 1950 len = strlen (data); 1951 } 1952 1953 return ucl_parser_add_chunk (parser, (const unsigned char *)data, len); 1954} |