diff --git a/docs/examples/templates.md b/docs/examples/templates.md
index 398f061..ab9f593 100644
--- a/docs/examples/templates.md
+++ b/docs/examples/templates.md
@@ -20,11 +20,11 @@ description = "Target templates"
type = "executable"
sources = ["src/templates.cpp"]
compile-definitions = ["IS_APP"]
-
# Unlike interface targets you can also inherit properties
-[template.app.properties]
-CXX_STANDARD = "11"
-CXX_STANDARD_REQUIRED = true
+properties = {
+ CXX_STANDARD = "11",
+ CXX_STANDARD_REQUIRED = true,
+}
[target.app-a]
type = "app"
diff --git a/tests/templates/cmake.toml b/tests/templates/cmake.toml
index 31bb2c6..625d27a 100644
--- a/tests/templates/cmake.toml
+++ b/tests/templates/cmake.toml
@@ -8,11 +8,11 @@ description = "Target templates"
type = "executable"
sources = ["src/templates.cpp"]
compile-definitions = ["IS_APP"]
-
# Unlike interface targets you can also inherit properties
-[template.app.properties]
-CXX_STANDARD = "11"
-CXX_STANDARD_REQUIRED = true
+properties = {
+ CXX_STANDARD = "11",
+ CXX_STANDARD_REQUIRED = true,
+}
[target.app-a]
type = "app"
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 3afac4c..c2a275e 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -9,9 +9,10 @@ add_library(ordered_map INTERFACE)
target_include_directories(ordered_map INTERFACE ordered-map-1.0.0/include)
target_compile_definitions(ordered_map INTERFACE NOMINMAX)
-# https://github.com/ToruNiina/toml11 (MIT)
-add_library(toml11 INTERFACE)
-target_include_directories(toml11 INTERFACE toml11-3.6.0)
+# https://github.com/ToruNiina/toml11 (MIT)
+add_library(toml11 INTERFACE)
+target_include_directories(toml11 INTERFACE toml11-3.8.1)
+target_compile_definitions(toml11 INTERFACE TOML11_USE_UNRELEASED_TOML_FEATURES)
# https://github.com/mpark/variant (BSL-1.0)
add_library(mpark_variant INTERFACE)
diff --git a/third_party/toml11-3.6.0/LICENSE b/third_party/toml11-3.8.1/LICENSE
similarity index 100%
rename from third_party/toml11-3.6.0/LICENSE
rename to third_party/toml11-3.8.1/LICENSE
diff --git a/third_party/toml11-3.6.0/toml.hpp b/third_party/toml11-3.8.1/toml.hpp
similarity index 85%
rename from third_party/toml11-3.6.0/toml.hpp
rename to third_party/toml11-3.8.1/toml.hpp
index ce578b6..e975f4e 100644
--- a/third_party/toml11-3.6.0/toml.hpp
+++ b/third_party/toml11-3.8.1/toml.hpp
@@ -25,21 +25,14 @@
#ifndef TOML_FOR_MODERN_CPP
#define TOML_FOR_MODERN_CPP
-#ifndef __cplusplus
-# error "__cplusplus is not defined"
-#endif
-
-#if __cplusplus < 201103L && _MSC_VER < 1900
-# error "toml11 requires C++11 or later."
-#endif
-
#define TOML11_VERSION_MAJOR 3
-#define TOML11_VERSION_MINOR 5
-#define TOML11_VERSION_PATCH 0
+#define TOML11_VERSION_MINOR 8
+#define TOML11_VERSION_PATCH 1
#include "toml/parser.hpp"
#include "toml/literal.hpp"
#include "toml/serializer.hpp"
#include "toml/get.hpp"
+#include "toml/macros.hpp"
#endif// TOML_FOR_MODERN_CPP
diff --git a/third_party/toml11-3.6.0/toml/color.hpp b/third_party/toml11-3.8.1/toml/color.hpp
similarity index 75%
rename from third_party/toml11-3.6.0/toml/color.hpp
rename to third_party/toml11-3.8.1/toml/color.hpp
index 4cb572c..a3fd890 100644
--- a/third_party/toml11-3.6.0/toml/color.hpp
+++ b/third_party/toml11-3.8.1/toml/color.hpp
@@ -17,11 +17,41 @@ namespace color_ansi
{
namespace detail
{
+
inline int colorize_index()
{
static const int index = std::ios_base::xalloc();
return index;
}
+
+// Control color mode globally
+class color_mode
+{
+ public:
+ inline void enable()
+ {
+ should_color_ = true;
+ }
+ inline void disable()
+ {
+ should_color_ = false;
+ }
+
+ inline bool should_color() const
+ {
+ return should_color_;
+ }
+
+ static color_mode& status()
+ {
+ static color_mode status_;
+ return status_;
+ }
+
+ private:
+ bool should_color_ = false;
+};
+
} // detail
inline std::ostream& colorize(std::ostream& os)
@@ -55,6 +85,21 @@ inline std::ostream& cyan (std::ostream& os)
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[36m";} return os;}
inline std::ostream& white (std::ostream& os)
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[37m";} return os;}
+
+inline void enable()
+{
+ return detail::color_mode::status().enable();
+}
+inline void disable()
+{
+ return detail::color_mode::status().disable();
+}
+
+inline bool should_color()
+{
+ return detail::color_mode::status().should_color();
+}
+
} // color_ansi
// ANSI escape sequence is the only and default colorization method currently
diff --git a/third_party/toml11-3.6.0/toml/combinator.hpp b/third_party/toml11-3.8.1/toml/combinator.hpp
similarity index 98%
rename from third_party/toml11-3.6.0/toml/combinator.hpp
rename to third_party/toml11-3.8.1/toml/combinator.hpp
index e250188..33ecca1 100644
--- a/third_party/toml11-3.6.0/toml/combinator.hpp
+++ b/third_party/toml11-3.8.1/toml/combinator.hpp
@@ -29,7 +29,7 @@ namespace detail
// to output character as an error message.
inline std::string show_char(const char c)
{
- // It supress an error that occurs only in Debug mode of MSVC++ on Windows.
+ // It suppresses an error that occurs only in Debug mode of MSVC++ on Windows.
// I'm not completely sure but they check the value of char to be in the
// range [0, 256) and some of the COMPLETELY VALID utf-8 character sometimes
// has negative value (if char has sign). So here it re-interprets c as
@@ -154,7 +154,7 @@ struct sequence
invoke(location& loc)
{
const auto first = loc.iter();
- const auto rslt = Head::invoke(loc);
+ auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.reset(first);
diff --git a/third_party/toml11-3.6.0/toml/comments.hpp b/third_party/toml11-3.8.1/toml/comments.hpp
similarity index 95%
rename from third_party/toml11-3.6.0/toml/comments.hpp
rename to third_party/toml11-3.8.1/toml/comments.hpp
index 1e17544..c0f66f3 100644
--- a/third_party/toml11-3.6.0/toml/comments.hpp
+++ b/third_party/toml11-3.8.1/toml/comments.hpp
@@ -4,11 +4,18 @@
#define TOML11_COMMENTS_HPP
#include
#include
+#include
#include
#include
#include
#include
+#ifdef TOML11_PRESERVE_COMMENTS_BY_DEFAULT
+# define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::preserve_comments
+#else
+# define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::discard_comments
+#endif
+
// This file provides mainly two classes, `preserve_comments` and `discard_comments`.
// Those two are a container that have the same interface as `std::vector`
// but bahaves in the opposite way. `preserve_comments` is just the same as
@@ -339,7 +346,7 @@ operator+(const empty_iterator& lhs, typename empty_iterator::differ
//
// Why this is chose as the default type is because the last version (2.x.y)
// does not contain any comments in a value. To minimize the impact on the
-// efficiency, this is choosed as a default.
+// efficiency, this is chosen as a default.
//
// To reduce the memory footprint, later we can try empty base optimization (EBO).
struct discard_comments
@@ -418,14 +425,14 @@ struct discard_comments
// empty, so accessing through operator[], front/back, data causes address
// error.
- reference operator[](const size_type) noexcept {return *data();}
- const_reference operator[](const size_type) const noexcept {return *data();}
+ reference operator[](const size_type) noexcept {never_call("toml::discard_comment::operator[]");}
+ const_reference operator[](const size_type) const noexcept {never_call("toml::discard_comment::operator[]");}
reference at(const size_type) {throw std::out_of_range("toml::discard_comment is always empty.");}
const_reference at(const size_type) const {throw std::out_of_range("toml::discard_comment is always empty.");}
- reference front() noexcept {return *data();}
- const_reference front() const noexcept {return *data();}
- reference back() noexcept {return *data();}
- const_reference back() const noexcept {return *data();}
+ reference front() noexcept {never_call("toml::discard_comment::front");}
+ const_reference front() const noexcept {never_call("toml::discard_comment::front");}
+ reference back() noexcept {never_call("toml::discard_comment::back");}
+ const_reference back() const noexcept {never_call("toml::discard_comment::back");}
pointer data() noexcept {return nullptr;}
const_pointer data() const noexcept {return nullptr;}
@@ -443,6 +450,18 @@ struct discard_comments
const_reverse_iterator rend() const noexcept {return const_iterator{};}
const_reverse_iterator crbegin() const noexcept {return const_iterator{};}
const_reverse_iterator crend() const noexcept {return const_iterator{};}
+
+ private:
+
+ [[noreturn]] static void never_call(const char *const this_function)
+ {
+#ifdef __has_builtin
+# if __has_builtin(__builtin_unreachable)
+ __builtin_unreachable();
+# endif
+#endif
+ throw std::logic_error{this_function};
+ }
};
inline bool operator==(const discard_comments&, const discard_comments&) noexcept {return true;}
diff --git a/third_party/toml11-3.6.0/toml/datetime.hpp b/third_party/toml11-3.8.1/toml/datetime.hpp
similarity index 96%
rename from third_party/toml11-3.6.0/toml/datetime.hpp
rename to third_party/toml11-3.8.1/toml/datetime.hpp
index d8127c1..83d04ba 100644
--- a/third_party/toml11-3.6.0/toml/datetime.hpp
+++ b/third_party/toml11-3.8.1/toml/datetime.hpp
@@ -21,34 +21,34 @@ namespace toml
namespace detail
{
// TODO: find more sophisticated way to handle this
-#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) || defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_POSIX_SOURCE)
+#if defined(_MSC_VER)
inline std::tm localtime_s(const std::time_t* src)
{
std::tm dst;
- const auto result = ::localtime_r(src, &dst);
- if (!result) { throw std::runtime_error("localtime_r failed."); }
+ const auto result = ::localtime_s(&dst, src);
+ if (result) { throw std::runtime_error("localtime_s failed."); }
return dst;
}
inline std::tm gmtime_s(const std::time_t* src)
{
std::tm dst;
- const auto result = ::gmtime_r(src, &dst);
- if (!result) { throw std::runtime_error("gmtime_r failed."); }
+ const auto result = ::gmtime_s(&dst, src);
+ if (result) { throw std::runtime_error("gmtime_s failed."); }
return dst;
}
-#elif defined(_MSC_VER)
+#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) || defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_POSIX_SOURCE)
inline std::tm localtime_s(const std::time_t* src)
{
std::tm dst;
- const auto result = ::localtime_s(&dst, src);
- if (result) { throw std::runtime_error("localtime_s failed."); }
+ const auto result = ::localtime_r(src, &dst);
+ if (!result) { throw std::runtime_error("localtime_r failed."); }
return dst;
}
inline std::tm gmtime_s(const std::time_t* src)
{
std::tm dst;
- const auto result = ::gmtime_s(&dst, src);
- if (result) { throw std::runtime_error("gmtime_s failed."); }
+ const auto result = ::gmtime_r(src, &dst);
+ if (!result) { throw std::runtime_error("gmtime_r failed."); }
return dst;
}
#else // fallback. not threadsafe
@@ -85,9 +85,9 @@ enum class month_t : std::uint8_t
struct local_date
{
- std::int16_t year; // A.D. (like, 2018)
- std::uint8_t month; // [0, 11]
- std::uint8_t day; // [1, 31]
+ std::int16_t year{}; // A.D. (like, 2018)
+ std::uint8_t month{}; // [0, 11]
+ std::uint8_t day{}; // [1, 31]
local_date(int y, month_t m, int d)
: year (static_cast(y)),
@@ -181,12 +181,12 @@ operator<<(std::basic_ostream& os, const local_date& date)
struct local_time
{
- std::uint8_t hour; // [0, 23]
- std::uint8_t minute; // [0, 59]
- std::uint8_t second; // [0, 60]
- std::uint16_t millisecond; // [0, 999]
- std::uint16_t microsecond; // [0, 999]
- std::uint16_t nanosecond; // [0, 999]
+ std::uint8_t hour{}; // [0, 23]
+ std::uint8_t minute{}; // [0, 59]
+ std::uint8_t second{}; // [0, 60]
+ std::uint16_t millisecond{}; // [0, 999]
+ std::uint16_t microsecond{}; // [0, 999]
+ std::uint16_t nanosecond{}; // [0, 999]
local_time(int h, int m, int s,
int ms = 0, int us = 0, int ns = 0)
@@ -297,8 +297,8 @@ operator<<(std::basic_ostream& os, const local_time& time)
struct time_offset
{
- std::int8_t hour; // [-12, 12]
- std::int8_t minute; // [-59, 59]
+ std::int8_t hour{}; // [-12, 12]
+ std::int8_t minute{}; // [-59, 59]
time_offset(int h, int m)
: hour (static_cast(h)),
@@ -364,8 +364,8 @@ operator<<(std::basic_ostream& os, const time_offset& offset)
struct local_datetime
{
- local_date date;
- local_time time;
+ local_date date{};
+ local_time time{};
local_datetime(local_date d, local_time t): date(d), time(t) {}
@@ -478,9 +478,9 @@ operator<<(std::basic_ostream& os, const local_datetime& dt)
struct offset_datetime
{
- local_date date;
- local_time time;
- time_offset offset;
+ local_date date{};
+ local_time time{};
+ time_offset offset{};
offset_datetime(local_date d, local_time t, time_offset o)
: date(d), time(t), offset(o)
diff --git a/third_party/toml11-3.6.0/toml/exception.hpp b/third_party/toml11-3.8.1/toml/exception.hpp
similarity index 81%
rename from third_party/toml11-3.6.0/toml/exception.hpp
rename to third_party/toml11-3.8.1/toml/exception.hpp
index c64651d..06bfe6e 100644
--- a/third_party/toml11-3.6.0/toml/exception.hpp
+++ b/third_party/toml11-3.8.1/toml/exception.hpp
@@ -2,14 +2,32 @@
// Distributed under the MIT License.
#ifndef TOML11_EXCEPTION_HPP
#define TOML11_EXCEPTION_HPP
-#include
+
+#include
#include
+#include
+
+#include
#include "source_location.hpp"
namespace toml
{
+struct file_io_error : public std::runtime_error
+{
+ public:
+ file_io_error(int errnum, const std::string& msg, const std::string& fname)
+ : std::runtime_error(msg + " \"" + fname + "\": errno = " + std::to_string(errnum)),
+ errno_(errnum)
+ {}
+
+ int get_errno() const noexcept {return errno_;}
+
+ private:
+ int errno_;
+};
+
struct exception : public std::exception
{
public:
diff --git a/third_party/toml11-3.6.0/toml/from.hpp b/third_party/toml11-3.8.1/toml/from.hpp
similarity index 93%
rename from third_party/toml11-3.6.0/toml/from.hpp
rename to third_party/toml11-3.8.1/toml/from.hpp
index 8251973..10815ca 100644
--- a/third_party/toml11-3.6.0/toml/from.hpp
+++ b/third_party/toml11-3.8.1/toml/from.hpp
@@ -2,7 +2,6 @@
// Distributed under the MIT License.
#ifndef TOML11_FROM_HPP
#define TOML11_FROM_HPP
-#include "traits.hpp"
namespace toml
{
diff --git a/third_party/toml11-3.6.0/toml/get.hpp b/third_party/toml11-3.8.1/toml/get.hpp
similarity index 89%
rename from third_party/toml11-3.6.0/toml/get.hpp
rename to third_party/toml11-3.8.1/toml/get.hpp
index 3be82bf..ac1b354 100644
--- a/third_party/toml11-3.6.0/toml/get.hpp
+++ b/third_party/toml11-3.8.1/toml/get.hpp
@@ -140,7 +140,7 @@ get(basic_value&& v)
// ============================================================================
// std::string_view
-#if __cplusplus >= 201703L
+#if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0
template class M, template class V>
inline detail::enable_if_t::value, std::string_view>
@@ -215,6 +215,7 @@ template, // T is a container
detail::negation>, // w/o push_back(...)
+ detail::negation>, // T does not have special conversion
detail::negation< // not toml::array
detail::is_exact_toml_type>>
>::value, T>
@@ -255,19 +256,37 @@ get(const basic_value&);
// toml::from::from_toml(v)
template class M, template class V,
- std::size_t S = sizeof(::toml::from)>
-T get(const basic_value&);
+ template class M, template class V>
+detail::enable_if_t::value, T>
+get(const basic_value&);
-// T(const toml::value&) and T is not toml::basic_value
+template class M, template class V>
+detail::enable_if_t::value, T>
+get(basic_value&);
+
+// T(const toml::value&) and T is not toml::basic_value,
+// and it does not have `from` nor `from_toml`.
template class M, template class V>
detail::enable_if_t>,
- std::is_constructible&>
+ std::is_constructible&>,
+ detail::negation>,
+ detail::negation>
>::value, T>
get(const basic_value&);
+template class M, template class V>
+detail::enable_if_t>,
+ std::is_constructible&>,
+ detail::negation>,
+ detail::negation>
+ >::value, T>
+get(basic_value&);
+
// ============================================================================
// array-like types; most likely STL container, like std::vector, etc.
@@ -321,6 +340,7 @@ template, // T is a container
detail::negation>, // w/o push_back
+ detail::negation>, // T does not have special conversion
detail::negation< // T is not toml::array
detail::is_exact_toml_type>>
>::value, T>
@@ -338,8 +358,10 @@ get(const basic_value& v)
{v.location(), "here"}
}));
}
- std::transform(ar.cbegin(), ar.cend(), container.begin(),
- [](const value& x){return ::toml::get(x);});
+ for(std::size_t i=0; i(ar[i]);
+ }
return container;
}
@@ -438,9 +460,16 @@ get(const basic_value& v)
return ud;
}
template class M, template class V,
- std::size_t>
-T get(const basic_value& v)
+ template class M, template class V>
+detail::enable_if_t::value, T>
+get(const basic_value& v)
+{
+ return ::toml::from::from_toml(v);
+}
+template class M, template class V>
+detail::enable_if_t::value, T>
+get(basic_value& v)
{
return ::toml::from::from_toml(v);
}
@@ -448,14 +477,29 @@ T get(const basic_value& v)
template class M, template class V>
detail::enable_if_t>,
- std::is_constructible&>
+ detail::negation>, // T is not a toml::value
+ std::is_constructible&>, // T is constructible from toml::value
+ detail::negation>, // and T does not have T.from_toml(v);
+ detail::negation> // and T does not have toml::from{};
>::value, T>
get(const basic_value& v)
{
return T(v);
}
+template class M, template class V>
+detail::enable_if_t>, // T is not a toml::value
+ std::is_constructible&>, // T is constructible from toml::value
+ detail::negation>, // and T does not have T.from_toml(v);
+ detail::negation> // and T does not have toml::from{};
+ >::value, T>
+get(basic_value& v)
+{
+ return T(v);
+}
+
// ============================================================================
// find
@@ -1031,6 +1075,50 @@ find_or(const basic_value& v, const toml::key& ky, T&& opt)
return get_or(tab.at(ky), std::forward(opt));
}
+// ---------------------------------------------------------------------------
+// recursive find-or with type deduction (find_or(value, keys, opt))
+
+template 1), std::nullptr_t> = nullptr>
+ // here we need to add SFINAE in the template parameter to avoid
+ // infinite recursion in type deduction on gcc
+auto find_or(Value&& v, const toml::key& ky, Ks&& ... keys)
+ -> decltype(find_or(std::forward(v), ky, detail::last_one(std::forward(keys)...)))
+{
+ if(!v.is_table())
+ {
+ return detail::last_one(std::forward(keys)...);
+ }
+ auto&& tab = std::forward(v).as_table();
+ if(tab.count(ky) == 0)
+ {
+ return detail::last_one(std::forward(keys)...);
+ }
+ return find_or(std::forward(tab).at(ky), std::forward(keys)...);
+}
+
+// ---------------------------------------------------------------------------
+// recursive find_or with explicit type specialization, find_or(value, keys...)
+
+template 1), std::nullptr_t> = nullptr>
+ // here we need to add SFINAE in the template parameter to avoid
+ // infinite recursion in type deduction on gcc
+auto find_or(Value&& v, const toml::key& ky, Ks&& ... keys)
+ -> decltype(find_or(std::forward(v), ky, detail::last_one(std::forward(keys)...)))
+{
+ if(!v.is_table())
+ {
+ return detail::last_one(std::forward(keys)...);
+ }
+ auto&& tab = std::forward(v).as_table();
+ if(tab.count(ky) == 0)
+ {
+ return detail::last_one(std::forward(keys)...);
+ }
+ return find_or(std::forward(tab).at(ky), std::forward(keys)...);
+}
+
// ============================================================================
// expect
diff --git a/third_party/toml11-3.6.0/toml/into.hpp b/third_party/toml11-3.8.1/toml/into.hpp
similarity index 94%
rename from third_party/toml11-3.6.0/toml/into.hpp
rename to third_party/toml11-3.8.1/toml/into.hpp
index 17f2248..7449556 100644
--- a/third_party/toml11-3.6.0/toml/into.hpp
+++ b/third_party/toml11-3.8.1/toml/into.hpp
@@ -2,7 +2,6 @@
// Distributed under the MIT License.
#ifndef TOML11_INTO_HPP
#define TOML11_INTO_HPP
-#include "traits.hpp"
namespace toml
{
diff --git a/third_party/toml11-3.6.0/toml/lexer.hpp b/third_party/toml11-3.8.1/toml/lexer.hpp
similarity index 87%
rename from third_party/toml11-3.6.0/toml/lexer.hpp
rename to third_party/toml11-3.8.1/toml/lexer.hpp
index 2eea996..2a1ff2d 100644
--- a/third_party/toml11-3.6.0/toml/lexer.hpp
+++ b/third_party/toml11-3.8.1/toml/lexer.hpp
@@ -5,7 +5,6 @@
#include
#include
#include
-#include
#include "combinator.hpp"
@@ -119,8 +118,8 @@ using lex_local_time = lex_partial_time;
// ===========================================================================
using lex_quotation_mark = character<'"'>;
-using lex_basic_unescaped = exclude, // 0x09 (tab)
- in_range<0x0a, 0x1F>, // is allowed
+using lex_basic_unescaped = exclude, // 0x09 (tab) is allowed
+ in_range<0x0A, 0x1F>,
character<0x22>, character<0x5C>,
character<0x7F>>>;
@@ -133,6 +132,9 @@ using lex_escape_seq_char = either, character<'\\'>,
character<'b'>, character<'f'>,
character<'n'>, character<'r'>,
character<'t'>,
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+ character<'e'>, // ESC (0x1B)
+#endif
lex_escape_unicode_short,
lex_escape_unicode_long
>;
@@ -166,7 +168,7 @@ using lex_basic_string = sequence, maybe
>;
-using lex_ml_basic_unescaped = exclude, // 0x09
- in_range<0x0a, 0x1F>, // is tab
+using lex_ml_basic_unescaped = exclude, // 0x09 is tab
+ in_range<0x0A, 0x1F>,
character<0x5C>, // backslash
character<0x7F>, // DEL
lex_ml_basic_string_delim>>;
@@ -196,8 +198,8 @@ using lex_ml_basic_string = sequence;
-using lex_literal_char = exclude,
- in_range<0x10, 0x19>, character<0x27>>>;
+using lex_literal_char = exclude, in_range<0x0A, 0x1F>,
+ character<0x7F>, character<0x27>>>;
using lex_apostrophe = character<'\''>;
using lex_literal_string = sequence,
@@ -212,7 +214,7 @@ using lex_ml_literal_string_close = sequence<
>;
using lex_ml_literal_char = exclude,
- in_range<0x10, 0x1F>,
+ in_range<0x0A, 0x1F>,
character<0x7F>,
lex_ml_literal_string_delim>>;
using lex_ml_literal_body = repeat,
@@ -225,12 +227,6 @@ using lex_string = either;
// ===========================================================================
-
-using lex_comment_start_symbol = character<'#'>;
-using lex_non_eol = either, exclude>>;
-using lex_comment = sequence>;
-
using lex_dot_sep = sequence, character<'.'>, maybe>;
using lex_unquoted_key = repeat,
lex_array_table_close>;
+using lex_utf8_1byte = in_range<0x00, 0x7F>;
+using lex_utf8_2byte = sequence<
+ in_range<'\xC2', '\xDF'>,
+ in_range<'\x80', '\xBF'>
+ >;
+using lex_utf8_3byte = sequence, in_range<'\xA0', '\xBF'>>,
+ sequence, in_range<'\x80', '\xBF'>>,
+ sequence, in_range<'\x80', '\x9F'>>,
+ sequence, in_range<'\x80', '\xBF'>>
+ >, in_range<'\x80', '\xBF'>>;
+using lex_utf8_4byte = sequence, in_range<'\x90', '\xBF'>>,
+ sequence, in_range<'\x80', '\xBF'>>,
+ sequence, in_range<'\x80', '\x8F'>>
+ >, in_range<'\x80', '\xBF'>, in_range<'\x80', '\xBF'>>;
+using lex_utf8_code = either<
+ lex_utf8_1byte,
+ lex_utf8_2byte,
+ lex_utf8_3byte,
+ lex_utf8_4byte
+ >;
+
+using lex_comment_start_symbol = character<'#'>;
+using lex_non_eol_ascii = either, in_range<0x20, 0x7E>>;
+using lex_comment = sequence, unlimited>>;
+
} // detail
} // toml
#endif // TOML_LEXER_HPP
diff --git a/third_party/toml11-3.6.0/toml/literal.hpp b/third_party/toml11-3.8.1/toml/literal.hpp
similarity index 80%
rename from third_party/toml11-3.6.0/toml/literal.hpp
rename to third_party/toml11-3.8.1/toml/literal.hpp
index 2c3d18c..5086a76 100644
--- a/third_party/toml11-3.6.0/toml/literal.hpp
+++ b/third_party/toml11-3.8.1/toml/literal.hpp
@@ -12,8 +12,11 @@ inline namespace toml_literals
{
// implementation
-inline ::toml::value literal_internal_impl(::toml::detail::location loc)
+inline ::toml::basic_value
+literal_internal_impl(::toml::detail::location loc)
{
+ using value_type = ::toml::basic_value<
+ TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>;
// if there are some comments or empty lines, skip them.
using skip_line = ::toml::detail::repeat,
@@ -50,7 +53,7 @@ inline ::toml::value literal_internal_impl(::toml::detail::location loc)
// If it is neither a table-key or a array-of-table-key, it may be a value.
if(!is_table_key && !is_aots_key)
{
- if(auto data = ::toml::detail::parse_value<::toml::value>(loc))
+ if(auto data = ::toml::detail::parse_value(loc, 0))
{
return data.unwrap();
}
@@ -67,7 +70,7 @@ inline ::toml::value literal_internal_impl(::toml::detail::location loc)
// It is a valid toml file.
// It should be parsed as if we parse a file with this content.
- if(auto data = ::toml::detail::parse_toml_file<::toml::value>(loc))
+ if(auto data = ::toml::detail::parse_toml_file(loc))
{
return data.unwrap();
}
@@ -78,11 +81,13 @@ inline ::toml::value literal_internal_impl(::toml::detail::location loc)
}
-inline ::toml::value operator"" _toml(const char* str, std::size_t len)
+inline ::toml::basic_value
+operator"" _toml(const char* str, std::size_t len)
{
::toml::detail::location loc(
std::string("TOML literal encoded in a C++ code"),
std::vector(str, str + len));
+ // literal length does not include the null character at the end.
return literal_internal_impl(std::move(loc));
}
@@ -91,7 +96,8 @@ inline ::toml::value operator"" _toml(const char* str, std::size_t len)
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
// value of u8"" literal has been changed from char to char8_t and char8_t is
// NOT compatible to char
-inline ::toml::value operator"" _toml(const char8_t* str, std::size_t len)
+inline ::toml::basic_value
+operator"" _toml(const char8_t* str, std::size_t len)
{
::toml::detail::location loc(
std::string("TOML literal encoded in a C++ code"),
diff --git a/third_party/toml11-3.8.1/toml/macros.hpp b/third_party/toml11-3.8.1/toml/macros.hpp
new file mode 100644
index 0000000..e8f91ae
--- /dev/null
+++ b/third_party/toml11-3.8.1/toml/macros.hpp
@@ -0,0 +1,121 @@
+#ifndef TOML11_MACROS_HPP
+#define TOML11_MACROS_HPP
+
+#define TOML11_STRINGIZE_AUX(x) #x
+#define TOML11_STRINGIZE(x) TOML11_STRINGIZE_AUX(x)
+
+#define TOML11_CONCATENATE_AUX(x, y) x##y
+#define TOML11_CONCATENATE(x, y) TOML11_CONCATENATE_AUX(x, y)
+
+// ============================================================================
+// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE
+
+#ifndef TOML11_WITHOUT_DEFINE_NON_INTRUSIVE
+
+// ----------------------------------------------------------------------------
+// TOML11_ARGS_SIZE
+
+#define TOML11_INDEX_RSEQ() \
+ 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
+ 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+#define TOML11_ARGS_SIZE_IMPL(\
+ ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, ARG10, \
+ ARG11, ARG12, ARG13, ARG14, ARG15, ARG16, ARG17, ARG18, ARG19, ARG20, \
+ ARG21, ARG22, ARG23, ARG24, ARG25, ARG26, ARG27, ARG28, ARG29, ARG30, \
+ ARG31, ARG32, N, ...) N
+#define TOML11_ARGS_SIZE_AUX(...) TOML11_ARGS_SIZE_IMPL(__VA_ARGS__)
+#define TOML11_ARGS_SIZE(...) TOML11_ARGS_SIZE_AUX(__VA_ARGS__, TOML11_INDEX_RSEQ())
+
+// ----------------------------------------------------------------------------
+// TOML11_FOR_EACH_VA_ARGS
+
+#define TOML11_FOR_EACH_VA_ARGS_AUX_1( FUNCTOR, ARG1 ) FUNCTOR(ARG1)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_2( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_1( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_3( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_2( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_4( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_3( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_5( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_4( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_6( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_5( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_7( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_6( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_8( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_7( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_9( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_8( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_10(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_9( FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_11(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_10(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_12(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_11(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_13(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_12(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_14(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_13(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_15(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_14(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_16(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_15(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_17(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_16(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_18(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_17(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_19(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_18(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_20(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_19(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_21(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_20(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_22(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_21(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_23(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_22(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_24(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_23(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_25(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_24(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_26(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_25(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_27(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_26(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_28(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_27(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_29(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_28(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_30(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_29(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_31(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_30(FUNCTOR, __VA_ARGS__)
+#define TOML11_FOR_EACH_VA_ARGS_AUX_32(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_31(FUNCTOR, __VA_ARGS__)
+
+#define TOML11_FOR_EACH_VA_ARGS(FUNCTOR, ...)\
+ TOML11_CONCATENATE(TOML11_FOR_EACH_VA_ARGS_AUX_, TOML11_ARGS_SIZE(__VA_ARGS__))(FUNCTOR, __VA_ARGS__)
+
+// ----------------------------------------------------------------------------
+// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE
+
+// use it in the following way.
+// ```cpp
+// namespace foo
+// {
+// struct Foo
+// {
+// std::string s;
+// double d;
+// int i;
+// };
+// } // foo
+//
+// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(foo::Foo, s, d, i)
+// ```
+// And then you can use `toml::find(file, "foo");`
+//
+#define TOML11_FIND_MEMBER_VARIABLE_FROM_VALUE(VAR_NAME)\
+ obj.VAR_NAME = toml::find(v, TOML11_STRINGIZE(VAR_NAME));
+
+#define TOML11_ASSIGN_MEMBER_VARIABLE_TO_VALUE(VAR_NAME)\
+ v[TOML11_STRINGIZE(VAR_NAME)] = obj.VAR_NAME;
+
+#define TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(NAME, ...)\
+ namespace toml { \
+ template<> \
+ struct from \
+ { \
+ template class T, \
+ template class A> \
+ static NAME from_toml(const basic_value& v) \
+ { \
+ NAME obj; \
+ TOML11_FOR_EACH_VA_ARGS(TOML11_FIND_MEMBER_VARIABLE_FROM_VALUE, __VA_ARGS__) \
+ return obj; \
+ } \
+ }; \
+ template<> \
+ struct into \
+ { \
+ static value into_toml(const NAME& obj) \
+ { \
+ ::toml::value v = ::toml::table{}; \
+ TOML11_FOR_EACH_VA_ARGS(TOML11_ASSIGN_MEMBER_VARIABLE_TO_VALUE, __VA_ARGS__) \
+ return v; \
+ } \
+ }; \
+ } /* toml */
+
+#endif// TOML11_WITHOUT_DEFINE_NON_INTRUSIVE
+
+#endif// TOML11_MACROS_HPP
diff --git a/third_party/toml11-3.6.0/toml/parser.hpp b/third_party/toml11-3.8.1/toml/parser.hpp
similarity index 74%
rename from third_party/toml11-3.6.0/toml/parser.hpp
rename to third_party/toml11-3.8.1/toml/parser.hpp
index a52d8c9..3f73ef9 100644
--- a/third_party/toml11-3.6.0/toml/parser.hpp
+++ b/third_party/toml11-3.8.1/toml/parser.hpp
@@ -8,17 +8,25 @@
#include "combinator.hpp"
#include "lexer.hpp"
+#include "macros.hpp"
#include "region.hpp"
#include "result.hpp"
#include "types.hpp"
#include "value.hpp"
-#if __cplusplus >= 201703L
+#ifndef TOML11_DISABLE_STD_FILESYSTEM
+#ifdef __cpp_lib_filesystem
#if __has_include()
#define TOML11_HAS_STD_FILESYSTEM
#include
#endif // has_include()
-#endif // cplusplus >= C++17
+#endif // __cpp_lib_filesystem
+#endif // TOML11_DISABLE_STD_FILESYSTEM
+
+// the previous commit works with 500+ recursions. so it may be too small.
+// but in most cases, i think we don't need such a deep recursion of
+// arrays or inline-tables.
+#define TOML11_VALUE_RECURSION_LIMIT 64
namespace toml
{
@@ -55,16 +63,55 @@ parse_binary_integer(location& loc)
{
auto str = token.unwrap().str();
assert(str.size() > 2); // minimum -> 0b1
+ assert(str.at(0) == '0' && str.at(1) == 'b');
+
+ // skip all the zeros and `_` locating at the MSB
+ str.erase(str.begin(), std::find_if(
+ str.begin() + 2, // to skip prefix `0b`
+ str.end(),
+ [](const char c) { return c == '1'; })
+ );
+ assert(str.empty() || str.front() == '1');
+
+ // since toml11 uses int64_t, 64bit (unsigned) input cannot be read.
+ const auto max_length = 63 + std::count(str.begin(), str.end(), '_');
+ if(static_cast(max_length) < str.size())
+ {
+ loc.reset(first);
+ return err(format_underline("toml::parse_binary_integer: "
+ "only signed 64bit integer is available",
+ {{source_location(loc), "too large input (> int64_t)"}}));
+ }
+
integer retval(0), base(1);
- for(auto i(str.rbegin()), e(str.rend() - 2); i!=e; ++i)
+ for(auto i(str.rbegin()), e(str.rend()); i!=e; ++i)
{
- if (*i == '1'){retval += base; base *= 2;}
- else if(*i == '0'){base *= 2;}
- else if(*i == '_'){/* do nothing. */}
- else // internal error.
+ assert(base != 0); // means overflow, checked in the above code
+ if(*i == '1')
+ {
+ retval += base;
+ if( (std::numeric_limits::max)() / 2 < base )
+ {
+ base = 0;
+ }
+ base *= 2;
+ }
+ else if(*i == '0')
+ {
+ if( (std::numeric_limits::max)() / 2 < base )
+ {
+ base = 0;
+ }
+ base *= 2;
+ }
+ else if(*i == '_')
+ {
+ // do nothing.
+ }
+ else // should be detected by lex_bin_int. [[unlikely]]
{
throw internal_error(format_underline(
- "toml::parse_integer: internal error",
+ "toml::parse_binary_integer: internal error",
{{source_location(token.unwrap()), "invalid token"}}),
source_location(loc));
}
@@ -89,6 +136,21 @@ parse_octal_integer(location& loc)
std::istringstream iss(str);
integer retval(0);
iss >> std::oct >> retval;
+ if(iss.fail())
+ {
+ // `istream` sets `failbit` if internally-called `std::num_get::get`
+ // fails.
+ // `std::num_get::get` calls `std::strtoll` if the argument type is
+ // signed.
+ // `std::strtoll` fails if
+ // - the value is out_of_range or
+ // - no conversion is possible.
+ // since we already checked that the string is valid octal integer,
+ // so the error reason is out_of_range.
+ loc.reset(first);
+ return err(format_underline("toml::parse_octal_integer:",
+ {{source_location(loc), "out of range"}}));
+ }
return ok(std::make_pair(retval, token.unwrap()));
}
loc.reset(first);
@@ -109,6 +171,13 @@ parse_hexadecimal_integer(location& loc)
std::istringstream iss(str);
integer retval(0);
iss >> std::hex >> retval;
+ if(iss.fail())
+ {
+ // see parse_octal_integer for detail of this error message.
+ loc.reset(first);
+ return err(format_underline("toml::parse_hexadecimal_integer:",
+ {{source_location(loc), "out of range"}}));
+ }
return ok(std::make_pair(retval, token.unwrap()));
}
loc.reset(first);
@@ -155,6 +224,13 @@ parse_integer(location& loc)
std::istringstream iss(str);
integer retval(0);
iss >> retval;
+ if(iss.fail())
+ {
+ // see parse_octal_integer for detail of this error message.
+ loc.reset(first);
+ return err(format_underline("toml::parse_integer:",
+ {{source_location(loc), "out of range"}}));
+ }
return ok(std::make_pair(retval, token.unwrap()));
}
loc.reset(first);
@@ -243,6 +319,13 @@ parse_floating(location& loc)
std::istringstream iss(str);
floating v(0.0);
iss >> v;
+ if(iss.fail())
+ {
+ // see parse_octal_integer for detail of this error message.
+ loc.reset(first);
+ return err(format_underline("toml::parse_floating:",
+ {{source_location(loc), "out of range"}}));
+ }
return ok(std::make_pair(v, token.unwrap()));
}
loc.reset(first);
@@ -325,6 +408,9 @@ inline result parse_escape_sequence(location& loc)
case 'n' :{loc.advance(); return ok(std::string("\n"));}
case 'f' :{loc.advance(); return ok(std::string("\f"));}
case 'r' :{loc.advance(); return ok(std::string("\r"));}
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+ case 'e' :{loc.advance(); return ok(std::string("\x1b"));} // ESC
+#endif
case 'u' :
{
if(const auto token = lex_escape_unicode_short::invoke(loc))
@@ -362,6 +448,19 @@ inline result parse_escape_sequence(location& loc)
return err(msg);
}
+inline std::ptrdiff_t check_utf8_validity(const std::string& reg)
+{
+ location loc("tmp", reg);
+ const auto u8 = repeat::invoke(loc);
+ if(!u8 || loc.iter() != loc.end())
+ {
+ const auto error_location = std::distance(loc.begin(), loc.iter());
+ assert(0 <= error_location);
+ return error_location;
+ }
+ return -1;
+}
+
inline result, std::string>
parse_ml_basic_string(location& loc)
{
@@ -430,7 +529,21 @@ parse_ml_basic_string(location& loc)
source_location(inner_loc));
}
}
- return ok(std::make_pair(toml::string(retval), token.unwrap()));
+
+ const auto err_loc = check_utf8_validity(token.unwrap().str());
+ if(err_loc == -1)
+ {
+ return ok(std::make_pair(toml::string(retval), token.unwrap()));
+ }
+ else
+ {
+ inner_loc.reset(first);
+ inner_loc.advance(err_loc);
+ throw syntax_error(format_underline(
+ "parse_ml_basic_string: invalid utf8 sequence found",
+ {{source_location(inner_loc), "here"}}),
+ source_location(inner_loc));
+ }
}
else
{
@@ -482,7 +595,21 @@ parse_basic_string(location& loc)
}
quot = lex_quotation_mark::invoke(inner_loc);
}
- return ok(std::make_pair(toml::string(retval), token.unwrap()));
+
+ const auto err_loc = check_utf8_validity(token.unwrap().str());
+ if(err_loc == -1)
+ {
+ return ok(std::make_pair(toml::string(retval), token.unwrap()));
+ }
+ else
+ {
+ inner_loc.reset(first);
+ inner_loc.advance(err_loc);
+ throw syntax_error(format_underline(
+ "parse_basic_string: invalid utf8 sequence found",
+ {{source_location(inner_loc), "here"}}),
+ source_location(inner_loc));
+ }
}
else
{
@@ -499,7 +626,8 @@ parse_ml_literal_string(location& loc)
const auto first = loc.iter();
if(const auto token = lex_ml_literal_string::invoke(loc))
{
- location inner_loc(loc.name(), token.unwrap().str());
+ auto inner_loc = loc;
+ inner_loc.reset(first);
const auto open = lex_ml_literal_string_open::invoke(inner_loc);
if(!open)
@@ -543,8 +671,22 @@ parse_ml_literal_string(location& loc)
source_location(inner_loc));
}
}
- return ok(std::make_pair(toml::string(retval, toml::string_t::literal),
- token.unwrap()));
+
+ const auto err_loc = check_utf8_validity(token.unwrap().str());
+ if(err_loc == -1)
+ {
+ return ok(std::make_pair(toml::string(retval, toml::string_t::literal),
+ token.unwrap()));
+ }
+ else
+ {
+ inner_loc.reset(first);
+ inner_loc.advance(err_loc);
+ throw syntax_error(format_underline(
+ "parse_ml_literal_string: invalid utf8 sequence found",
+ {{source_location(inner_loc), "here"}}),
+ source_location(inner_loc));
+ }
}
else
{
@@ -561,7 +703,8 @@ parse_literal_string(location& loc)
const auto first = loc.iter();
if(const auto token = lex_literal_string::invoke(loc))
{
- location inner_loc(loc.name(), token.unwrap().str());
+ auto inner_loc = loc;
+ inner_loc.reset(first);
const auto open = lex_apostrophe::invoke(inner_loc);
if(!open)
@@ -582,9 +725,23 @@ parse_literal_string(location& loc)
{{source_location(inner_loc), "should be '"}}),
source_location(inner_loc));
}
- return ok(std::make_pair(
- toml::string(body.unwrap().str(), toml::string_t::literal),
- token.unwrap()));
+
+ const auto err_loc = check_utf8_validity(token.unwrap().str());
+ if(err_loc == -1)
+ {
+ return ok(std::make_pair(
+ toml::string(body.unwrap().str(), toml::string_t::literal),
+ token.unwrap()));
+ }
+ else
+ {
+ inner_loc.reset(first);
+ inner_loc.advance(err_loc);
+ throw syntax_error(format_underline(
+ "parse_literal_string: invalid utf8 sequence found",
+ {{source_location(inner_loc), "here"}}),
+ source_location(inner_loc));
+ }
}
else
{
@@ -638,7 +795,7 @@ parse_local_date(location& loc)
if(!y || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-')
{
throw internal_error(format_underline(
- "toml::parse_inner_local_date: invalid year format",
+ "toml::parse_local_date: invalid year format",
{{source_location(inner_loc), "should be `-`"}}),
source_location(inner_loc));
}
@@ -660,12 +817,36 @@ parse_local_date(location& loc)
{{source_location(inner_loc), "here"}}),
source_location(inner_loc));
}
- return ok(std::make_pair(local_date(
- static_cast(from_string(y.unwrap().str(), 0)),
- static_cast(
- static_cast(from_string(m.unwrap().str(), 0)-1)),
- static_cast(from_string(d.unwrap().str(), 0))),
- token.unwrap()));
+
+ const auto year = static_cast(from_string(y.unwrap().str(), 0));
+ const auto month = static_cast(from_string(m.unwrap().str(), 0));
+ const auto day = static_cast(from_string(d.unwrap().str(), 0));
+
+ // We briefly check whether the input date is valid or not. But here, we
+ // only check if the RFC3339 compliance.
+ // Actually there are several special date that does not exist,
+ // because of historical reasons, such as 1582/10/5-1582/10/14 (only in
+ // several countries). But here, we do not care about such a complicated
+ // rule. It makes the code complicated and there is only low probability
+ // that such a specific date is needed in practice. If someone need to
+ // validate date accurately, that means that the one need a specialized
+ // library for their purpose in a different layer.
+ {
+ const bool is_leap = (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
+ const auto max_day = (month == 2) ? (is_leap ? 29 : 28) :
+ ((month == 4 || month == 6 || month == 9 || month == 11) ? 30 : 31);
+
+ if((month < 1 || 12 < month) || (day < 1 || max_day < day))
+ {
+ throw syntax_error(format_underline("toml::parse_date: "
+ "invalid date: it does not conform RFC3339.", {{
+ source_location(loc), "month should be 01-12, day should be"
+ " 01-28,29,30,31, depending on month/year."
+ }}), source_location(inner_loc));
+ }
+ }
+ return ok(std::make_pair(local_date(year, static_cast(month - 1), day),
+ token.unwrap()));
}
else
{
@@ -709,10 +890,22 @@ parse_local_time(location& loc)
{{source_location(inner_loc), "here"}}),
source_location(inner_loc));
}
- local_time time(
- from_string(h.unwrap().str(), 0),
- from_string(m.unwrap().str(), 0),
- from_string(s.unwrap().str(), 0), 0, 0);
+
+ const int hour = from_string(h.unwrap().str(), 0);
+ const int minute = from_string(m.unwrap().str(), 0);
+ const int second = from_string(s.unwrap().str(), 0);
+
+ if((hour < 0 || 23 < hour) || (minute < 0 || 59 < minute) ||
+ (second < 0 || 60 < second)) // it may be leap second
+ {
+ throw syntax_error(format_underline("toml::parse_local_time: "
+ "invalid time: it does not conform RFC3339.", {{
+ source_location(loc), "hour should be 00-23, minute should be"
+ " 00-59, second should be 00-60 (depending on the leap"
+ " second rules.)"}}), source_location(inner_loc));
+ }
+
+ local_time time(hour, minute, second, 0, 0);
const auto before_secfrac = inner_loc.iter();
if(const auto secfrac = lex_time_secfrac::invoke(inner_loc))
@@ -792,7 +985,7 @@ parse_local_datetime(location& loc)
{
throw internal_error(format_underline(
"toml::parse_local_datetime: invalid datetime format",
- {{source_location(inner_loc), "invalid time fomrat"}}),
+ {{source_location(inner_loc), "invalid time format"}}),
source_location(inner_loc));
}
return ok(std::make_pair(
@@ -826,15 +1019,26 @@ parse_offset_datetime(location& loc)
if(const auto ofs = lex_time_numoffset::invoke(inner_loc))
{
const auto str = ofs.unwrap().str();
+
+ const auto hour = from_string(str.substr(1,2), 0);
+ const auto minute = from_string(str.substr(4,2), 0);
+
+ if((hour < 0 || 23 < hour) || (minute < 0 || 59 < minute))
+ {
+ throw syntax_error(format_underline("toml::parse_offset_datetime: "
+ "invalid offset: it does not conform RFC3339.", {{
+ source_location(loc), "month should be 01-12, day should be"
+ " 01-28,29,30,31, depending on month/year."
+ }}), source_location(inner_loc));
+ }
+
if(str.front() == '+')
{
- offset = time_offset(from_string(str.substr(1,2), 0),
- from_string(str.substr(4,2), 0));
+ offset = time_offset(hour, minute);
}
else
{
- offset = time_offset(-from_string(str.substr(1,2), 0),
- -from_string(str.substr(4,2), 0));
+ offset = time_offset(-hour, -minute);
}
}
else if(*inner_loc.iter() != 'Z' && *inner_loc.iter() != 'z')
@@ -898,7 +1102,7 @@ parse_key(location& loc)
else
{
throw internal_error(format_underline(
- "toml::detail::parse_key: dotted key contains invalid key",
+ "toml::parse_key: dotted key contains invalid key",
{{source_location(inner_loc), k.unwrap_err()}}),
source_location(inner_loc));
}
@@ -930,7 +1134,7 @@ parse_key(location& loc)
return ok(std::make_pair(std::vector(1, smpl.unwrap().first),
smpl.unwrap().second));
}
- return err(format_underline("toml::parse_key: an invalid key appeaed.",
+ return err(format_underline("toml::parse_key: an invalid key appeared.",
{{source_location(loc), "is not a valid key"}}, {
"bare keys : non-empty strings composed only of [A-Za-z0-9_-].",
"quoted keys: same as \"basic strings\" or 'literal strings'.",
@@ -940,15 +1144,23 @@ parse_key(location& loc)
// forward-decl to implement parse_array and parse_table
template
-result parse_value(location&);
+result parse_value(location&, const std::size_t n_rec);
template
result, std::string>
-parse_array(location& loc)
+parse_array(location& loc, const std::size_t n_rec)
{
using value_type = Value;
using array_type = typename value_type::array_type;
+ if(n_rec > TOML11_VALUE_RECURSION_LIMIT)
+ {
+ // parse_array does not have any way to handle recursive error currently...
+ throw syntax_error(std::string("toml::parse_array: recursion limit ("
+ TOML11_STRINGIZE(TOML11_VALUE_RECURSION_LIMIT) ") exceeded"),
+ source_location(loc));
+ }
+
const auto first = loc.iter();
if(loc.iter() == loc.end())
{
@@ -975,7 +1187,7 @@ parse_array(location& loc)
region(loc, first, loc.iter())));
}
- if(auto val = parse_value(loc))
+ if(auto val = parse_value(loc, n_rec+1))
{
// After TOML v1.0.0-rc.1, array becomes to be able to have values
// with different types. So here we will omit this by default.
@@ -1049,7 +1261,7 @@ parse_array(location& loc)
template
result, region>, Value>, std::string>
-parse_key_value_pair(location& loc)
+parse_key_value_pair(location& loc, const std::size_t n_rec)
{
using value_type = Value;
@@ -1096,7 +1308,7 @@ parse_key_value_pair(location& loc)
}
const auto after_kvsp = loc.iter(); // err msg
- auto val = parse_value(loc);
+ auto val = parse_value(loc, n_rec);
if(!val)
{
std::string msg;
@@ -1139,6 +1351,11 @@ std::string format_dotted_keys(InputIterator first, const InputIterator last)
// forward decl for is_valid_forward_table_definition
result, region>, std::string>
parse_table_key(location& loc);
+result, region>, std::string>
+parse_array_table_key(location& loc);
+template
+result, std::string>
+parse_inline_table(location& loc, const std::size_t n_rec);
// The following toml file is allowed.
// ```toml
@@ -1164,16 +1381,81 @@ parse_table_key(location& loc);
// of the key. If the key region points deeper node, it would be allowed.
// Otherwise, the key points the same node. It would be rejected.
template
-bool is_valid_forward_table_definition(const Value& fwd,
+bool is_valid_forward_table_definition(const Value& fwd, const Value& inserting,
Iterator key_first, Iterator key_curr, Iterator key_last)
{
+ // ------------------------------------------------------------------------
+ // check type of the value to be inserted/merged
+
+ std::string inserting_reg = "";
+ if(const auto ptr = detail::get_region(inserting))
+ {
+ inserting_reg = ptr->str();
+ }
+ location inserting_def("internal", std::move(inserting_reg));
+ if(const auto inlinetable = parse_inline_table(inserting_def, 0))
+ {
+ // check if we are overwriting existing table.
+ // ```toml
+ // # NG
+ // a.b = 42
+ // a = {d = 3.14}
+ // ```
+ // Inserting an inline table to a existing super-table is not allowed in
+ // any case. If we found it, we can reject it without further checking.
+ return false;
+ }
+
+ // Valid and invalid cases when inserting to the [a.b] table:
+ //
+ // ## Invalid
+ //
+ // ```toml
+ // # invalid
+ // [a]
+ // b.c.d = "foo"
+ // [a.b] # a.b is already defined and closed
+ // d = "bar"
+ // ```
+ // ```toml
+ // # invalid
+ // a = {b.c.d = "foo"}
+ // [a.b] # a is already defined and inline table is closed
+ // d = "bar"
+ // ```
+ // ```toml
+ // # invalid
+ // a.b.c.d = "foo"
+ // [a.b] # a.b is already defined and dotted-key table is closed
+ // d = "bar"
+ // ```
+ //
+ // ## Valid
+ //
+ // ```toml
+ // # OK. a.b is defined, but is *overwritable*
+ // [a.b.c]
+ // d = "foo"
+ // [a.b]
+ // d = "bar"
+ // ```
+ // ```toml
+ // # OK. a.b is defined, but is *overwritable*
+ // [a]
+ // b.c.d = "foo"
+ // b.e = "bar"
+ // ```
+
+ // ------------------------------------------------------------------------
+ // check table defined before
+
std::string internal = "";
if(const auto ptr = detail::get_region(fwd))
{
internal = ptr->str();
}
location def("internal", std::move(internal));
- if(const auto tabkeys = parse_table_key(def))
+ if(const auto tabkeys = parse_table_key(def)) // [table.key]
{
// table keys always contains all the nodes from the root.
const auto& tks = tabkeys.unwrap().first;
@@ -1186,7 +1468,22 @@ bool is_valid_forward_table_definition(const Value& fwd,
// the keys are not equivalent. it is allowed.
return true;
}
- if(const auto dotkeys = parse_key(def))
+ // nested array-of-table definition implicitly defines tables.
+ // those tables can be reopened.
+ if(const auto atabkeys = parse_array_table_key(def))
+ {
+ // table keys always contains all the nodes from the root.
+ const auto& tks = atabkeys.unwrap().first;
+ if(std::size_t(std::distance(key_first, key_last)) == tks.size() &&
+ std::equal(tks.begin(), tks.end(), key_first))
+ {
+ // the keys are equivalent. it is not allowed.
+ return false;
+ }
+ // the keys are not equivalent. it is allowed.
+ return true;
+ }
+ if(const auto dotkeys = parse_key(def)) // a.b.c = "foo"
{
// consider the following case.
// [a]
@@ -1194,6 +1491,18 @@ bool is_valid_forward_table_definition(const Value& fwd,
// [a.b.c]
// e = 2.71
// this defines the table [a.b.c] twice. no?
+ if(const auto reopening_dotkey_by_table = parse_table_key(inserting_def))
+ {
+ // re-opening a dotkey-defined table by a table is invalid.
+ // only dotkey can append a key-val. Like:
+ // ```toml
+ // a.b.c = "foo"
+ // a.b.d = "bar" # OK. reopen `a.b` by dotkey
+ // [a.b]
+ // e = "bar" # Invalid. re-opening `a.b` by [a.b] is not allowed.
+ // ```
+ return false;
+ }
// a dotted key starts from the node representing a table in which the
// dotted key belongs to.
@@ -1266,7 +1575,10 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
}
// the above if-else-if checks tab->at(k) is an array
auto& a = tab->at(k).as_array();
- if(!(a.front().is_table()))
+ // If table element is defined as [[array_of_tables]], it
+ // cannot be an empty array. If an array of tables is
+ // defined as `aot = []`, it cannot be appended.
+ if(a.empty() || !(a.front().is_table()))
{
throw syntax_error(format_underline(concat_to_string(
"toml::insert_value: array of table (\"",
@@ -1286,7 +1598,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
// b = 54
// ```
// Here, from the type information, these cannot be detected
- // bacause inline table is also a table.
+ // because inline table is also a table.
// But toml v0.5.0 explicitly says it is invalid. The above
// array-of-tables has a static size and appending to the
// array is invalid.
@@ -1315,7 +1627,41 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
}
else // if not, we need to create the array of table
{
- value_type aot(array_type(1, v), key_reg);
+ // XXX: Consider the following array of tables.
+ // ```toml
+ // # This is a comment.
+ // [[aot]]
+ // foo = "bar"
+ // ```
+ // Here, the comment is for `aot`. But here, actually two
+ // values are defined. An array that contains tables, named
+ // `aot`, and the 0th element of the `aot`, `{foo = "bar"}`.
+ // Those two are different from each other. But both of them
+ // points to the same portion of the TOML file, `[[aot]]`,
+ // so `key_reg.comments()` returns `# This is a comment`.
+ // If it is assigned as a comment of `aot` defined here, the
+ // comment will be duplicated. Both the `aot` itself and
+ // the 0-th element will have the same comment. This causes
+ // "duplication of the same comments" bug when the data is
+ // serialized.
+ // Next, consider the following.
+ // ```toml
+ // # comment 1
+ // aot = [
+ // # comment 2
+ // {foo = "bar"},
+ // ]
+ // ```
+ // In this case, we can distinguish those two comments. So
+ // here we need to add "comment 1" to the `aot` and
+ // "comment 2" to the 0th element of that.
+ // To distinguish those two, we check the key region.
+ std::vector comments{/* empty by default */};
+ if(key_reg.str().substr(0, 2) != "[[")
+ {
+ comments = key_reg.comments();
+ }
+ value_type aot(array_type(1, v), key_reg, std::move(comments));
tab->insert(std::make_pair(k, aot));
return ok(true);
}
@@ -1326,7 +1672,7 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
if(tab->at(k).is_table() && v.is_table())
{
if(!is_valid_forward_table_definition(
- tab->at(k), first, iter, last))
+ tab->at(k), v, first, iter, last))
{
throw syntax_error(format_underline(concat_to_string(
"toml::insert_value: table (\"",
@@ -1344,6 +1690,16 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
auto& t = tab->at(k).as_table();
for(const auto& kv : v.as_table())
{
+ if(tab->at(k).contains(kv.first))
+ {
+ throw syntax_error(format_underline(concat_to_string(
+ "toml::insert_value: value (\"",
+ format_dotted_keys(first, last),
+ "\") already exists."), {
+ {t.at(kv.first).location(), "already exists here"},
+ {v.location(), "this defined twice"}
+ }), v.location());
+ }
t[kv.first] = kv.second;
}
detail::change_region(tab->at(k), key_reg);
@@ -1384,7 +1740,8 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
// [x.y.z]
if(tab->count(k) == 0)
{
- (*tab)[k] = value_type(table_type{}, key_reg);
+ // a table that is defined implicitly doesn't have any comments.
+ (*tab)[k] = value_type(table_type{}, key_reg, {/*no comment*/});
}
// type checking...
@@ -1424,6 +1781,29 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
{v.location(), "inserting this"}
}), v.location());
}
+ if(a.empty())
+ {
+ throw syntax_error(format_underline(concat_to_string(
+ "toml::insert_value: table (\"",
+ format_dotted_keys(first, last), "\") conflicts with"
+ " existing value"), {
+ {tab->at(k).location(), std::string("this array is not insertable")},
+ {v.location(), std::string("appending it to the statically sized array")}
+ }), v.location());
+ }
+ if(const auto ptr = detail::get_region(a.at(0)))
+ {
+ if(ptr->str().substr(0,2) != "[[")
+ {
+ throw syntax_error(format_underline(concat_to_string(
+ "toml::insert_value: a table (\"",
+ format_dotted_keys(first, last), "\") cannot be "
+ "inserted to an existing inline array-of-tables"), {
+ {tab->at(k).location(), std::string("this array of table has a static size")},
+ {v.location(), std::string("appending it to the statically sized array")}
+ }), v.location());
+ }
+ }
tab = std::addressof(a.back().as_table());
}
else
@@ -1444,11 +1824,18 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
template
result, std::string>
-parse_inline_table(location& loc)
+parse_inline_table(location& loc, const std::size_t n_rec)
{
using value_type = Value;
using table_type = typename value_type::table_type;
+ if(n_rec > TOML11_VALUE_RECURSION_LIMIT)
+ {
+ throw syntax_error(std::string("toml::parse_inline_table: recursion limit ("
+ TOML11_STRINGIZE(TOML11_VALUE_RECURSION_LIMIT) ") exceeded"),
+ source_location(loc));
+ }
+
const auto first = loc.iter();
table_type retval;
if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
@@ -1457,22 +1844,33 @@ parse_inline_table(location& loc)
{{source_location(loc), "the next token is not an inline table"}}));
}
loc.advance();
+
+ // check if the inline table is an empty table = { }
+ maybe::invoke(loc);
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+ // TOML 1.1.0: allow newlines in inline tables
+ while(loc.iter() != loc.end() &&
+ (*loc.iter() == '\r' || *loc.iter() == '\n'))
+ {
+ loc.advance();
+ }
+ maybe::invoke(loc); // skip whitespace after newlines
+#endif
+ if(loc.iter() != loc.end() && *loc.iter() == '}')
+ {
+ loc.advance(); // skip `}`
+ return ok(std::make_pair(retval, region(loc, first, loc.iter())));
+ }
+
// it starts from "{". it should be formatted as inline-table
while(loc.iter() != loc.end())
{
- maybe::invoke(loc);
- if(loc.iter() != loc.end() && *loc.iter() == '}')
- {
- loc.advance(); // skip `}`
- return ok(std::make_pair(retval,
- region(loc, first, loc.iter())));
- }
-
- const auto kv_r = parse_key_value_pair(loc);
+ const auto kv_r = parse_key_value_pair(loc, n_rec+1);
if(!kv_r)
{
return err(kv_r.unwrap_err());
}
+
const auto& kvpair = kv_r.unwrap();
const std::vector& keys = kvpair.first.first;
const auto& key_reg = kvpair.first.second;
@@ -1489,10 +1887,19 @@ parse_inline_table(location& loc)
using lex_table_separator = sequence, character<','>>;
const auto sp = lex_table_separator::invoke(loc);
+
if(!sp)
{
maybe::invoke(loc);
- if(loc.iter() != loc.end() && *loc.iter() == '}')
+
+ if(loc.iter() == loc.end())
+ {
+ throw syntax_error(format_underline(
+ "toml::parse_inline_table: missing table separator `}` ",
+ {{source_location(loc), "should be `}`"}}),
+ source_location(loc));
+ }
+ else if(*loc.iter() == '}')
{
loc.advance(); // skip `}`
return ok(std::make_pair(
@@ -1513,6 +1920,33 @@ parse_inline_table(location& loc)
source_location(loc));
}
}
+ else // `,` is found
+ {
+ maybe::invoke(loc);
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+ // TOML 1.1.0: allow newlines after commas in inline tables
+ while(loc.iter() != loc.end() &&
+ (*loc.iter() == '\r' || *loc.iter() == '\n'))
+ {
+ loc.advance();
+ }
+ maybe::invoke(loc); // skip whitespace after newlines
+#endif
+ if(loc.iter() != loc.end() && *loc.iter() == '}')
+ {
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+ // TOML 1.1.0: trailing comma is allowed in inline tables
+ loc.advance(); // skip `}`
+ return ok(std::make_pair(retval, region(loc, first, loc.iter())));
+#else
+ throw syntax_error(format_underline(
+ "toml::parse_inline_table: trailing comma is not allowed in"
+ " an inline table",
+ {{source_location(loc), "should be `}`"}}),
+ source_location(loc));
+#endif
+ }
+ }
}
loc.reset(first);
throw syntax_error(format_underline("toml::parse_inline_table: "
@@ -1674,11 +2108,24 @@ inline result guess_value_type(const location& loc)
}
}
-template
-result parse_value(location& loc)
+template
+result
+parse_value_helper(result, std::string> rslt)
{
- using value_type = Value;
+ if(rslt.is_ok())
+ {
+ auto comments = rslt.as_ok().second.comments();
+ return ok(Value(std::move(rslt.as_ok()), std::move(comments)));
+ }
+ else
+ {
+ return err(std::move(rslt.as_err()));
+ }
+}
+template
+result parse_value(location& loc, const std::size_t n_rec)
+{
const auto first = loc.iter();
if(first == loc.end())
{
@@ -1691,18 +2138,19 @@ result parse_value(location& loc)
{
return err(type.unwrap_err());
}
+
switch(type.unwrap())
{
- case value_t::boolean : {return parse_boolean(loc); }
- case value_t::integer : {return parse_integer(loc); }
- case value_t::floating : {return parse_floating(loc); }
- case value_t::string : {return parse_string(loc); }
- case value_t::offset_datetime: {return parse_offset_datetime(loc);}
- case value_t::local_datetime : {return parse_local_datetime(loc); }
- case value_t::local_date : {return parse_local_date(loc); }
- case value_t::local_time : {return parse_local_time(loc); }
- case value_t::array : {return parse_array(loc); }
- case value_t::table : {return parse_inline_table(loc);}
+ case value_t::boolean : {return parse_value_helper(parse_boolean(loc) );}
+ case value_t::integer : {return parse_value_helper(parse_integer(loc) );}
+ case value_t::floating : {return parse_value_helper(parse_floating(loc) );}
+ case value_t::string : {return parse_value_helper(parse_string(loc) );}
+ case value_t::offset_datetime: {return parse_value_helper(parse_offset_datetime(loc) );}
+ case value_t::local_datetime : {return parse_value_helper(parse_local_datetime(loc) );}
+ case value_t::local_date : {return parse_value_helper(parse_local_date(loc) );}
+ case value_t::local_time : {return parse_value_helper(parse_local_time(loc) );}
+ case value_t::array : {return parse_value_helper(parse_array