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 st->obj = obj;
548 st->level = level;
549 LL_PREPEND (parser->stack, st);
550 parser->cur_obj = obj;
551
552 return obj;
553}
554
555int
556ucl_maybe_parse_number (ucl_object_t *obj,
557 const char *start, const char *end, const char **pos, bool allow_double, bool number_bytes)
558{
559 const char *p = start, *c = start;
560 char *endptr;
561 bool got_dot = false, got_exp = false, need_double = false,
562 is_date = false, valid_start = false, is_hex = false,
563 is_neg = false;
564 double dv = 0;
565 int64_t lv = 0;
566
567 if (*p == '-') {
568 is_neg = true;
569 c ++;
570 p ++;
--- 81 unchanged lines hidden (view full) ---
652 }
653 }
654 if (errno == ERANGE) {
655 *pos = start;
656 return ERANGE;
657 }
658
659 /* Now check endptr */
660 if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0') {
661 p = endptr;
662 goto set_obj;
663 }
664
665 if (endptr < end && endptr != start) {
666 p = endptr;
667 switch (*p) {
668 case 'm':
--- 4 unchanged lines hidden (view full) ---
673 case 'K':
674 if (end - p >= 2) {
675 if (p[1] == 's' || p[1] == 'S') {
676 /* Milliseconds */
677 if (!need_double) {
678 need_double = true;
679 dv = lv;
680 }
681 is_date = true;
682 if (p[0] == 'm' || p[0] == 'M') {
683 dv /= 1000.;
684 }
685 else {
686 dv *= ucl_lex_num_multiplier (*p, false);
687 }
688 p += 2;
689 goto set_obj;
--- 13 unchanged lines hidden (view full) ---
703 dv *= ucl_lex_num_multiplier (*p, false);
704 }
705 else {
706 lv *= ucl_lex_num_multiplier (*p, number_bytes);
707 }
708 p ++;
709 goto set_obj;
710 }
711 else if (end - p >= 3) {
712 if (tolower (p[0]) == 'm' &&
713 tolower (p[1]) == 'i' &&
714 tolower (p[2]) == 'n') {
715 /* Minutes */
716 if (!need_double) {
717 need_double = true;
718 dv = lv;
719 }
720 is_date = true;
721 dv *= 60.;
722 p += 3;
723 goto set_obj;
724 }
725 }
726 }
727 else {
728 if (need_double) {
729 dv *= ucl_lex_num_multiplier (*p, false);
730 }
731 else {
732 lv *= ucl_lex_num_multiplier (*p, number_bytes);
733 }
734 p ++;
735 goto set_obj;
736 }
737 break;
738 case 'S':
739 case 's':
740 if (p == end - 1 || ucl_lex_is_atom_end (p[1])) {
741 if (!need_double) {
742 need_double = true;
743 dv = lv;
744 }
745 p ++;
746 is_date = true;
747 goto set_obj;
748 }
749 break;
750 case 'h':
751 case 'H':
752 case 'd':
753 case 'D':
754 case 'w':
755 case 'W':
756 case 'Y':
757 case 'y':
758 if (p == end - 1 || ucl_lex_is_atom_end (p[1])) {
759 if (!need_double) {
760 need_double = true;
761 dv = lv;
762 }
763 is_date = true;
764 dv *= ucl_lex_time_multiplier (*p);
765 p ++;
766 goto set_obj;
767 }
768 break;
769 }
770 }
771
772 *pos = c;
773 return EINVAL;
774
775 set_obj:
776 if (allow_double && (need_double || is_date)) {
777 if (!is_date) {
778 obj->type = UCL_FLOAT;
779 }
780 else {
781 obj->type = UCL_TIME;
782 }
783 obj->value.dv = is_neg ? (-dv) : dv;
784 }
785 else {
--- 12 unchanged lines hidden (view full) ---
798 */
799static bool
800ucl_lex_number (struct ucl_parser *parser,
801 struct ucl_chunk *chunk, ucl_object_t *obj)
802{
803 const unsigned char *pos;
804 int ret;
805
806 ret = ucl_maybe_parse_number (obj, chunk->pos, chunk->end, (const char **)&pos, true, false);
807
808 if (ret == 0) {
809 chunk->remain -= pos - chunk->pos;
810 chunk->column += pos - chunk->pos;
811 chunk->pos = pos;
812 return true;
813 }
814 else if (ret == ERANGE) {
--- 488 unchanged lines hidden (view full) ---
1303 parser->state = UCL_STATE_AFTER_VALUE;
1304 p = chunk->pos;
1305 return true;
1306 break;
1307 case '{':
1308 obj = ucl_get_value_object (parser);
1309 /* We have a new object */
1310 obj = ucl_add_parser_stack (obj, parser, false, parser->stack->level);
1311
1312 ucl_chunk_skipc (chunk, p);
1313 return true;
1314 break;
1315 case '[':
1316 obj = ucl_get_value_object (parser);
1317 /* We have a new array */
1318 obj = ucl_add_parser_stack (obj, parser, true, parser->stack->level);
1319
1320 ucl_chunk_skipc (chunk, p);
1321 return true;
1322 break;
1323 case ']':
1324 /* We have the array ending */
1325 if (parser->stack && parser->stack->obj->type == UCL_ARRAY) {
1326 parser->state = UCL_STATE_AFTER_VALUE;
--- 276 unchanged lines hidden (view full) ---
1603
1604 if (parser->top_obj == NULL) {
1605 if (*chunk->pos == '[') {
1606 obj = ucl_add_parser_stack (NULL, parser, true, 0);
1607 }
1608 else {
1609 obj = ucl_add_parser_stack (NULL, parser, false, 0);
1610 }
1611 parser->top_obj = obj;
1612 parser->cur_obj = obj;
1613 parser->state = UCL_STATE_INIT;
1614 }
1615
1616 p = chunk->pos;
1617 while (chunk->pos < chunk->end) {
1618 switch (parser->state) {
--- 49 unchanged lines hidden (view full) ---
1668 if (end_of_object) {
1669 p = chunk->pos;
1670 parser->state = UCL_STATE_AFTER_VALUE;
1671 continue;
1672 }
1673 else if (parser->state != UCL_STATE_MACRO_NAME) {
1674 if (next_key && parser->stack->obj->type == UCL_OBJECT) {
1675 /* Parse more keys and nest objects accordingly */
1676 obj = ucl_add_parser_stack (parser->cur_obj, parser, false, parser->stack->level + 1);
1677 }
1678 else {
1679 parser->state = UCL_STATE_VALUE;
1680 }
1681 }
1682 else {
1683 c = chunk->pos;
1684 }
--- 97 unchanged lines hidden (view full) ---
1782}
1783
1784struct ucl_parser*
1785ucl_parser_new (int flags)
1786{
1787 struct ucl_parser *new;
1788
1789 new = UCL_ALLOC (sizeof (struct ucl_parser));
1790 memset (new, 0, sizeof (struct ucl_parser));
1791
1792 ucl_parser_register_macro (new, "include", ucl_include_handler, new);
1793 ucl_parser_register_macro (new, "try_include", ucl_try_include_handler, new);
1794 ucl_parser_register_macro (new, "includes", ucl_includes_handler, new);
1795
1796 new->flags = flags;
1797
--- 5 unchanged lines hidden (view full) ---
1803
1804
1805void
1806ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
1807 ucl_macro_handler handler, void* ud)
1808{
1809 struct ucl_macro *new;
1810
1811 new = UCL_ALLOC (sizeof (struct ucl_macro));
1812 memset (new, 0, sizeof (struct ucl_macro));
1813 new->handler = handler;
1814 new->name = strdup (macro);
1815 new->ud = ud;
1816 HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
1817}
1818
1819void
--- 26 unchanged lines hidden (view full) ---
1846 else {
1847 /* Do nothing */
1848 return;
1849 }
1850 }
1851 else {
1852 if (new == NULL) {
1853 new = UCL_ALLOC (sizeof (struct ucl_variable));
1854 memset (new, 0, sizeof (struct ucl_variable));
1855 new->var = strdup (var);
1856 new->var_len = strlen (var);
1857 new->value = strdup (value);
1858 new->value_len = strlen (value);
1859
1860 LL_PREPEND (parser->variables, new);
1861 }
--- 6 unchanged lines hidden (view full) ---
1868}
1869
1870bool
1871ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
1872 size_t len)
1873{
1874 struct ucl_chunk *chunk;
1875
1876 if (parser->state != UCL_STATE_ERROR) {
1877 chunk = UCL_ALLOC (sizeof (struct ucl_chunk));
1878 chunk->begin = data;
1879 chunk->remain = len;
1880 chunk->pos = chunk->begin;
1881 chunk->end = chunk->begin + len;
1882 chunk->line = 1;
1883 chunk->column = 0;
1884 LL_PREPEND (parser->chunks, chunk);
1885 parser->recursion ++;
--- 4 unchanged lines hidden (view full) ---
1890 }
1891 return ucl_state_machine (parser);
1892 }
1893
1894 ucl_create_err (&parser->err, "a parser is in an invalid state");
1895
1896 return false;
1897}
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 st->obj = obj;
548 st->level = level;
549 LL_PREPEND (parser->stack, st);
550 parser->cur_obj = obj;
551
552 return obj;
553}
554
555int
556ucl_maybe_parse_number (ucl_object_t *obj,
557 const char *start, const char *end, const char **pos, bool allow_double, bool number_bytes)
558{
559 const char *p = start, *c = start;
560 char *endptr;
561 bool got_dot = false, got_exp = false, need_double = false,
562 is_date = false, valid_start = false, is_hex = false,
563 is_neg = false;
564 double dv = 0;
565 int64_t lv = 0;
566
567 if (*p == '-') {
568 is_neg = true;
569 c ++;
570 p ++;
--- 81 unchanged lines hidden (view full) ---
652 }
653 }
654 if (errno == ERANGE) {
655 *pos = start;
656 return ERANGE;
657 }
658
659 /* Now check endptr */
660 if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0') {
661 p = endptr;
662 goto set_obj;
663 }
664
665 if (endptr < end && endptr != start) {
666 p = endptr;
667 switch (*p) {
668 case 'm':
--- 4 unchanged lines hidden (view full) ---
673 case 'K':
674 if (end - p >= 2) {
675 if (p[1] == 's' || p[1] == 'S') {
676 /* Milliseconds */
677 if (!need_double) {
678 need_double = true;
679 dv = lv;
680 }
681 is_date = true;
682 if (p[0] == 'm' || p[0] == 'M') {
683 dv /= 1000.;
684 }
685 else {
686 dv *= ucl_lex_num_multiplier (*p, false);
687 }
688 p += 2;
689 goto set_obj;
--- 13 unchanged lines hidden (view full) ---
703 dv *= ucl_lex_num_multiplier (*p, false);
704 }
705 else {
706 lv *= ucl_lex_num_multiplier (*p, number_bytes);
707 }
708 p ++;
709 goto set_obj;
710 }
711 else if (end - p >= 3) {
712 if (tolower (p[0]) == 'm' &&
713 tolower (p[1]) == 'i' &&
714 tolower (p[2]) == 'n') {
715 /* Minutes */
716 if (!need_double) {
717 need_double = true;
718 dv = lv;
719 }
720 is_date = true;
721 dv *= 60.;
722 p += 3;
723 goto set_obj;
724 }
725 }
726 }
727 else {
728 if (need_double) {
729 dv *= ucl_lex_num_multiplier (*p, false);
730 }
731 else {
732 lv *= ucl_lex_num_multiplier (*p, number_bytes);
733 }
734 p ++;
735 goto set_obj;
736 }
737 break;
738 case 'S':
739 case 's':
740 if (p == end - 1 || ucl_lex_is_atom_end (p[1])) {
741 if (!need_double) {
742 need_double = true;
743 dv = lv;
744 }
745 p ++;
746 is_date = true;
747 goto set_obj;
748 }
749 break;
750 case 'h':
751 case 'H':
752 case 'd':
753 case 'D':
754 case 'w':
755 case 'W':
756 case 'Y':
757 case 'y':
758 if (p == end - 1 || ucl_lex_is_atom_end (p[1])) {
759 if (!need_double) {
760 need_double = true;
761 dv = lv;
762 }
763 is_date = true;
764 dv *= ucl_lex_time_multiplier (*p);
765 p ++;
766 goto set_obj;
767 }
768 break;
769 }
770 }
771
772 *pos = c;
773 return EINVAL;
774
775 set_obj:
776 if (allow_double && (need_double || is_date)) {
777 if (!is_date) {
778 obj->type = UCL_FLOAT;
779 }
780 else {
781 obj->type = UCL_TIME;
782 }
783 obj->value.dv = is_neg ? (-dv) : dv;
784 }
785 else {
--- 12 unchanged lines hidden (view full) ---
798 */
799static bool
800ucl_lex_number (struct ucl_parser *parser,
801 struct ucl_chunk *chunk, ucl_object_t *obj)
802{
803 const unsigned char *pos;
804 int ret;
805
806 ret = ucl_maybe_parse_number (obj, chunk->pos, chunk->end, (const char **)&pos, true, false);
807
808 if (ret == 0) {
809 chunk->remain -= pos - chunk->pos;
810 chunk->column += pos - chunk->pos;
811 chunk->pos = pos;
812 return true;
813 }
814 else if (ret == ERANGE) {
--- 488 unchanged lines hidden (view full) ---
1303 parser->state = UCL_STATE_AFTER_VALUE;
1304 p = chunk->pos;
1305 return true;
1306 break;
1307 case '{':
1308 obj = ucl_get_value_object (parser);
1309 /* We have a new object */
1310 obj = ucl_add_parser_stack (obj, parser, false, parser->stack->level);
1311
1312 ucl_chunk_skipc (chunk, p);
1313 return true;
1314 break;
1315 case '[':
1316 obj = ucl_get_value_object (parser);
1317 /* We have a new array */
1318 obj = ucl_add_parser_stack (obj, parser, true, parser->stack->level);
1319
1320 ucl_chunk_skipc (chunk, p);
1321 return true;
1322 break;
1323 case ']':
1324 /* We have the array ending */
1325 if (parser->stack && parser->stack->obj->type == UCL_ARRAY) {
1326 parser->state = UCL_STATE_AFTER_VALUE;
--- 276 unchanged lines hidden (view full) ---
1603
1604 if (parser->top_obj == NULL) {
1605 if (*chunk->pos == '[') {
1606 obj = ucl_add_parser_stack (NULL, parser, true, 0);
1607 }
1608 else {
1609 obj = ucl_add_parser_stack (NULL, parser, false, 0);
1610 }
1611 parser->top_obj = obj;
1612 parser->cur_obj = obj;
1613 parser->state = UCL_STATE_INIT;
1614 }
1615
1616 p = chunk->pos;
1617 while (chunk->pos < chunk->end) {
1618 switch (parser->state) {
--- 49 unchanged lines hidden (view full) ---
1668 if (end_of_object) {
1669 p = chunk->pos;
1670 parser->state = UCL_STATE_AFTER_VALUE;
1671 continue;
1672 }
1673 else if (parser->state != UCL_STATE_MACRO_NAME) {
1674 if (next_key && parser->stack->obj->type == UCL_OBJECT) {
1675 /* Parse more keys and nest objects accordingly */
1676 obj = ucl_add_parser_stack (parser->cur_obj, parser, false, parser->stack->level + 1);
1677 }
1678 else {
1679 parser->state = UCL_STATE_VALUE;
1680 }
1681 }
1682 else {
1683 c = chunk->pos;
1684 }
--- 97 unchanged lines hidden (view full) ---
1782}
1783
1784struct ucl_parser*
1785ucl_parser_new (int flags)
1786{
1787 struct ucl_parser *new;
1788
1789 new = UCL_ALLOC (sizeof (struct ucl_parser));
1790 memset (new, 0, sizeof (struct ucl_parser));
1791
1792 ucl_parser_register_macro (new, "include", ucl_include_handler, new);
1793 ucl_parser_register_macro (new, "try_include", ucl_try_include_handler, new);
1794 ucl_parser_register_macro (new, "includes", ucl_includes_handler, new);
1795
1796 new->flags = flags;
1797
--- 5 unchanged lines hidden (view full) ---
1803
1804
1805void
1806ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
1807 ucl_macro_handler handler, void* ud)
1808{
1809 struct ucl_macro *new;
1810
1811 new = UCL_ALLOC (sizeof (struct ucl_macro));
1812 memset (new, 0, sizeof (struct ucl_macro));
1813 new->handler = handler;
1814 new->name = strdup (macro);
1815 new->ud = ud;
1816 HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
1817}
1818
1819void
--- 26 unchanged lines hidden (view full) ---
1846 else {
1847 /* Do nothing */
1848 return;
1849 }
1850 }
1851 else {
1852 if (new == NULL) {
1853 new = UCL_ALLOC (sizeof (struct ucl_variable));
1854 memset (new, 0, sizeof (struct ucl_variable));
1855 new->var = strdup (var);
1856 new->var_len = strlen (var);
1857 new->value = strdup (value);
1858 new->value_len = strlen (value);
1859
1860 LL_PREPEND (parser->variables, new);
1861 }
--- 6 unchanged lines hidden (view full) ---
1868}
1869
1870bool
1871ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
1872 size_t len)
1873{
1874 struct ucl_chunk *chunk;
1875
1876 if (parser->state != UCL_STATE_ERROR) {
1877 chunk = UCL_ALLOC (sizeof (struct ucl_chunk));
1878 chunk->begin = data;
1879 chunk->remain = len;
1880 chunk->pos = chunk->begin;
1881 chunk->end = chunk->begin + len;
1882 chunk->line = 1;
1883 chunk->column = 0;
1884 LL_PREPEND (parser->chunks, chunk);
1885 parser->recursion ++;
--- 4 unchanged lines hidden (view full) ---
1890 }
1891 return ucl_state_machine (parser);
1892 }
1893
1894 ucl_create_err (&parser->err, "a parser is in an invalid state");
1895
1896 return false;
1897}