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}
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}