aboutsummaryrefslogtreecommitdiff
path: root/src/toml11/toml
diff options
context:
space:
mode:
authorWinter <winter@winter.cafe>2024-03-26 22:36:17 -0400
committerWinter <winter@winter.cafe>2024-03-27 21:04:00 -0400
commit80405d06264f0de1c16ee2646388ab501df20628 (patch)
treeb90d7a475e059552ebdde80ebb8b390a79b8d571 /src/toml11/toml
parentedba570664b952facde43fd0414e60f0a42851da (diff)
Stop vendoring toml11
We don't apply any patches to it, and vendoring it locks users into bugs (it hasn't been updated since its introduction in late 2021). Closes https://git.lix.systems/lix-project/lix/issues/164 Change-Id: Ied071c841fc30b0dfb575151afd1e7f66970fdb9
Diffstat (limited to 'src/toml11/toml')
-rw-r--r--src/toml11/toml/color.hpp64
-rw-r--r--src/toml11/toml/combinator.hpp306
-rw-r--r--src/toml11/toml/comments.hpp472
-rw-r--r--src/toml11/toml/datetime.hpp631
-rw-r--r--src/toml11/toml/exception.hpp65
-rw-r--r--src/toml11/toml/from.hpp19
-rw-r--r--src/toml11/toml/get.hpp1117
-rw-r--r--src/toml11/toml/into.hpp19
-rw-r--r--src/toml11/toml/lexer.hpp293
-rw-r--r--src/toml11/toml/literal.hpp113
-rw-r--r--src/toml11/toml/macros.hpp121
-rw-r--r--src/toml11/toml/parser.hpp2364
-rw-r--r--src/toml11/toml/region.hpp417
-rw-r--r--src/toml11/toml/result.hpp717
-rw-r--r--src/toml11/toml/serializer.hpp922
-rw-r--r--src/toml11/toml/source_location.hpp233
-rw-r--r--src/toml11/toml/storage.hpp43
-rw-r--r--src/toml11/toml/string.hpp225
-rw-r--r--src/toml11/toml/traits.hpp327
-rw-r--r--src/toml11/toml/types.hpp173
-rw-r--r--src/toml11/toml/utility.hpp149
-rw-r--r--src/toml11/toml/value.hpp2035
22 files changed, 0 insertions, 10825 deletions
diff --git a/src/toml11/toml/color.hpp b/src/toml11/toml/color.hpp
deleted file mode 100644
index 4cb572cb0..000000000
--- a/src/toml11/toml/color.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef TOML11_COLOR_HPP
-#define TOML11_COLOR_HPP
-#include <cstdint>
-#include <ostream>
-
-#ifdef TOML11_COLORIZE_ERROR_MESSAGE
-#define TOML11_ERROR_MESSAGE_COLORIZED true
-#else
-#define TOML11_ERROR_MESSAGE_COLORIZED false
-#endif
-
-namespace toml
-{
-
-// put ANSI escape sequence to ostream
-namespace color_ansi
-{
-namespace detail
-{
-inline int colorize_index()
-{
- static const int index = std::ios_base::xalloc();
- return index;
-}
-} // detail
-
-inline std::ostream& colorize(std::ostream& os)
-{
- // by default, it is zero.
- os.iword(detail::colorize_index()) = 1;
- return os;
-}
-inline std::ostream& nocolorize(std::ostream& os)
-{
- os.iword(detail::colorize_index()) = 0;
- return os;
-}
-inline std::ostream& reset (std::ostream& os)
-{if(os.iword(detail::colorize_index()) == 1) {os << "\033[00m";} return os;}
-inline std::ostream& bold (std::ostream& os)
-{if(os.iword(detail::colorize_index()) == 1) {os << "\033[01m";} return os;}
-inline std::ostream& grey (std::ostream& os)
-{if(os.iword(detail::colorize_index()) == 1) {os << "\033[30m";} return os;}
-inline std::ostream& red (std::ostream& os)
-{if(os.iword(detail::colorize_index()) == 1) {os << "\033[31m";} return os;}
-inline std::ostream& green (std::ostream& os)
-{if(os.iword(detail::colorize_index()) == 1) {os << "\033[32m";} return os;}
-inline std::ostream& yellow (std::ostream& os)
-{if(os.iword(detail::colorize_index()) == 1) {os << "\033[33m";} return os;}
-inline std::ostream& blue (std::ostream& os)
-{if(os.iword(detail::colorize_index()) == 1) {os << "\033[34m";} return os;}
-inline std::ostream& magenta(std::ostream& os)
-{if(os.iword(detail::colorize_index()) == 1) {os << "\033[35m";} return os;}
-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;}
-} // color_ansi
-
-// ANSI escape sequence is the only and default colorization method currently
-namespace color = color_ansi;
-
-} // toml
-#endif// TOML11_COLOR_HPP
diff --git a/src/toml11/toml/combinator.hpp b/src/toml11/toml/combinator.hpp
deleted file mode 100644
index 33ecca1eb..000000000
--- a/src/toml11/toml/combinator.hpp
+++ /dev/null
@@ -1,306 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_COMBINATOR_HPP
-#define TOML11_COMBINATOR_HPP
-#include <cassert>
-#include <cctype>
-#include <cstdio>
-
-#include <array>
-#include <iomanip>
-#include <iterator>
-#include <limits>
-#include <type_traits>
-
-#include "region.hpp"
-#include "result.hpp"
-#include "traits.hpp"
-#include "utility.hpp"
-
-// they scans characters and returns region if it matches to the condition.
-// when they fail, it does not change the location.
-// in lexer.hpp, these are used.
-
-namespace toml
-{
-namespace detail
-{
-
-// to output character as an error message.
-inline std::string show_char(const char c)
-{
- // 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
- // unsigned char through pointer. In general, converting pointer to a
- // pointer that has different type cause UB, but `(signed|unsigned)?char`
- // are one of the exceptions. Converting pointer only to char and std::byte
- // (c++17) are valid.
- if(std::isgraph(*reinterpret_cast<unsigned char const*>(std::addressof(c))))
- {
- return std::string(1, c);
- }
- else
- {
- std::array<char, 5> buf;
- buf.fill('\0');
- const auto r = std::snprintf(
- buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
- (void) r; // Unused variable warning
- assert(r == static_cast<int>(buf.size()) - 1);
- return std::string(buf.data());
- }
-}
-
-template<char C>
-struct character
-{
- static constexpr char target = C;
-
- static result<region, none_t>
- invoke(location& loc)
- {
- if(loc.iter() == loc.end()) {return none();}
- const auto first = loc.iter();
-
- const char c = *(loc.iter());
- if(c != target)
- {
- return none();
- }
- loc.advance(); // update location
-
- return ok(region(loc, first, loc.iter()));
- }
-};
-template<char C>
-constexpr char character<C>::target;
-
-// closed interval [Low, Up]. both Low and Up are included.
-template<char Low, char Up>
-struct in_range
-{
- // assuming ascii part of UTF-8...
- static_assert(Low <= Up, "lower bound should be less than upper bound.");
-
- static constexpr char upper = Up;
- static constexpr char lower = Low;
-
- static result<region, none_t>
- invoke(location& loc)
- {
- if(loc.iter() == loc.end()) {return none();}
- const auto first = loc.iter();
-
- const char c = *(loc.iter());
- if(c < lower || upper < c)
- {
- return none();
- }
-
- loc.advance();
- return ok(region(loc, first, loc.iter()));
- }
-};
-template<char L, char U> constexpr char in_range<L, U>::upper;
-template<char L, char U> constexpr char in_range<L, U>::lower;
-
-// keep iterator if `Combinator` matches. otherwise, increment `iter` by 1 char.
-// for detecting invalid characters, like control sequences in toml string.
-template<typename Combinator>
-struct exclude
-{
- static result<region, none_t>
- invoke(location& loc)
- {
- if(loc.iter() == loc.end()) {return none();}
- auto first = loc.iter();
-
- auto rslt = Combinator::invoke(loc);
- if(rslt.is_ok())
- {
- loc.reset(first);
- return none();
- }
- loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
- return ok(region(loc, first, loc.iter()));
- }
-};
-
-// increment `iter`, if matches. otherwise, just return empty string.
-template<typename Combinator>
-struct maybe
-{
- static result<region, none_t>
- invoke(location& loc)
- {
- const auto rslt = Combinator::invoke(loc);
- if(rslt.is_ok())
- {
- return rslt;
- }
- return ok(region(loc));
- }
-};
-
-template<typename ... Ts>
-struct sequence;
-
-template<typename Head, typename ... Tail>
-struct sequence<Head, Tail...>
-{
- static result<region, none_t>
- invoke(location& loc)
- {
- const auto first = loc.iter();
- auto rslt = Head::invoke(loc);
- if(rslt.is_err())
- {
- loc.reset(first);
- return none();
- }
- return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
- }
-
- // called from the above function only, recursively.
- template<typename Iterator>
- static result<region, none_t>
- invoke(location& loc, region reg, Iterator first)
- {
- const auto rslt = Head::invoke(loc);
- if(rslt.is_err())
- {
- loc.reset(first);
- return none();
- }
- reg += rslt.unwrap(); // concat regions
- return sequence<Tail...>::invoke(loc, std::move(reg), first);
- }
-};
-
-template<typename Head>
-struct sequence<Head>
-{
- // would be called from sequence<T ...>::invoke only.
- template<typename Iterator>
- static result<region, none_t>
- invoke(location& loc, region reg, Iterator first)
- {
- const auto rslt = Head::invoke(loc);
- if(rslt.is_err())
- {
- loc.reset(first);
- return none();
- }
- reg += rslt.unwrap(); // concat regions
- return ok(reg);
- }
-};
-
-template<typename ... Ts>
-struct either;
-
-template<typename Head, typename ... Tail>
-struct either<Head, Tail...>
-{
- static result<region, none_t>
- invoke(location& loc)
- {
- const auto rslt = Head::invoke(loc);
- if(rslt.is_ok()) {return rslt;}
- return either<Tail...>::invoke(loc);
- }
-};
-template<typename Head>
-struct either<Head>
-{
- static result<region, none_t>
- invoke(location& loc)
- {
- return Head::invoke(loc);
- }
-};
-
-template<typename T, typename N>
-struct repeat;
-
-template<std::size_t N> struct exactly{};
-template<std::size_t N> struct at_least{};
-struct unlimited{};
-
-template<typename T, std::size_t N>
-struct repeat<T, exactly<N>>
-{
- static result<region, none_t>
- invoke(location& loc)
- {
- region retval(loc);
- const auto first = loc.iter();
- for(std::size_t i=0; i<N; ++i)
- {
- auto rslt = T::invoke(loc);
- if(rslt.is_err())
- {
- loc.reset(first);
- return none();
- }
- retval += rslt.unwrap();
- }
- return ok(std::move(retval));
- }
-};
-
-template<typename T, std::size_t N>
-struct repeat<T, at_least<N>>
-{
- static result<region, none_t>
- invoke(location& loc)
- {
- region retval(loc);
-
- const auto first = loc.iter();
- for(std::size_t i=0; i<N; ++i)
- {
- auto rslt = T::invoke(loc);
- if(rslt.is_err())
- {
- loc.reset(first);
- return none();
- }
- retval += rslt.unwrap();
- }
- while(true)
- {
- auto rslt = T::invoke(loc);
- if(rslt.is_err())
- {
- return ok(std::move(retval));
- }
- retval += rslt.unwrap();
- }
- }
-};
-
-template<typename T>
-struct repeat<T, unlimited>
-{
- static result<region, none_t>
- invoke(location& loc)
- {
- region retval(loc);
- while(true)
- {
- auto rslt = T::invoke(loc);
- if(rslt.is_err())
- {
- return ok(std::move(retval));
- }
- retval += rslt.unwrap();
- }
- }
-};
-
-} // detail
-} // toml
-#endif// TOML11_COMBINATOR_HPP
diff --git a/src/toml11/toml/comments.hpp b/src/toml11/toml/comments.hpp
deleted file mode 100644
index ec2504117..000000000
--- a/src/toml11/toml/comments.hpp
+++ /dev/null
@@ -1,472 +0,0 @@
-// Copyright Toru Niina 2019.
-// Distributed under the MIT License.
-#ifndef TOML11_COMMENTS_HPP
-#define TOML11_COMMENTS_HPP
-#include <initializer_list>
-#include <iterator>
-#include <stdexcept>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-#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<std::string>`
-// but bahaves in the opposite way. `preserve_comments` is just the same as
-// `std::vector<std::string>` and each `std::string` corresponds to a comment line.
-// Conversely, `discard_comments` discards all the strings and ignores everything
-// assigned in it. `discard_comments` is always empty and you will encounter an
-// error whenever you access to the element.
-namespace toml
-{
-struct discard_comments; // forward decl
-
-// use it in the following way
-//
-// const toml::basic_value<toml::preserve_comments> data =
-// toml::parse<toml::preserve_comments>("example.toml");
-//
-// the interface is almost the same as std::vector<std::string>.
-struct preserve_comments
-{
- // `container_type` is not provided in discard_comments.
- // do not use this inner-type in a generic code.
- using container_type = std::vector<std::string>;
-
- using size_type = container_type::size_type;
- using difference_type = container_type::difference_type;
- using value_type = container_type::value_type;
- using reference = container_type::reference;
- using const_reference = container_type::const_reference;
- using pointer = container_type::pointer;
- using const_pointer = container_type::const_pointer;
- using iterator = container_type::iterator;
- using const_iterator = container_type::const_iterator;
- using reverse_iterator = container_type::reverse_iterator;
- using const_reverse_iterator = container_type::const_reverse_iterator;
-
- preserve_comments() = default;
- ~preserve_comments() = default;
- preserve_comments(preserve_comments const&) = default;
- preserve_comments(preserve_comments &&) = default;
- preserve_comments& operator=(preserve_comments const&) = default;
- preserve_comments& operator=(preserve_comments &&) = default;
-
- explicit preserve_comments(const std::vector<std::string>& c): comments(c){}
- explicit preserve_comments(std::vector<std::string>&& c)
- : comments(std::move(c))
- {}
- preserve_comments& operator=(const std::vector<std::string>& c)
- {
- comments = c;
- return *this;
- }
- preserve_comments& operator=(std::vector<std::string>&& c)
- {
- comments = std::move(c);
- return *this;
- }
-
- explicit preserve_comments(const discard_comments&) {}
-
- explicit preserve_comments(size_type n): comments(n) {}
- preserve_comments(size_type n, const std::string& x): comments(n, x) {}
- preserve_comments(std::initializer_list<std::string> x): comments(x) {}
- template<typename InputIterator>
- preserve_comments(InputIterator first, InputIterator last)
- : comments(first, last)
- {}
-
- template<typename InputIterator>
- void assign(InputIterator first, InputIterator last) {comments.assign(first, last);}
- void assign(std::initializer_list<std::string> ini) {comments.assign(ini);}
- void assign(size_type n, const std::string& val) {comments.assign(n, val);}
-
- // Related to the issue #97.
- //
- // It is known that `std::vector::insert` and `std::vector::erase` in
- // the standard library implementation included in GCC 4.8.5 takes
- // `std::vector::iterator` instead of `std::vector::const_iterator`.
- // Because of the const-correctness, we cannot convert a `const_iterator` to
- // an `iterator`. It causes compilation error in GCC 4.8.5.
-#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && !defined(__clang__)
-# if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) <= 40805
-# define TOML11_WORKAROUND_GCC_4_8_X_STANDARD_LIBRARY_IMPLEMENTATION
-# endif
-#endif
-
-#ifdef TOML11_WORKAROUND_GCC_4_8_X_STANDARD_LIBRARY_IMPLEMENTATION
- iterator insert(iterator p, const std::string& x)
- {
- return comments.insert(p, x);
- }
- iterator insert(iterator p, std::string&& x)
- {
- return comments.insert(p, std::move(x));
- }
- void insert(iterator p, size_type n, const std::string& x)
- {
- return comments.insert(p, n, x);
- }
- template<typename InputIterator>
- void insert(iterator p, InputIterator first, InputIterator last)
- {
- return comments.insert(p, first, last);
- }
- void insert(iterator p, std::initializer_list<std::string> ini)
- {
- return comments.insert(p, ini);
- }
-
- template<typename ... Ts>
- iterator emplace(iterator p, Ts&& ... args)
- {
- return comments.emplace(p, std::forward<Ts>(args)...);
- }
-
- iterator erase(iterator pos) {return comments.erase(pos);}
- iterator erase(iterator first, iterator last)
- {
- return comments.erase(first, last);
- }
-#else
- iterator insert(const_iterator p, const std::string& x)
- {
- return comments.insert(p, x);
- }
- iterator insert(const_iterator p, std::string&& x)
- {
- return comments.insert(p, std::move(x));
- }
- iterator insert(const_iterator p, size_type n, const std::string& x)
- {
- return comments.insert(p, n, x);
- }
- template<typename InputIterator>
- iterator insert(const_iterator p, InputIterator first, InputIterator last)
- {
- return comments.insert(p, first, last);
- }
- iterator insert(const_iterator p, std::initializer_list<std::string> ini)
- {
- return comments.insert(p, ini);
- }
-
- template<typename ... Ts>
- iterator emplace(const_iterator p, Ts&& ... args)
- {
- return comments.emplace(p, std::forward<Ts>(args)...);
- }
-
- iterator erase(const_iterator pos) {return comments.erase(pos);}
- iterator erase(const_iterator first, const_iterator last)
- {
- return comments.erase(first, last);
- }
-#endif
-
- void swap(preserve_comments& other) {comments.swap(other.comments);}
-
- void push_back(const std::string& v) {comments.push_back(v);}
- void push_back(std::string&& v) {comments.push_back(std::move(v));}
- void pop_back() {comments.pop_back();}
-
- template<typename ... Ts>
- void emplace_back(Ts&& ... args) {comments.emplace_back(std::forward<Ts>(args)...);}
-
- void clear() {comments.clear();}
-
- size_type size() const noexcept {return comments.size();}
- size_type max_size() const noexcept {return comments.max_size();}
- size_type capacity() const noexcept {return comments.capacity();}
- bool empty() const noexcept {return comments.empty();}
-
- void reserve(size_type n) {comments.reserve(n);}
- void resize(size_type n) {comments.resize(n);}
- void resize(size_type n, const std::string& c) {comments.resize(n, c);}
- void shrink_to_fit() {comments.shrink_to_fit();}
-
- reference operator[](const size_type n) noexcept {return comments[n];}
- const_reference operator[](const size_type n) const noexcept {return comments[n];}
- reference at(const size_type n) {return comments.at(n);}
- const_reference at(const size_type n) const {return comments.at(n);}
- reference front() noexcept {return comments.front();}
- const_reference front() const noexcept {return comments.front();}
- reference back() noexcept {return comments.back();}
- const_reference back() const noexcept {return comments.back();}
-
- pointer data() noexcept {return comments.data();}
- const_pointer data() const noexcept {return comments.data();}
-
- iterator begin() noexcept {return comments.begin();}
- iterator end() noexcept {return comments.end();}
- const_iterator begin() const noexcept {return comments.begin();}
- const_iterator end() const noexcept {return comments.end();}
- const_iterator cbegin() const noexcept {return comments.cbegin();}
- const_iterator cend() const noexcept {return comments.cend();}
-
- reverse_iterator rbegin() noexcept {return comments.rbegin();}
- reverse_iterator rend() noexcept {return comments.rend();}
- const_reverse_iterator rbegin() const noexcept {return comments.rbegin();}
- const_reverse_iterator rend() const noexcept {return comments.rend();}
- const_reverse_iterator crbegin() const noexcept {return comments.crbegin();}
- const_reverse_iterator crend() const noexcept {return comments.crend();}
-
- friend bool operator==(const preserve_comments&, const preserve_comments&);
- friend bool operator!=(const preserve_comments&, const preserve_comments&);
- friend bool operator< (const preserve_comments&, const preserve_comments&);
- friend bool operator<=(const preserve_comments&, const preserve_comments&);
- friend bool operator> (const preserve_comments&, const preserve_comments&);
- friend bool operator>=(const preserve_comments&, const preserve_comments&);
-
- friend void swap(preserve_comments&, std::vector<std::string>&);
- friend void swap(std::vector<std::string>&, preserve_comments&);
-
- private:
-
- container_type comments;
-};
-
-inline bool operator==(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments == rhs.comments;}
-inline bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments != rhs.comments;}
-inline bool operator< (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments < rhs.comments;}
-inline bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments <= rhs.comments;}
-inline bool operator> (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments > rhs.comments;}
-inline bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments >= rhs.comments;}
-
-inline void swap(preserve_comments& lhs, preserve_comments& rhs)
-{
- lhs.swap(rhs);
- return;
-}
-inline void swap(preserve_comments& lhs, std::vector<std::string>& rhs)
-{
- lhs.comments.swap(rhs);
- return;
-}
-inline void swap(std::vector<std::string>& lhs, preserve_comments& rhs)
-{
- lhs.swap(rhs.comments);
- return;
-}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const preserve_comments& com)
-{
- for(const auto& c : com)
- {
- os << '#' << c << '\n';
- }
- return os;
-}
-
-namespace detail
-{
-
-// To provide the same interface with `preserve_comments`, `discard_comments`
-// should have an iterator. But it does not contain anything, so we need to
-// add an iterator that points nothing.
-//
-// It always points null, so DO NOT unwrap this iterator. It always crashes
-// your program.
-template<typename T, bool is_const>
-struct empty_iterator
-{
- using value_type = T;
- using reference_type = typename std::conditional<is_const, T const&, T&>::type;
- using pointer_type = typename std::conditional<is_const, T const*, T*>::type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::random_access_iterator_tag;
-
- empty_iterator() = default;
- ~empty_iterator() = default;
- empty_iterator(empty_iterator const&) = default;
- empty_iterator(empty_iterator &&) = default;
- empty_iterator& operator=(empty_iterator const&) = default;
- empty_iterator& operator=(empty_iterator &&) = default;
-
- // DO NOT call these operators.
- reference_type operator*() const noexcept {std::terminate();}
- pointer_type operator->() const noexcept {return nullptr;}
- reference_type operator[](difference_type) const noexcept {return this->operator*();}
-
- // These operators do nothing.
- empty_iterator& operator++() noexcept {return *this;}
- empty_iterator operator++(int) noexcept {return *this;}
- empty_iterator& operator--() noexcept {return *this;}
- empty_iterator operator--(int) noexcept {return *this;}
-
- empty_iterator& operator+=(difference_type) noexcept {return *this;}
- empty_iterator& operator-=(difference_type) noexcept {return *this;}
-
- empty_iterator operator+(difference_type) const noexcept {return *this;}
- empty_iterator operator-(difference_type) const noexcept {return *this;}
-};
-
-template<typename T, bool C>
-bool operator==(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
-template<typename T, bool C>
-bool operator!=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
-template<typename T, bool C>
-bool operator< (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
-template<typename T, bool C>
-bool operator<=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
-template<typename T, bool C>
-bool operator> (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
-template<typename T, bool C>
-bool operator>=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
-
-template<typename T, bool C>
-typename empty_iterator<T, C>::difference_type
-operator-(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return 0;}
-
-template<typename T, bool C>
-empty_iterator<T, C>
-operator+(typename empty_iterator<T, C>::difference_type, const empty_iterator<T, C>& rhs) noexcept {return rhs;}
-template<typename T, bool C>
-empty_iterator<T, C>
-operator+(const empty_iterator<T, C>& lhs, typename empty_iterator<T, C>::difference_type) noexcept {return lhs;}
-
-} // detail
-
-// The default comment type. It discards all the comments. It requires only one
-// byte to contain, so the memory footprint is smaller than preserve_comments.
-//
-// It just ignores `push_back`, `insert`, `erase`, and any other modifications.
-// IT always returns size() == 0, the iterator taken by `begin()` is always the
-// same as that of `end()`, and accessing through `operator[]` or iterators
-// always causes a segmentation fault. DO NOT access to the element of this.
-//
-// 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 chosen as a default.
-//
-// To reduce the memory footprint, later we can try empty base optimization (EBO).
-struct discard_comments
-{
- using size_type = std::size_t;
- using difference_type = std::ptrdiff_t;
- using value_type = std::string;
- using reference = std::string&;
- using const_reference = std::string const&;
- using pointer = std::string*;
- using const_pointer = std::string const*;
- using iterator = detail::empty_iterator<std::string, false>;
- using const_iterator = detail::empty_iterator<std::string, true>;
- using reverse_iterator = detail::empty_iterator<std::string, false>;
- using const_reverse_iterator = detail::empty_iterator<std::string, true>;
-
- discard_comments() = default;
- ~discard_comments() = default;
- discard_comments(discard_comments const&) = default;
- discard_comments(discard_comments &&) = default;
- discard_comments& operator=(discard_comments const&) = default;
- discard_comments& operator=(discard_comments &&) = default;
-
- explicit discard_comments(const std::vector<std::string>&) noexcept {}
- explicit discard_comments(std::vector<std::string>&&) noexcept {}
- discard_comments& operator=(const std::vector<std::string>&) noexcept {return *this;}
- discard_comments& operator=(std::vector<std::string>&&) noexcept {return *this;}
-
- explicit discard_comments(const preserve_comments&) noexcept {}
-
- explicit discard_comments(size_type) noexcept {}
- discard_comments(size_type, const std::string&) noexcept {}
- discard_comments(std::initializer_list<std::string>) noexcept {}
- template<typename InputIterator>
- discard_comments(InputIterator, InputIterator) noexcept {}
-
- template<typename InputIterator>
- void assign(InputIterator, InputIterator) noexcept {}
- void assign(std::initializer_list<std::string>) noexcept {}
- void assign(size_type, const std::string&) noexcept {}
-
- iterator insert(const_iterator, const std::string&) {return iterator{};}
- iterator insert(const_iterator, std::string&&) {return iterator{};}
- iterator insert(const_iterator, size_type, const std::string&) {return iterator{};}
- template<typename InputIterator>
- iterator insert(const_iterator, InputIterator, InputIterator) {return iterator{};}
- iterator insert(const_iterator, std::initializer_list<std::string>) {return iterator{};}
-
- template<typename ... Ts>
- iterator emplace(const_iterator, Ts&& ...) {return iterator{};}
- iterator erase(const_iterator) {return iterator{};}
- iterator erase(const_iterator, const_iterator) {return iterator{};}
-
- void swap(discard_comments&) {return;}
-
- void push_back(const std::string&) {return;}
- void push_back(std::string&& ) {return;}
- void pop_back() {return;}
-
- template<typename ... Ts>
- void emplace_back(Ts&& ...) {return;}
-
- void clear() {return;}
-
- size_type size() const noexcept {return 0;}
- size_type max_size() const noexcept {return 0;}
- size_type capacity() const noexcept {return 0;}
- bool empty() const noexcept {return true;}
-
- void reserve(size_type) {return;}
- void resize(size_type) {return;}
- void resize(size_type, const std::string&) {return;}
- void shrink_to_fit() {return;}
-
- // DO NOT access to the element of this container. This container is always
- // 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 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();}
-
- pointer data() noexcept {return nullptr;}
- const_pointer data() const noexcept {return nullptr;}
-
- iterator begin() noexcept {return iterator{};}
- iterator end() noexcept {return iterator{};}
- const_iterator begin() const noexcept {return const_iterator{};}
- const_iterator end() const noexcept {return const_iterator{};}
- const_iterator cbegin() const noexcept {return const_iterator{};}
- const_iterator cend() const noexcept {return const_iterator{};}
-
- reverse_iterator rbegin() noexcept {return iterator{};}
- reverse_iterator rend() noexcept {return iterator{};}
- const_reverse_iterator rbegin() const noexcept {return const_iterator{};}
- 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{};}
-};
-
-inline bool operator==(const discard_comments&, const discard_comments&) noexcept {return true;}
-inline bool operator!=(const discard_comments&, const discard_comments&) noexcept {return false;}
-inline bool operator< (const discard_comments&, const discard_comments&) noexcept {return false;}
-inline bool operator<=(const discard_comments&, const discard_comments&) noexcept {return true;}
-inline bool operator> (const discard_comments&, const discard_comments&) noexcept {return false;}
-inline bool operator>=(const discard_comments&, const discard_comments&) noexcept {return true;}
-
-inline void swap(const discard_comments&, const discard_comments&) noexcept {return;}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const discard_comments&)
-{
- return os;
-}
-
-} // toml11
-#endif// TOML11_COMMENTS_HPP
diff --git a/src/toml11/toml/datetime.hpp b/src/toml11/toml/datetime.hpp
deleted file mode 100644
index d8127c150..000000000
--- a/src/toml11/toml/datetime.hpp
+++ /dev/null
@@ -1,631 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_DATETIME_HPP
-#define TOML11_DATETIME_HPP
-#include <cstdint>
-#include <cstdlib>
-#include <ctime>
-
-#include <array>
-#include <chrono>
-#include <iomanip>
-#include <ostream>
-#include <tuple>
-
-namespace toml
-{
-
-// To avoid non-threadsafe std::localtime. In C11 (not C++11!), localtime_s is
-// provided in the absolutely same purpose, but C++11 is actually not compatible
-// with C11. We need to dispatch the function depending on the OS.
-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)
-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."); }
- 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."); }
- return dst;
-}
-#elif defined(_MSC_VER)
-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."); }
- 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."); }
- return dst;
-}
-#else // fallback. not threadsafe
-inline std::tm localtime_s(const std::time_t* src)
-{
- const auto result = std::localtime(src);
- if (!result) { throw std::runtime_error("localtime failed."); }
- return *result;
-}
-inline std::tm gmtime_s(const std::time_t* src)
-{
- const auto result = std::gmtime(src);
- if (!result) { throw std::runtime_error("gmtime failed."); }
- return *result;
-}
-#endif
-} // detail
-
-enum class month_t : std::uint8_t
-{
- Jan = 0,
- Feb = 1,
- Mar = 2,
- Apr = 3,
- May = 4,
- Jun = 5,
- Jul = 6,
- Aug = 7,
- Sep = 8,
- Oct = 9,
- Nov = 10,
- Dec = 11
-};
-
-struct local_date
-{
- 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<std::int16_t>(y)),
- month(static_cast<std::uint8_t>(m)),
- day (static_cast<std::uint8_t>(d))
- {}
-
- explicit local_date(const std::tm& t)
- : year (static_cast<std::int16_t>(t.tm_year + 1900)),
- month(static_cast<std::uint8_t>(t.tm_mon)),
- day (static_cast<std::uint8_t>(t.tm_mday))
- {}
-
- explicit local_date(const std::chrono::system_clock::time_point& tp)
- {
- const auto t = std::chrono::system_clock::to_time_t(tp);
- const auto time = detail::localtime_s(&t);
- *this = local_date(time);
- }
-
- explicit local_date(const std::time_t t)
- : local_date(std::chrono::system_clock::from_time_t(t))
- {}
-
- operator std::chrono::system_clock::time_point() const
- {
- // std::mktime returns date as local time zone. no conversion needed
- std::tm t;
- t.tm_sec = 0;
- t.tm_min = 0;
- t.tm_hour = 0;
- t.tm_mday = static_cast<int>(this->day);
- t.tm_mon = static_cast<int>(this->month);
- t.tm_year = static_cast<int>(this->year) - 1900;
- t.tm_wday = 0; // the value will be ignored
- t.tm_yday = 0; // the value will be ignored
- t.tm_isdst = -1;
- return std::chrono::system_clock::from_time_t(std::mktime(&t));
- }
-
- operator std::time_t() const
- {
- return std::chrono::system_clock::to_time_t(
- std::chrono::system_clock::time_point(*this));
- }
-
- local_date() = default;
- ~local_date() = default;
- local_date(local_date const&) = default;
- local_date(local_date&&) = default;
- local_date& operator=(local_date const&) = default;
- local_date& operator=(local_date&&) = default;
-};
-
-inline bool operator==(const local_date& lhs, const local_date& rhs)
-{
- return std::make_tuple(lhs.year, lhs.month, lhs.day) ==
- std::make_tuple(rhs.year, rhs.month, rhs.day);
-}
-inline bool operator!=(const local_date& lhs, const local_date& rhs)
-{
- return !(lhs == rhs);
-}
-inline bool operator< (const local_date& lhs, const local_date& rhs)
-{
- return std::make_tuple(lhs.year, lhs.month, lhs.day) <
- std::make_tuple(rhs.year, rhs.month, rhs.day);
-}
-inline bool operator<=(const local_date& lhs, const local_date& rhs)
-{
- return (lhs < rhs) || (lhs == rhs);
-}
-inline bool operator> (const local_date& lhs, const local_date& rhs)
-{
- return !(lhs <= rhs);
-}
-inline bool operator>=(const local_date& lhs, const local_date& rhs)
-{
- return !(lhs < rhs);
-}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const local_date& date)
-{
- os << std::setfill('0') << std::setw(4) << static_cast<int>(date.year ) << '-';
- os << std::setfill('0') << std::setw(2) << static_cast<int>(date.month) + 1 << '-';
- os << std::setfill('0') << std::setw(2) << static_cast<int>(date.day ) ;
- return os;
-}
-
-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]
-
- local_time(int h, int m, int s,
- int ms = 0, int us = 0, int ns = 0)
- : hour (static_cast<std::uint8_t>(h)),
- minute(static_cast<std::uint8_t>(m)),
- second(static_cast<std::uint8_t>(s)),
- millisecond(static_cast<std::uint16_t>(ms)),
- microsecond(static_cast<std::uint16_t>(us)),
- nanosecond (static_cast<std::uint16_t>(ns))
- {}
-
- explicit local_time(const std::tm& t)
- : hour (static_cast<std::uint8_t>(t.tm_hour)),
- minute(static_cast<std::uint8_t>(t.tm_min)),
- second(static_cast<std::uint8_t>(t.tm_sec)),
- millisecond(0), microsecond(0), nanosecond(0)
- {}
-
- template<typename Rep, typename Period>
- explicit local_time(const std::chrono::duration<Rep, Period>& t)
- {
- const auto h = std::chrono::duration_cast<std::chrono::hours>(t);
- this->hour = static_cast<std::uint8_t>(h.count());
- const auto t2 = t - h;
- const auto m = std::chrono::duration_cast<std::chrono::minutes>(t2);
- this->minute = static_cast<std::uint8_t>(m.count());
- const auto t3 = t2 - m;
- const auto s = std::chrono::duration_cast<std::chrono::seconds>(t3);
- this->second = static_cast<std::uint8_t>(s.count());
- const auto t4 = t3 - s;
- const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t4);
- this->millisecond = static_cast<std::uint16_t>(ms.count());
- const auto t5 = t4 - ms;
- const auto us = std::chrono::duration_cast<std::chrono::microseconds>(t5);
- this->microsecond = static_cast<std::uint16_t>(us.count());
- const auto t6 = t5 - us;
- const auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t6);
- this->nanosecond = static_cast<std::uint16_t>(ns.count());
- }
-
- operator std::chrono::nanoseconds() const
- {
- return std::chrono::nanoseconds (this->nanosecond) +
- std::chrono::microseconds(this->microsecond) +
- std::chrono::milliseconds(this->millisecond) +
- std::chrono::seconds(this->second) +
- std::chrono::minutes(this->minute) +
- std::chrono::hours(this->hour);
- }
-
- local_time() = default;
- ~local_time() = default;
- local_time(local_time const&) = default;
- local_time(local_time&&) = default;
- local_time& operator=(local_time const&) = default;
- local_time& operator=(local_time&&) = default;
-};
-
-inline bool operator==(const local_time& lhs, const local_time& rhs)
-{
- return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) ==
- std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond);
-}
-inline bool operator!=(const local_time& lhs, const local_time& rhs)
-{
- return !(lhs == rhs);
-}
-inline bool operator< (const local_time& lhs, const local_time& rhs)
-{
- return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) <
- std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond);
-}
-inline bool operator<=(const local_time& lhs, const local_time& rhs)
-{
- return (lhs < rhs) || (lhs == rhs);
-}
-inline bool operator> (const local_time& lhs, const local_time& rhs)
-{
- return !(lhs <= rhs);
-}
-inline bool operator>=(const local_time& lhs, const local_time& rhs)
-{
- return !(lhs < rhs);
-}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const local_time& time)
-{
- os << std::setfill('0') << std::setw(2) << static_cast<int>(time.hour ) << ':';
- os << std::setfill('0') << std::setw(2) << static_cast<int>(time.minute) << ':';
- os << std::setfill('0') << std::setw(2) << static_cast<int>(time.second);
- if(time.millisecond != 0 || time.microsecond != 0 || time.nanosecond != 0)
- {
- os << '.';
- os << std::setfill('0') << std::setw(3) << static_cast<int>(time.millisecond);
- if(time.microsecond != 0 || time.nanosecond != 0)
- {
- os << std::setfill('0') << std::setw(3) << static_cast<int>(time.microsecond);
- if(time.nanosecond != 0)
- {
- os << std::setfill('0') << std::setw(3) << static_cast<int>(time.nanosecond);
- }
- }
- }
- return os;
-}
-
-struct time_offset
-{
- std::int8_t hour; // [-12, 12]
- std::int8_t minute; // [-59, 59]
-
- time_offset(int h, int m)
- : hour (static_cast<std::int8_t>(h)),
- minute(static_cast<std::int8_t>(m))
- {}
-
- operator std::chrono::minutes() const
- {
- return std::chrono::minutes(this->minute) +
- std::chrono::hours(this->hour);
- }
-
- time_offset() = default;
- ~time_offset() = default;
- time_offset(time_offset const&) = default;
- time_offset(time_offset&&) = default;
- time_offset& operator=(time_offset const&) = default;
- time_offset& operator=(time_offset&&) = default;
-};
-
-inline bool operator==(const time_offset& lhs, const time_offset& rhs)
-{
- return std::make_tuple(lhs.hour, lhs.minute) ==
- std::make_tuple(rhs.hour, rhs.minute);
-}
-inline bool operator!=(const time_offset& lhs, const time_offset& rhs)
-{
- return !(lhs == rhs);
-}
-inline bool operator< (const time_offset& lhs, const time_offset& rhs)
-{
- return std::make_tuple(lhs.hour, lhs.minute) <
- std::make_tuple(rhs.hour, rhs.minute);
-}
-inline bool operator<=(const time_offset& lhs, const time_offset& rhs)
-{
- return (lhs < rhs) || (lhs == rhs);
-}
-inline bool operator> (const time_offset& lhs, const time_offset& rhs)
-{
- return !(lhs <= rhs);
-}
-inline bool operator>=(const time_offset& lhs, const time_offset& rhs)
-{
- return !(lhs < rhs);
-}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const time_offset& offset)
-{
- if(offset.hour == 0 && offset.minute == 0)
- {
- os << 'Z';
- return os;
- }
- int minute = static_cast<int>(offset.hour) * 60 + offset.minute;
- if(minute < 0){os << '-'; minute = std::abs(minute);} else {os << '+';}
- os << std::setfill('0') << std::setw(2) << minute / 60 << ':';
- os << std::setfill('0') << std::setw(2) << minute % 60;
- return os;
-}
-
-struct local_datetime
-{
- local_date date;
- local_time time;
-
- local_datetime(local_date d, local_time t): date(d), time(t) {}
-
- explicit local_datetime(const std::tm& t): date(t), time(t){}
-
- explicit local_datetime(const std::chrono::system_clock::time_point& tp)
- {
- const auto t = std::chrono::system_clock::to_time_t(tp);
- std::tm ltime = detail::localtime_s(&t);
-
- this->date = local_date(ltime);
- this->time = local_time(ltime);
-
- // std::tm lacks subsecond information, so diff between tp and tm
- // can be used to get millisecond & microsecond information.
- const auto t_diff = tp -
- std::chrono::system_clock::from_time_t(std::mktime(&ltime));
- this->time.millisecond = static_cast<std::uint16_t>(
- std::chrono::duration_cast<std::chrono::milliseconds>(t_diff).count());
- this->time.microsecond = static_cast<std::uint16_t>(
- std::chrono::duration_cast<std::chrono::microseconds>(t_diff).count());
- this->time.nanosecond = static_cast<std::uint16_t>(
- std::chrono::duration_cast<std::chrono::nanoseconds >(t_diff).count());
- }
-
- explicit local_datetime(const std::time_t t)
- : local_datetime(std::chrono::system_clock::from_time_t(t))
- {}
-
- operator std::chrono::system_clock::time_point() const
- {
- using internal_duration =
- typename std::chrono::system_clock::time_point::duration;
-
- // Normally DST begins at A.M. 3 or 4. If we re-use conversion operator
- // of local_date and local_time independently, the conversion fails if
- // it is the day when DST begins or ends. Since local_date considers the
- // time is 00:00 A.M. and local_time does not consider DST because it
- // does not have any date information. We need to consider both date and
- // time information at the same time to convert it correctly.
-
- std::tm t;
- t.tm_sec = static_cast<int>(this->time.second);
- t.tm_min = static_cast<int>(this->time.minute);
- t.tm_hour = static_cast<int>(this->time.hour);
- t.tm_mday = static_cast<int>(this->date.day);
- t.tm_mon = static_cast<int>(this->date.month);
- t.tm_year = static_cast<int>(this->date.year) - 1900;
- t.tm_wday = 0; // the value will be ignored
- t.tm_yday = 0; // the value will be ignored
- t.tm_isdst = -1;
-
- // std::mktime returns date as local time zone. no conversion needed
- auto dt = std::chrono::system_clock::from_time_t(std::mktime(&t));
- dt += std::chrono::duration_cast<internal_duration>(
- std::chrono::milliseconds(this->time.millisecond) +
- std::chrono::microseconds(this->time.microsecond) +
- std::chrono::nanoseconds (this->time.nanosecond));
- return dt;
- }
-
- operator std::time_t() const
- {
- return std::chrono::system_clock::to_time_t(
- std::chrono::system_clock::time_point(*this));
- }
-
- local_datetime() = default;
- ~local_datetime() = default;
- local_datetime(local_datetime const&) = default;
- local_datetime(local_datetime&&) = default;
- local_datetime& operator=(local_datetime const&) = default;
- local_datetime& operator=(local_datetime&&) = default;
-};
-
-inline bool operator==(const local_datetime& lhs, const local_datetime& rhs)
-{
- return std::make_tuple(lhs.date, lhs.time) ==
- std::make_tuple(rhs.date, rhs.time);
-}
-inline bool operator!=(const local_datetime& lhs, const local_datetime& rhs)
-{
- return !(lhs == rhs);
-}
-inline bool operator< (const local_datetime& lhs, const local_datetime& rhs)
-{
- return std::make_tuple(lhs.date, lhs.time) <
- std::make_tuple(rhs.date, rhs.time);
-}
-inline bool operator<=(const local_datetime& lhs, const local_datetime& rhs)
-{
- return (lhs < rhs) || (lhs == rhs);
-}
-inline bool operator> (const local_datetime& lhs, const local_datetime& rhs)
-{
- return !(lhs <= rhs);
-}
-inline bool operator>=(const local_datetime& lhs, const local_datetime& rhs)
-{
- return !(lhs < rhs);
-}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const local_datetime& dt)
-{
- os << dt.date << 'T' << dt.time;
- return os;
-}
-
-struct offset_datetime
-{
- 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)
- {}
- offset_datetime(const local_datetime& dt, time_offset o)
- : date(dt.date), time(dt.time), offset(o)
- {}
- explicit offset_datetime(const local_datetime& ld)
- : date(ld.date), time(ld.time), offset(get_local_offset(nullptr))
- // use the current local timezone offset
- {}
- explicit offset_datetime(const std::chrono::system_clock::time_point& tp)
- : offset(0, 0) // use gmtime
- {
- const auto timet = std::chrono::system_clock::to_time_t(tp);
- const auto tm = detail::gmtime_s(&timet);
- this->date = local_date(tm);
- this->time = local_time(tm);
- }
- explicit offset_datetime(const std::time_t& t)
- : offset(0, 0) // use gmtime
- {
- const auto tm = detail::gmtime_s(&t);
- this->date = local_date(tm);
- this->time = local_time(tm);
- }
- explicit offset_datetime(const std::tm& t)
- : offset(0, 0) // assume gmtime
- {
- this->date = local_date(t);
- this->time = local_time(t);
- }
-
- operator std::chrono::system_clock::time_point() const
- {
- // get date-time
- using internal_duration =
- typename std::chrono::system_clock::time_point::duration;
-
- // first, convert it to local date-time information in the same way as
- // local_datetime does. later we will use time_t to adjust time offset.
- std::tm t;
- t.tm_sec = static_cast<int>(this->time.second);
- t.tm_min = static_cast<int>(this->time.minute);
- t.tm_hour = static_cast<int>(this->time.hour);
- t.tm_mday = static_cast<int>(this->date.day);
- t.tm_mon = static_cast<int>(this->date.month);
- t.tm_year = static_cast<int>(this->date.year) - 1900;
- t.tm_wday = 0; // the value will be ignored
- t.tm_yday = 0; // the value will be ignored
- t.tm_isdst = -1;
- const std::time_t tp_loc = std::mktime(std::addressof(t));
-
- auto tp = std::chrono::system_clock::from_time_t(tp_loc);
- tp += std::chrono::duration_cast<internal_duration>(
- std::chrono::milliseconds(this->time.millisecond) +
- std::chrono::microseconds(this->time.microsecond) +
- std::chrono::nanoseconds (this->time.nanosecond));
-
- // Since mktime uses local time zone, it should be corrected.
- // `12:00:00+09:00` means `03:00:00Z`. So mktime returns `03:00:00Z` if
- // we are in `+09:00` timezone. To represent `12:00:00Z` there, we need
- // to add `+09:00` to `03:00:00Z`.
- // Here, it uses the time_t converted from date-time info to handle
- // daylight saving time.
- const auto ofs = get_local_offset(std::addressof(tp_loc));
- tp += std::chrono::hours (ofs.hour);
- tp += std::chrono::minutes(ofs.minute);
-
- // We got `12:00:00Z` by correcting local timezone applied by mktime.
- // Then we will apply the offset. Let's say `12:00:00-08:00` is given.
- // And now, we have `12:00:00Z`. `12:00:00-08:00` means `20:00:00Z`.
- // So we need to subtract the offset.
- tp -= std::chrono::minutes(this->offset);
- return tp;
- }
-
- operator std::time_t() const
- {
- return std::chrono::system_clock::to_time_t(
- std::chrono::system_clock::time_point(*this));
- }
-
- offset_datetime() = default;
- ~offset_datetime() = default;
- offset_datetime(offset_datetime const&) = default;
- offset_datetime(offset_datetime&&) = default;
- offset_datetime& operator=(offset_datetime const&) = default;
- offset_datetime& operator=(offset_datetime&&) = default;
-
- private:
-
- static time_offset get_local_offset(const std::time_t* tp)
- {
- // get local timezone with the same date-time information as mktime
- const auto t = detail::localtime_s(tp);
-
- std::array<char, 6> buf;
- const auto result = std::strftime(buf.data(), 6, "%z", &t); // +hhmm\0
- if(result != 5)
- {
- throw std::runtime_error("toml::offset_datetime: cannot obtain "
- "timezone information of current env");
- }
- const int ofs = std::atoi(buf.data());
- const int ofs_h = ofs / 100;
- const int ofs_m = ofs - (ofs_h * 100);
- return time_offset(ofs_h, ofs_m);
- }
-};
-
-inline bool operator==(const offset_datetime& lhs, const offset_datetime& rhs)
-{
- return std::make_tuple(lhs.date, lhs.time, lhs.offset) ==
- std::make_tuple(rhs.date, rhs.time, rhs.offset);
-}
-inline bool operator!=(const offset_datetime& lhs, const offset_datetime& rhs)
-{
- return !(lhs == rhs);
-}
-inline bool operator< (const offset_datetime& lhs, const offset_datetime& rhs)
-{
- return std::make_tuple(lhs.date, lhs.time, lhs.offset) <
- std::make_tuple(rhs.date, rhs.time, rhs.offset);
-}
-inline bool operator<=(const offset_datetime& lhs, const offset_datetime& rhs)
-{
- return (lhs < rhs) || (lhs == rhs);
-}
-inline bool operator> (const offset_datetime& lhs, const offset_datetime& rhs)
-{
- return !(lhs <= rhs);
-}
-inline bool operator>=(const offset_datetime& lhs, const offset_datetime& rhs)
-{
- return !(lhs < rhs);
-}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const offset_datetime& dt)
-{
- os << dt.date << 'T' << dt.time << dt.offset;
- return os;
-}
-
-}//toml
-#endif// TOML11_DATETIME
diff --git a/src/toml11/toml/exception.hpp b/src/toml11/toml/exception.hpp
deleted file mode 100644
index c64651d0a..000000000
--- a/src/toml11/toml/exception.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_EXCEPTION_HPP
-#define TOML11_EXCEPTION_HPP
-#include <stdexcept>
-#include <string>
-
-#include "source_location.hpp"
-
-namespace toml
-{
-
-struct exception : public std::exception
-{
- public:
- explicit exception(const source_location& loc): loc_(loc) {}
- virtual ~exception() noexcept override = default;
- virtual const char* what() const noexcept override {return "";}
- virtual source_location const& location() const noexcept {return loc_;}
-
- protected:
- source_location loc_;
-};
-
-struct syntax_error : public toml::exception
-{
- public:
- explicit syntax_error(const std::string& what_arg, const source_location& loc)
- : exception(loc), what_(what_arg)
- {}
- virtual ~syntax_error() noexcept override = default;
- virtual const char* what() const noexcept override {return what_.c_str();}
-
- protected:
- std::string what_;
-};
-
-struct type_error : public toml::exception
-{
- public:
- explicit type_error(const std::string& what_arg, const source_location& loc)
- : exception(loc), what_(what_arg)
- {}
- virtual ~type_error() noexcept override = default;
- virtual const char* what() const noexcept override {return what_.c_str();}
-
- protected:
- std::string what_;
-};
-
-struct internal_error : public toml::exception
-{
- public:
- explicit internal_error(const std::string& what_arg, const source_location& loc)
- : exception(loc), what_(what_arg)
- {}
- virtual ~internal_error() noexcept override = default;
- virtual const char* what() const noexcept override {return what_.c_str();}
-
- protected:
- std::string what_;
-};
-
-} // toml
-#endif // TOML_EXCEPTION
diff --git a/src/toml11/toml/from.hpp b/src/toml11/toml/from.hpp
deleted file mode 100644
index 10815caf5..000000000
--- a/src/toml11/toml/from.hpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright Toru Niina 2019.
-// Distributed under the MIT License.
-#ifndef TOML11_FROM_HPP
-#define TOML11_FROM_HPP
-
-namespace toml
-{
-
-template<typename T>
-struct from;
-// {
-// static T from_toml(const toml::value& v)
-// {
-// // User-defined conversions ...
-// }
-// };
-
-} // toml
-#endif // TOML11_FROM_HPP
diff --git a/src/toml11/toml/get.hpp b/src/toml11/toml/get.hpp
deleted file mode 100644
index d7fdf553b..000000000
--- a/src/toml11/toml/get.hpp
+++ /dev/null
@@ -1,1117 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_GET_HPP
-#define TOML11_GET_HPP
-#include <algorithm>
-
-#include "from.hpp"
-#include "result.hpp"
-#include "value.hpp"
-
-namespace toml
-{
-
-// ============================================================================
-// exact toml::* type
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> &
-get(basic_value<C, M, V>& v)
-{
- return v.template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>();
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const&
-get(const basic_value<C, M, V>& v)
-{
- return v.template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>();
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>
-get(basic_value<C, M, V>&& v)
-{
- return T(std::move(v).template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>());
-}
-
-// ============================================================================
-// T == toml::value; identity transformation.
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T>&
-get(basic_value<C, M, V>& v)
-{
- return v;
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T> const&
-get(const basic_value<C, M, V>& v)
-{
- return v;
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T>
-get(basic_value<C, M, V>&& v)
-{
- return basic_value<C, M, V>(std::move(v));
-}
-
-// ============================================================================
-// T == toml::basic_value<C2, M2, V2>; basic_value -> basic_value
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<detail::conjunction<detail::is_basic_value<T>,
- detail::negation<std::is_same<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>& v)
-{
- return T(v);
-}
-
-// ============================================================================
-// integer convertible from toml::Integer
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<detail::conjunction<
- std::is_integral<T>, // T is integral
- detail::negation<std::is_same<T, bool>>, // but not bool
- detail::negation< // but not toml::integer
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>& v)
-{
- return static_cast<T>(v.as_integer());
-}
-
-// ============================================================================
-// floating point convertible from toml::Float
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<detail::conjunction<
- std::is_floating_point<T>, // T is floating_point
- detail::negation< // but not toml::floating
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>& v)
-{
- return static_cast<T>(v.as_floating());
-}
-
-// ============================================================================
-// std::string; toml uses its own toml::string, but it should be convertible to
-// std::string seamlessly
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
-get(basic_value<C, M, V>& v)
-{
- return v.as_string().str;
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
-get(const basic_value<C, M, V>& v)
-{
- return v.as_string().str;
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>
-get(basic_value<C, M, V>&& v)
-{
- return std::string(std::move(v.as_string().str));
-}
-
-// ============================================================================
-// std::string_view
-
-#if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<std::is_same<T, std::string_view>::value, std::string_view>
-get(const basic_value<C, M, V>& v)
-{
- return std::string_view(v.as_string().str);
-}
-#endif
-
-// ============================================================================
-// std::chrono::duration from toml::local_time.
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<detail::is_chrono_duration<T>::value, T>
-get(const basic_value<C, M, V>& v)
-{
- return std::chrono::duration_cast<T>(
- std::chrono::nanoseconds(v.as_local_time()));
-}
-
-// ============================================================================
-// std::chrono::system_clock::time_point from toml::datetime variants
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-inline detail::enable_if_t<
- std::is_same<std::chrono::system_clock::time_point, T>::value, T>
-get(const basic_value<C, M, V>& v)
-{
- switch(v.type())
- {
- case value_t::local_date:
- {
- return std::chrono::system_clock::time_point(v.as_local_date());
- }
- case value_t::local_datetime:
- {
- return std::chrono::system_clock::time_point(v.as_local_datetime());
- }
- case value_t::offset_datetime:
- {
- return std::chrono::system_clock::time_point(v.as_offset_datetime());
- }
- default:
- {
- throw type_error(detail::format_underline("toml::value: "
- "bad_cast to std::chrono::system_clock::time_point", {
- {v.location(), concat_to_string("the actual type is ", v.type())}
- }), v.location());
- }
- }
-}
-
-// ============================================================================
-// forward declaration to use this recursively. ignore this and go ahead.
-
-// array-like type with push_back(value) method
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::is_container<T>, // T is a container
- detail::has_push_back_method<T>, // T::push_back(value) works
- detail::negation< // but not toml::array
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>&);
-
-// array-like type without push_back(value) method
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::is_container<T>, // T is a container
- detail::negation<detail::has_push_back_method<T>>, // w/o push_back(...)
- detail::negation< // not toml::array
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>&);
-
-// std::pair<T1, T2>
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_std_pair<T>::value, T>
-get(const basic_value<C, M, V>&);
-
-// std::tuple<T1, T2, ...>
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_std_tuple<T>::value, T>
-get(const basic_value<C, M, V>&);
-
-// map-like classes
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::is_map<T>, // T is map
- detail::negation< // but not toml::table
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>&);
-
-// T.from_toml(v)
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::negation< // not a toml::* type
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>,
- detail::has_from_toml_method<T, C, M, V>, // but has from_toml(toml::value)
- std::is_default_constructible<T> // and default constructible
- >::value, T>
-get(const basic_value<C, M, V>&);
-
-// toml::from<T>::from_toml(v)
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::has_specialized_from<T>::value, T>
-get(const basic_value<C, M, V>&);
-
-// T(const toml::value&) and T is not toml::basic_value,
-// and it does not have `from<T>` nor `from_toml`.
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::negation<detail::is_basic_value<T>>,
- std::is_constructible<T, const basic_value<C, M, V>&>,
- detail::negation<detail::has_from_toml_method<T, C, M, V>>,
- detail::negation<detail::has_specialized_from<T>>
- >::value, T>
-get(const basic_value<C, M, V>&);
-
-// ============================================================================
-// array-like types; most likely STL container, like std::vector, etc.
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::is_container<T>, // T is a container
- detail::has_push_back_method<T>, // container.push_back(elem) works
- detail::negation< // but not toml::array
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>& v)
-{
- using value_type = typename T::value_type;
- const auto& ary = v.as_array();
-
- T container;
- try_reserve(container, ary.size());
-
- for(const auto& elem : ary)
- {
- container.push_back(get<value_type>(elem));
- }
- return container;
-}
-
-// ============================================================================
-// std::forward_list does not have push_back, insert, or emplace.
-// It has insert_after, emplace_after, push_front.
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_std_forward_list<T>::value, T>
-get(const basic_value<C, M, V>& v)
-{
- using value_type = typename T::value_type;
- T container;
- for(const auto& elem : v.as_array())
- {
- container.push_front(get<value_type>(elem));
- }
- container.reverse();
- return container;
-}
-
-// ============================================================================
-// array-like types, without push_back(). most likely [std|boost]::array.
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::is_container<T>, // T is a container
- detail::negation<detail::has_push_back_method<T>>, // w/o push_back
- detail::negation< // T is not toml::array
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>& v)
-{
- using value_type = typename T::value_type;
- const auto& ar = v.as_array();
-
- T container;
- if(ar.size() != container.size())
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "toml::get: specified container size is ", container.size(),
- " but there are ", ar.size(), " elements in toml array."), {
- {v.location(), "here"}
- }));
- }
- for(std::size_t i=0; i<ar.size(); ++i)
- {
- container[i] = ::toml::get<value_type>(ar[i]);
- }
- return container;
-}
-
-// ============================================================================
-// std::pair.
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_std_pair<T>::value, T>
-get(const basic_value<C, M, V>& v)
-{
- using first_type = typename T::first_type;
- using second_type = typename T::second_type;
-
- const auto& ar = v.as_array();
- if(ar.size() != 2)
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "toml::get: specified std::pair but there are ", ar.size(),
- " elements in toml array."), {{v.location(), "here"}}));
- }
- return std::make_pair(::toml::get<first_type >(ar.at(0)),
- ::toml::get<second_type>(ar.at(1)));
-}
-
-// ============================================================================
-// std::tuple.
-
-namespace detail
-{
-template<typename T, typename Array, std::size_t ... I>
-T get_tuple_impl(const Array& a, index_sequence<I...>)
-{
- return std::make_tuple(
- ::toml::get<typename std::tuple_element<I, T>::type>(a.at(I))...);
-}
-} // detail
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_std_tuple<T>::value, T>
-get(const basic_value<C, M, V>& v)
-{
- const auto& ar = v.as_array();
- if(ar.size() != std::tuple_size<T>::value)
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "toml::get: specified std::tuple with ",
- std::tuple_size<T>::value, " elements, but there are ", ar.size(),
- " elements in toml array."), {{v.location(), "here"}}));
- }
- return detail::get_tuple_impl<T>(ar,
- detail::make_index_sequence<std::tuple_size<T>::value>{});
-}
-
-// ============================================================================
-// map-like types; most likely STL map, like std::map or std::unordered_map.
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::is_map<T>, // T is map
- detail::negation< // but not toml::array
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>
- >::value, T>
-get(const basic_value<C, M, V>& v)
-{
- using key_type = typename T::key_type;
- using mapped_type = typename T::mapped_type;
- static_assert(std::is_convertible<std::string, key_type>::value,
- "toml::get only supports map type of which key_type is "
- "convertible from std::string.");
- T map;
- for(const auto& kv : v.as_table())
- {
- map.emplace(key_type(kv.first), get<mapped_type>(kv.second));
- }
- return map;
-}
-
-// ============================================================================
-// user-defined, but compatible types.
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::negation< // not a toml::* type
- detail::is_exact_toml_type<T, basic_value<C, M, V>>>,
- detail::has_from_toml_method<T, C, M, V>, // but has from_toml(toml::value) memfn
- std::is_default_constructible<T> // and default constructible
- >::value, T>
-get(const basic_value<C, M, V>& v)
-{
- T ud;
- ud.from_toml(v);
- return ud;
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::has_specialized_from<T>::value, T>
-get(const basic_value<C, M, V>& v)
-{
- return ::toml::from<T>::from_toml(v);
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::negation<detail::is_basic_value<T>>, // T is not a toml::value
- std::is_constructible<T, const basic_value<C, M, V>&>, // T is constructible from toml::value
- detail::negation<detail::has_from_toml_method<T, C, M, V>>, // and T does not have T.from_toml(v);
- detail::negation<detail::has_specialized_from<T>> // and T does not have toml::from<T>{};
- >::value, T>
-get(const basic_value<C, M, V>& v)
-{
- return T(v);
-}
-
-// ============================================================================
-// find
-
-// ----------------------------------------------------------------------------
-// these overloads do not require to set T. and returns value itself.
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V> const& find(const basic_value<C, M, V>& v, const key& ky)
-{
- const auto& tab = v.as_table();
- if(tab.count(ky) == 0)
- {
- detail::throw_key_not_found_error(v, ky);
- }
- return tab.at(ky);
-}
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V>& find(basic_value<C, M, V>& v, const key& ky)
-{
- auto& tab = v.as_table();
- if(tab.count(ky) == 0)
- {
- detail::throw_key_not_found_error(v, ky);
- }
- return tab.at(ky);
-}
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V> find(basic_value<C, M, V>&& v, const key& ky)
-{
- typename basic_value<C, M, V>::table_type tab = std::move(v).as_table();
- if(tab.count(ky) == 0)
- {
- detail::throw_key_not_found_error(v, ky);
- }
- return basic_value<C, M, V>(std::move(tab.at(ky)));
-}
-
-// ----------------------------------------------------------------------------
-// find(value, idx)
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V> const&
-find(const basic_value<C, M, V>& v, const std::size_t idx)
-{
- const auto& ary = v.as_array();
- if(ary.size() <= idx)
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "index ", idx, " is out of range"), {{v.location(), "in this array"}}));
- }
- return ary.at(idx);
-}
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V>& find(basic_value<C, M, V>& v, const std::size_t idx)
-{
- auto& ary = v.as_array();
- if(ary.size() <= idx)
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "index ", idx, " is out of range"), {{v.location(), "in this array"}}));
- }
- return ary.at(idx);
-}
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V> find(basic_value<C, M, V>&& v, const std::size_t idx)
-{
- auto& ary = v.as_array();
- if(ary.size() <= idx)
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "index ", idx, " is out of range"), {{v.location(), "in this array"}}));
- }
- return basic_value<C, M, V>(std::move(ary.at(idx)));
-}
-
-// ----------------------------------------------------------------------------
-// find<T>(value, key);
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))
-find(const basic_value<C, M, V>& v, const key& ky)
-{
- const auto& tab = v.as_table();
- if(tab.count(ky) == 0)
- {
- detail::throw_key_not_found_error(v, ky);
- }
- return ::toml::get<T>(tab.at(ky));
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
-find(basic_value<C, M, V>& v, const key& ky)
-{
- auto& tab = v.as_table();
- if(tab.count(ky) == 0)
- {
- detail::throw_key_not_found_error(v, ky);
- }
- return ::toml::get<T>(tab.at(ky));
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
-find(basic_value<C, M, V>&& v, const key& ky)
-{
- typename basic_value<C, M, V>::table_type tab = std::move(v).as_table();
- if(tab.count(ky) == 0)
- {
- detail::throw_key_not_found_error(v, ky);
- }
- return ::toml::get<T>(std::move(tab.at(ky)));
-}
-
-// ----------------------------------------------------------------------------
-// find<T>(value, idx)
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))
-find(const basic_value<C, M, V>& v, const std::size_t idx)
-{
- const auto& ary = v.as_array();
- if(ary.size() <= idx)
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "index ", idx, " is out of range"), {{v.location(), "in this array"}}));
- }
- return ::toml::get<T>(ary.at(idx));
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
-find(basic_value<C, M, V>& v, const std::size_t idx)
-{
- auto& ary = v.as_array();
- if(ary.size() <= idx)
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "index ", idx, " is out of range"), {{v.location(), "in this array"}}));
- }
- return ::toml::get<T>(ary.at(idx));
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
-find(basic_value<C, M, V>&& v, const std::size_t idx)
-{
- typename basic_value<C, M, V>::array_type ary = std::move(v).as_array();
- if(ary.size() <= idx)
- {
- throw std::out_of_range(detail::format_underline(concat_to_string(
- "index ", idx, " is out of range"), {{v.location(), "in this array"}}));
- }
- return ::toml::get<T>(std::move(ary.at(idx)));
-}
-
-// --------------------------------------------------------------------------
-// toml::find(toml::value, toml::key, Ts&& ... keys)
-
-namespace detail
-{
-// It suppresses warnings by -Wsign-conversion. Let's say we have the following
-// code.
-// ```cpp
-// const auto x = toml::find<std::string>(data, "array", 0);
-// ```
-// Here, the type of literal number `0` is `int`. `int` is a signed integer.
-// `toml::find` takes `std::size_t` as an index. So it causes implicit sign
-// conversion and `-Wsign-conversion` warns about it. Using `0u` instead of `0`
-// suppresses the warning, but it makes user code messy.
-// To suppress this warning, we need to be aware of type conversion caused
-// by `toml::find(v, key1, key2, ... keys)`. But the thing is that the types of
-// keys can be any combination of {string-like, size_t-like}. Of course we can't
-// write down all the combinations. Thus we need to use some function that
-// recognize the type of argument and cast it into `std::string` or
-// `std::size_t` depending on the context.
-// `key_cast` does the job. It has 2 overloads. One is invoked when the
-// argument type is an integer and cast the argument into `std::size_t`. The
-// other is invoked when the argument type is not an integer, possibly one of
-// std::string, const char[N] or const char*, and construct std::string from
-// the argument.
-// `toml::find(v, k1, k2, ... ks)` uses `key_cast` before passing `ks` to
-// `toml::find(v, k)` to suppress -Wsign-conversion.
-
-template<typename T>
-enable_if_t<conjunction<std::is_integral<remove_cvref_t<T>>,
- negation<std::is_same<remove_cvref_t<T>, bool>>>::value, std::size_t>
-key_cast(T&& v) noexcept
-{
- return std::size_t(v);
-}
-template<typename T>
-enable_if_t<negation<conjunction<std::is_integral<remove_cvref_t<T>>,
- negation<std::is_same<remove_cvref_t<T>, bool>>>>::value, std::string>
-key_cast(T&& v) noexcept
-{
- return std::string(std::forward<T>(v));
-}
-} // detail
-
-template<typename C,
- template<typename ...> class M, template<typename ...> class V,
- typename Key1, typename Key2, typename ... Keys>
-const basic_value<C, M, V>&
-find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
-{
- return ::toml::find(::toml::find(v, detail::key_cast(k1)),
- detail::key_cast(k2), std::forward<Keys>(keys)...);
-}
-template<typename C,
- template<typename ...> class M, template<typename ...> class V,
- typename Key1, typename Key2, typename ... Keys>
-basic_value<C, M, V>&
-find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
-{
- return ::toml::find(::toml::find(v, detail::key_cast(k1)),
- detail::key_cast(k2), std::forward<Keys>(keys)...);
-}
-template<typename C,
- template<typename ...> class M, template<typename ...> class V,
- typename Key1, typename Key2, typename ... Keys>
-basic_value<C, M, V>
-find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
-{
- return ::toml::find(::toml::find(std::move(v), std::forward<Key1>(k1)),
- detail::key_cast(k2), std::forward<Keys>(keys)...);
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V,
- typename Key1, typename Key2, typename ... Keys>
-decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>()))
-find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
-{
- return ::toml::find<T>(::toml::find(v, detail::key_cast(k1)),
- detail::key_cast(k2), std::forward<Keys>(keys)...);
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V,
- typename Key1, typename Key2, typename ... Keys>
-decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
-find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
-{
- return ::toml::find<T>(::toml::find(v, detail::key_cast(k1)),
- detail::key_cast(k2), std::forward<Keys>(keys)...);
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V,
- typename Key1, typename Key2, typename ... Keys>
-decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
-find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
-{
- return ::toml::find<T>(::toml::find(std::move(v), detail::key_cast(k1)),
- detail::key_cast(k2), std::forward<Keys>(keys)...);
-}
-
-// ============================================================================
-// get_or(value, fallback)
-
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V> const&
-get_or(const basic_value<C, M, V>& v, const basic_value<C, M, V>&)
-{
- return v;
-}
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V>&
-get_or(basic_value<C, M, V>& v, basic_value<C, M, V>&)
-{
- return v;
-}
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V>
-get_or(basic_value<C, M, V>&& v, basic_value<C, M, V>&&)
-{
- return v;
-}
-
-// ----------------------------------------------------------------------------
-// specialization for the exact toml types (return type becomes lvalue ref)
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<
- detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const&
-get_or(const basic_value<C, M, V>& v, const T& opt)
-{
- try
- {
- return get<detail::remove_cvref_t<T>>(v);
- }
- catch(...)
- {
- return opt;
- }
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<
- detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&
-get_or(basic_value<C, M, V>& v, T& opt)
-{
- try
- {
- return get<detail::remove_cvref_t<T>>(v);
- }
- catch(...)
- {
- return opt;
- }
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_exact_toml_type<detail::remove_cvref_t<T>,
- basic_value<C, M, V>>::value, detail::remove_cvref_t<T>>
-get_or(basic_value<C, M, V>&& v, T&& opt)
-{
- try
- {
- return get<detail::remove_cvref_t<T>>(std::move(v));
- }
- catch(...)
- {
- return detail::remove_cvref_t<T>(std::forward<T>(opt));
- }
-}
-
-// ----------------------------------------------------------------------------
-// specialization for std::string (return type becomes lvalue ref)
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<std::is_same<detail::remove_cvref_t<T>, std::string>::value,
- std::string> const&
-get_or(const basic_value<C, M, V>& v, const T& opt)
-{
- try
- {
- return v.as_string().str;
- }
- catch(...)
- {
- return opt;
- }
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
-get_or(basic_value<C, M, V>& v, T& opt)
-{
- try
- {
- return v.as_string().str;
- }
- catch(...)
- {
- return opt;
- }
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<
- std::is_same<detail::remove_cvref_t<T>, std::string>::value, std::string>
-get_or(basic_value<C, M, V>&& v, T&& opt)
-{
- try
- {
- return std::move(v.as_string().str);
- }
- catch(...)
- {
- return std::string(std::forward<T>(opt));
- }
-}
-
-// ----------------------------------------------------------------------------
-// specialization for string literal
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::is_string_literal<
- typename std::remove_reference<T>::type>::value, std::string>
-get_or(const basic_value<C, M, V>& v, T&& opt)
-{
- try
- {
- return std::move(v.as_string().str);
- }
- catch(...)
- {
- return std::string(std::forward<T>(opt));
- }
-}
-
-// ----------------------------------------------------------------------------
-// others (require type conversion and return type cannot be lvalue reference)
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- detail::negation<detail::is_exact_toml_type<detail::remove_cvref_t<T>,
- basic_value<C, M, V>>>,
- detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>,
- detail::negation<detail::is_string_literal<
- typename std::remove_reference<T>::type>>
- >::value, detail::remove_cvref_t<T>>
-get_or(const basic_value<C, M, V>& v, T&& opt)
-{
- try
- {
- return get<detail::remove_cvref_t<T>>(v);
- }
- catch(...)
- {
- return detail::remove_cvref_t<T>(std::forward<T>(opt));
- }
-}
-
-// ===========================================================================
-// find_or(value, key, fallback)
-
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V> const&
-find_or(const basic_value<C, M, V>& v, const key& ky,
- const basic_value<C, M, V>& opt)
-{
- if(!v.is_table()) {return opt;}
- const auto& tab = v.as_table();
- if(tab.count(ky) == 0) {return opt;}
- return tab.at(ky);
-}
-
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V>&
-find_or(basic_value<C, M, V>& v, const toml::key& ky, basic_value<C, M, V>& opt)
-{
- if(!v.is_table()) {return opt;}
- auto& tab = v.as_table();
- if(tab.count(ky) == 0) {return opt;}
- return tab.at(ky);
-}
-
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-basic_value<C, M, V>
-find_or(basic_value<C, M, V>&& v, const toml::key& ky, basic_value<C, M, V>&& opt)
-{
- if(!v.is_table()) {return opt;}
- auto tab = std::move(v).as_table();
- if(tab.count(ky) == 0) {return opt;}
- return basic_value<C, M, V>(std::move(tab.at(ky)));
-}
-
-// ---------------------------------------------------------------------------
-// exact types (return type can be a reference)
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<
- detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const&
-find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt)
-{
- if(!v.is_table()) {return opt;}
- const auto& tab = v.as_table();
- if(tab.count(ky) == 0) {return opt;}
- return get_or(tab.at(ky), opt);
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<
- detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&
-find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
-{
- if(!v.is_table()) {return opt;}
- auto& tab = v.as_table();
- if(tab.count(ky) == 0) {return opt;}
- return get_or(tab.at(ky), opt);
-}
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<
- detail::is_exact_toml_type<T, basic_value<C, M, V>>::value,
- detail::remove_cvref_t<T>>
-find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
-{
- if(!v.is_table()) {return std::forward<T>(opt);}
- auto tab = std::move(v).as_table();
- if(tab.count(ky) == 0) {return std::forward<T>(opt);}
- return get_or(std::move(tab.at(ky)), std::forward<T>(opt));
-}
-
-// ---------------------------------------------------------------------------
-// std::string (return type can be a reference)
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
-find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt)
-{
- if(!v.is_table()) {return opt;}
- const auto& tab = v.as_table();
- if(tab.count(ky) == 0) {return opt;}
- return get_or(tab.at(ky), opt);
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
-find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
-{
- if(!v.is_table()) {return opt;}
- auto& tab = v.as_table();
- if(tab.count(ky) == 0) {return opt;}
- return get_or(tab.at(ky), opt);
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<std::is_same<T, std::string>::value, std::string>
-find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
-{
- if(!v.is_table()) {return std::forward<T>(opt);}
- auto tab = std::move(v).as_table();
- if(tab.count(ky) == 0) {return std::forward<T>(opt);}
- return get_or(std::move(tab.at(ky)), std::forward<T>(opt));
-}
-
-// ---------------------------------------------------------------------------
-// string literal (deduced as std::string)
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<
- detail::is_string_literal<typename std::remove_reference<T>::type>::value,
- std::string>
-find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
-{
- if(!v.is_table()) {return std::string(opt);}
- const auto& tab = v.as_table();
- if(tab.count(ky) == 0) {return std::string(opt);}
- return get_or(tab.at(ky), std::forward<T>(opt));
-}
-
-// ---------------------------------------------------------------------------
-// others (require type conversion and return type cannot be lvalue reference)
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-detail::enable_if_t<detail::conjunction<
- // T is not an exact toml type
- detail::negation<detail::is_exact_toml_type<
- detail::remove_cvref_t<T>, basic_value<C, M, V>>>,
- // T is not std::string
- detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>,
- // T is not a string literal
- detail::negation<detail::is_string_literal<
- typename std::remove_reference<T>::type>>
- >::value, detail::remove_cvref_t<T>>
-find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
-{
- if(!v.is_table()) {return std::forward<T>(opt);}
- const auto& tab = v.as_table();
- if(tab.count(ky) == 0) {return std::forward<T>(opt);}
- return get_or(tab.at(ky), std::forward<T>(opt));
-}
-
-// ---------------------------------------------------------------------------
-// recursive find-or with type deduction (find_or(value, keys, opt))
-
-template<typename Value, typename ... Ks,
- typename detail::enable_if_t<(sizeof...(Ks) > 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<Value>(v), ky, detail::last_one(std::forward<Ks>(keys)...)))
-{
- if(!v.is_table())
- {
- return detail::last_one(std::forward<Ks>(keys)...);
- }
- auto&& tab = std::forward<Value>(v).as_table();
- if(tab.count(ky) == 0)
- {
- return detail::last_one(std::forward<Ks>(keys)...);
- }
- return find_or(std::forward<decltype(tab)>(tab).at(ky), std::forward<Ks>(keys)...);
-}
-
-// ---------------------------------------------------------------------------
-// recursive find_or with explicit type specialization, find_or<int>(value, keys...)
-
-template<typename T, typename Value, typename ... Ks,
- typename detail::enable_if_t<(sizeof...(Ks) > 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<T>(std::forward<Value>(v), ky, detail::last_one(std::forward<Ks>(keys)...)))
-{
- if(!v.is_table())
- {
- return detail::last_one(std::forward<Ks>(keys)...);
- }
- auto&& tab = std::forward<Value>(v).as_table();
- if(tab.count(ky) == 0)
- {
- return detail::last_one(std::forward<Ks>(keys)...);
- }
- return find_or(std::forward<decltype(tab)>(tab).at(ky), std::forward<Ks>(keys)...);
-}
-
-// ============================================================================
-// expect
-
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-result<T, std::string> expect(const basic_value<C, M, V>& v) noexcept
-{
- try
- {
- return ok(get<T>(v));
- }
- catch(const std::exception& e)
- {
- return err(e.what());
- }
-}
-template<typename T, typename C,
- template<typename ...> class M, template<typename ...> class V>
-result<T, std::string>
-expect(const basic_value<C, M, V>& v, const toml::key& k) noexcept
-{
- try
- {
- return ok(find<T>(v, k));
- }
- catch(const std::exception& e)
- {
- return err(e.what());
- }
-}
-
-} // toml
-#endif// TOML11_GET
diff --git a/src/toml11/toml/into.hpp b/src/toml11/toml/into.hpp
deleted file mode 100644
index 74495560e..000000000
--- a/src/toml11/toml/into.hpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright Toru Niina 2019.
-// Distributed under the MIT License.
-#ifndef TOML11_INTO_HPP
-#define TOML11_INTO_HPP
-
-namespace toml
-{
-
-template<typename T>
-struct into;
-// {
-// static toml::value into_toml(const T& user_defined_type)
-// {
-// // User-defined conversions ...
-// }
-// };
-
-} // toml
-#endif // TOML11_INTO_HPP
diff --git a/src/toml11/toml/lexer.hpp b/src/toml11/toml/lexer.hpp
deleted file mode 100644
index ea5050b8d..000000000
--- a/src/toml11/toml/lexer.hpp
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_LEXER_HPP
-#define TOML11_LEXER_HPP
-#include <istream>
-#include <sstream>
-#include <stdexcept>
-#include <fstream>
-
-#include "combinator.hpp"
-
-namespace toml
-{
-namespace detail
-{
-
-// these scans contents from current location in a container of char
-// and extract a region that matches their own pattern.
-// to see the implementation of each component, see combinator.hpp.
-
-using lex_wschar = either<character<' '>, character<'\t'>>;
-using lex_ws = repeat<lex_wschar, at_least<1>>;
-using lex_newline = either<character<'\n'>,
- sequence<character<'\r'>, character<'\n'>>>;
-using lex_lower = in_range<'a', 'z'>;
-using lex_upper = in_range<'A', 'Z'>;
-using lex_alpha = either<lex_lower, lex_upper>;
-using lex_digit = in_range<'0', '9'>;
-using lex_nonzero = in_range<'1', '9'>;
-using lex_oct_dig = in_range<'0', '7'>;
-using lex_bin_dig = in_range<'0', '1'>;
-using lex_hex_dig = either<lex_digit, in_range<'A', 'F'>, in_range<'a', 'f'>>;
-
-using lex_hex_prefix = sequence<character<'0'>, character<'x'>>;
-using lex_oct_prefix = sequence<character<'0'>, character<'o'>>;
-using lex_bin_prefix = sequence<character<'0'>, character<'b'>>;
-using lex_underscore = character<'_'>;
-using lex_plus = character<'+'>;
-using lex_minus = character<'-'>;
-using lex_sign = either<lex_plus, lex_minus>;
-
-// digit | nonzero 1*(digit | _ digit)
-using lex_unsigned_dec_int = either<sequence<lex_nonzero, repeat<
- either<lex_digit, sequence<lex_underscore, lex_digit>>, at_least<1>>>,
- lex_digit>;
-// (+|-)? unsigned_dec_int
-using lex_dec_int = sequence<maybe<lex_sign>, lex_unsigned_dec_int>;
-
-// hex_prefix hex_dig *(hex_dig | _ hex_dig)
-using lex_hex_int = sequence<lex_hex_prefix, sequence<lex_hex_dig, repeat<
- either<lex_hex_dig, sequence<lex_underscore, lex_hex_dig>>, unlimited>>>;
-// oct_prefix oct_dig *(oct_dig | _ oct_dig)
-using lex_oct_int = sequence<lex_oct_prefix, sequence<lex_oct_dig, repeat<
- either<lex_oct_dig, sequence<lex_underscore, lex_oct_dig>>, unlimited>>>;
-// bin_prefix bin_dig *(bin_dig | _ bin_dig)
-using lex_bin_int = sequence<lex_bin_prefix, sequence<lex_bin_dig, repeat<
- either<lex_bin_dig, sequence<lex_underscore, lex_bin_dig>>, unlimited>>>;
-
-// (dec_int | hex_int | oct_int | bin_int)
-using lex_integer = either<lex_bin_int, lex_oct_int, lex_hex_int, lex_dec_int>;
-
-// ===========================================================================
-
-using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
-using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
-using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
-
-using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
- sequence<lex_underscore, lex_digit>>, unlimited>>;
-
-using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;
-
-using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>,
- maybe<lex_sign>, lex_zero_prefixable_int>;
-
-using lex_float = either<lex_special_float,
- sequence<lex_dec_int, either<lex_exponent_part,
- sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;
-
-// ===========================================================================
-
-using lex_true = sequence<character<'t'>, character<'r'>,
- character<'u'>, character<'e'>>;
-using lex_false = sequence<character<'f'>, character<'a'>, character<'l'>,
- character<'s'>, character<'e'>>;
-using lex_boolean = either<lex_true, lex_false>;
-
-// ===========================================================================
-
-using lex_date_fullyear = repeat<lex_digit, exactly<4>>;
-using lex_date_month = repeat<lex_digit, exactly<2>>;
-using lex_date_mday = repeat<lex_digit, exactly<2>>;
-using lex_time_delim = either<character<'T'>, character<'t'>, character<' '>>;
-using lex_time_hour = repeat<lex_digit, exactly<2>>;
-using lex_time_minute = repeat<lex_digit, exactly<2>>;
-using lex_time_second = repeat<lex_digit, exactly<2>>;
-using lex_time_secfrac = sequence<character<'.'>,
- repeat<lex_digit, at_least<1>>>;
-
-using lex_time_numoffset = sequence<either<character<'+'>, character<'-'>>,
- sequence<lex_time_hour, character<':'>,
- lex_time_minute>>;
-using lex_time_offset = either<character<'Z'>, character<'z'>,
- lex_time_numoffset>;
-
-using lex_partial_time = sequence<lex_time_hour, character<':'>,
- lex_time_minute, character<':'>,
- lex_time_second, maybe<lex_time_secfrac>>;
-using lex_full_date = sequence<lex_date_fullyear, character<'-'>,
- lex_date_month, character<'-'>,
- lex_date_mday>;
-using lex_full_time = sequence<lex_partial_time, lex_time_offset>;
-
-using lex_offset_date_time = sequence<lex_full_date, lex_time_delim, lex_full_time>;
-using lex_local_date_time = sequence<lex_full_date, lex_time_delim, lex_partial_time>;
-using lex_local_date = lex_full_date;
-using lex_local_time = lex_partial_time;
-
-// ===========================================================================
-
-using lex_quotation_mark = character<'"'>;
-using lex_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09 (tab) is allowed
- in_range<0x0A, 0x1F>,
- character<0x22>, character<0x5C>,
- character<0x7F>>>;
-
-using lex_escape = character<'\\'>;
-using lex_escape_unicode_short = sequence<character<'u'>,
- repeat<lex_hex_dig, exactly<4>>>;
-using lex_escape_unicode_long = sequence<character<'U'>,
- repeat<lex_hex_dig, exactly<8>>>;
-using lex_escape_seq_char = either<character<'"'>, character<'\\'>,
- character<'b'>, character<'f'>,
- character<'n'>, character<'r'>,
- character<'t'>,
- lex_escape_unicode_short,
- lex_escape_unicode_long
- >;
-using lex_escaped = sequence<lex_escape, lex_escape_seq_char>;
-using lex_basic_char = either<lex_basic_unescaped, lex_escaped>;
-using lex_basic_string = sequence<lex_quotation_mark,
- repeat<lex_basic_char, unlimited>,
- lex_quotation_mark>;
-
-// After toml post-v0.5.0, it is explicitly clarified how quotes in ml-strings
-// are allowed to be used.
-// After this, the following strings are *explicitly* allowed.
-// - One or two `"`s in a multi-line basic string is allowed wherever it is.
-// - Three consecutive `"`s in a multi-line basic string is considered as a delimiter.
-// - One or two `"`s can appear just before or after the delimiter.
-// ```toml
-// str4 = """Here are two quotation marks: "". Simple enough."""
-// str5 = """Here are three quotation marks: ""\"."""
-// str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
-// str7 = """"This," she said, "is just a pointless statement.""""
-// ```
-// In the current implementation (v3.3.0), it is difficult to parse `str7` in
-// the above example. It is difficult to recognize `"` at the end of string body
-// collectly. It will be misunderstood as a `"""` delimiter and an additional,
-// invalid `"`. Like this:
-// ```console
-// what(): [error] toml::parse_table: invalid line format
-// --> hoge.toml
-// |
-// 13 | str7 = """"This," she said, "is just a pointless statement.""""
-// | ^- expected newline, but got '"'.
-// ```
-// As a quick workaround for this problem, `lex_ml_basic_string_delim` was
-// split into two, `lex_ml_basic_string_open` and `lex_ml_basic_string_close`.
-// `lex_ml_basic_string_open` allows only `"""`. `_close` allows 3-5 `"`s.
-// In parse_ml_basic_string() function, the trailing `"`s will be attached to
-// the string body.
-//
-using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
-using lex_ml_basic_string_open = lex_ml_basic_string_delim;
-using lex_ml_basic_string_close = sequence<
- repeat<lex_quotation_mark, exactly<3>>,
- maybe<lex_quotation_mark>, maybe<lex_quotation_mark>
- >;
-
-using lex_ml_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09 is tab
- in_range<0x0A, 0x1F>,
- character<0x5C>, // backslash
- character<0x7F>, // DEL
- lex_ml_basic_string_delim>>;
-
-using lex_ml_basic_escaped_newline = sequence<
- lex_escape, maybe<lex_ws>, lex_newline,
- repeat<either<lex_ws, lex_newline>, unlimited>>;
-
-using lex_ml_basic_char = either<lex_ml_basic_unescaped, lex_escaped>;
-using lex_ml_basic_body = repeat<either<lex_ml_basic_char, lex_newline,
- lex_ml_basic_escaped_newline>,
- unlimited>;
-using lex_ml_basic_string = sequence<lex_ml_basic_string_open,
- lex_ml_basic_body,
- lex_ml_basic_string_close>;
-
-using lex_literal_char = exclude<either<in_range<0x00, 0x08>, in_range<0x0A, 0x1F>,
- character<0x7F>, character<0x27>>>;
-using lex_apostrophe = character<'\''>;
-using lex_literal_string = sequence<lex_apostrophe,
- repeat<lex_literal_char, unlimited>,
- lex_apostrophe>;
-
-// the same reason as above.
-using lex_ml_literal_string_delim = repeat<lex_apostrophe, exactly<3>>;
-using lex_ml_literal_string_open = lex_ml_literal_string_delim;
-using lex_ml_literal_string_close = sequence<
- repeat<lex_apostrophe, exactly<3>>,
- maybe<lex_apostrophe>, maybe<lex_apostrophe>
- >;
-
-using lex_ml_literal_char = exclude<either<in_range<0x00, 0x08>,
- in_range<0x0A, 0x1F>,
- character<0x7F>,
- lex_ml_literal_string_delim>>;
-using lex_ml_literal_body = repeat<either<lex_ml_literal_char, lex_newline>,
- unlimited>;
-using lex_ml_literal_string = sequence<lex_ml_literal_string_open,
- lex_ml_literal_body,
- lex_ml_literal_string_close>;
-
-using lex_string = either<lex_ml_basic_string, lex_basic_string,
- lex_ml_literal_string, lex_literal_string>;
-
-// ===========================================================================
-using lex_dot_sep = sequence<maybe<lex_ws>, character<'.'>, maybe<lex_ws>>;
-
-using lex_unquoted_key = repeat<either<lex_alpha, lex_digit,
- character<'-'>, character<'_'>>,
- at_least<1>>;
-using lex_quoted_key = either<lex_basic_string, lex_literal_string>;
-using lex_simple_key = either<lex_unquoted_key, lex_quoted_key>;
-using lex_dotted_key = sequence<lex_simple_key,
- repeat<sequence<lex_dot_sep, lex_simple_key>,
- at_least<1>
- >
- >;
-using lex_key = either<lex_dotted_key, lex_simple_key>;
-
-using lex_keyval_sep = sequence<maybe<lex_ws>,
- character<'='>,
- maybe<lex_ws>>;
-
-using lex_std_table_open = character<'['>;
-using lex_std_table_close = character<']'>;
-using lex_std_table = sequence<lex_std_table_open,
- maybe<lex_ws>,
- lex_key,
- maybe<lex_ws>,
- lex_std_table_close>;
-
-using lex_array_table_open = sequence<lex_std_table_open, lex_std_table_open>;
-using lex_array_table_close = sequence<lex_std_table_close, lex_std_table_close>;
-using lex_array_table = sequence<lex_array_table_open,
- maybe<lex_ws>,
- lex_key,
- maybe<lex_ws>,
- lex_array_table_close>;
-
-using lex_utf8_1byte = in_range<0x00, 0x7F>;
-using lex_utf8_2byte = sequence<
- in_range<static_cast<char>(0xC2), static_cast<char>(0xDF)>,
- in_range<static_cast<char>(0x80), static_cast<char>(0xBF)>
- >;
-using lex_utf8_3byte = sequence<either<
- sequence<character<static_cast<char>(0xE0)>, in_range<static_cast<char>(0xA0), static_cast<char>(0xBF)>>,
- sequence<in_range <static_cast<char>(0xE1), static_cast<char>(0xEC)>, in_range<static_cast<char>(0x80), static_cast<char>(0xBF)>>,
- sequence<character<static_cast<char>(0xED)>, in_range<static_cast<char>(0x80), static_cast<char>(0x9F)>>,
- sequence<in_range <static_cast<char>(0xEE), static_cast<char>(0xEF)>, in_range<static_cast<char>(0x80), static_cast<char>(0xBF)>>
- >, in_range<static_cast<char>(0x80), static_cast<char>(0xBF)>>;
-using lex_utf8_4byte = sequence<either<
- sequence<character<static_cast<char>(0xF0)>, in_range<static_cast<char>(0x90), static_cast<char>(0xBF)>>,
- sequence<in_range <static_cast<char>(0xF1), static_cast<char>(0xF3)>, in_range<static_cast<char>(0x80), static_cast<char>(0xBF)>>,
- sequence<character<static_cast<char>(0xF4)>, in_range<static_cast<char>(0x80), static_cast<char>(0x8F)>>
- >, in_range<static_cast<char>(0x80), static_cast<char>(0xBF)>,
- in_range<static_cast<char>(0x80), static_cast<char>(0xBF)>>;
-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<character<0x09>, in_range<0x20, 0x7E>>;
-using lex_comment = sequence<lex_comment_start_symbol, repeat<either<
- lex_non_eol_ascii, lex_utf8_2byte, lex_utf8_3byte, lex_utf8_4byte>, unlimited>>;
-
-} // detail
-} // toml
-#endif // TOML_LEXER_HPP
diff --git a/src/toml11/toml/literal.hpp b/src/toml11/toml/literal.hpp
deleted file mode 100644
index 04fbbc13e..000000000
--- a/src/toml11/toml/literal.hpp
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright Toru Niina 2019.
-// Distributed under the MIT License.
-#ifndef TOML11_LITERAL_HPP
-#define TOML11_LITERAL_HPP
-#include "parser.hpp"
-
-namespace toml
-{
-inline namespace literals
-{
-inline namespace toml_literals
-{
-
-// implementation
-inline ::toml::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
-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<toml::detail::sequence<
- ::toml::detail::maybe<::toml::detail::lex_ws>,
- ::toml::detail::maybe<::toml::detail::lex_comment>,
- ::toml::detail::lex_newline
- >, ::toml::detail::at_least<1>>;
- skip_line::invoke(loc);
-
- // if there are some whitespaces before a value, skip them.
- using skip_ws = ::toml::detail::repeat<
- ::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
- skip_ws::invoke(loc);
-
- // to distinguish arrays and tables, first check it is a table or not.
- //
- // "[1,2,3]"_toml; // this is an array
- // "[table]"_toml; // a table that has an empty table named "table" inside.
- // "[[1,2,3]]"_toml; // this is an array of arrays
- // "[[table]]"_toml; // this is a table that has an array of tables inside.
- //
- // "[[1]]"_toml; // this can be both... (currently it becomes a table)
- // "1 = [{}]"_toml; // this is a table that has an array of table named 1.
- // "[[1,]]"_toml; // this is an array of arrays.
- // "[[1],]"_toml; // this also.
-
- const auto the_front = loc.iter();
-
- const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
- loc.reset(the_front);
-
- const bool is_aots_key = ::toml::detail::lex_array_table::invoke(loc);
- loc.reset(the_front);
-
- // 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<value_type>(loc))
- {
- return data.unwrap();
- }
- }
-
- // Note that still it can be a table, because the literal might be something
- // like the following.
- // ```cpp
- // R"( // c++11 raw string literals
- // key = "value"
- // int = 42
- // )"_toml;
- // ```
- // 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<value_type>(loc))
- {
- return data.unwrap();
- }
- else // none of them.
- {
- throw ::toml::syntax_error(data.unwrap_err(), source_location(loc));
- }
-
-}
-
-inline ::toml::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
-operator"" _toml(const char* str, std::size_t len)
-{
- ::toml::detail::location loc(
- std::string("TOML literal encoded in a C++ code"),
- std::vector<char>(str, str + len));
- // literal length does not include the null character at the end.
- return literal_internal_impl(std::move(loc));
-}
-
-// value of __cplusplus in C++2a/20 mode is not fixed yet along compilers.
-// So here we use the feature test macro for `char8_t` itself.
-#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::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
-operator"" _toml(const char8_t* str, std::size_t len)
-{
- ::toml::detail::location loc(
- std::string("TOML literal encoded in a C++ code"),
- std::vector<char>(reinterpret_cast<const char*>(str),
- reinterpret_cast<const char*>(str) + len));
- return literal_internal_impl(std::move(loc));
-}
-#endif
-
-} // toml_literals
-} // literals
-} // toml
-#endif//TOML11_LITERAL_HPP
diff --git a/src/toml11/toml/macros.hpp b/src/toml11/toml/macros.hpp
deleted file mode 100644
index e8f91aecd..000000000
--- a/src/toml11/toml/macros.hpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#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<foo::Foo>(file, "foo");`
-//
-#define TOML11_FIND_MEMBER_VARIABLE_FROM_VALUE(VAR_NAME)\
- obj.VAR_NAME = toml::find<decltype(obj.VAR_NAME)>(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<NAME> \
- { \
- template<typename C, template<typename ...> class T, \
- template<typename ...> class A> \
- static NAME from_toml(const basic_value<C, T, A>& v) \
- { \
- NAME obj; \
- TOML11_FOR_EACH_VA_ARGS(TOML11_FIND_MEMBER_VARIABLE_FROM_VALUE, __VA_ARGS__) \
- return obj; \
- } \
- }; \
- template<> \
- struct into<NAME> \
- { \
- 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/src/toml11/toml/parser.hpp b/src/toml11/toml/parser.hpp
deleted file mode 100644
index e31179918..000000000
--- a/src/toml11/toml/parser.hpp
+++ /dev/null
@@ -1,2364 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_PARSER_HPP
-#define TOML11_PARSER_HPP
-#include <cstring>
-#include <fstream>
-#include <sstream>
-
-#include "combinator.hpp"
-#include "lexer.hpp"
-#include "region.hpp"
-#include "result.hpp"
-#include "types.hpp"
-#include "value.hpp"
-
-#ifndef TOML11_DISABLE_STD_FILESYSTEM
-#ifdef __cpp_lib_filesystem
-#if __has_include(<filesystem>)
-#define TOML11_HAS_STD_FILESYSTEM
-#include <filesystem>
-#endif // has_include(<string_view>)
-#endif // __cpp_lib_filesystem
-#endif // TOML11_DISABLE_STD_FILESYSTEM
-
-namespace toml
-{
-namespace detail
-{
-
-inline result<std::pair<boolean, region>, std::string>
-parse_boolean(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_boolean::invoke(loc))
- {
- const auto reg = token.unwrap();
- if (reg.str() == "true") {return ok(std::make_pair(true, reg));}
- else if(reg.str() == "false") {return ok(std::make_pair(false, reg));}
- else // internal error.
- {
- throw internal_error(format_underline(
- "toml::parse_boolean: internal error",
- {{source_location(reg), "invalid token"}}),
- source_location(reg));
- }
- }
- loc.reset(first); //rollback
- return err(format_underline("toml::parse_boolean: ",
- {{source_location(loc), "the next token is not a boolean"}}));
-}
-
-inline result<std::pair<integer, region>, std::string>
-parse_binary_integer(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_bin_int::invoke(loc))
- {
- auto str = token.unwrap().str();
- assert(str.size() > 2); // minimum -> 0b1
- integer retval(0), base(1);
- for(auto i(str.rbegin()), e(str.rend() - 2); i!=e; ++i)
- {
- if (*i == '1'){retval += base; base *= 2;}
- else if(*i == '0'){base *= 2;}
- else if(*i == '_'){/* do nothing. */}
- else // internal error.
- {
- throw internal_error(format_underline(
- "toml::parse_integer: internal error",
- {{source_location(token.unwrap()), "invalid token"}}),
- source_location(loc));
- }
- }
- return ok(std::make_pair(retval, token.unwrap()));
- }
- loc.reset(first);
- return err(format_underline("toml::parse_binary_integer:",
- {{source_location(loc), "the next token is not an integer"}}));
-}
-
-inline result<std::pair<integer, region>, std::string>
-parse_octal_integer(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_oct_int::invoke(loc))
- {
- auto str = token.unwrap().str();
- str.erase(std::remove(str.begin(), str.end(), '_'), str.end());
- str.erase(str.begin()); str.erase(str.begin()); // remove `0o` prefix
-
- std::istringstream iss(str);
- integer retval(0);
- iss >> std::oct >> retval;
- return ok(std::make_pair(retval, token.unwrap()));
- }
- loc.reset(first);
- return err(format_underline("toml::parse_octal_integer:",
- {{source_location(loc), "the next token is not an integer"}}));
-}
-
-inline result<std::pair<integer, region>, std::string>
-parse_hexadecimal_integer(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_hex_int::invoke(loc))
- {
- auto str = token.unwrap().str();
- str.erase(std::remove(str.begin(), str.end(), '_'), str.end());
- str.erase(str.begin()); str.erase(str.begin()); // remove `0x` prefix
-
- std::istringstream iss(str);
- integer retval(0);
- iss >> std::hex >> retval;
- return ok(std::make_pair(retval, token.unwrap()));
- }
- loc.reset(first);
- return err(format_underline("toml::parse_hexadecimal_integer",
- {{source_location(loc), "the next token is not an integer"}}));
-}
-
-inline result<std::pair<integer, region>, std::string>
-parse_integer(location& loc)
-{
- const auto first = loc.iter();
- if(first != loc.end() && *first == '0')
- {
- const auto second = std::next(first);
- if(second == loc.end()) // the token is just zero.
- {
- loc.advance();
- return ok(std::make_pair(0, region(loc, first, second)));
- }
-
- if(*second == 'b') {return parse_binary_integer (loc);} // 0b1100
- if(*second == 'o') {return parse_octal_integer (loc);} // 0o775
- if(*second == 'x') {return parse_hexadecimal_integer(loc);} // 0xC0FFEE
-
- if(std::isdigit(*second))
- {
- return err(format_underline("toml::parse_integer: "
- "leading zero in an Integer is not allowed.",
- {{source_location(loc), "leading zero"}}));
- }
- else if(std::isalpha(*second))
- {
- return err(format_underline("toml::parse_integer: "
- "unknown integer prefix appeared.",
- {{source_location(loc), "none of 0x, 0o, 0b"}}));
- }
- }
-
- if(const auto token = lex_dec_int::invoke(loc))
- {
- auto str = token.unwrap().str();
- str.erase(std::remove(str.begin(), str.end(), '_'), str.end());
-
- std::istringstream iss(str);
- integer retval(0);
- iss >> retval;
- return ok(std::make_pair(retval, token.unwrap()));
- }
- loc.reset(first);
- return err(format_underline("toml::parse_integer: ",
- {{source_location(loc), "the next token is not an integer"}}));
-}
-
-inline result<std::pair<floating, region>, std::string>
-parse_floating(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_float::invoke(loc))
- {
- auto str = token.unwrap().str();
- if(str == "inf" || str == "+inf")
- {
- if(std::numeric_limits<floating>::has_infinity)
- {
- return ok(std::make_pair(
- std::numeric_limits<floating>::infinity(), token.unwrap()));
- }
- else
- {
- throw std::domain_error("toml::parse_floating: inf value found"
- " but the current environment does not support inf. Please"
- " make sure that the floating-point implementation conforms"
- " IEEE 754/ISO 60559 international standard.");
- }
- }
- else if(str == "-inf")
- {
- if(std::numeric_limits<floating>::has_infinity)
- {
- return ok(std::make_pair(
- -std::numeric_limits<floating>::infinity(), token.unwrap()));
- }
- else
- {
- throw std::domain_error("toml::parse_floating: inf value found"
- " but the current environment does not support inf. Please"
- " make sure that the floating-point implementation conforms"
- " IEEE 754/ISO 60559 international standard.");
- }
- }
- else if(str == "nan" || str == "+nan")
- {
- if(std::numeric_limits<floating>::has_quiet_NaN)
- {
- return ok(std::make_pair(
- std::numeric_limits<floating>::quiet_NaN(), token.unwrap()));
- }
- else if(std::numeric_limits<floating>::has_signaling_NaN)
- {
- return ok(std::make_pair(
- std::numeric_limits<floating>::signaling_NaN(), token.unwrap()));
- }
- else
- {
- throw std::domain_error("toml::parse_floating: NaN value found"
- " but the current environment does not support NaN. Please"
- " make sure that the floating-point implementation conforms"
- " IEEE 754/ISO 60559 international standard.");
- }
- }
- else if(str == "-nan")
- {
- if(std::numeric_limits<floating>::has_quiet_NaN)
- {
- return ok(std::make_pair(
- -std::numeric_limits<floating>::quiet_NaN(), token.unwrap()));
- }
- else if(std::numeric_limits<floating>::has_signaling_NaN)
- {
- return ok(std::make_pair(
- -std::numeric_limits<floating>::signaling_NaN(), token.unwrap()));
- }
- else
- {
- throw std::domain_error("toml::parse_floating: NaN value found"
- " but the current environment does not support NaN. Please"
- " make sure that the floating-point implementation conforms"
- " IEEE 754/ISO 60559 international standard.");
- }
- }
- str.erase(std::remove(str.begin(), str.end(), '_'), str.end());
- std::istringstream iss(str);
- floating v(0.0);
- iss >> v;
- return ok(std::make_pair(v, token.unwrap()));
- }
- loc.reset(first);
- return err(format_underline("toml::parse_floating: ",
- {{source_location(loc), "the next token is not a float"}}));
-}
-
-inline std::string read_utf8_codepoint(const region& reg, const location& loc)
-{
- const auto str = reg.str().substr(1);
- std::uint_least32_t codepoint;
- std::istringstream iss(str);
- iss >> std::hex >> codepoint;
-
- const auto to_char = [](const std::uint_least32_t i) noexcept -> char {
- const auto uc = static_cast<unsigned char>(i);
- return *reinterpret_cast<const char*>(std::addressof(uc));
- };
-
- std::string character;
- if(codepoint < 0x80) // U+0000 ... U+0079 ; just an ASCII.
- {
- character += static_cast<char>(codepoint);
- }
- else if(codepoint < 0x800) //U+0080 ... U+07FF
- {
- // 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111
- character += to_char(0xC0| codepoint >> 6);
- character += to_char(0x80|(codepoint & 0x3F));
- }
- else if(codepoint < 0x10000) // U+0800...U+FFFF
- {
- if(0xD800 <= codepoint && codepoint <= 0xDFFF)
- {
- throw syntax_error(format_underline(
- "toml::read_utf8_codepoint: codepoints in the range "
- "[0xD800, 0xDFFF] are not valid UTF-8.", {{
- source_location(loc), "not a valid UTF-8 codepoint"
- }}), source_location(loc));
- }
- assert(codepoint < 0xD800 || 0xDFFF < codepoint);
- // 1110yyyy 10yxxxxx 10xxxxxx
- character += to_char(0xE0| codepoint >> 12);
- character += to_char(0x80|(codepoint >> 6 & 0x3F));
- character += to_char(0x80|(codepoint & 0x3F));
- }
- else if(codepoint < 0x110000) // U+010000 ... U+10FFFF
- {
- // 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
- character += to_char(0xF0| codepoint >> 18);
- character += to_char(0x80|(codepoint >> 12 & 0x3F));
- character += to_char(0x80|(codepoint >> 6 & 0x3F));
- character += to_char(0x80|(codepoint & 0x3F));
- }
- else // out of UTF-8 region
- {
- throw syntax_error(format_underline("toml::read_utf8_codepoint:"
- " input codepoint is too large.",
- {{source_location(loc), "should be in [0x00..0x10FFFF]"}}),
- source_location(loc));
- }
- return character;
-}
-
-inline result<std::string, std::string> parse_escape_sequence(location& loc)
-{
- const auto first = loc.iter();
- if(first == loc.end() || *first != '\\')
- {
- return err(format_underline("toml::parse_escape_sequence: ", {{
- source_location(loc), "the next token is not a backslash \"\\\""}}));
- }
- loc.advance();
- switch(*loc.iter())
- {
- case '\\':{loc.advance(); return ok(std::string("\\"));}
- case '"' :{loc.advance(); return ok(std::string("\""));}
- case 'b' :{loc.advance(); return ok(std::string("\b"));}
- case 't' :{loc.advance(); return ok(std::string("\t"));}
- 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"));}
- case 'u' :
- {
- if(const auto token = lex_escape_unicode_short::invoke(loc))
- {
- return ok(read_utf8_codepoint(token.unwrap(), loc));
- }
- else
- {
- return err(format_underline("parse_escape_sequence: "
- "invalid token found in UTF-8 codepoint uXXXX.",
- {{source_location(loc), "here"}}));
- }
- }
- case 'U':
- {
- if(const auto token = lex_escape_unicode_long::invoke(loc))
- {
- return ok(read_utf8_codepoint(token.unwrap(), loc));
- }
- else
- {
- return err(format_underline("parse_escape_sequence: "
- "invalid token found in UTF-8 codepoint Uxxxxxxxx",
- {{source_location(loc), "here"}}));
- }
- }
- }
-
- const auto msg = format_underline("parse_escape_sequence: "
- "unknown escape sequence appeared.", {{source_location(loc),
- "escape sequence is one of \\, \", b, t, n, f, r, uxxxx, Uxxxxxxxx"}},
- /* Hints = */{"if you want to write backslash as just one backslash, "
- "use literal string like: regex = '<\\i\\c*\\s*>'"});
- loc.reset(first);
- return err(msg);
-}
-
-inline std::ptrdiff_t check_utf8_validity(const std::string& reg)
-{
- location loc("tmp", reg);
- const auto u8 = repeat<lex_utf8_code, unlimited>::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::pair<toml::string, region>, std::string>
-parse_ml_basic_string(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_ml_basic_string::invoke(loc))
- {
- auto inner_loc = loc;
- inner_loc.reset(first);
-
- std::string retval;
- retval.reserve(token.unwrap().size());
-
- auto delim = lex_ml_basic_string_open::invoke(inner_loc);
- if(!delim)
- {
- throw internal_error(format_underline(
- "parse_ml_basic_string: invalid token",
- {{source_location(inner_loc), "should be \"\"\""}}),
- source_location(inner_loc));
- }
- // immediate newline is ignored (if exists)
- /* discard return value */ lex_newline::invoke(inner_loc);
-
- delim = none();
- while(!delim)
- {
- using lex_unescaped_seq = repeat<
- either<lex_ml_basic_unescaped, lex_newline>, unlimited>;
- if(auto unescaped = lex_unescaped_seq::invoke(inner_loc))
- {
- retval += unescaped.unwrap().str();
- }
- if(auto escaped = parse_escape_sequence(inner_loc))
- {
- retval += escaped.unwrap();
- }
- if(auto esc_nl = lex_ml_basic_escaped_newline::invoke(inner_loc))
- {
- // ignore newline after escape until next non-ws char
- }
- if(inner_loc.iter() == inner_loc.end())
- {
- throw internal_error(format_underline(
- "parse_ml_basic_string: unexpected end of region",
- {{source_location(inner_loc), "not sufficient token"}}),
- source_location(inner_loc));
- }
- delim = lex_ml_basic_string_close::invoke(inner_loc);
- }
- // `lex_ml_basic_string_close` allows 3 to 5 `"`s to allow 1 or 2 `"`s
- // at just before the delimiter. Here, we need to attach `"`s at the
- // end of the string body, if it exists.
- // For detail, see the definition of `lex_ml_basic_string_close`.
- assert(std::all_of(delim.unwrap().first(), delim.unwrap().last(),
- [](const char c) noexcept {return c == '\"';}));
- switch(delim.unwrap().size())
- {
- case 3: {break;}
- case 4: {retval += "\""; break;}
- case 5: {retval += "\"\""; break;}
- default:
- {
- throw internal_error(format_underline(
- "parse_ml_basic_string: closing delimiter has invalid length",
- {{source_location(inner_loc), "end of this"}}),
- source_location(inner_loc));
- }
- }
-
- 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
- {
- loc.reset(first);
- return err(format_underline("toml::parse_ml_basic_string: "
- "the next token is not a valid multiline string",
- {{source_location(loc), "here"}}));
- }
-}
-
-inline result<std::pair<toml::string, region>, std::string>
-parse_basic_string(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_basic_string::invoke(loc))
- {
- auto inner_loc = loc;
- inner_loc.reset(first);
-
- auto quot = lex_quotation_mark::invoke(inner_loc);
- if(!quot)
- {
- throw internal_error(format_underline("parse_basic_string: "
- "invalid token", {{source_location(inner_loc), "should be \""}}),
- source_location(inner_loc));
- }
-
- std::string retval;
- retval.reserve(token.unwrap().size());
-
- quot = none();
- while(!quot)
- {
- using lex_unescaped_seq = repeat<lex_basic_unescaped, unlimited>;
- if(auto unescaped = lex_unescaped_seq::invoke(inner_loc))
- {
- retval += unescaped.unwrap().str();
- }
- if(auto escaped = parse_escape_sequence(inner_loc))
- {
- retval += escaped.unwrap();
- }
- if(inner_loc.iter() == inner_loc.end())
- {
- throw internal_error(format_underline(
- "parse_basic_string: unexpected end of region",
- {{source_location(inner_loc), "not sufficient token"}}),
- source_location(inner_loc));
- }
- quot = lex_quotation_mark::invoke(inner_loc);
- }
-
- 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
- {
- loc.reset(first); // rollback
- return err(format_underline("toml::parse_basic_string: "
- "the next token is not a valid string",
- {{source_location(loc), "here"}}));
- }
-}
-
-inline result<std::pair<toml::string, region>, std::string>
-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());
-
- const auto open = lex_ml_literal_string_open::invoke(inner_loc);
- if(!open)
- {
- throw internal_error(format_underline(
- "parse_ml_literal_string: invalid token",
- {{source_location(inner_loc), "should be '''"}}),
- source_location(inner_loc));
- }
- // immediate newline is ignored (if exists)
- /* discard return value */ lex_newline::invoke(inner_loc);
-
- const auto body = lex_ml_literal_body::invoke(inner_loc);
-
- const auto close = lex_ml_literal_string_close::invoke(inner_loc);
- if(!close)
- {
- throw internal_error(format_underline(
- "parse_ml_literal_string: invalid token",
- {{source_location(inner_loc), "should be '''"}}),
- source_location(inner_loc));
- }
- // `lex_ml_literal_string_close` allows 3 to 5 `'`s to allow 1 or 2 `'`s
- // at just before the delimiter. Here, we need to attach `'`s at the
- // end of the string body, if it exists.
- // For detail, see the definition of `lex_ml_basic_string_close`.
-
- std::string retval = body.unwrap().str();
- assert(std::all_of(close.unwrap().first(), close.unwrap().last(),
- [](const char c) noexcept {return c == '\'';}));
- switch(close.unwrap().size())
- {
- case 3: {break;}
- case 4: {retval += "'"; break;}
- case 5: {retval += "''"; break;}
- default:
- {
- throw internal_error(format_underline(
- "parse_ml_literal_string: closing delimiter has invalid length",
- {{source_location(inner_loc), "end of this"}}),
- source_location(inner_loc));
- }
- }
-
- 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_basic_string: invalid utf8 sequence found",
- {{source_location(inner_loc), "here"}}),
- source_location(inner_loc));
- }
- }
- else
- {
- loc.reset(first); // rollback
- return err(format_underline("toml::parse_ml_literal_string: "
- "the next token is not a valid multiline literal string",
- {{source_location(loc), "here"}}));
- }
-}
-
-inline result<std::pair<toml::string, region>, std::string>
-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());
-
- const auto open = lex_apostrophe::invoke(inner_loc);
- if(!open)
- {
- throw internal_error(format_underline(
- "parse_literal_string: invalid token",
- {{source_location(inner_loc), "should be '"}}),
- source_location(inner_loc));
- }
-
- const auto body = repeat<lex_literal_char, unlimited>::invoke(inner_loc);
-
- const auto close = lex_apostrophe::invoke(inner_loc);
- if(!close)
- {
- throw internal_error(format_underline(
- "parse_literal_string: invalid token",
- {{source_location(inner_loc), "should be '"}}),
- source_location(inner_loc));
- }
-
- 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_ml_basic_string: invalid utf8 sequence found",
- {{source_location(inner_loc), "here"}}),
- source_location(inner_loc));
- }
- }
- else
- {
- loc.reset(first); // rollback
- return err(format_underline("toml::parse_literal_string: "
- "the next token is not a valid literal string",
- {{source_location(loc), "here"}}));
- }
-}
-
-inline result<std::pair<toml::string, region>, std::string>
-parse_string(location& loc)
-{
- if(loc.iter() != loc.end() && *(loc.iter()) == '"')
- {
- if(loc.iter() + 1 != loc.end() && *(loc.iter() + 1) == '"' &&
- loc.iter() + 2 != loc.end() && *(loc.iter() + 2) == '"')
- {
- return parse_ml_basic_string(loc);
- }
- else
- {
- return parse_basic_string(loc);
- }
- }
- else if(loc.iter() != loc.end() && *(loc.iter()) == '\'')
- {
- if(loc.iter() + 1 != loc.end() && *(loc.iter() + 1) == '\'' &&
- loc.iter() + 2 != loc.end() && *(loc.iter() + 2) == '\'')
- {
- return parse_ml_literal_string(loc);
- }
- else
- {
- return parse_literal_string(loc);
- }
- }
- return err(format_underline("toml::parse_string: ",
- {{source_location(loc), "the next token is not a string"}}));
-}
-
-inline result<std::pair<local_date, region>, std::string>
-parse_local_date(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_local_date::invoke(loc))
- {
- location inner_loc(loc.name(), token.unwrap().str());
-
- const auto y = lex_date_fullyear::invoke(inner_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",
- {{source_location(inner_loc), "should be `-`"}}),
- source_location(inner_loc));
- }
- inner_loc.advance();
- const auto m = lex_date_month::invoke(inner_loc);
- if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-')
- {
- throw internal_error(format_underline(
- "toml::parse_local_date: invalid month format",
- {{source_location(inner_loc), "should be `-`"}}),
- source_location(inner_loc));
- }
- inner_loc.advance();
- const auto d = lex_date_mday::invoke(inner_loc);
- if(!d)
- {
- throw internal_error(format_underline(
- "toml::parse_local_date: invalid day format",
- {{source_location(inner_loc), "here"}}),
- source_location(inner_loc));
- }
-
- const auto year = static_cast<std::int16_t>(from_string<int>(y.unwrap().str(), 0));
- const auto month = static_cast<std::int8_t >(from_string<int>(m.unwrap().str(), 0));
- const auto day = static_cast<std::int8_t >(from_string<int>(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_t>(month - 1), day),
- token.unwrap()));
- }
- else
- {
- loc.reset(first);
- return err(format_underline("toml::parse_local_date: ",
- {{source_location(loc), "the next token is not a local_date"}}));
- }
-}
-
-inline result<std::pair<local_time, region>, std::string>
-parse_local_time(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_local_time::invoke(loc))
- {
- location inner_loc(loc.name(), token.unwrap().str());
-
- const auto h = lex_time_hour::invoke(inner_loc);
- if(!h || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':')
- {
- throw internal_error(format_underline(
- "toml::parse_local_time: invalid year format",
- {{source_location(inner_loc), "should be `:`"}}),
- source_location(inner_loc));
- }
- inner_loc.advance();
- const auto m = lex_time_minute::invoke(inner_loc);
- if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':')
- {
- throw internal_error(format_underline(
- "toml::parse_local_time: invalid month format",
- {{source_location(inner_loc), "should be `:`"}}),
- source_location(inner_loc));
- }
- inner_loc.advance();
- const auto s = lex_time_second::invoke(inner_loc);
- if(!s)
- {
- throw internal_error(format_underline(
- "toml::parse_local_time: invalid second format",
- {{source_location(inner_loc), "here"}}),
- source_location(inner_loc));
- }
-
- const int hour = from_string<int>(h.unwrap().str(), 0);
- const int minute = from_string<int>(m.unwrap().str(), 0);
- const int second = from_string<int>(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_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))
- {
- auto sf = secfrac.unwrap().str();
- sf.erase(sf.begin()); // sf.front() == '.'
- switch(sf.size() % 3)
- {
- case 2: sf += '0'; break;
- case 1: sf += "00"; break;
- case 0: break;
- default: break;
- }
- if(sf.size() >= 9)
- {
- time.millisecond = from_string<std::uint16_t>(sf.substr(0, 3), 0u);
- time.microsecond = from_string<std::uint16_t>(sf.substr(3, 3), 0u);
- time.nanosecond = from_string<std::uint16_t>(sf.substr(6, 3), 0u);
- }
- else if(sf.size() >= 6)
- {
- time.millisecond = from_string<std::uint16_t>(sf.substr(0, 3), 0u);
- time.microsecond = from_string<std::uint16_t>(sf.substr(3, 3), 0u);
- }
- else if(sf.size() >= 3)
- {
- time.millisecond = from_string<std::uint16_t>(sf, 0u);
- time.microsecond = 0u;
- }
- }
- else
- {
- if(before_secfrac != inner_loc.iter())
- {
- throw internal_error(format_underline(
- "toml::parse_local_time: invalid subsecond format",
- {{source_location(inner_loc), "here"}}),
- source_location(inner_loc));
- }
- }
- return ok(std::make_pair(time, token.unwrap()));
- }
- else
- {
- loc.reset(first);
- return err(format_underline("toml::parse_local_time: ",
- {{source_location(loc), "the next token is not a local_time"}}));
- }
-}
-
-inline result<std::pair<local_datetime, region>, std::string>
-parse_local_datetime(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_local_date_time::invoke(loc))
- {
- location inner_loc(loc.name(), token.unwrap().str());
- const auto date = parse_local_date(inner_loc);
- if(!date || inner_loc.iter() == inner_loc.end())
- {
- throw internal_error(format_underline(
- "toml::parse_local_datetime: invalid datetime format",
- {{source_location(inner_loc), "date, not datetime"}}),
- source_location(inner_loc));
- }
- const char delim = *(inner_loc.iter());
- if(delim != 'T' && delim != 't' && delim != ' ')
- {
- throw internal_error(format_underline(
- "toml::parse_local_datetime: invalid datetime format",
- {{source_location(inner_loc), "should be `T` or ` ` (space)"}}),
- source_location(inner_loc));
- }
- inner_loc.advance();
- const auto time = parse_local_time(inner_loc);
- if(!time)
- {
- throw internal_error(format_underline(
- "toml::parse_local_datetime: invalid datetime format",
- {{source_location(inner_loc), "invalid time format"}}),
- source_location(inner_loc));
- }
- return ok(std::make_pair(
- local_datetime(date.unwrap().first, time.unwrap().first),
- token.unwrap()));
- }
- else
- {
- loc.reset(first);
- return err(format_underline("toml::parse_local_datetime: ",
- {{source_location(loc), "the next token is not a local_datetime"}}));
- }
-}
-
-inline result<std::pair<offset_datetime, region>, std::string>
-parse_offset_datetime(location& loc)
-{
- const auto first = loc.iter();
- if(const auto token = lex_offset_date_time::invoke(loc))
- {
- location inner_loc(loc.name(), token.unwrap().str());
- const auto datetime = parse_local_datetime(inner_loc);
- if(!datetime || inner_loc.iter() == inner_loc.end())
- {
- throw internal_error(format_underline(
- "toml::parse_offset_datetime: invalid datetime format",
- {{source_location(inner_loc), "date, not datetime"}}),
- source_location(inner_loc));
- }
- time_offset offset(0, 0);
- if(const auto ofs = lex_time_numoffset::invoke(inner_loc))
- {
- const auto str = ofs.unwrap().str();
-
- const auto hour = from_string<int>(str.substr(1,2), 0);
- const auto minute = from_string<int>(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(hour, minute);
- }
- else
- {
- offset = time_offset(-hour, -minute);
- }
- }
- else if(*inner_loc.iter() != 'Z' && *inner_loc.iter() != 'z')
- {
- throw internal_error(format_underline(
- "toml::parse_offset_datetime: invalid datetime format",
- {{source_location(inner_loc), "should be `Z` or `+HH:MM`"}}),
- source_location(inner_loc));
- }
- return ok(std::make_pair(offset_datetime(datetime.unwrap().first, offset),
- token.unwrap()));
- }
- else
- {
- loc.reset(first);
- return err(format_underline("toml::parse_offset_datetime: ",
- {{source_location(loc), "the next token is not a offset_datetime"}}));
- }
-}
-
-inline result<std::pair<key, region>, std::string>
-parse_simple_key(location& loc)
-{
- if(const auto bstr = parse_basic_string(loc))
- {
- return ok(std::make_pair(bstr.unwrap().first.str, bstr.unwrap().second));
- }
- if(const auto lstr = parse_literal_string(loc))
- {
- return ok(std::make_pair(lstr.unwrap().first.str, lstr.unwrap().second));
- }
- if(const auto bare = lex_unquoted_key::invoke(loc))
- {
- const auto reg = bare.unwrap();
- return ok(std::make_pair(reg.str(), reg));
- }
- return err(format_underline("toml::parse_simple_key: ",
- {{source_location(loc), "the next token is not a simple key"}}));
-}
-
-// dotted key become vector of keys
-inline result<std::pair<std::vector<key>, region>, std::string>
-parse_key(location& loc)
-{
- const auto first = loc.iter();
- // dotted key -> `foo.bar.baz` where several single keys are chained by
- // dots. Whitespaces between keys and dots are allowed.
- if(const auto token = lex_dotted_key::invoke(loc))
- {
- const auto reg = token.unwrap();
- location inner_loc(loc.name(), reg.str());
- std::vector<key> keys;
-
- while(inner_loc.iter() != inner_loc.end())
- {
- lex_ws::invoke(inner_loc);
- if(const auto k = parse_simple_key(inner_loc))
- {
- keys.push_back(k.unwrap().first);
- }
- else
- {
- throw internal_error(format_underline(
- "toml::detail::parse_key: dotted key contains invalid key",
- {{source_location(inner_loc), k.unwrap_err()}}),
- source_location(inner_loc));
- }
-
- lex_ws::invoke(inner_loc);
- if(inner_loc.iter() == inner_loc.end())
- {
- break;
- }
- else if(*inner_loc.iter() == '.')
- {
- inner_loc.advance(); // to skip `.`
- }
- else
- {
- throw internal_error(format_underline("toml::parse_key: "
- "dotted key contains invalid key ",
- {{source_location(inner_loc), "should be `.`"}}),
- source_location(inner_loc));
- }
- }
- return ok(std::make_pair(keys, reg));
- }
- loc.reset(first);
-
- // simple_key: a single (basic_string|literal_string|bare key)
- if(const auto smpl = parse_simple_key(loc))
- {
- return ok(std::make_pair(std::vector<key>(1, smpl.unwrap().first),
- smpl.unwrap().second));
- }
- 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'.",
- "dotted keys: sequence of bare or quoted keys joined with a dot."
- }));
-}
-
-// forward-decl to implement parse_array and parse_table
-template<typename Value>
-result<Value, std::string> parse_value(location&);
-
-template<typename Value>
-result<std::pair<typename Value::array_type, region>, std::string>
-parse_array(location& loc)
-{
- using value_type = Value;
- using array_type = typename value_type::array_type;
-
- const auto first = loc.iter();
- if(loc.iter() == loc.end())
- {
- return err("toml::parse_array: input is empty");
- }
- if(*loc.iter() != '[')
- {
- return err("toml::parse_array: token is not an array");
- }
- loc.advance();
-
- using lex_ws_comment_newline = repeat<
- either<lex_wschar, lex_newline, lex_comment>, unlimited>;
-
- array_type retval;
- while(loc.iter() != loc.end())
- {
- lex_ws_comment_newline::invoke(loc); // skip
-
- if(loc.iter() != loc.end() && *loc.iter() == ']')
- {
- loc.advance(); // skip ']'
- return ok(std::make_pair(retval,
- region(loc, first, loc.iter())));
- }
-
- if(auto val = parse_value<value_type>(loc))
- {
- // 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.
- //
- // But some of the test-suite checks if the parser accepts a hetero-
- // geneous arrays, so we keep this for a while.
-#ifdef TOML11_DISALLOW_HETEROGENEOUS_ARRAYS
- if(!retval.empty() && retval.front().type() != val.as_ok().type())
- {
- auto array_start_loc = loc;
- array_start_loc.reset(first);
-
- throw syntax_error(format_underline("toml::parse_array: "
- "type of elements should be the same each other.", {
- {source_location(array_start_loc), "array starts here"},
- {
- retval.front().location(),
- "value has type " + stringize(retval.front().type())
- },
- {
- val.unwrap().location(),
- "value has different type, " + stringize(val.unwrap().type())
- }
- }), source_location(loc));
- }
-#endif
- retval.push_back(std::move(val.unwrap()));
- }
- else
- {
- auto array_start_loc = loc;
- array_start_loc.reset(first);
-
- throw syntax_error(format_underline("toml::parse_array: "
- "value having invalid format appeared in an array", {
- {source_location(array_start_loc), "array starts here"},
- {source_location(loc), "it is not a valid value."}
- }), source_location(loc));
- }
-
- using lex_array_separator = sequence<maybe<lex_ws_comment_newline>, character<','>>;
- const auto sp = lex_array_separator::invoke(loc);
- if(!sp)
- {
- lex_ws_comment_newline::invoke(loc);
- if(loc.iter() != loc.end() && *loc.iter() == ']')
- {
- loc.advance(); // skip ']'
- return ok(std::make_pair(retval,
- region(loc, first, loc.iter())));
- }
- else
- {
- auto array_start_loc = loc;
- array_start_loc.reset(first);
-
- throw syntax_error(format_underline("toml::parse_array:"
- " missing array separator `,` after a value", {
- {source_location(array_start_loc), "array starts here"},
- {source_location(loc), "should be `,`"}
- }), source_location(loc));
- }
- }
- }
- loc.reset(first);
- throw syntax_error(format_underline("toml::parse_array: "
- "array did not closed by `]`",
- {{source_location(loc), "should be closed"}}),
- source_location(loc));
-}
-
-template<typename Value>
-result<std::pair<std::pair<std::vector<key>, region>, Value>, std::string>
-parse_key_value_pair(location& loc)
-{
- using value_type = Value;
-
- const auto first = loc.iter();
- auto key_reg = parse_key(loc);
- if(!key_reg)
- {
- std::string msg = std::move(key_reg.unwrap_err());
- // if the next token is keyvalue-separator, it means that there are no
- // key. then we need to show error as "empty key is not allowed".
- if(const auto keyval_sep = lex_keyval_sep::invoke(loc))
- {
- loc.reset(first);
- msg = format_underline("toml::parse_key_value_pair: "
- "empty key is not allowed.",
- {{source_location(loc), "key expected before '='"}});
- }
- return err(std::move(msg));
- }
-
- const auto kvsp = lex_keyval_sep::invoke(loc);
- if(!kvsp)
- {
- std::string msg;
- // if the line contains '=' after the invalid sequence, possibly the
- // error is in the key (like, invalid character in bare key).
- const auto line_end = std::find(loc.iter(), loc.end(), '\n');
- if(std::find(loc.iter(), line_end, '=') != line_end)
- {
- msg = format_underline("toml::parse_key_value_pair: "
- "invalid format for key",
- {{source_location(loc), "invalid character in key"}},
- {"Did you forget '.' to separate dotted-key?",
- "Allowed characters for bare key are [0-9a-zA-Z_-]."});
- }
- else // if not, the error is lack of key-value separator.
- {
- msg = format_underline("toml::parse_key_value_pair: "
- "missing key-value separator `=`",
- {{source_location(loc), "should be `=`"}});
- }
- loc.reset(first);
- return err(std::move(msg));
- }
-
- const auto after_kvsp = loc.iter(); // err msg
- auto val = parse_value<value_type>(loc);
- if(!val)
- {
- std::string msg;
- loc.reset(after_kvsp);
- // check there is something not a comment/whitespace after `=`
- if(sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>::invoke(loc))
- {
- loc.reset(after_kvsp);
- msg = format_underline("toml::parse_key_value_pair: "
- "missing value after key-value separator '='",
- {{source_location(loc), "expected value, but got nothing"}});
- }
- else // there is something not a comment/whitespace, so invalid format.
- {
- msg = std::move(val.unwrap_err());
- }
- loc.reset(first);
- return err(msg);
- }
- return ok(std::make_pair(std::move(key_reg.unwrap()),
- std::move(val.unwrap())));
-}
-
-// for error messages.
-template<typename InputIterator>
-std::string format_dotted_keys(InputIterator first, const InputIterator last)
-{
- static_assert(std::is_same<key,
- typename std::iterator_traits<InputIterator>::value_type>::value,"");
-
- std::string retval(*first++);
- for(; first != last; ++first)
- {
- retval += '.';
- retval += *first;
- }
- return retval;
-}
-
-// forward decl for is_valid_forward_table_definition
-result<std::pair<std::vector<key>, region>, std::string>
-parse_table_key(location& loc);
-template<typename Value>
-result<std::pair<typename Value::table_type, region>, std::string>
-parse_inline_table(location& loc);
-
-// The following toml file is allowed.
-// ```toml
-// [a.b.c] # here, table `a` has element `b`.
-// foo = "bar"
-// [a] # merge a = {baz = "qux"} to a = {b = {...}}
-// baz = "qux"
-// ```
-// But the following is not allowed.
-// ```toml
-// [a]
-// b.c.foo = "bar"
-// [a] # error! the same table [a] defined!
-// baz = "qux"
-// ```
-// The following is neither allowed.
-// ```toml
-// a = { b.c.foo = "bar"}
-// [a] # error! the same table [a] defined!
-// baz = "qux"
-// ```
-// Here, it parses region of `tab->at(k)` as a table key and check the depth
-// 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<typename Value, typename Iterator>
-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<Value>(inserting_def))
- {
- // 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;
- }
-
- // ------------------------------------------------------------------------
- // 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)) // [table.key]
- {
- // table keys always contains all the nodes from the root.
- const auto& tks = tabkeys.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))
- {
- // consider the following case.
- // [a]
- // b.c = {d = 42}
- // [a.b.c]
- // e = 2.71
- // this defines the table [a.b.c] twice. no?
-
- // a dotted key starts from the node representing a table in which the
- // dotted key belongs to.
- const auto& dks = dotkeys.unwrap().first;
- if(std::size_t(std::distance(key_curr, key_last)) == dks.size() &&
- std::equal(dks.begin(), dks.end(), key_curr))
- {
- // the keys are equivalent. it is not allowed.
- return false;
- }
- // the keys are not equivalent. it is allowed.
- return true;
- }
- return false;
-}
-
-template<typename Value, typename InputIterator>
-result<bool, std::string>
-insert_nested_key(typename Value::table_type& root, const Value& v,
- InputIterator iter, const InputIterator last,
- region key_reg,
- const bool is_array_of_table = false)
-{
- static_assert(std::is_same<key,
- typename std::iterator_traits<InputIterator>::value_type>::value,"");
-
- using value_type = Value;
- using table_type = typename value_type::table_type;
- using array_type = typename value_type::array_type;
-
- const auto first = iter;
- assert(iter != last);
-
- table_type* tab = std::addressof(root);
- for(; iter != last; ++iter) // search recursively
- {
- const key& k = *iter;
- if(std::next(iter) == last) // k is the last key
- {
- // XXX if the value is array-of-tables, there can be several
- // tables that are in the same array. in that case, we need to
- // find the last element and insert it to there.
- if(is_array_of_table)
- {
- if(tab->count(k) == 1) // there is already an array of table
- {
- if(tab->at(k).is_table())
- {
- // show special err msg for conflicting table
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: array of table (\"",
- format_dotted_keys(first, last),
- "\") cannot be defined"), {
- {tab->at(k).location(), "table already defined"},
- {v.location(), "this conflicts with the previous table"}
- }), v.location());
- }
- else if(!(tab->at(k).is_array()))
- {
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: array of table (\"",
- format_dotted_keys(first, last), "\") collides with"
- " existing value"), {
- {tab->at(k).location(),
- concat_to_string("this ", tab->at(k).type(),
- " value already exists")},
- {v.location(),
- "while inserting this array-of-tables"}
- }), v.location());
- }
- // the above if-else-if checks tab->at(k) is an array
- auto& a = tab->at(k).as_array();
- // 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 (\"",
- format_dotted_keys(first, last), "\") collides with"
- " existing value"), {
- {tab->at(k).location(),
- concat_to_string("this ", tab->at(k).type(),
- " value already exists")},
- {v.location(),
- "while inserting this array-of-tables"}
- }), v.location());
- }
- // avoid conflicting array of table like the following.
- // ```toml
- // a = [{b = 42}] # define a as an array of *inline* tables
- // [[a]] # a is an array of *multi-line* tables
- // b = 54
- // ```
- // Here, from the type information, these cannot be detected
- // 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.
- // In this library, multi-line table value has a region
- // that points to the key of the table (e.g. [[a]]). By
- // comparing the first two letters in key, we can detect
- // the array-of-table is inline or multiline.
- if(const auto ptr = detail::get_region(a.front()))
- {
- if(ptr->str().substr(0,2) != "[[")
- {
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: array of table (\"",
- format_dotted_keys(first, last), "\") collides "
- "with existing array-of-tables"), {
- {tab->at(k).location(),
- concat_to_string("this ", tab->at(k).type(),
- " value has static size")},
- {v.location(),
- "appending it to the statically sized array"}
- }), v.location());
- }
- }
- a.push_back(v);
- return ok(true);
- }
- else // if not, we need to create the array of table
- {
- // 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<std::string> 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);
- }
- } // end if(array of table)
-
- if(tab->count(k) == 1)
- {
- if(tab->at(k).is_table() && v.is_table())
- {
- if(!is_valid_forward_table_definition(
- tab->at(k), v, first, iter, last))
- {
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: table (\"",
- format_dotted_keys(first, last),
- "\") already exists."), {
- {tab->at(k).location(), "table already exists here"},
- {v.location(), "table defined twice"}
- }), v.location());
- }
- // to allow the following toml file.
- // [a.b.c]
- // d = 42
- // [a]
- // e = 2.71
- 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);
- return ok(true);
- }
- else if(v.is_table() &&
- tab->at(k).is_array() &&
- tab->at(k).as_array().size() > 0 &&
- tab->at(k).as_array().front().is_table())
- {
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: array of tables (\"",
- format_dotted_keys(first, last), "\") already exists."), {
- {tab->at(k).location(), "array of tables defined here"},
- {v.location(), "table conflicts with the previous array of table"}
- }), v.location());
- }
- else
- {
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: value (\"",
- format_dotted_keys(first, last), "\") already exists."), {
- {tab->at(k).location(), "value already exists here"},
- {v.location(), "value defined twice"}
- }), v.location());
- }
- }
- tab->insert(std::make_pair(k, v));
- return ok(true);
- }
- else // k is not the last one, we should insert recursively
- {
- // if there is no corresponding value, insert it first.
- // related: you don't need to write
- // # [x]
- // # [x.y]
- // to write
- // [x.y.z]
- if(tab->count(k) == 0)
- {
- // a table that is defined implicitly doesn't have any comments.
- (*tab)[k] = value_type(table_type{}, key_reg, {/*no comment*/});
- }
-
- // type checking...
- if(tab->at(k).is_table())
- {
- // According to toml-lang/toml:36d3091b3 "Clarify that inline
- // tables are immutable", check if it adds key-value pair to an
- // inline table.
- if(const auto* ptr = get_region(tab->at(k)))
- {
- // here, if the value is a (multi-line) table, the region
- // should be something like `[table-name]`.
- if(ptr->front() == '{')
- {
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: inserting to an inline table (",
- format_dotted_keys(first, std::next(iter)),
- ") but inline tables are immutable"), {
- {tab->at(k).location(), "inline tables are immutable"},
- {v.location(), "inserting this"}
- }), v.location());
- }
- }
- tab = std::addressof((*tab)[k].as_table());
- }
- else if(tab->at(k).is_array()) // inserting to array-of-tables?
- {
- auto& a = (*tab)[k].as_array();
- if(!a.back().is_table())
- {
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: target (",
- format_dotted_keys(first, std::next(iter)),
- ") is neither table nor an array of tables"), {
- {a.back().location(), concat_to_string(
- "actual type is ", a.back().type())},
- {v.location(), "inserting this"}
- }), v.location());
- }
- tab = std::addressof(a.back().as_table());
- }
- else
- {
- throw syntax_error(format_underline(concat_to_string(
- "toml::insert_value: target (",
- format_dotted_keys(first, std::next(iter)),
- ") is neither table nor an array of tables"), {
- {tab->at(k).location(), concat_to_string(
- "actual type is ", tab->at(k).type())},
- {v.location(), "inserting this"}
- }), v.location());
- }
- }
- }
- return err(std::string("toml::detail::insert_nested_key: never reach here"));
-}
-
-template<typename Value>
-result<std::pair<typename Value::table_type, region>, std::string>
-parse_inline_table(location& loc)
-{
- using value_type = Value;
- using table_type = typename value_type::table_type;
-
- const auto first = loc.iter();
- table_type retval;
- if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
- {
- return err(format_underline("toml::parse_inline_table: ",
- {{source_location(loc), "the next token is not an inline table"}}));
- }
- loc.advance();
-
- // check if the inline table is an empty table = { }
- maybe<lex_ws>::invoke(loc);
- 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())
- {
- const auto kv_r = parse_key_value_pair<value_type>(loc);
- if(!kv_r)
- {
- return err(kv_r.unwrap_err());
- }
-
- const auto& kvpair = kv_r.unwrap();
- const std::vector<key>& keys = kvpair.first.first;
- const auto& key_reg = kvpair.first.second;
- const value_type& val = kvpair.second;
-
- const auto inserted =
- insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg);
- if(!inserted)
- {
- throw internal_error("toml::parse_inline_table: "
- "failed to insert value into table: " + inserted.unwrap_err(),
- source_location(loc));
- }
-
- using lex_table_separator = sequence<maybe<lex_ws>, character<','>>;
- const auto sp = lex_table_separator::invoke(loc);
-
- if(!sp)
- {
- maybe<lex_ws>::invoke(loc);
-
- 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(
- retval, region(loc, first, loc.iter())));
- }
- else if(*loc.iter() == '#' || *loc.iter() == '\r' || *loc.iter() == '\n')
- {
- throw syntax_error(format_underline(
- "toml::parse_inline_table: missing curly brace `}`",
- {{source_location(loc), "should be `}`"}}),
- source_location(loc));
- }
- else
- {
- throw syntax_error(format_underline(
- "toml::parse_inline_table: missing table separator `,` ",
- {{source_location(loc), "should be `,`"}}),
- source_location(loc));
- }
- }
- else // `,` is found
- {
- maybe<lex_ws>::invoke(loc);
- if(loc.iter() != loc.end() && *loc.iter() == '}')
- {
- 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));
- }
- }
- }
- loc.reset(first);
- throw syntax_error(format_underline("toml::parse_inline_table: "
- "inline table did not closed by `}`",
- {{source_location(loc), "should be closed"}}),
- source_location(loc));
-}
-
-inline result<value_t, std::string> guess_number_type(const location& l)
-{
- // This function tries to find some (common) mistakes by checking characters
- // that follows the last character of a value. But it is often difficult
- // because some non-newline characters can appear after a value. E.g.
- // spaces, tabs, commas (in an array or inline table), closing brackets
- // (of an array or inline table), comment-sign (#). Since this function
- // does not parse further, those characters are always allowed to be there.
- location loc = l;
-
- if(lex_offset_date_time::invoke(loc)) {return ok(value_t::offset_datetime);}
- loc.reset(l.iter());
-
- if(lex_local_date_time::invoke(loc))
- {
- // bad offset may appear after this.
- if(loc.iter() != loc.end() && (*loc.iter() == '+' || *loc.iter() == '-'
- || *loc.iter() == 'Z' || *loc.iter() == 'z'))
- {
- return err(format_underline("bad offset: should be [+-]HH:MM or Z",
- {{source_location(loc), "[+-]HH:MM or Z"}},
- {"pass: +09:00, -05:30", "fail: +9:00, -5:30"}));
- }
- return ok(value_t::local_datetime);
- }
- loc.reset(l.iter());
-
- if(lex_local_date::invoke(loc))
- {
- // bad time may appear after this.
- // A space is allowed as a delimiter between local time. But there are
- // both cases in which a space becomes valid or invalid.
- // - invalid: 2019-06-16 7:00:00
- // - valid : 2019-06-16 07:00:00
- if(loc.iter() != loc.end())
- {
- const auto c = *loc.iter();
- if(c == 'T' || c == 't')
- {
- return err(format_underline("bad time: should be HH:MM:SS.subsec",
- {{source_location(loc), "HH:MM:SS.subsec"}},
- {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
- "fail: 1979-05-27T7:32:00, 1979-05-27 17:32"}));
- }
- if('0' <= c && c <= '9')
- {
- return err(format_underline("bad time: missing T",
- {{source_location(loc), "T or space required here"}},
- {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
- "fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
- }
- if(c == ' ' && std::next(loc.iter()) != loc.end() &&
- ('0' <= *std::next(loc.iter()) && *std::next(loc.iter())<= '9'))
- {
- loc.advance();
- return err(format_underline("bad time: should be HH:MM:SS.subsec",
- {{source_location(loc), "HH:MM:SS.subsec"}},
- {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
- "fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
- }
- }
- return ok(value_t::local_date);
- }
- loc.reset(l.iter());
-
- if(lex_local_time::invoke(loc)) {return ok(value_t::local_time);}
- loc.reset(l.iter());
-
- if(lex_float::invoke(loc))
- {
- if(loc.iter() != loc.end() && *loc.iter() == '_')
- {
- return err(format_underline("bad float: `_` should be surrounded by digits",
- {{source_location(loc), "here"}},
- {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
- "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
- }
- return ok(value_t::floating);
- }
- loc.reset(l.iter());
-
- if(lex_integer::invoke(loc))
- {
- if(loc.iter() != loc.end())
- {
- const auto c = *loc.iter();
- if(c == '_')
- {
- return err(format_underline("bad integer: `_` should be surrounded by digits",
- {{source_location(loc), "here"}},
- {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
- "fail: 1__000, 0123"}));
- }
- if('0' <= c && c <= '9')
- {
- // leading zero. point '0'
- loc.retrace();
- return err(format_underline("bad integer: leading zero",
- {{source_location(loc), "here"}},
- {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
- "fail: 1__000, 0123"}));
- }
- if(c == ':' || c == '-')
- {
- return err(format_underline("bad datetime: invalid format",
- {{source_location(loc), "here"}},
- {"pass: 1979-05-27T07:32:00-07:00, 1979-05-27 07:32:00.999999Z",
- "fail: 1979-05-27T7:32:00-7:00, 1979-05-27 7:32-00:30"}));
- }
- if(c == '.' || c == 'e' || c == 'E')
- {
- return err(format_underline("bad float: invalid format",
- {{source_location(loc), "here"}},
- {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
- "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
- }
- }
- return ok(value_t::integer);
- }
- if(loc.iter() != loc.end() && *loc.iter() == '.')
- {
- return err(format_underline("bad float: invalid format",
- {{source_location(loc), "integer part required before this"}},
- {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
- "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
- }
- if(loc.iter() != loc.end() && *loc.iter() == '_')
- {
- return err(format_underline("bad number: `_` should be surrounded by digits",
- {{source_location(loc), "`_` is not surrounded by digits"}},
- {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
- "fail: 1__000, 0123"}));
- }
- return err(format_underline("bad format: unknown value appeared",
- {{source_location(loc), "here"}}));
-}
-
-inline result<value_t, std::string> guess_value_type(const location& loc)
-{
- switch(*loc.iter())
- {
- case '"' : {return ok(value_t::string); }
- case '\'': {return ok(value_t::string); }
- case 't' : {return ok(value_t::boolean); }
- case 'f' : {return ok(value_t::boolean); }
- case '[' : {return ok(value_t::array); }
- case '{' : {return ok(value_t::table); }
- case 'i' : {return ok(value_t::floating);} // inf.
- case 'n' : {return ok(value_t::floating);} // nan.
- default : {return guess_number_type(loc);}
- }
-}
-
-template<typename Value, typename T>
-result<Value, std::string>
-parse_value_helper(result<std::pair<T, region>, std::string> rslt)
-{
- 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<typename Value>
-result<Value, std::string> parse_value(location& loc)
-{
- const auto first = loc.iter();
- if(first == loc.end())
- {
- return err(format_underline("toml::parse_value: input is empty",
- {{source_location(loc), ""}}));
- }
-
- const auto type = guess_value_type(loc);
- if(!type)
- {
- return err(type.unwrap_err());
- }
-
- switch(type.unwrap())
- {
- case value_t::boolean : {return parse_value_helper<Value>(parse_boolean(loc) );}
- case value_t::integer : {return parse_value_helper<Value>(parse_integer(loc) );}
- case value_t::floating : {return parse_value_helper<Value>(parse_floating(loc) );}
- case value_t::string : {return parse_value_helper<Value>(parse_string(loc) );}
- case value_t::offset_datetime: {return parse_value_helper<Value>(parse_offset_datetime(loc) );}
- case value_t::local_datetime : {return parse_value_helper<Value>(parse_local_datetime(loc) );}
- case value_t::local_date : {return parse_value_helper<Value>(parse_local_date(loc) );}
- case value_t::local_time : {return parse_value_helper<Value>(parse_local_time(loc) );}
- case value_t::array : {return parse_value_helper<Value>(parse_array<Value>(loc) );}
- case value_t::table : {return parse_value_helper<Value>(parse_inline_table<Value>(loc));}
- default:
- {
- const auto msg = format_underline("toml::parse_value: "
- "unknown token appeared", {{source_location(loc), "unknown"}});
- loc.reset(first);
- return err(msg);
- }
- }
-}
-
-inline result<std::pair<std::vector<key>, region>, std::string>
-parse_table_key(location& loc)
-{
- if(auto token = lex_std_table::invoke(loc))
- {
- location inner_loc(loc.name(), token.unwrap().str());
-
- const auto open = lex_std_table_open::invoke(inner_loc);
- if(!open || inner_loc.iter() == inner_loc.end())
- {
- throw internal_error(format_underline(
- "toml::parse_table_key: no `[`",
- {{source_location(inner_loc), "should be `[`"}}),
- source_location(inner_loc));
- }
- // to skip [ a . b . c ]
- // ^----------- this whitespace
- lex_ws::invoke(inner_loc);
- const auto keys = parse_key(inner_loc);
- if(!keys)
- {
- throw internal_error(format_underline(
- "toml::parse_table_key: invalid key",
- {{source_location(inner_loc), "not key"}}),
- source_location(inner_loc));
- }
- // to skip [ a . b . c ]
- // ^-- this whitespace
- lex_ws::invoke(inner_loc);
- const auto close = lex_std_table_close::invoke(inner_loc);
- if(!close)
- {
- throw internal_error(format_underline(
- "toml::parse_table_key: no `]`",
- {{source_location(inner_loc), "should be `]`"}}),
- source_location(inner_loc));
- }
-
- // after [table.key], newline or EOF(empty table) required.
- if(loc.iter() != loc.end())
- {
- using lex_newline_after_table_key =
- sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>;
- const auto nl = lex_newline_after_table_key::invoke(loc);
- if(!nl)
- {
- throw syntax_error(format_underline(
- "toml::parse_table_key: newline required after [table.key]",
- {{source_location(loc), "expected newline"}}),
- source_location(loc));
- }
- }
- return ok(std::make_pair(keys.unwrap().first, token.unwrap()));
- }
- else
- {
- return err(format_underline("toml::parse_table_key: "
- "not a valid table key", {{source_location(loc), "here"}}));
- }
-}
-
-inline result<std::pair<std::vector<key>, region>, std::string>
-parse_array_table_key(location& loc)
-{
- if(auto token = lex_array_table::invoke(loc))
- {
- location inner_loc(loc.name(), token.unwrap().str());
-
- const auto open = lex_array_table_open::invoke(inner_loc);
- if(!open || inner_loc.iter() == inner_loc.end())
- {
- throw internal_error(format_underline(
- "toml::parse_array_table_key: no `[[`",
- {{source_location(inner_loc), "should be `[[`"}}),
- source_location(inner_loc));
- }
- lex_ws::invoke(inner_loc);
- const auto keys = parse_key(inner_loc);
- if(!keys)
- {
- throw internal_error(format_underline(
- "toml::parse_array_table_key: invalid key",
- {{source_location(inner_loc), "not a key"}}),
- source_location(inner_loc));
- }
- lex_ws::invoke(inner_loc);
- const auto close = lex_array_table_close::invoke(inner_loc);
- if(!close)
- {
- throw internal_error(format_underline(
- "toml::parse_table_key: no `]]`",
- {{source_location(inner_loc), "should be `]]`"}}),
- source_location(inner_loc));
- }
-
- // after [[table.key]], newline or EOF(empty table) required.
- if(loc.iter() != loc.end())
- {
- using lex_newline_after_table_key =
- sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>;
- const auto nl = lex_newline_after_table_key::invoke(loc);
- if(!nl)
- {
- throw syntax_error(format_underline("toml::"
- "parse_array_table_key: newline required after [[table.key]]",
- {{source_location(loc), "expected newline"}}),
- source_location(loc));
- }
- }
- return ok(std::make_pair(keys.unwrap().first, token.unwrap()));
- }
- else
- {
- return err(format_underline("toml::parse_array_table_key: "
- "not a valid table key", {{source_location(loc), "here"}}));
- }
-}
-
-// parse table body (key-value pairs until the iter hits the next [tablekey])
-template<typename Value>
-result<typename Value::table_type, std::string>
-parse_ml_table(location& loc)
-{
- using value_type = Value;
- using table_type = typename value_type::table_type;
-
- const auto first = loc.iter();
- if(first == loc.end())
- {
- return ok(table_type{});
- }
-
- // XXX at lest one newline is needed.
- using skip_line = repeat<
- sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
- skip_line::invoke(loc);
- lex_ws::invoke(loc);
-
- table_type tab;
- while(loc.iter() != loc.end())
- {
- lex_ws::invoke(loc);
- const auto before = loc.iter();
- if(const auto tmp = parse_array_table_key(loc)) // next table found
- {
- loc.reset(before);
- return ok(tab);
- }
- if(const auto tmp = parse_table_key(loc)) // next table found
- {
- loc.reset(before);
- return ok(tab);
- }
-
- if(const auto kv = parse_key_value_pair<value_type>(loc))
- {
- const auto& kvpair = kv.unwrap();
- const std::vector<key>& keys = kvpair.first.first;
- const auto& key_reg = kvpair.first.second;
- const value_type& val = kvpair.second;
- const auto inserted =
- insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg);
- if(!inserted)
- {
- return err(inserted.unwrap_err());
- }
- }
- else
- {
- return err(kv.unwrap_err());
- }
-
- // comment lines are skipped by the above function call.
- // However, since the `skip_line` requires at least 1 newline, it fails
- // if the file ends with ws and/or comment without newline.
- // `skip_line` matches `ws? + comment? + newline`, not `ws` or `comment`
- // itself. To skip the last ws and/or comment, call lexers.
- // It does not matter if these fails, so the return value is discarded.
- lex_ws::invoke(loc);
- lex_comment::invoke(loc);
-
- // skip_line is (whitespace? comment? newline)_{1,}. multiple empty lines
- // and comments after the last key-value pairs are allowed.
- const auto newline = skip_line::invoke(loc);
- if(!newline && loc.iter() != loc.end())
- {
- const auto before2 = loc.iter();
- lex_ws::invoke(loc); // skip whitespace
- const auto msg = format_underline("toml::parse_table: "
- "invalid line format", {{source_location(loc), concat_to_string(
- "expected newline, but got '", show_char(*loc.iter()), "'.")}});
- loc.reset(before2);
- return err(msg);
- }
-
- // the skip_lines only matches with lines that includes newline.
- // to skip the last line that includes comment and/or whitespace
- // but no newline, call them one more time.
- lex_ws::invoke(loc);
- lex_comment::invoke(loc);
- }
- return ok(tab);
-}
-
-template<typename Value>
-result<Value, std::string> parse_toml_file(location& loc)
-{
- using value_type = Value;
- using table_type = typename value_type::table_type;
-
- const auto first = loc.iter();
- if(first == loc.end())
- {
- // For empty files, return an empty table with an empty region (zero-length).
- // Without the region, error messages would miss the filename.
- return ok(value_type(table_type{}, region(loc, first, first), {}));
- }
-
- // put the first line as a region of a file
- // Here first != loc.end(), so taking std::next is okay
- const region file(loc, first, std::next(loc.iter()));
-
- // The first successive comments that are separated from the first value
- // by an empty line are for a file itself.
- // ```toml
- // # this is a comment for a file.
- //
- // key = "the first value"
- // ```
- // ```toml
- // # this is a comment for "the first value".
- // key = "the first value"
- // ```
- std::vector<std::string> comments;
- using lex_first_comments = sequence<
- repeat<sequence<maybe<lex_ws>, lex_comment, lex_newline>, at_least<1>>,
- sequence<maybe<lex_ws>, lex_newline>
- >;
- if(const auto token = lex_first_comments::invoke(loc))
- {
- location inner_loc(loc.name(), token.unwrap().str());
- while(inner_loc.iter() != inner_loc.end())
- {
- maybe<lex_ws>::invoke(inner_loc); // remove ws if exists
- if(lex_newline::invoke(inner_loc))
- {
- assert(inner_loc.iter() == inner_loc.end());
- break; // empty line found.
- }
- auto com = lex_comment::invoke(inner_loc).unwrap().str();
- com.erase(com.begin()); // remove # sign
- comments.push_back(std::move(com));
- lex_newline::invoke(inner_loc);
- }
- }
-
- table_type data;
- // root object is also a table, but without [tablename]
- if(const auto tab = parse_ml_table<value_type>(loc))
- {
- data = std::move(tab.unwrap());
- }
- else // failed (empty table is regarded as success in parse_ml_table)
- {
- return err(tab.unwrap_err());
- }
- while(loc.iter() != loc.end())
- {
- // here, the region of [table] is regarded as the table-key because
- // the table body is normally too big and it is not so informative
- // if the first key-value pair of the table is shown in the error
- // message.
- if(const auto tabkey = parse_array_table_key(loc))
- {
- const auto tab = parse_ml_table<value_type>(loc);
- if(!tab){return err(tab.unwrap_err());}
-
- const auto& tk = tabkey.unwrap();
- const auto& keys = tk.first;
- const auto& reg = tk.second;
-
- const auto inserted = insert_nested_key(data,
- value_type(tab.unwrap(), reg, reg.comments()),
- keys.begin(), keys.end(), reg,
- /*is_array_of_table=*/ true);
- if(!inserted) {return err(inserted.unwrap_err());}
-
- continue;
- }
- if(const auto tabkey = parse_table_key(loc))
- {
- const auto tab = parse_ml_table<value_type>(loc);
- if(!tab){return err(tab.unwrap_err());}
-
- const auto& tk = tabkey.unwrap();
- const auto& keys = tk.first;
- const auto& reg = tk.second;
-
- const auto inserted = insert_nested_key(data,
- value_type(tab.unwrap(), reg, reg.comments()),
- keys.begin(), keys.end(), reg);
- if(!inserted) {return err(inserted.unwrap_err());}
-
- continue;
- }
- return err(format_underline("toml::parse_toml_file: "
- "unknown line appeared", {{source_location(loc), "unknown format"}}));
- }
-
- return ok(Value(std::move(data), file, comments));
-}
-
-} // detail
-
-template<typename Comment = TOML11_DEFAULT_COMMENT_STRATEGY,
- template<typename ...> class Table = std::unordered_map,
- template<typename ...> class Array = std::vector>
-basic_value<Comment, Table, Array>
-parse(std::istream& is, const std::string& fname = "unknown file")
-{
- using value_type = basic_value<Comment, Table, Array>;
-
- const auto beg = is.tellg();
- is.seekg(0, std::ios::end);
- const auto end = is.tellg();
- const auto fsize = end - beg;
- is.seekg(beg);
-
- // read whole file as a sequence of char
- assert(fsize >= 0);
- std::vector<char> letters(static_cast<std::size_t>(fsize));
- is.read(letters.data(), fsize);
-
- // append LF.
- // Although TOML does not require LF at the EOF, to make parsing logic
- // simpler, we "normalize" the content by adding LF if it does not exist.
- // It also checks if the last char is CR, to avoid changing the meaning.
- // This is not the *best* way to deal with the last character, but is a
- // simple and quick fix.
- if(!letters.empty() && letters.back() != '\n' && letters.back() != '\r')
- {
- letters.push_back('\n');
- }
-
- detail::location loc(std::move(fname), std::move(letters));
-
- // skip BOM if exists.
- // XXX component of BOM (like 0xEF) exceeds the representable range of
- // signed char, so on some (actually, most) of the environment, these cannot
- // be compared to char. However, since we are always out of luck, we need to
- // check our chars are equivalent to BOM. To do this, first we need to
- // convert char to unsigned char to guarantee the comparability.
- if(loc.source()->size() >= 3)
- {
- std::array<unsigned char, 3> BOM;
- std::memcpy(BOM.data(), loc.source()->data(), 3);
- if(BOM[0] == 0xEF && BOM[1] == 0xBB && BOM[2] == 0xBF)
- {
- loc.advance(3); // BOM found. skip.
- }
- }
-
- const auto data = detail::parse_toml_file<value_type>(loc);
- if(!data)
- {
- throw syntax_error(data.unwrap_err(), source_location(loc));
- }
- return data.unwrap();
-}
-
-template<typename Comment = TOML11_DEFAULT_COMMENT_STRATEGY,
- template<typename ...> class Table = std::unordered_map,
- template<typename ...> class Array = std::vector>
-basic_value<Comment, Table, Array> parse(const std::string& fname)
-{
- std::ifstream ifs(fname.c_str(), std::ios_base::binary);
- if(!ifs.good())
- {
- throw std::runtime_error("toml::parse: file open error -> " + fname);
- }
- return parse<Comment, Table, Array>(ifs, fname);
-}
-
-#ifdef TOML11_HAS_STD_FILESYSTEM
-// This function just forwards `parse("filename.toml")` to std::string version
-// to avoid the ambiguity in overload resolution.
-//
-// Both std::string and std::filesystem::path are convertible from const char*.
-// Without this, both parse(std::string) and parse(std::filesystem::path)
-// matches to parse("filename.toml"). This breaks the existing code.
-//
-// This function exactly matches to the invocation with c-string.
-// So this function is preferred than others and the ambiguity disappears.
-template<typename Comment = TOML11_DEFAULT_COMMENT_STRATEGY,
- template<typename ...> class Table = std::unordered_map,
- template<typename ...> class Array = std::vector>
-basic_value<Comment, Table, Array> parse(const char* fname)
-{
- return parse<Comment, Table, Array>(std::string(fname));
-}
-
-template<typename Comment = TOML11_DEFAULT_COMMENT_STRATEGY,
- template<typename ...> class Table = std::unordered_map,
- template<typename ...> class Array = std::vector>
-basic_value<Comment, Table, Array> parse(const std::filesystem::path& fpath)
-{
- std::ifstream ifs(fpath, std::ios_base::binary);
- if(!ifs.good())
- {
- throw std::runtime_error("toml::parse: file open error -> " +
- fpath.string());
- }
- return parse<Comment, Table, Array>(ifs, fpath.string());
-}
-#endif // TOML11_HAS_STD_FILESYSTEM
-
-} // toml
-#endif// TOML11_PARSER_HPP
diff --git a/src/toml11/toml/region.hpp b/src/toml11/toml/region.hpp
deleted file mode 100644
index 2e01e51d0..000000000
--- a/src/toml11/toml/region.hpp
+++ /dev/null
@@ -1,417 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_REGION_HPP
-#define TOML11_REGION_HPP
-#include <memory>
-#include <vector>
-#include <algorithm>
-#include <initializer_list>
-#include <iterator>
-#include <iomanip>
-#include <cassert>
-#include "color.hpp"
-
-namespace toml
-{
-namespace detail
-{
-
-// helper function to avoid std::string(0, 'c') or std::string(iter, iter)
-template<typename Iterator>
-std::string make_string(Iterator first, Iterator last)
-{
- if(first == last) {return "";}
- return std::string(first, last);
-}
-inline std::string make_string(std::size_t len, char c)
-{
- if(len == 0) {return "";}
- return std::string(len, c);
-}
-
-// region_base is a base class of location and region that are defined below.
-// it will be used to generate better error messages.
-struct region_base
-{
- region_base() = default;
- virtual ~region_base() = default;
- region_base(const region_base&) = default;
- region_base(region_base&& ) = default;
- region_base& operator=(const region_base&) = default;
- region_base& operator=(region_base&& ) = default;
-
- virtual bool is_ok() const noexcept {return false;}
- virtual char front() const noexcept {return '\0';}
-
- virtual std::string str() const {return std::string("unknown region");}
- virtual std::string name() const {return std::string("unknown file");}
- virtual std::string line() const {return std::string("unknown line");}
- virtual std::string line_num() const {return std::string("?");}
-
- // length of the region
- virtual std::size_t size() const noexcept {return 0;}
- // number of characters in the line before the region
- virtual std::size_t before() const noexcept {return 0;}
- // number of characters in the line after the region
- virtual std::size_t after() const noexcept {return 0;}
-
- virtual std::vector<std::string> comments() const {return {};}
- // ```toml
- // # comment_before
- // key = "value" # comment_inline
- // ```
-};
-
-// location represents a position in a container, which contains a file content.
-// it can be considered as a region that contains only one character.
-//
-// it contains pointer to the file content and iterator that points the current
-// location.
-struct location final : public region_base
-{
- using const_iterator = typename std::vector<char>::const_iterator;
- using difference_type = typename const_iterator::difference_type;
- using source_ptr = std::shared_ptr<const std::vector<char>>;
-
- location(std::string source_name, std::vector<char> cont)
- : source_(std::make_shared<std::vector<char>>(std::move(cont))),
- line_number_(1), source_name_(std::move(source_name)), iter_(source_->cbegin())
- {}
- location(std::string source_name, const std::string& cont)
- : source_(std::make_shared<std::vector<char>>(cont.begin(), cont.end())),
- line_number_(1), source_name_(std::move(source_name)), iter_(source_->cbegin())
- {}
-
- location(const location&) = default;
- location(location&&) = default;
- location& operator=(const location&) = default;
- location& operator=(location&&) = default;
- ~location() = default;
-
- bool is_ok() const noexcept override {return static_cast<bool>(source_);}
- char front() const noexcept override {return *iter_;}
-
- // this const prohibits codes like `++(loc.iter())`.
- const const_iterator iter() const noexcept {return iter_;}
-
- const_iterator begin() const noexcept {return source_->cbegin();}
- const_iterator end() const noexcept {return source_->cend();}
-
- // XXX `location::line_num()` used to be implemented using `std::count` to
- // count a number of '\n'. But with a long toml file (typically, 10k lines),
- // it becomes intolerably slow because each time it generates error messages,
- // it counts '\n' from thousands of characters. To workaround it, I decided
- // to introduce `location::line_number_` member variable and synchronize it
- // to the location changes the point to look. So an overload of `iter()`
- // which returns mutable reference is removed and `advance()`, `retrace()`
- // and `reset()` is added.
- void advance(difference_type n = 1) noexcept
- {
- this->line_number_ += static_cast<std::size_t>(
- std::count(this->iter_, std::next(this->iter_, n), '\n'));
- this->iter_ += n;
- return;
- }
- void retrace(difference_type n = 1) noexcept
- {
- this->line_number_ -= static_cast<std::size_t>(
- std::count(std::prev(this->iter_, n), this->iter_, '\n'));
- this->iter_ -= n;
- return;
- }
- void reset(const_iterator rollback) noexcept
- {
- // since c++11, std::distance works in both ways for random-access
- // iterators and returns a negative value if `first > last`.
- if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
- {
- this->line_number_ -= static_cast<std::size_t>(
- std::count(rollback, this->iter_, '\n'));
- }
- else // iter < rollback [[unlikely]]
- {
- this->line_number_ += static_cast<std::size_t>(
- std::count(this->iter_, rollback, '\n'));
- }
- this->iter_ = rollback;
- return;
- }
-
- std::string str() const override {return make_string(1, *this->iter());}
- std::string name() const override {return source_name_;}
-
- std::string line_num() const override
- {
- return std::to_string(this->line_number_);
- }
-
- std::string line() const override
- {
- return make_string(this->line_begin(), this->line_end());
- }
-
- const_iterator line_begin() const noexcept
- {
- using reverse_iterator = std::reverse_iterator<const_iterator>;
- return std::find(reverse_iterator(this->iter()),
- reverse_iterator(this->begin()), '\n').base();
- }
- const_iterator line_end() const noexcept
- {
- return std::find(this->iter(), this->end(), '\n');
- }
-
- // location is always points a character. so the size is 1.
- std::size_t size() const noexcept override
- {
- return 1u;
- }
- std::size_t before() const noexcept override
- {
- const auto sz = std::distance(this->line_begin(), this->iter());
- assert(sz >= 0);
- return static_cast<std::size_t>(sz);
- }
- std::size_t after() const noexcept override
- {
- const auto sz = std::distance(this->iter(), this->line_end());
- assert(sz >= 0);
- return static_cast<std::size_t>(sz);
- }
-
- source_ptr const& source() const& noexcept {return source_;}
- source_ptr&& source() && noexcept {return std::move(source_);}
-
- private:
-
- source_ptr source_;
- std::size_t line_number_;
- std::string source_name_;
- const_iterator iter_;
-};
-
-// region represents a range in a container, which contains a file content.
-//
-// it contains pointer to the file content and iterator that points the first
-// and last location.
-struct region final : public region_base
-{
- using const_iterator = typename std::vector<char>::const_iterator;
- using source_ptr = std::shared_ptr<const std::vector<char>>;
-
- // delete default constructor. source_ never be null.
- region() = delete;
-
- explicit region(const location& loc)
- : source_(loc.source()), source_name_(loc.name()),
- first_(loc.iter()), last_(loc.iter())
- {}
- explicit region(location&& loc)
- : source_(loc.source()), source_name_(loc.name()),
- first_(loc.iter()), last_(loc.iter())
- {}
-
- region(const location& loc, const_iterator f, const_iterator l)
- : source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
- {}
- region(location&& loc, const_iterator f, const_iterator l)
- : source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
- {}
-
- region(const region&) = default;
- region(region&&) = default;
- region& operator=(const region&) = default;
- region& operator=(region&&) = default;
- ~region() = default;
-
- region& operator+=(const region& other)
- {
- // different regions cannot be concatenated
- assert(this->begin() == other.begin() && this->end() == other.end() &&
- this->last_ == other.first_);
-
- this->last_ = other.last_;
- return *this;
- }
-
- bool is_ok() const noexcept override {return static_cast<bool>(source_);}
- char front() const noexcept override {return *first_;}
-
- std::string str() const override {return make_string(first_, last_);}
- std::string line() const override
- {
- if(this->contain_newline())
- {
- return make_string(this->line_begin(),
- std::find(this->line_begin(), this->last(), '\n'));
- }
- return make_string(this->line_begin(), this->line_end());
- }
- std::string line_num() const override
- {
- return std::to_string(1 + std::count(this->begin(), this->first(), '\n'));
- }
-
- std::size_t size() const noexcept override
- {
- const auto sz = std::distance(first_, last_);
- assert(sz >= 0);
- return static_cast<std::size_t>(sz);
- }
- std::size_t before() const noexcept override
- {
- const auto sz = std::distance(this->line_begin(), this->first());
- assert(sz >= 0);
- return static_cast<std::size_t>(sz);
- }
- std::size_t after() const noexcept override
- {
- const auto sz = std::distance(this->last(), this->line_end());
- assert(sz >= 0);
- return static_cast<std::size_t>(sz);
- }
-
- bool contain_newline() const noexcept
- {
- return std::find(this->first(), this->last(), '\n') != this->last();
- }
-
- const_iterator line_begin() const noexcept
- {
- using reverse_iterator = std::reverse_iterator<const_iterator>;
- return std::find(reverse_iterator(this->first()),
- reverse_iterator(this->begin()), '\n').base();
- }
- const_iterator line_end() const noexcept
- {
- return std::find(this->last(), this->end(), '\n');
- }
-
- const_iterator begin() const noexcept {return source_->cbegin();}
- const_iterator end() const noexcept {return source_->cend();}
- const_iterator first() const noexcept {return first_;}
- const_iterator last() const noexcept {return last_;}
-
- source_ptr const& source() const& noexcept {return source_;}
- source_ptr&& source() && noexcept {return std::move(source_);}
-
- std::string name() const override {return source_name_;}
-
- std::vector<std::string> comments() const override
- {
- // assuming the current region (`*this`) points a value.
- // ```toml
- // a = "value"
- // ^^^^^^^- this region
- // ```
- using rev_iter = std::reverse_iterator<const_iterator>;
-
- std::vector<std::string> com{};
- {
- // find comments just before the current region.
- // ```toml
- // # this should be collected.
- // # this also.
- // a = value # not this.
- // ```
-
- // # this is a comment for `a`, not array elements.
- // a = [1, 2, 3, 4, 5]
- if(this->first() == std::find_if(this->line_begin(), this->first(),
- [](const char c) noexcept -> bool {return c == '[' || c == '{';}))
- {
- auto iter = this->line_begin(); // points the first character
- while(iter != this->begin())
- {
- iter = std::prev(iter);
-
- // range [line_start, iter) represents the previous line
- const auto line_start = std::find(
- rev_iter(iter), rev_iter(this->begin()), '\n').base();
- const auto comment_found = std::find(line_start, iter, '#');
- if(comment_found == iter)
- {
- break; // comment not found.
- }
-
- // exclude the following case.
- // > a = "foo" # comment // <-- this is not a comment for b but a.
- // > b = "current value"
- if(std::all_of(line_start, comment_found,
- [](const char c) noexcept -> bool {
- return c == ' ' || c == '\t';
- }))
- {
- // unwrap the first '#' by std::next.
- auto s = make_string(std::next(comment_found), iter);
- if(!s.empty() && s.back() == '\r') {s.pop_back();}
- com.push_back(std::move(s));
- }
- else
- {
- break;
- }
- iter = line_start;
- }
- }
- }
-
- if(com.size() > 1)
- {
- std::reverse(com.begin(), com.end());
- }
-
- {
- // find comments just after the current region.
- // ```toml
- // # not this.
- // a = value # this one.
- // a = [ # not this (technically difficult)
- //
- // ] # and this.
- // ```
- // The reason why it's difficult is that it requires parsing in the
- // following case.
- // ```toml
- // a = [ 10 # this comment is for `10`. not for `a` but `a[0]`.
- // # ...
- // ] # this is apparently a comment for a.
- //
- // b = [
- // 3.14 ] # there is no way to add a comment to `3.14` currently.
- //
- // c = [
- // 3.14 # do this if you need a comment here.
- // ]
- // ```
- const auto comment_found =
- std::find(this->last(), this->line_end(), '#');
- if(comment_found != this->line_end()) // '#' found
- {
- // table = {key = "value"} # what is this for?
- // the above comment is not for "value", but {key="value"}.
- if(comment_found == std::find_if(this->last(), comment_found,
- [](const char c) noexcept -> bool {
- return !(c == ' ' || c == '\t' || c == ',');
- }))
- {
- // unwrap the first '#' by std::next.
- auto s = make_string(std::next(comment_found), this->line_end());
- if(!s.empty() && s.back() == '\r') {s.pop_back();}
- com.push_back(std::move(s));
- }
- }
- }
- return com;
- }
-
- private:
-
- source_ptr source_;
- std::string source_name_;
- const_iterator first_, last_;
-};
-
-} // detail
-} // toml
-#endif// TOML11_REGION_H
diff --git a/src/toml11/toml/result.hpp b/src/toml11/toml/result.hpp
deleted file mode 100644
index 77cd46c64..000000000
--- a/src/toml11/toml/result.hpp
+++ /dev/null
@@ -1,717 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_RESULT_HPP
-#define TOML11_RESULT_HPP
-#include "traits.hpp"
-#include <type_traits>
-#include <stdexcept>
-#include <utility>
-#include <new>
-#include <string>
-#include <sstream>
-#include <cassert>
-
-namespace toml
-{
-
-template<typename T>
-struct success
-{
- using value_type = T;
- value_type value;
-
- explicit success(const value_type& v)
- noexcept(std::is_nothrow_copy_constructible<value_type>::value)
- : value(v)
- {}
- explicit success(value_type&& v)
- noexcept(std::is_nothrow_move_constructible<value_type>::value)
- : value(std::move(v))
- {}
-
- template<typename U>
- explicit success(U&& v): value(std::forward<U>(v)) {}
-
- template<typename U>
- explicit success(const success<U>& v): value(v.value) {}
- template<typename U>
- explicit success(success<U>&& v): value(std::move(v.value)) {}
-
- ~success() = default;
- success(const success&) = default;
- success(success&&) = default;
- success& operator=(const success&) = default;
- success& operator=(success&&) = default;
-};
-
-template<typename T>
-struct failure
-{
- using value_type = T;
- value_type value;
-
- explicit failure(const value_type& v)
- noexcept(std::is_nothrow_copy_constructible<value_type>::value)
- : value(v)
- {}
- explicit failure(value_type&& v)
- noexcept(std::is_nothrow_move_constructible<value_type>::value)
- : value(std::move(v))
- {}
-
- template<typename U>
- explicit failure(U&& v): value(std::forward<U>(v)) {}
-
- template<typename U>
- explicit failure(const failure<U>& v): value(v.value) {}
- template<typename U>
- explicit failure(failure<U>&& v): value(std::move(v.value)) {}
-
- ~failure() = default;
- failure(const failure&) = default;
- failure(failure&&) = default;
- failure& operator=(const failure&) = default;
- failure& operator=(failure&&) = default;
-};
-
-template<typename T>
-success<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
-ok(T&& v)
-{
- return success<
- typename std::remove_cv<typename std::remove_reference<T>::type>::type
- >(std::forward<T>(v));
-}
-template<typename T>
-failure<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
-err(T&& v)
-{
- return failure<
- typename std::remove_cv<typename std::remove_reference<T>::type>::type
- >(std::forward<T>(v));
-}
-
-inline success<std::string> ok(const char* literal)
-{
- return success<std::string>(std::string(literal));
-}
-inline failure<std::string> err(const char* literal)
-{
- return failure<std::string>(std::string(literal));
-}
-
-
-template<typename T, typename E>
-struct result
-{
- using value_type = T;
- using error_type = E;
- using success_type = success<value_type>;
- using failure_type = failure<error_type>;
-
- result(const success_type& s): is_ok_(true)
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(s);
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- result(const failure_type& f): is_ok_(false)
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- result(success_type&& s): is_ok_(true)
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- result(failure_type&& f): is_ok_(false)
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
-
- template<typename U>
- result(const success<U>& s): is_ok_(true)
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- template<typename U>
- result(const failure<U>& f): is_ok_(false)
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- template<typename U>
- result(success<U>&& s): is_ok_(true)
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- template<typename U>
- result(failure<U>&& f): is_ok_(false)
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
-
- result& operator=(const success_type& s)
- {
- this->cleanup();
- this->is_ok_ = true;
- auto tmp = ::new(std::addressof(this->succ)) success_type(s);
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- return *this;
- }
- result& operator=(const failure_type& f)
- {
- this->cleanup();
- this->is_ok_ = false;
- auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- return *this;
- }
- result& operator=(success_type&& s)
- {
- this->cleanup();
- this->is_ok_ = true;
- auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- return *this;
- }
- result& operator=(failure_type&& f)
- {
- this->cleanup();
- this->is_ok_ = false;
- auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- return *this;
- }
-
- template<typename U>
- result& operator=(const success<U>& s)
- {
- this->cleanup();
- this->is_ok_ = true;
- auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- return *this;
- }
- template<typename U>
- result& operator=(const failure<U>& f)
- {
- this->cleanup();
- this->is_ok_ = false;
- auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- return *this;
- }
- template<typename U>
- result& operator=(success<U>&& s)
- {
- this->cleanup();
- this->is_ok_ = true;
- auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- return *this;
- }
- template<typename U>
- result& operator=(failure<U>&& f)
- {
- this->cleanup();
- this->is_ok_ = false;
- auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- return *this;
- }
-
- ~result() noexcept {this->cleanup();}
-
- result(const result& other): is_ok_(other.is_ok())
- {
- if(other.is_ok())
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- else
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- }
- result(result&& other): is_ok_(other.is_ok())
- {
- if(other.is_ok())
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- else
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- }
-
- template<typename U, typename F>
- result(const result<U, F>& other): is_ok_(other.is_ok())
- {
- if(other.is_ok())
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- else
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- }
- template<typename U, typename F>
- result(result<U, F>&& other): is_ok_(other.is_ok())
- {
- if(other.is_ok())
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- else
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- }
-
- result& operator=(const result& other)
- {
- this->cleanup();
- if(other.is_ok())
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- else
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- is_ok_ = other.is_ok();
- return *this;
- }
- result& operator=(result&& other)
- {
- this->cleanup();
- if(other.is_ok())
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- else
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- is_ok_ = other.is_ok();
- return *this;
- }
-
- template<typename U, typename F>
- result& operator=(const result<U, F>& other)
- {
- this->cleanup();
- if(other.is_ok())
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- else
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- is_ok_ = other.is_ok();
- return *this;
- }
- template<typename U, typename F>
- result& operator=(result<U, F>&& other)
- {
- this->cleanup();
- if(other.is_ok())
- {
- auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
- assert(tmp == std::addressof(this->succ));
- (void)tmp;
- }
- else
- {
- auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
- assert(tmp == std::addressof(this->fail));
- (void)tmp;
- }
- is_ok_ = other.is_ok();
- return *this;
- }
-
- bool is_ok() const noexcept {return is_ok_;}
- bool is_err() const noexcept {return !is_ok_;}
-
- operator bool() const noexcept {return is_ok_;}
-
- value_type& unwrap() &
- {
- if(is_err())
- {
- throw std::runtime_error("toml::result: bad unwrap: " +
- format_error(this->as_err()));
- }
- return this->succ.value;
- }
- value_type const& unwrap() const&
- {
- if(is_err())
- {
- throw std::runtime_error("toml::result: bad unwrap: " +
- format_error(this->as_err()));
- }
- return this->succ.value;
- }
- value_type&& unwrap() &&
- {
- if(is_err())
- {
- throw std::runtime_error("toml::result: bad unwrap: " +
- format_error(this->as_err()));
- }
- return std::move(this->succ.value);
- }
-
- value_type& unwrap_or(value_type& opt) &
- {
- if(is_err()) {return opt;}
- return this->succ.value;
- }
- value_type const& unwrap_or(value_type const& opt) const&
- {
- if(is_err()) {return opt;}
- return this->succ.value;
- }
- value_type unwrap_or(value_type opt) &&
- {
- if(is_err()) {return opt;}
- return this->succ.value;
- }
-
- error_type& unwrap_err() &
- {
- if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
- return this->fail.value;
- }
- error_type const& unwrap_err() const&
- {
- if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
- return this->fail.value;
- }
- error_type&& unwrap_err() &&
- {
- if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
- return std::move(this->fail.value);
- }
-
- value_type& as_ok() & noexcept {return this->succ.value;}
- value_type const& as_ok() const& noexcept {return this->succ.value;}
- value_type&& as_ok() && noexcept {return std::move(this->succ.value);}
-
- error_type& as_err() & noexcept {return this->fail.value;}
- error_type const& as_err() const& noexcept {return this->fail.value;}
- error_type&& as_err() && noexcept {return std::move(this->fail.value);}
-
-
- // prerequisities
- // F: T -> U
- // retval: result<U, E>
- template<typename F>
- result<detail::return_type_of_t<F, value_type&>, error_type>
- map(F&& f) &
- {
- if(this->is_ok()){return ok(f(this->as_ok()));}
- return err(this->as_err());
- }
- template<typename F>
- result<detail::return_type_of_t<F, value_type const&>, error_type>
- map(F&& f) const&
- {
- if(this->is_ok()){return ok(f(this->as_ok()));}
- return err(this->as_err());
- }
- template<typename F>
- result<detail::return_type_of_t<F, value_type &&>, error_type>
- map(F&& f) &&
- {
- if(this->is_ok()){return ok(f(std::move(this->as_ok())));}
- return err(std::move(this->as_err()));
- }
-
- // prerequisities
- // F: E -> F
- // retval: result<T, F>
- template<typename F>
- result<value_type, detail::return_type_of_t<F, error_type&>>
- map_err(F&& f) &
- {
- if(this->is_err()){return err(f(this->as_err()));}
- return ok(this->as_ok());
- }
- template<typename F>
- result<value_type, detail::return_type_of_t<F, error_type const&>>
- map_err(F&& f) const&
- {
- if(this->is_err()){return err(f(this->as_err()));}
- return ok(this->as_ok());
- }
- template<typename F>
- result<value_type, detail::return_type_of_t<F, error_type&&>>
- map_err(F&& f) &&
- {
- if(this->is_err()){return err(f(std::move(this->as_err())));}
- return ok(std::move(this->as_ok()));
- }
-
- // prerequisities
- // F: T -> U
- // retval: U
- template<typename F, typename U>
- detail::return_type_of_t<F, value_type&>
- map_or_else(F&& f, U&& opt) &
- {
- if(this->is_err()){return std::forward<U>(opt);}
- return f(this->as_ok());
- }
- template<typename F, typename U>
- detail::return_type_of_t<F, value_type const&>
- map_or_else(F&& f, U&& opt) const&
- {
- if(this->is_err()){return std::forward<U>(opt);}
- return f(this->as_ok());
- }
- template<typename F, typename U>
- detail::return_type_of_t<F, value_type&&>
- map_or_else(F&& f, U&& opt) &&
- {
- if(this->is_err()){return std::forward<U>(opt);}
- return f(std::move(this->as_ok()));
- }
-
- // prerequisities
- // F: E -> U
- // retval: U
- template<typename F, typename U>
- detail::return_type_of_t<F, error_type&>
- map_err_or_else(F&& f, U&& opt) &
- {
- if(this->is_ok()){return std::forward<U>(opt);}
- return f(this->as_err());
- }
- template<typename F, typename U>
- detail::return_type_of_t<F, error_type const&>
- map_err_or_else(F&& f, U&& opt) const&
- {
- if(this->is_ok()){return std::forward<U>(opt);}
- return f(this->as_err());
- }
- template<typename F, typename U>
- detail::return_type_of_t<F, error_type&&>
- map_err_or_else(F&& f, U&& opt) &&
- {
- if(this->is_ok()){return std::forward<U>(opt);}
- return f(std::move(this->as_err()));
- }
-
- // prerequisities:
- // F: func T -> U
- // toml::err(error_type) should be convertible to U.
- // normally, type U is another result<S, F> and E is convertible to F
- template<typename F>
- detail::return_type_of_t<F, value_type&>
- and_then(F&& f) &
- {
- if(this->is_ok()){return f(this->as_ok());}
- return err(this->as_err());
- }
- template<typename F>
- detail::return_type_of_t<F, value_type const&>
- and_then(F&& f) const&
- {
- if(this->is_ok()){return f(this->as_ok());}
- return err(this->as_err());
- }
- template<typename F>
- detail::return_type_of_t<F, value_type&&>
- and_then(F&& f) &&
- {
- if(this->is_ok()){return f(std::move(this->as_ok()));}
- return err(std::move(this->as_err()));
- }
-
- // prerequisities:
- // F: func E -> U
- // toml::ok(value_type) should be convertible to U.
- // normally, type U is another result<S, F> and T is convertible to S
- template<typename F>
- detail::return_type_of_t<F, error_type&>
- or_else(F&& f) &
- {
- if(this->is_err()){return f(this->as_err());}
- return ok(this->as_ok());
- }
- template<typename F>
- detail::return_type_of_t<F, error_type const&>
- or_else(F&& f) const&
- {
- if(this->is_err()){return f(this->as_err());}
- return ok(this->as_ok());
- }
- template<typename F>
- detail::return_type_of_t<F, error_type&&>
- or_else(F&& f) &&
- {
- if(this->is_err()){return f(std::move(this->as_err()));}
- return ok(std::move(this->as_ok()));
- }
-
- // if *this is error, returns *this. otherwise, returns other.
- result and_other(const result& other) const&
- {
- return this->is_err() ? *this : other;
- }
- result and_other(result&& other) &&
- {
- return this->is_err() ? std::move(*this) : std::move(other);
- }
-
- // if *this is okay, returns *this. otherwise, returns other.
- result or_other(const result& other) const&
- {
- return this->is_ok() ? *this : other;
- }
- result or_other(result&& other) &&
- {
- return this->is_ok() ? std::move(*this) : std::move(other);
- }
-
- void swap(result<T, E>& other)
- {
- result<T, E> tmp(std::move(*this));
- *this = std::move(other);
- other = std::move(tmp);
- return ;
- }
-
- private:
-
- static std::string format_error(std::exception const& excpt)
- {
- return std::string(excpt.what());
- }
- template<typename U, typename std::enable_if<!std::is_base_of<
- std::exception, U>::value, std::nullptr_t>::type = nullptr>
- static std::string format_error(U const& others)
- {
- std::ostringstream oss; oss << others;
- return oss.str();
- }
-
- void cleanup() noexcept
- {
- if(this->is_ok_) {this->succ.~success_type();}
- else {this->fail.~failure_type();}
- return;
- }
-
- private:
-
- bool is_ok_;
- union
- {
- success_type succ;
- failure_type fail;
- };
-};
-
-template<typename T, typename E>
-void swap(result<T, E>& lhs, result<T, E>& rhs)
-{
- lhs.swap(rhs);
- return;
-}
-
-// this might be confusing because it eagerly evaluated, while in the other
-// cases operator && and || are short-circuited.
-//
-// template<typename T, typename E>
-// inline result<T, E>
-// operator&&(const result<T, E>& lhs, const result<T, E>& rhs) noexcept
-// {
-// return lhs.is_ok() ? rhs : lhs;
-// }
-//
-// template<typename T, typename E>
-// inline result<T, E>
-// operator||(const result<T, E>& lhs, const result<T, E>& rhs) noexcept
-// {
-// return lhs.is_ok() ? lhs : rhs;
-// }
-
-// ----------------------------------------------------------------------------
-// re-use result<T, E> as a optional<T> with none_t
-
-namespace detail
-{
-struct none_t {};
-inline bool operator==(const none_t&, const none_t&) noexcept {return true;}
-inline bool operator!=(const none_t&, const none_t&) noexcept {return false;}
-inline bool operator< (const none_t&, const none_t&) noexcept {return false;}
-inline bool operator<=(const none_t&, const none_t&) noexcept {return true;}
-inline bool operator> (const none_t&, const none_t&) noexcept {return false;}
-inline bool operator>=(const none_t&, const none_t&) noexcept {return true;}
-template<typename charT, typename traitsT>
-std::basic_ostream<charT, traitsT>&
-operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&)
-{
- os << "none";
- return os;
-}
-inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};}
-} // detail
-} // toml11
-#endif// TOML11_RESULT_H
diff --git a/src/toml11/toml/serializer.hpp b/src/toml11/toml/serializer.hpp
deleted file mode 100644
index 88ae775a8..000000000
--- a/src/toml11/toml/serializer.hpp
+++ /dev/null
@@ -1,922 +0,0 @@
-// Copyright Toru Niina 2019.
-// Distributed under the MIT License.
-#ifndef TOML11_SERIALIZER_HPP
-#define TOML11_SERIALIZER_HPP
-#include <cmath>
-#include <cstdio>
-
-#include <limits>
-
-#include "lexer.hpp"
-#include "value.hpp"
-
-namespace toml
-{
-
-// This function serialize a key. It checks a string is a bare key and
-// escapes special characters if the string is not compatible to a bare key.
-// ```cpp
-// std::string k("non.bare.key"); // the key itself includes `.`s.
-// std::string formatted = toml::format_key(k);
-// assert(formatted == "\"non.bare.key\"");
-// ```
-//
-// This function is exposed to make it easy to write a user-defined serializer.
-// Since toml restricts characters available in a bare key, generally a string
-// should be escaped. But checking whether a string needs to be surrounded by
-// a `"` and escaping some special character is boring.
-template<typename charT, typename traits, typename Alloc>
-std::basic_string<charT, traits, Alloc>
-format_key(const std::basic_string<charT, traits, Alloc>& k)
-{
- if(k.empty())
- {
- return std::string("\"\"");
- }
-
- // check the key can be a bare (unquoted) key
- detail::location loc(k, std::vector<char>(k.begin(), k.end()));
- detail::lex_unquoted_key::invoke(loc);
- if(loc.iter() == loc.end())
- {
- return k; // all the tokens are consumed. the key is unquoted-key.
- }
-
- //if it includes special characters, then format it in a "quoted" key.
- std::basic_string<charT, traits, Alloc> serialized("\"");
- for(const char c : k)
- {
- switch(c)
- {
- case '\\': {serialized += "\\\\"; break;}
- case '\"': {serialized += "\\\""; break;}
- case '\b': {serialized += "\\b"; break;}
- case '\t': {serialized += "\\t"; break;}
- case '\f': {serialized += "\\f"; break;}
- case '\n': {serialized += "\\n"; break;}
- case '\r': {serialized += "\\r"; break;}
- default : {serialized += c; break;}
- }
- }
- serialized += "\"";
- return serialized;
-}
-
-template<typename charT, typename traits, typename Alloc>
-std::basic_string<charT, traits, Alloc>
-format_keys(const std::vector<std::basic_string<charT, traits, Alloc>>& keys)
-{
- if(keys.empty())
- {
- return std::string("\"\"");
- }
-
- std::basic_string<charT, traits, Alloc> serialized;
- for(const auto& ky : keys)
- {
- serialized += format_key(ky);
- serialized += charT('.');
- }
- serialized.pop_back(); // remove the last dot '.'
- return serialized;
-}
-
-template<typename Value>
-struct serializer
-{
- static_assert(detail::is_basic_value<Value>::value,
- "toml::serializer is for toml::value and its variants, "
- "toml::basic_value<...>.");
-
- using value_type = Value;
- using key_type = typename value_type::key_type ;
- using comment_type = typename value_type::comment_type ;
- using boolean_type = typename value_type::boolean_type ;
- using integer_type = typename value_type::integer_type ;
- using floating_type = typename value_type::floating_type ;
- using string_type = typename value_type::string_type ;
- using local_time_type = typename value_type::local_time_type ;
- using local_date_type = typename value_type::local_date_type ;
- using local_datetime_type = typename value_type::local_datetime_type ;
- using offset_datetime_type = typename value_type::offset_datetime_type;
- using array_type = typename value_type::array_type ;
- using table_type = typename value_type::table_type ;
-
- serializer(const std::size_t w = 80u,
- const int float_prec = std::numeric_limits<toml::floating>::max_digits10,
- const bool can_be_inlined = false,
- const bool no_comment = false,
- std::vector<toml::key> ks = {},
- const bool value_has_comment = false)
- : can_be_inlined_(can_be_inlined), no_comment_(no_comment),
- value_has_comment_(value_has_comment && !no_comment),
- float_prec_(float_prec), width_(w), keys_(std::move(ks))
- {}
- ~serializer() = default;
-
- std::string operator()(const boolean_type& b) const
- {
- return b ? "true" : "false";
- }
- std::string operator()(const integer_type i) const
- {
- return std::to_string(i);
- }
- std::string operator()(const floating_type f) const
- {
- if(std::isnan(f))
- {
- if(std::signbit(f))
- {
- return std::string("-nan");
- }
- else
- {
- return std::string("nan");
- }
- }
- else if(!std::isfinite(f))
- {
- if(std::signbit(f))
- {
- return std::string("-inf");
- }
- else
- {
- return std::string("inf");
- }
- }
-
- const auto fmt = "%.*g";
- const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f);
- // +1 for null character(\0)
- std::vector<char> buf(static_cast<std::size_t>(bsz + 1), '\0');
- std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f);
-
- std::string token(buf.begin(), std::prev(buf.end()));
- if(!token.empty() && token.back() == '.') // 1. => 1.0
- {
- token += '0';
- }
-
- const auto e = std::find_if(
- token.cbegin(), token.cend(), [](const char c) noexcept -> bool {
- return c == 'e' || c == 'E';
- });
- const auto has_exponent = (token.cend() != e);
- const auto has_fraction = (token.cend() != std::find(
- token.cbegin(), token.cend(), '.'));
-
- if(!has_exponent && !has_fraction)
- {
- // the resulting value does not have any float specific part!
- token += ".0";
- }
- return token;
- }
- std::string operator()(const string_type& s) const
- {
- if(s.kind == string_t::basic)
- {
- if((std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
- std::find(s.str.cbegin(), s.str.cend(), '\"') != s.str.cend()) &&
- this->width_ != (std::numeric_limits<std::size_t>::max)())
- {
- // if linefeed or double-quote is contained,
- // make it multiline basic string.
- const auto escaped = this->escape_ml_basic_string(s.str);
- std::string open("\"\"\"");
- std::string close("\"\"\"");
- if(escaped.find('\n') != std::string::npos ||
- this->width_ < escaped.size() + 6)
- {
- // if the string body contains newline or is enough long,
- // add newlines after and before delimiters.
- open += "\n";
- close = std::string("\\\n") + close;
- }
- return open + escaped + close;
- }
-
- // no linefeed. try to make it oneline-string.
- std::string oneline = this->escape_basic_string(s.str);
- if(oneline.size() + 2 < width_ || width_ < 2)
- {
- const std::string quote("\"");
- return quote + oneline + quote;
- }
-
- // the line is too long compared to the specified width.
- // split it into multiple lines.
- std::string token("\"\"\"\n");
- while(!oneline.empty())
- {
- if(oneline.size() < width_)
- {
- token += oneline;
- oneline.clear();
- }
- else if(oneline.at(width_-2) == '\\')
- {
- token += oneline.substr(0, width_-2);
- token += "\\\n";
- oneline.erase(0, width_-2);
- }
- else
- {
- token += oneline.substr(0, width_-1);
- token += "\\\n";
- oneline.erase(0, width_-1);
- }
- }
- return token + std::string("\\\n\"\"\"");
- }
- else // the string `s` is literal-string.
- {
- if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
- std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
- {
- std::string open("'''");
- if(this->width_ + 6 < s.str.size())
- {
- open += '\n'; // the first newline is ignored by TOML spec
- }
- const std::string close("'''");
- return open + s.str + close;
- }
- else
- {
- const std::string quote("'");
- return quote + s.str + quote;
- }
- }
- }
-
- std::string operator()(const local_date_type& d) const
- {
- std::ostringstream oss;
- oss << d;
- return oss.str();
- }
- std::string operator()(const local_time_type& t) const
- {
- std::ostringstream oss;
- oss << t;
- return oss.str();
- }
- std::string operator()(const local_datetime_type& dt) const
- {
- std::ostringstream oss;
- oss << dt;
- return oss.str();
- }
- std::string operator()(const offset_datetime_type& odt) const
- {
- std::ostringstream oss;
- oss << odt;
- return oss.str();
- }
-
- std::string operator()(const array_type& v) const
- {
- if(v.empty())
- {
- return std::string("[]");
- }
- if(this->is_array_of_tables(v))
- {
- return make_array_of_tables(v);
- }
-
- // not an array of tables. normal array.
- // first, try to make it inline if none of the elements have a comment.
- if( ! this->has_comment_inside(v))
- {
- const auto inl = this->make_inline_array(v);
- if(inl.size() < this->width_ &&
- std::find(inl.cbegin(), inl.cend(), '\n') == inl.cend())
- {
- return inl;
- }
- }
-
- // if the length exceeds this->width_, print multiline array.
- // key = [
- // # ...
- // 42,
- // ...
- // ]
- std::string token;
- std::string current_line;
- token += "[\n";
- for(const auto& item : v)
- {
- if( ! item.comments().empty() && !no_comment_)
- {
- // if comment exists, the element must be the only element in the line.
- // e.g. the following is not allowed.
- // ```toml
- // array = [
- // # comment for what?
- // 1, 2, 3, 4, 5
- // ]
- // ```
- if(!current_line.empty())
- {
- if(current_line.back() != '\n')
- {
- current_line += '\n';
- }
- token += current_line;
- current_line.clear();
- }
- for(const auto& c : item.comments())
- {
- token += '#';
- token += c;
- token += '\n';
- }
- token += toml::visit(*this, item);
- if(!token.empty() && token.back() == '\n') {token.pop_back();}
- token += ",\n";
- continue;
- }
- std::string next_elem;
- if(item.is_table())
- {
- serializer ser(*this);
- ser.can_be_inlined_ = true;
- ser.width_ = (std::numeric_limits<std::size_t>::max)();
- next_elem += toml::visit(ser, item);
- }
- else
- {
- next_elem += toml::visit(*this, item);
- }
-
- // comma before newline.
- if(!next_elem.empty() && next_elem.back() == '\n') {next_elem.pop_back();}
-
- // if current line does not exceeds the width limit, continue.
- if(current_line.size() + next_elem.size() + 1 < this->width_)
- {
- current_line += next_elem;
- current_line += ',';
- }
- else if(current_line.empty())
- {
- // if current line was empty, force put the next_elem because
- // next_elem is not splittable
- token += next_elem;
- token += ",\n";
- // current_line is kept empty
- }
- else // reset current_line
- {
- assert(current_line.back() == ',');
- token += current_line;
- token += '\n';
- current_line = next_elem;
- current_line += ',';
- }
- }
- if(!current_line.empty())
- {
- if(!current_line.empty() && current_line.back() != '\n')
- {
- current_line += '\n';
- }
- token += current_line;
- }
- token += "]\n";
- return token;
- }
-
- // templatize for any table-like container
- std::string operator()(const table_type& v) const
- {
- // if an element has a comment, then it can't be inlined.
- // table = {# how can we write a comment for this? key = "value"}
- if(this->can_be_inlined_ && !(this->has_comment_inside(v)))
- {
- std::string token;
- if(!this->keys_.empty())
- {
- token += format_key(this->keys_.back());
- token += " = ";
- }
- token += this->make_inline_table(v);
- if(token.size() < this->width_ &&
- token.end() == std::find(token.begin(), token.end(), '\n'))
- {
- return token;
- }
- }
-
- std::string token;
- if(!keys_.empty())
- {
- token += '[';
- token += format_keys(keys_);
- token += "]\n";
- }
- token += this->make_multiline_table(v);
- return token;
- }
-
- private:
-
- std::string escape_basic_string(const std::string& s) const
- {
- //XXX assuming `s` is a valid utf-8 sequence.
- std::string retval;
- for(const char c : s)
- {
- switch(c)
- {
- case '\\': {retval += "\\\\"; break;}
- case '\"': {retval += "\\\""; break;}
- case '\b': {retval += "\\b"; break;}
- case '\t': {retval += "\\t"; break;}
- case '\f': {retval += "\\f"; break;}
- case '\n': {retval += "\\n"; break;}
- case '\r': {retval += "\\r"; break;}
- default :
- {
- if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F)
- {
- retval += "\\u00";
- retval += char(48 + (c / 16));
- retval += char((c % 16 < 10 ? 48 : 55) + (c % 16));
- }
- else
- {
- retval += c;
- }
- }
- }
- }
- return retval;
- }
-
- std::string escape_ml_basic_string(const std::string& s) const
- {
- std::string retval;
- for(auto i=s.cbegin(), e=s.cend(); i!=e; ++i)
- {
- switch(*i)
- {
- case '\\': {retval += "\\\\"; break;}
- // One or two consecutive "s are allowed.
- // Later we will check there are no three consecutive "s.
- // case '\"': {retval += "\\\""; break;}
- case '\b': {retval += "\\b"; break;}
- case '\t': {retval += "\\t"; break;}
- case '\f': {retval += "\\f"; break;}
- case '\n': {retval += "\n"; break;}
- case '\r':
- {
- if(std::next(i) != e && *std::next(i) == '\n')
- {
- retval += "\r\n";
- ++i;
- }
- else
- {
- retval += "\\r";
- }
- break;
- }
- default :
- {
- const auto c = *i;
- if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F)
- {
- retval += "\\u00";
- retval += char(48 + (c / 16));
- retval += char((c % 16 < 10 ? 48 : 55) + (c % 16));
- }
- else
- {
- retval += c;
- }
- }
-
- }
- }
- // Only 1 or 2 consecutive `"`s are allowed in multiline basic string.
- // 3 consecutive `"`s are considered as a closing delimiter.
- // We need to check if there are 3 or more consecutive `"`s and insert
- // backslash to break them down into several short `"`s like the `str6`
- // in the following example.
- // ```toml
- // str4 = """Here are two quotation marks: "". Simple enough."""
- // # str5 = """Here are three quotation marks: """.""" # INVALID
- // str5 = """Here are three quotation marks: ""\"."""
- // str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
- // ```
- auto found_3_quotes = retval.find("\"\"\"");
- while(found_3_quotes != std::string::npos)
- {
- retval.replace(found_3_quotes, 3, "\"\"\\\"");
- found_3_quotes = retval.find("\"\"\"");
- }
- return retval;
- }
-
- // if an element of a table or an array has a comment, it cannot be inlined.
- bool has_comment_inside(const array_type& a) const noexcept
- {
- // if no_comment is set, comments would not be written.
- if(this->no_comment_) {return false;}
-
- for(const auto& v : a)
- {
- if(!v.comments().empty()) {return true;}
- }
- return false;
- }
- bool has_comment_inside(const table_type& t) const noexcept
- {
- // if no_comment is set, comments would not be written.
- if(this->no_comment_) {return false;}
-
- for(const auto& kv : t)
- {
- if(!kv.second.comments().empty()) {return true;}
- }
- return false;
- }
-
- std::string make_inline_array(const array_type& v) const
- {
- assert(!has_comment_inside(v));
- std::string token;
- token += '[';
- bool is_first = true;
- for(const auto& item : v)
- {
- if(is_first) {is_first = false;} else {token += ',';}
- token += visit(serializer(
- (std::numeric_limits<std::size_t>::max)(), this->float_prec_,
- /* inlined */ true, /*no comment*/ false, /*keys*/ {},
- /*has_comment*/ !item.comments().empty()), item);
- }
- token += ']';
- return token;
- }
-
- std::string make_inline_table(const table_type& v) const
- {
- assert(!has_comment_inside(v));
- assert(this->can_be_inlined_);
- std::string token;
- token += '{';
- bool is_first = true;
- for(const auto& kv : v)
- {
- // in inline tables, trailing comma is not allowed (toml-lang #569).
- if(is_first) {is_first = false;} else {token += ',';}
- token += format_key(kv.first);
- token += '=';
- token += visit(serializer(
- (std::numeric_limits<std::size_t>::max)(), this->float_prec_,
- /* inlined */ true, /*no comment*/ false, /*keys*/ {},
- /*has_comment*/ !kv.second.comments().empty()), kv.second);
- }
- token += '}';
- return token;
- }
-
- std::string make_multiline_table(const table_type& v) const
- {
- std::string token;
-
- // print non-table elements first.
- // ```toml
- // [foo] # a table we're writing now here
- // key = "value" # <- non-table element, "key"
- // # ...
- // [foo.bar] # <- table element, "bar"
- // ```
- // because after printing [foo.bar], the remaining non-table values will
- // be assigned into [foo.bar], not [foo]. Those values should be printed
- // earlier.
- for(const auto& kv : v)
- {
- if(kv.second.is_table() || is_array_of_tables(kv.second))
- {
- continue;
- }
-
- token += write_comments(kv.second);
-
- const auto key_and_sep = format_key(kv.first) + " = ";
- const auto residual_width = (this->width_ > key_and_sep.size()) ?
- this->width_ - key_and_sep.size() : 0;
- token += key_and_sep;
- token += visit(serializer(residual_width, this->float_prec_,
- /*can be inlined*/ true, /*no comment*/ false, /*keys*/ {},
- /*has_comment*/ !kv.second.comments().empty()), kv.second);
-
- if(token.back() != '\n')
- {
- token += '\n';
- }
- }
-
- // normal tables / array of tables
-
- // after multiline table appeared, the other tables cannot be inline
- // because the table would be assigned into the table.
- // [foo]
- // ...
- // bar = {...} # <- bar will be a member of [foo].
- bool multiline_table_printed = false;
- for(const auto& kv : v)
- {
- if(!kv.second.is_table() && !is_array_of_tables(kv.second))
- {
- continue; // other stuff are already serialized. skip them.
- }
-
- std::vector<toml::key> ks(this->keys_);
- ks.push_back(kv.first);
-
- auto tmp = visit(serializer(this->width_, this->float_prec_,
- !multiline_table_printed, this->no_comment_, ks,
- /*has_comment*/ !kv.second.comments().empty()), kv.second);
-
- // If it is the first time to print a multi-line table, it would be
- // helpful to separate normal key-value pair and subtables by a
- // newline.
- // (this checks if the current key-value pair contains newlines.
- // but it is not perfect because multi-line string can also contain
- // a newline. in such a case, an empty line will be written) TODO
- if((!multiline_table_printed) &&
- std::find(tmp.cbegin(), tmp.cend(), '\n') != tmp.cend())
- {
- multiline_table_printed = true;
- token += '\n'; // separate key-value pairs and subtables
-
- token += write_comments(kv.second);
- token += tmp;
-
- // care about recursive tables (all tables in each level prints
- // newline and there will be a full of newlines)
- if(tmp.substr(tmp.size() - 2, 2) != "\n\n" &&
- tmp.substr(tmp.size() - 4, 4) != "\r\n\r\n" )
- {
- token += '\n';
- }
- }
- else
- {
- token += write_comments(kv.second);
- token += tmp;
- token += '\n';
- }
- }
- return token;
- }
-
- std::string make_array_of_tables(const array_type& v) const
- {
- // if it's not inlined, we need to add `[[table.key]]`.
- // but if it can be inlined, we can format it as the following.
- // ```
- // table.key = [
- // {...},
- // # comment
- // {...},
- // ]
- // ```
- // This function checks if inlinization is possible or not, and then
- // format the array-of-tables in a proper way.
- //
- // Note about comments:
- //
- // If the array itself has a comment (value_has_comment_ == true), we
- // should try to make it inline.
- // ```toml
- // # comment about array
- // array = [
- // # comment about table element
- // {of = "table"}
- // ]
- // ```
- // If it is formatted as a multiline table, the two comments becomes
- // indistinguishable.
- // ```toml
- // # comment about array
- // # comment about table element
- // [[array]]
- // of = "table"
- // ```
- // So we need to try to make it inline, and it force-inlines regardless
- // of the line width limit.
- // It may fail if the element of a table has comment. In that case,
- // the array-of-tables will be formatted as a multiline table.
- if(this->can_be_inlined_ || this->value_has_comment_)
- {
- std::string token;
- if(!keys_.empty())
- {
- token += format_key(keys_.back());
- token += " = ";
- }
-
- bool failed = false;
- token += "[\n";
- for(const auto& item : v)
- {
- // if an element of the table has a comment, the table
- // cannot be inlined.
- if(this->has_comment_inside(item.as_table()))
- {
- failed = true;
- break;
- }
- // write comments for the table itself
- token += write_comments(item);
-
- const auto t = this->make_inline_table(item.as_table());
-
- if(t.size() + 1 > width_ || // +1 for the last comma {...},
- std::find(t.cbegin(), t.cend(), '\n') != t.cend())
- {
- // if the value itself has a comment, ignore the line width limit
- if( ! this->value_has_comment_)
- {
- failed = true;
- break;
- }
- }
- token += t;
- token += ",\n";
- }
-
- if( ! failed)
- {
- token += "]\n";
- return token;
- }
- // if failed, serialize them as [[array.of.tables]].
- }
-
- std::string token;
- for(const auto& item : v)
- {
- token += write_comments(item);
- token += "[[";
- token += format_keys(keys_);
- token += "]]\n";
- token += this->make_multiline_table(item.as_table());
- }
- return token;
- }
-
- std::string write_comments(const value_type& v) const
- {
- std::string retval;
- if(this->no_comment_) {return retval;}
-
- for(const auto& c : v.comments())
- {
- retval += '#';
- retval += c;
- retval += '\n';
- }
- return retval;
- }
-
- bool is_array_of_tables(const value_type& v) const
- {
- if(!v.is_array() || v.as_array().empty()) {return false;}
- return is_array_of_tables(v.as_array());
- }
- bool is_array_of_tables(const array_type& v) const
- {
- // Since TOML v0.5.0, heterogeneous arrays are allowed. So we need to
- // check all the element in an array to check if the array is an array
- // of tables.
- return std::all_of(v.begin(), v.end(), [](const value_type& elem) {
- return elem.is_table();
- });
- }
-
- private:
-
- bool can_be_inlined_;
- bool no_comment_;
- bool value_has_comment_;
- int float_prec_;
- std::size_t width_;
- std::vector<toml::key> keys_;
-};
-
-template<typename C,
- template<typename ...> class M, template<typename ...> class V>
-std::string
-format(const basic_value<C, M, V>& v, std::size_t w = 80u,
- int fprec = std::numeric_limits<toml::floating>::max_digits10,
- bool no_comment = false, bool force_inline = false)
-{
- using value_type = basic_value<C, M, V>;
- // if value is a table, it is considered to be a root object.
- // the root object can't be an inline table.
- if(v.is_table())
- {
- std::ostringstream oss;
- if(!v.comments().empty())
- {
- oss << v.comments();
- oss << '\n'; // to split the file comment from the first element
- }
- const auto serialized = visit(serializer<value_type>(w, fprec, false, no_comment), v);
- oss << serialized;
- return oss.str();
- }
- return visit(serializer<value_type>(w, fprec, force_inline), v);
-}
-
-namespace detail
-{
-template<typename charT, typename traits>
-int comment_index(std::basic_ostream<charT, traits>&)
-{
- static const int index = std::ios_base::xalloc();
- return index;
-}
-} // detail
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-nocomment(std::basic_ostream<charT, traits>& os)
-{
- // by default, it is zero. and by default, it shows comments.
- os.iword(detail::comment_index(os)) = 1;
- return os;
-}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-showcomment(std::basic_ostream<charT, traits>& os)
-{
- // by default, it is zero. and by default, it shows comments.
- os.iword(detail::comment_index(os)) = 0;
- return os;
-}
-
-template<typename charT, typename traits, typename C,
- template<typename ...> class M, template<typename ...> class V>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const basic_value<C, M, V>& v)
-{
- using value_type = basic_value<C, M, V>;
-
- // get status of std::setw().
- const auto w = static_cast<std::size_t>(os.width());
- const int fprec = static_cast<int>(os.precision());
- os.width(0);
-
- // by default, iword is initialized by 0. And by default, toml11 outputs
- // comments. So `0` means showcomment. 1 means nocommnet.
- const bool no_comment = (1 == os.iword(detail::comment_index(os)));
-
- if(!no_comment && v.is_table() && !v.comments().empty())
- {
- os << v.comments();
- os << '\n'; // to split the file comment from the first element
- }
- // the root object can't be an inline table. so pass `false`.
- const auto serialized = visit(serializer<value_type>(w, fprec, no_comment, false), v);
- os << serialized;
-
- // if v is a non-table value, and has only one comment, then
- // put a comment just after a value. in the following way.
- //
- // ```toml
- // key = "value" # comment.
- // ```
- //
- // Since the top-level toml object is a table, one who want to put a
- // non-table toml value must use this in a following way.
- //
- // ```cpp
- // toml::value v;
- // std::cout << "user-defined-key = " << v << std::endl;
- // ```
- //
- // In this case, it is impossible to put comments before key-value pair.
- // The only way to preserve comments is to put all of them after a value.
- if(!no_comment && !v.is_table() && !v.comments().empty())
- {
- os << " #";
- for(const auto& c : v.comments()) {os << c;}
- }
- return os;
-}
-
-} // toml
-#endif// TOML11_SERIALIZER_HPP
diff --git a/src/toml11/toml/source_location.hpp b/src/toml11/toml/source_location.hpp
deleted file mode 100644
index fa175b5b4..000000000
--- a/src/toml11/toml/source_location.hpp
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright Toru Niina 2019.
-// Distributed under the MIT License.
-#ifndef TOML11_SOURCE_LOCATION_HPP
-#define TOML11_SOURCE_LOCATION_HPP
-#include <cstdint>
-#include <sstream>
-
-#include "region.hpp"
-
-namespace toml
-{
-
-// A struct to contain location in a toml file.
-// The interface imitates std::experimental::source_location,
-// but not completely the same.
-//
-// It would be constructed by toml::value. It can be used to generate
-// user-defined error messages.
-//
-// - std::uint_least32_t line() const noexcept
-// - returns the line number where the region is on.
-// - std::uint_least32_t column() const noexcept
-// - returns the column number where the region starts.
-// - std::uint_least32_t region() const noexcept
-// - returns the size of the region.
-//
-// +-- line() +-- region of interest (region() == 9)
-// v .---+---.
-// 12 | value = "foo bar"
-// ^
-// +-- column()
-//
-// - std::string const& file_name() const noexcept;
-// - name of the file.
-// - std::string const& line_str() const noexcept;
-// - the whole line that contains the region of interest.
-//
-struct source_location
-{
- public:
-
- source_location()
- : line_num_(1), column_num_(1), region_size_(1),
- file_name_("unknown file"), line_str_("")
- {}
-
- explicit source_location(const detail::region_base* reg)
- : line_num_(1), column_num_(1), region_size_(1),
- file_name_("unknown file"), line_str_("")
- {
- if(reg)
- {
- if(reg->line_num() != detail::region_base().line_num())
- {
- line_num_ = static_cast<std::uint_least32_t>(
- std::stoul(reg->line_num()));
- }
- column_num_ = static_cast<std::uint_least32_t>(reg->before() + 1);
- region_size_ = static_cast<std::uint_least32_t>(reg->size());
- file_name_ = reg->name();
- line_str_ = reg->line();
- }
- }
-
- explicit source_location(const detail::region& reg)
- : line_num_(static_cast<std::uint_least32_t>(std::stoul(reg.line_num()))),
- column_num_(static_cast<std::uint_least32_t>(reg.before() + 1)),
- region_size_(static_cast<std::uint_least32_t>(reg.size())),
- file_name_(reg.name()),
- line_str_ (reg.line())
- {}
- explicit source_location(const detail::location& loc)
- : line_num_(static_cast<std::uint_least32_t>(std::stoul(loc.line_num()))),
- column_num_(static_cast<std::uint_least32_t>(loc.before() + 1)),
- region_size_(static_cast<std::uint_least32_t>(loc.size())),
- file_name_(loc.name()),
- line_str_ (loc.line())
- {}
-
- ~source_location() = default;
- source_location(source_location const&) = default;
- source_location(source_location &&) = default;
- source_location& operator=(source_location const&) = default;
- source_location& operator=(source_location &&) = default;
-
- std::uint_least32_t line() const noexcept {return line_num_;}
- std::uint_least32_t column() const noexcept {return column_num_;}
- std::uint_least32_t region() const noexcept {return region_size_;}
-
- std::string const& file_name() const noexcept {return file_name_;}
- std::string const& line_str() const noexcept {return line_str_;}
-
- private:
-
- std::uint_least32_t line_num_;
- std::uint_least32_t column_num_;
- std::uint_least32_t region_size_;
- std::string file_name_;
- std::string line_str_;
-};
-
-namespace detail
-{
-
-// internal error message generation.
-inline std::string format_underline(const std::string& message,
- const std::vector<std::pair<source_location, std::string>>& loc_com,
- const std::vector<std::string>& helps = {},
- const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
-{
- std::size_t line_num_width = 0;
- for(const auto& lc : loc_com)
- {
- std::uint_least32_t line = lc.first.line();
- std::size_t digit = 0;
- while(line != 0)
- {
- line /= 10;
- digit += 1;
- }
- line_num_width = (std::max)(line_num_width, digit);
- }
- // 1 is the minimum width
- line_num_width = std::max<std::size_t>(line_num_width, 1);
-
- std::ostringstream retval;
-
- if(colorize)
- {
- retval << color::colorize; // turn on ANSI color
- }
-
- // XXX
- // Here, before `colorize` support, it does not output `[error]` prefix
- // automatically. So some user may output it manually and this change may
- // duplicate the prefix. To avoid it, check the first 7 characters and
- // if it is "[error]", it removes that part from the message shown.
- if(message.size() > 7 && message.substr(0, 7) == "[error]")
- {
- retval << color::bold << color::red << "[error]" << color::reset
- << color::bold << message.substr(7) << color::reset << '\n';
- }
- else
- {
- retval << color::bold << color::red << "[error] " << color::reset
- << color::bold << message << color::reset << '\n';
- }
-
- const auto format_one_location = [line_num_width]
- (std::ostringstream& oss,
- const source_location& loc, const std::string& comment) -> void
- {
- oss << ' ' << color::bold << color::blue
- << std::setw(static_cast<int>(line_num_width))
- << std::right << loc.line() << " | " << color::reset
- << loc.line_str() << '\n';
-
- oss << make_string(line_num_width + 1, ' ')
- << color::bold << color::blue << " | " << color::reset
- << make_string(loc.column()-1 /*1-origin*/, ' ');
-
- if(loc.region() == 1)
- {
- // invalid
- // ^------
- oss << color::bold << color::red << "^---" << color::reset;
- }
- else
- {
- // invalid
- // ~~~~~~~
- const auto underline_len = (std::min)(
- static_cast<std::size_t>(loc.region()), loc.line_str().size());
- oss << color::bold << color::red
- << make_string(underline_len, '~') << color::reset;
- }
- oss << ' ';
- oss << comment;
- return;
- };
-
- assert(!loc_com.empty());
-
- // --> example.toml
- // |
- retval << color::bold << color::blue << " --> " << color::reset
- << loc_com.front().first.file_name() << '\n';
- retval << make_string(line_num_width + 1, ' ')
- << color::bold << color::blue << " |\n" << color::reset;
- // 1 | key value
- // | ^--- missing =
- format_one_location(retval, loc_com.front().first, loc_com.front().second);
-
- // process the rest of the locations
- for(std::size_t i=1; i<loc_com.size(); ++i)
- {
- const auto& prev = loc_com.at(i-1);
- const auto& curr = loc_com.at(i);
-
- retval << '\n';
- // if the filenames are the same, print "..."
- if(prev.first.file_name() == curr.first.file_name())
- {
- retval << color::bold << color::blue << " ...\n" << color::reset;
- }
- else // if filename differs, print " --> filename.toml" again
- {
- retval << color::bold << color::blue << " --> " << color::reset
- << curr.first.file_name() << '\n';
- retval << make_string(line_num_width + 1, ' ')
- << color::bold << color::blue << " |\n" << color::reset;
- }
-
- format_one_location(retval, curr.first, curr.second);
- }
-
- if(!helps.empty())
- {
- retval << '\n';
- retval << make_string(line_num_width + 1, ' ');
- retval << color::bold << color::blue << " |" << color::reset;
- for(const auto& help : helps)
- {
- retval << color::bold << "\nHint: " << color::reset;
- retval << help;
- }
- }
- return retval.str();
-}
-
-} // detail
-} // toml
-#endif// TOML11_SOURCE_LOCATION_HPP
diff --git a/src/toml11/toml/storage.hpp b/src/toml11/toml/storage.hpp
deleted file mode 100644
index 202f9035f..000000000
--- a/src/toml11/toml/storage.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_STORAGE_HPP
-#define TOML11_STORAGE_HPP
-#include "utility.hpp"
-
-namespace toml
-{
-namespace detail
-{
-
-// this contains pointer and deep-copy the content if copied.
-// to avoid recursive pointer.
-template<typename T>
-struct storage
-{
- using value_type = T;
-
- explicit storage(value_type const& v): ptr(toml::make_unique<T>(v)) {}
- explicit storage(value_type&& v): ptr(toml::make_unique<T>(std::move(v))) {}
- ~storage() = default;
- storage(const storage& rhs): ptr(toml::make_unique<T>(*rhs.ptr)) {}
- storage& operator=(const storage& rhs)
- {
- this->ptr = toml::make_unique<T>(*rhs.ptr);
- return *this;
- }
- storage(storage&&) = default;
- storage& operator=(storage&&) = default;
-
- bool is_ok() const noexcept {return static_cast<bool>(ptr);}
-
- value_type& value() & noexcept {return *ptr;}
- value_type const& value() const& noexcept {return *ptr;}
- value_type&& value() && noexcept {return std::move(*ptr);}
-
- private:
- std::unique_ptr<value_type> ptr;
-};
-
-} // detail
-} // toml
-#endif// TOML11_STORAGE_HPP
diff --git a/src/toml11/toml/string.hpp b/src/toml11/toml/string.hpp
deleted file mode 100644
index 5136d8c56..000000000
--- a/src/toml11/toml/string.hpp
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_STRING_HPP
-#define TOML11_STRING_HPP
-#include <cstdint>
-
-#include <algorithm>
-#include <string>
-
-#if __cplusplus >= 201703L
-#if __has_include(<string_view>)
-#define TOML11_USING_STRING_VIEW 1
-#include <string_view>
-#endif
-#endif
-
-namespace toml
-{
-
-enum class string_t : std::uint8_t
-{
- basic = 0,
- literal = 1,
-};
-
-struct string
-{
- string() = default;
- ~string() = default;
- string(const string& s) = default;
- string(string&& s) = default;
- string& operator=(const string& s) = default;
- string& operator=(string&& s) = default;
-
- string(const std::string& s): kind(string_t::basic), str(s){}
- string(const std::string& s, string_t k): kind(k), str(s){}
- string(const char* s): kind(string_t::basic), str(s){}
- string(const char* s, string_t k): kind(k), str(s){}
-
- string(std::string&& s): kind(string_t::basic), str(std::move(s)){}
- string(std::string&& s, string_t k): kind(k), str(std::move(s)){}
-
- string& operator=(const std::string& s)
- {kind = string_t::basic; str = s; return *this;}
- string& operator=(std::string&& s)
- {kind = string_t::basic; str = std::move(s); return *this;}
-
- operator std::string& () & noexcept {return str;}
- operator std::string const& () const& noexcept {return str;}
- operator std::string&& () && noexcept {return std::move(str);}
-
- string& operator+=(const char* rhs) {str += rhs; return *this;}
- string& operator+=(const char rhs) {str += rhs; return *this;}
- string& operator+=(const std::string& rhs) {str += rhs; return *this;}
- string& operator+=(const string& rhs) {str += rhs.str; return *this;}
-
-#if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0
- explicit string(std::string_view s): kind(string_t::basic), str(s){}
- string(std::string_view s, string_t k): kind(k), str(s){}
-
- string& operator=(std::string_view s)
- {kind = string_t::basic; str = s; return *this;}
-
- explicit operator std::string_view() const noexcept
- {return std::string_view(str);}
-
- string& operator+=(const std::string_view& rhs) {str += rhs; return *this;}
-#endif
-
- string_t kind;
- std::string str;
-};
-
-inline bool operator==(const string& lhs, const string& rhs)
-{
- return lhs.kind == rhs.kind && lhs.str == rhs.str;
-}
-inline bool operator!=(const string& lhs, const string& rhs)
-{
- return !(lhs == rhs);
-}
-inline bool operator<(const string& lhs, const string& rhs)
-{
- return (lhs.kind == rhs.kind) ? (lhs.str < rhs.str) : (lhs.kind < rhs.kind);
-}
-inline bool operator>(const string& lhs, const string& rhs)
-{
- return rhs < lhs;
-}
-inline bool operator<=(const string& lhs, const string& rhs)
-{
- return !(rhs < lhs);
-}
-inline bool operator>=(const string& lhs, const string& rhs)
-{
- return !(lhs < rhs);
-}
-
-inline bool
-operator==(const string& lhs, const std::string& rhs) {return lhs.str == rhs;}
-inline bool
-operator!=(const string& lhs, const std::string& rhs) {return lhs.str != rhs;}
-inline bool
-operator< (const string& lhs, const std::string& rhs) {return lhs.str < rhs;}
-inline bool
-operator> (const string& lhs, const std::string& rhs) {return lhs.str > rhs;}
-inline bool
-operator<=(const string& lhs, const std::string& rhs) {return lhs.str <= rhs;}
-inline bool
-operator>=(const string& lhs, const std::string& rhs) {return lhs.str >= rhs;}
-
-inline bool
-operator==(const std::string& lhs, const string& rhs) {return lhs == rhs.str;}
-inline bool
-operator!=(const std::string& lhs, const string& rhs) {return lhs != rhs.str;}
-inline bool
-operator< (const std::string& lhs, const string& rhs) {return lhs < rhs.str;}
-inline bool
-operator> (const std::string& lhs, const string& rhs) {return lhs > rhs.str;}
-inline bool
-operator<=(const std::string& lhs, const string& rhs) {return lhs <= rhs.str;}
-inline bool
-operator>=(const std::string& lhs, const string& rhs) {return lhs >= rhs.str;}
-
-inline bool
-operator==(const string& lhs, const char* rhs) {return lhs.str == std::string(rhs);}
-inline bool
-operator!=(const string& lhs, const char* rhs) {return lhs.str != std::string(rhs);}
-inline bool
-operator< (const string& lhs, const char* rhs) {return lhs.str < std::string(rhs);}
-inline bool
-operator> (const string& lhs, const char* rhs) {return lhs.str > std::string(rhs);}
-inline bool
-operator<=(const string& lhs, const char* rhs) {return lhs.str <= std::string(rhs);}
-inline bool
-operator>=(const string& lhs, const char* rhs) {return lhs.str >= std::string(rhs);}
-
-inline bool
-operator==(const char* lhs, const string& rhs) {return std::string(lhs) == rhs.str;}
-inline bool
-operator!=(const char* lhs, const string& rhs) {return std::string(lhs) != rhs.str;}
-inline bool
-operator< (const char* lhs, const string& rhs) {return std::string(lhs) < rhs.str;}
-inline bool
-operator> (const char* lhs, const string& rhs) {return std::string(lhs) > rhs.str;}
-inline bool
-operator<=(const char* lhs, const string& rhs) {return std::string(lhs) <= rhs.str;}
-inline bool
-operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.str;}
-
-template<typename charT, typename traits>
-std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, const string& s)
-{
- if(s.kind == string_t::basic)
- {
- if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
- {
- // it contains newline. make it multiline string.
- os << "\"\"\"\n";
- for(auto i=s.str.cbegin(), e=s.str.cend(); i!=e; ++i)
- {
- switch(*i)
- {
- case '\\': {os << "\\\\"; break;}
- case '\"': {os << "\\\""; break;}
- case '\b': {os << "\\b"; break;}
- case '\t': {os << "\\t"; break;}
- case '\f': {os << "\\f"; break;}
- case '\n': {os << '\n'; break;}
- case '\r':
- {
- // since it is a multiline string,
- // CRLF is not needed to be escaped.
- if(std::next(i) != e && *std::next(i) == '\n')
- {
- os << "\r\n";
- ++i;
- }
- else
- {
- os << "\\r";
- }
- break;
- }
- default: {os << *i; break;}
- }
- }
- os << "\\\n\"\"\"";
- return os;
- }
- // no newline. make it inline.
- os << "\"";
- for(const auto c : s.str)
- {
- switch(c)
- {
- case '\\': {os << "\\\\"; break;}
- case '\"': {os << "\\\""; break;}
- case '\b': {os << "\\b"; break;}
- case '\t': {os << "\\t"; break;}
- case '\f': {os << "\\f"; break;}
- case '\n': {os << "\\n"; break;}
- case '\r': {os << "\\r"; break;}
- default : {os << c; break;}
- }
- }
- os << "\"";
- return os;
- }
- // the string `s` is literal-string.
- if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
- std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
- {
- // contains newline or single quote. make it multiline.
- os << "'''\n" << s.str << "'''";
- return os;
- }
- // normal literal string
- os << '\'' << s.str << '\'';
- return os;
-}
-
-} // toml
-#endif// TOML11_STRING_H
diff --git a/src/toml11/toml/traits.hpp b/src/toml11/toml/traits.hpp
deleted file mode 100644
index 5495c93b2..000000000
--- a/src/toml11/toml/traits.hpp
+++ /dev/null
@@ -1,327 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_TRAITS_HPP
-#define TOML11_TRAITS_HPP
-
-#include "from.hpp"
-#include "into.hpp"
-
-#include <chrono>
-#include <forward_list>
-#include <string>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-
-#if __cplusplus >= 201703L
-#if __has_include(<string_view>)
-#include <string_view>
-#endif // has_include(<string_view>)
-#endif // cplusplus >= C++17
-
-namespace toml
-{
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-class basic_value;
-
-namespace detail
-{
-// ---------------------------------------------------------------------------
-// check whether type T is a kind of container/map class
-
-struct has_iterator_impl
-{
- template<typename T> static std::true_type check(typename T::iterator*);
- template<typename T> static std::false_type check(...);
-};
-struct has_value_type_impl
-{
- template<typename T> static std::true_type check(typename T::value_type*);
- template<typename T> static std::false_type check(...);
-};
-struct has_key_type_impl
-{
- template<typename T> static std::true_type check(typename T::key_type*);
- template<typename T> static std::false_type check(...);
-};
-struct has_mapped_type_impl
-{
- template<typename T> static std::true_type check(typename T::mapped_type*);
- template<typename T> static std::false_type check(...);
-};
-struct has_reserve_method_impl
-{
- template<typename T> static std::false_type check(...);
- template<typename T> static std::true_type check(
- decltype(std::declval<T>().reserve(std::declval<std::size_t>()))*);
-};
-struct has_push_back_method_impl
-{
- template<typename T> static std::false_type check(...);
- template<typename T> static std::true_type check(
- decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()))*);
-};
-struct is_comparable_impl
-{
- template<typename T> static std::false_type check(...);
- template<typename T> static std::true_type check(
- decltype(std::declval<T>() < std::declval<T>())*);
-};
-
-struct has_from_toml_method_impl
-{
- template<typename T, typename C,
- template<typename ...> class Tb, template<typename ...> class A>
- static std::true_type check(
- decltype(std::declval<T>().from_toml(
- std::declval<::toml::basic_value<C, Tb, A>>()))*);
-
- template<typename T, typename C,
- template<typename ...> class Tb, template<typename ...> class A>
- static std::false_type check(...);
-};
-struct has_into_toml_method_impl
-{
- template<typename T>
- static std::true_type check(decltype(std::declval<T>().into_toml())*);
- template<typename T>
- static std::false_type check(...);
-};
-
-struct has_specialized_from_impl
-{
- template<typename T>
- static std::false_type check(...);
- template<typename T, std::size_t S = sizeof(::toml::from<T>)>
- static std::true_type check(::toml::from<T>*);
-};
-struct has_specialized_into_impl
-{
- template<typename T>
- static std::false_type check(...);
- template<typename T, std::size_t S = sizeof(::toml::into<T>)>
- static std::true_type check(::toml::from<T>*);
-};
-
-
-/// Intel C++ compiler can not use decltype in parent class declaration, here
-/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076
-#ifdef __INTEL_COMPILER
-#define decltype(...) std::enable_if<true, decltype(__VA_ARGS__)>::type
-#endif
-
-template<typename T>
-struct has_iterator : decltype(has_iterator_impl::check<T>(nullptr)){};
-template<typename T>
-struct has_value_type : decltype(has_value_type_impl::check<T>(nullptr)){};
-template<typename T>
-struct has_key_type : decltype(has_key_type_impl::check<T>(nullptr)){};
-template<typename T>
-struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
-template<typename T>
-struct has_reserve_method : decltype(has_reserve_method_impl::check<T>(nullptr)){};
-template<typename T>
-struct has_push_back_method : decltype(has_push_back_method_impl::check<T>(nullptr)){};
-template<typename T>
-struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){};
-
-template<typename T, typename C,
- template<typename ...> class Tb, template<typename ...> class A>
-struct has_from_toml_method
-: decltype(has_from_toml_method_impl::check<T, C, Tb, A>(nullptr)){};
-
-template<typename T>
-struct has_into_toml_method
-: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
-
-template<typename T>
-struct has_specialized_from : decltype(has_specialized_from_impl::check<T>(nullptr)){};
-template<typename T>
-struct has_specialized_into : decltype(has_specialized_into_impl::check<T>(nullptr)){};
-
-#ifdef __INTEL_COMPILER
-#undef decltype
-#endif
-
-// ---------------------------------------------------------------------------
-// C++17 and/or/not
-
-#if __cplusplus >= 201703L
-
-using std::conjunction;
-using std::disjunction;
-using std::negation;
-
-#else
-
-template<typename ...> struct conjunction : std::true_type{};
-template<typename T> struct conjunction<T> : T{};
-template<typename T, typename ... Ts>
-struct conjunction<T, Ts...> :
- std::conditional<static_cast<bool>(T::value), conjunction<Ts...>, T>::type
-{};
-
-template<typename ...> struct disjunction : std::false_type{};
-template<typename T> struct disjunction<T> : T {};
-template<typename T, typename ... Ts>
-struct disjunction<T, Ts...> :
- std::conditional<static_cast<bool>(T::value), T, disjunction<Ts...>>::type
-{};
-
-template<typename T>
-struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
-
-#endif
-
-// ---------------------------------------------------------------------------
-// type checkers
-
-template<typename T> struct is_std_pair : std::false_type{};
-template<typename T1, typename T2>
-struct is_std_pair<std::pair<T1, T2>> : std::true_type{};
-
-template<typename T> struct is_std_tuple : std::false_type{};
-template<typename ... Ts>
-struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};
-
-template<typename T> struct is_std_forward_list : std::false_type{};
-template<typename T>
-struct is_std_forward_list<std::forward_list<T>> : std::true_type{};
-
-template<typename T> struct is_chrono_duration: std::false_type{};
-template<typename Rep, typename Period>
-struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
-
-template<typename T>
-struct is_map : conjunction< // map satisfies all the following conditions
- has_iterator<T>, // has T::iterator
- has_value_type<T>, // has T::value_type
- has_key_type<T>, // has T::key_type
- has_mapped_type<T> // has T::mapped_type
- >{};
-template<typename T> struct is_map<T&> : is_map<T>{};
-template<typename T> struct is_map<T const&> : is_map<T>{};
-template<typename T> struct is_map<T volatile&> : is_map<T>{};
-template<typename T> struct is_map<T const volatile&> : is_map<T>{};
-
-template<typename T>
-struct is_container : conjunction<
- negation<is_map<T>>, // not a map
- negation<std::is_same<T, std::string>>, // not a std::string
-#if __cplusplus >= 201703L
-#if __has_include(<string_view>)
- negation<std::is_same<T, std::string_view>>, // not a std::string_view
-#endif // has_include(<string_view>)
-#endif
- has_iterator<T>, // has T::iterator
- has_value_type<T> // has T::value_type
- >{};
-template<typename T> struct is_container<T&> : is_container<T>{};
-template<typename T> struct is_container<T const&> : is_container<T>{};
-template<typename T> struct is_container<T volatile&> : is_container<T>{};
-template<typename T> struct is_container<T const volatile&> : is_container<T>{};
-
-template<typename T>
-struct is_basic_value: std::false_type{};
-template<typename T> struct is_basic_value<T&> : is_basic_value<T>{};
-template<typename T> struct is_basic_value<T const&> : is_basic_value<T>{};
-template<typename T> struct is_basic_value<T volatile&> : is_basic_value<T>{};
-template<typename T> struct is_basic_value<T const volatile&> : is_basic_value<T>{};
-template<typename C, template<typename ...> class M, template<typename ...> class V>
-struct is_basic_value<::toml::basic_value<C, M, V>>: std::true_type{};
-
-// ---------------------------------------------------------------------------
-// C++14 index_sequence
-
-#if __cplusplus >= 201402L
-
-using std::index_sequence;
-using std::make_index_sequence;
-
-#else
-
-template<std::size_t ... Ns> struct index_sequence{};
-
-template<typename IS, std::size_t N> struct push_back_index_sequence{};
-template<std::size_t N, std::size_t ... Ns>
-struct push_back_index_sequence<index_sequence<Ns...>, N>
-{
- typedef index_sequence<Ns..., N> type;
-};
-
-template<std::size_t N>
-struct index_sequence_maker
-{
- typedef typename push_back_index_sequence<
- typename index_sequence_maker<N-1>::type, N>::type type;
-};
-template<>
-struct index_sequence_maker<0>
-{
- typedef index_sequence<0> type;
-};
-template<std::size_t N>
-using make_index_sequence = typename index_sequence_maker<N-1>::type;
-
-#endif // __cplusplus >= 2014
-
-// ---------------------------------------------------------------------------
-// C++14 enable_if_t
-
-#if __cplusplus >= 201402L
-
-using std::enable_if_t;
-
-#else
-
-template<bool B, typename T>
-using enable_if_t = typename std::enable_if<B, T>::type;
-
-#endif // __cplusplus >= 2014
-
-// ---------------------------------------------------------------------------
-// return_type_of_t
-
-#if __cplusplus >= 201703L && defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable>=201703
-
-template<typename F, typename ... Args>
-using return_type_of_t = std::invoke_result_t<F, Args...>;
-
-#else
-// result_of is deprecated after C++17
-template<typename F, typename ... Args>
-using return_type_of_t = typename std::result_of<F(Args...)>::type;
-
-#endif
-
-// ---------------------------------------------------------------------------
-// is_string_literal
-//
-// to use this, pass `typename remove_reference<T>::type` to T.
-
-template<typename T>
-struct is_string_literal:
-disjunction<
- std::is_same<const char*, T>,
- conjunction<
- std::is_array<T>,
- std::is_same<const char, typename std::remove_extent<T>::type>
- >
- >{};
-
-// ---------------------------------------------------------------------------
-// C++20 remove_cvref_t
-
-template<typename T>
-struct remove_cvref
-{
- using type = typename std::remove_cv<
- typename std::remove_reference<T>::type>::type;
-};
-
-template<typename T>
-using remove_cvref_t = typename remove_cvref<T>::type;
-
-}// detail
-}//toml
-#endif // TOML_TRAITS
diff --git a/src/toml11/toml/types.hpp b/src/toml11/toml/types.hpp
deleted file mode 100644
index 1e420e7fd..000000000
--- a/src/toml11/toml/types.hpp
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_TYPES_HPP
-#define TOML11_TYPES_HPP
-#include <unordered_map>
-#include <vector>
-
-#include "comments.hpp"
-#include "datetime.hpp"
-#include "string.hpp"
-#include "traits.hpp"
-
-namespace toml
-{
-
-template<typename Comment, // discard/preserve_comment
- template<typename ...> class Table, // map-like class
- template<typename ...> class Array> // vector-like class
-class basic_value;
-
-using character = char;
-using key = std::string;
-
-#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ <= 4
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wshadow"
-#endif
-
-using boolean = bool;
-using integer = std::int64_t;
-using floating = double; // "float" is a keyword, cannot use it here.
-// the following stuffs are structs defined here, so aliases are not needed.
-// - string
-// - offset_datetime
-// - offset_datetime
-// - local_datetime
-// - local_date
-// - local_time
-
-#if defined(__GNUC__) && !defined(__clang__)
-# pragma GCC diagnostic pop
-#endif
-
-// default toml::value and default array/table. these are defined after defining
-// basic_value itself.
-// using value = basic_value<discard_comments, std::unordered_map, std::vector>;
-// using array = typename value::array_type;
-// using table = typename value::table_type;
-
-// to avoid warnings about `value_t::integer` is "shadowing" toml::integer in
-// GCC -Wshadow=global.
-#if defined(__GNUC__) && !defined(__clang__)
-# pragma GCC diagnostic push
-# if 7 <= __GNUC__
-# pragma GCC diagnostic ignored "-Wshadow=global"
-# else // gcc-6 or older
-# pragma GCC diagnostic ignored "-Wshadow"
-# endif
-#endif
-enum class value_t : std::uint8_t
-{
- empty = 0,
- boolean = 1,
- integer = 2,
- floating = 3,
- string = 4,
- offset_datetime = 5,
- local_datetime = 6,
- local_date = 7,
- local_time = 8,
- array = 9,
- table = 10,
-};
-#if defined(__GNUC__) && !defined(__clang__)
-# pragma GCC diagnostic pop
-#endif
-
-template<typename charT, typename traits>
-inline std::basic_ostream<charT, traits>&
-operator<<(std::basic_ostream<charT, traits>& os, value_t t)
-{
- switch(t)
- {
- case value_t::boolean : os << "boolean"; return os;
- case value_t::integer : os << "integer"; return os;
- case value_t::floating : os << "floating"; return os;
- case value_t::string : os << "string"; return os;
- case value_t::offset_datetime : os << "offset_datetime"; return os;
- case value_t::local_datetime : os << "local_datetime"; return os;
- case value_t::local_date : os << "local_date"; return os;
- case value_t::local_time : os << "local_time"; return os;
- case value_t::array : os << "array"; return os;
- case value_t::table : os << "table"; return os;
- case value_t::empty : os << "empty"; return os;
- default : os << "unknown"; return os;
- }
-}
-
-template<typename charT = char,
- typename traits = std::char_traits<charT>,
- typename alloc = std::allocator<charT>>
-inline std::basic_string<charT, traits, alloc> stringize(value_t t)
-{
- std::basic_ostringstream<charT, traits, alloc> oss;
- oss << t;
- return oss.str();
-}
-
-namespace detail
-{
-
-// helper to define a type that represents a value_t value.
-template<value_t V>
-using value_t_constant = std::integral_constant<value_t, V>;
-
-// meta-function that convertes from value_t to the exact toml type that corresponds to.
-// It takes toml::basic_value type because array and table types depend on it.
-template<value_t t, typename Value> struct enum_to_type {using type = void ;};
-template<typename Value> struct enum_to_type<value_t::empty , Value>{using type = void ;};
-template<typename Value> struct enum_to_type<value_t::boolean , Value>{using type = boolean ;};
-template<typename Value> struct enum_to_type<value_t::integer , Value>{using type = integer ;};
-template<typename Value> struct enum_to_type<value_t::floating , Value>{using type = floating ;};
-template<typename Value> struct enum_to_type<value_t::string , Value>{using type = string ;};
-template<typename Value> struct enum_to_type<value_t::offset_datetime, Value>{using type = offset_datetime ;};
-template<typename Value> struct enum_to_type<value_t::local_datetime , Value>{using type = local_datetime ;};
-template<typename Value> struct enum_to_type<value_t::local_date , Value>{using type = local_date ;};
-template<typename Value> struct enum_to_type<value_t::local_time , Value>{using type = local_time ;};
-template<typename Value> struct enum_to_type<value_t::array , Value>{using type = typename Value::array_type;};
-template<typename Value> struct enum_to_type<value_t::table , Value>{using type = typename Value::table_type;};
-
-// meta-function that converts from an exact toml type to the enum that corresponds to.
-template<typename T, typename Value>
-struct type_to_enum : std::conditional<
- std::is_same<T, typename Value::array_type>::value, // if T == array_type,
- value_t_constant<value_t::array>, // then value_t::array
- typename std::conditional< // else...
- std::is_same<T, typename Value::table_type>::value, // if T == table_type
- value_t_constant<value_t::table>, // then value_t::table
- value_t_constant<value_t::empty> // else value_t::empty
- >::type
- >::type {};
-template<typename Value> struct type_to_enum<boolean , Value>: value_t_constant<value_t::boolean > {};
-template<typename Value> struct type_to_enum<integer , Value>: value_t_constant<value_t::integer > {};
-template<typename Value> struct type_to_enum<floating , Value>: value_t_constant<value_t::floating > {};
-template<typename Value> struct type_to_enum<string , Value>: value_t_constant<value_t::string > {};
-template<typename Value> struct type_to_enum<offset_datetime, Value>: value_t_constant<value_t::offset_datetime> {};
-template<typename Value> struct type_to_enum<local_datetime , Value>: value_t_constant<value_t::local_datetime > {};
-template<typename Value> struct type_to_enum<local_date , Value>: value_t_constant<value_t::local_date > {};
-template<typename Value> struct type_to_enum<local_time , Value>: value_t_constant<value_t::local_time > {};
-
-// meta-function that checks the type T is the same as one of the toml::* types.
-template<typename T, typename Value>
-struct is_exact_toml_type : disjunction<
- std::is_same<T, boolean >,
- std::is_same<T, integer >,
- std::is_same<T, floating >,
- std::is_same<T, string >,
- std::is_same<T, offset_datetime>,
- std::is_same<T, local_datetime >,
- std::is_same<T, local_date >,
- std::is_same<T, local_time >,
- std::is_same<T, typename Value::array_type>,
- std::is_same<T, typename Value::table_type>
- >{};
-template<typename T, typename V> struct is_exact_toml_type<T&, V> : is_exact_toml_type<T, V>{};
-template<typename T, typename V> struct is_exact_toml_type<T const&, V> : is_exact_toml_type<T, V>{};
-template<typename T, typename V> struct is_exact_toml_type<T volatile&, V> : is_exact_toml_type<T, V>{};
-template<typename T, typename V> struct is_exact_toml_type<T const volatile&, V>: is_exact_toml_type<T, V>{};
-
-} // detail
-} // toml
-
-#endif// TOML11_TYPES_H
diff --git a/src/toml11/toml/utility.hpp b/src/toml11/toml/utility.hpp
deleted file mode 100644
index 4a6b4309d..000000000
--- a/src/toml11/toml/utility.hpp
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_UTILITY_HPP
-#define TOML11_UTILITY_HPP
-#include <memory>
-#include <sstream>
-#include <utility>
-
-#include "traits.hpp"
-
-#if __cplusplus >= 201402L
-# define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]]
-#elif defined(__GNUC__)
-# define TOML11_MARK_AS_DEPRECATED(msg) __attribute__((deprecated(msg)))
-#elif defined(_MSC_VER)
-# define TOML11_MARK_AS_DEPRECATED(msg) __declspec(deprecated(msg))
-#else
-# define TOML11_MARK_AS_DEPRECATED
-#endif
-
-namespace toml
-{
-
-#if __cplusplus >= 201402L
-
-using std::make_unique;
-
-#else
-
-template<typename T, typename ... Ts>
-inline std::unique_ptr<T> make_unique(Ts&& ... args)
-{
- return std::unique_ptr<T>(new T(std::forward<Ts>(args)...));
-}
-
-#endif // __cplusplus >= 2014
-
-namespace detail
-{
-template<typename Container>
-void try_reserve_impl(Container& container, std::size_t N, std::true_type)
-{
- container.reserve(N);
- return;
-}
-template<typename Container>
-void try_reserve_impl(Container&, std::size_t, std::false_type) noexcept
-{
- return;
-}
-} // detail
-
-template<typename Container>
-void try_reserve(Container& container, std::size_t N)
-{
- if(N <= container.size()) {return;}
- detail::try_reserve_impl(container, N, detail::has_reserve_method<Container>{});
- return;
-}
-
-namespace detail
-{
-inline std::string concat_to_string_impl(std::ostringstream& oss)
-{
- return oss.str();
-}
-template<typename T, typename ... Ts>
-std::string concat_to_string_impl(std::ostringstream& oss, T&& head, Ts&& ... tail)
-{
- oss << std::forward<T>(head);
- return concat_to_string_impl(oss, std::forward<Ts>(tail) ... );
-}
-} // detail
-
-template<typename ... Ts>
-std::string concat_to_string(Ts&& ... args)
-{
- std::ostringstream oss;
- oss << std::boolalpha << std::fixed;
- return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...);
-}
-
-template<typename T>
-T from_string(const std::string& str, T opt)
-{
- T v(opt);
- std::istringstream iss(str);
- iss >> v;
- return v;
-}
-
-namespace detail
-{
-#if __cplusplus >= 201402L
-template<typename T>
-decltype(auto) last_one(T&& tail) noexcept
-{
- return std::forward<T>(tail);
-}
-
-template<typename T, typename ... Ts>
-decltype(auto) last_one(T&& /*head*/, Ts&& ... tail) noexcept
-{
- return last_one(std::forward<Ts>(tail)...);
-}
-#else // C++11
-// The following code
-// ```cpp
-// 1 | template<typename T, typename ... Ts>
-// 2 | auto last_one(T&& /*head*/, Ts&& ... tail)
-// 3 | -> decltype(last_one(std::forward<Ts>(tail)...))
-// 4 | {
-// 5 | return last_one(std::forward<Ts>(tail)...);
-// 6 | }
-// ```
-// does not work because the function `last_one(...)` is not yet defined at
-// line #3, so `decltype()` cannot deduce the type returned from `last_one`.
-// So we need to determine return type in a different way, like a meta func.
-
-template<typename T, typename ... Ts>
-struct last_one_in_pack
-{
- using type = typename last_one_in_pack<Ts...>::type;
-};
-template<typename T>
-struct last_one_in_pack<T>
-{
- using type = T;
-};
-template<typename ... Ts>
-using last_one_in_pack_t = typename last_one_in_pack<Ts...>::type;
-
-template<typename T>
-T&& last_one(T&& tail) noexcept
-{
- return std::forward<T>(tail);
-}
-template<typename T, typename ... Ts>
-enable_if_t<(sizeof...(Ts) > 0), last_one_in_pack_t<Ts&& ...>>
-last_one(T&& /*head*/, Ts&& ... tail)
-{
- return last_one(std::forward<Ts>(tail)...);
-}
-
-#endif
-} // detail
-
-}// toml
-#endif // TOML11_UTILITY
diff --git a/src/toml11/toml/value.hpp b/src/toml11/toml/value.hpp
deleted file mode 100644
index 1b43db8d4..000000000
--- a/src/toml11/toml/value.hpp
+++ /dev/null
@@ -1,2035 +0,0 @@
-// Copyright Toru Niina 2017.
-// Distributed under the MIT License.
-#ifndef TOML11_VALUE_HPP
-#define TOML11_VALUE_HPP
-#include <cassert>
-
-#include "comments.hpp"
-#include "exception.hpp"
-#include "into.hpp"
-#include "region.hpp"
-#include "source_location.hpp"
-#include "storage.hpp"
-#include "traits.hpp"
-#include "types.hpp"
-#include "utility.hpp"
-
-namespace toml
-{
-
-namespace detail
-{
-
-// to show error messages. not recommended for users.
-template<typename Value>
-inline region_base const* get_region(const Value& v)
-{
- return v.region_info_.get();
-}
-
-template<typename Value>
-void change_region(Value& v, region reg)
-{
- v.region_info_ = std::make_shared<region>(std::move(reg));
- return;
-}
-
-template<value_t Expected, typename Value>
-[[noreturn]] inline void
-throw_bad_cast(const std::string& funcname, value_t actual, const Value& v)
-{
- throw type_error(detail::format_underline(
- concat_to_string(funcname, "bad_cast to ", Expected), {
- {v.location(), concat_to_string("the actual type is ", actual)}
- }), v.location());
-}
-
-// Throw `out_of_range` from `toml::value::at()` and `toml::find()`
-// after generating an error message.
-//
-// The implementation is a bit complicated and there are many edge-cases.
-// If you are not interested in the error message generation, just skip this.
-template<typename Value>
-[[noreturn]] void
-throw_key_not_found_error(const Value& v, const key& ky)
-{
- // The top-level table has its region at the first character of the file.
- // That means that, in the case when a key is not found in the top-level
- // table, the error message points to the first character. If the file has
- // its first table at the first line, the error message would be like this.
- // ```console
- // [error] key "a" not found
- // --> example.toml
- // |
- // 1 | [table]
- // | ^------ in this table
- // ```
- // It actually points to the top-level table at the first character,
- // not `[table]`. But it is too confusing. To avoid the confusion, the error
- // message should explicitly say "key not found in the top-level table",
- // or "the parsed file is empty" if there is no content at all (0 bytes in file).
- const auto loc = v.location();
- if(loc.line() == 1 && loc.region() == 0)
- {
- // First line with a zero-length region means "empty file".
- // The region will be generated at `parse_toml_file` function
- // if the file contains no bytes.
- throw std::out_of_range(format_underline(concat_to_string(
- "key \"", ky, "\" not found in the top-level table"), {
- {loc, "the parsed file is empty"}
- }));
- }
- else if(loc.line() == 1 && loc.region() == 1)
- {
- // Here it assumes that top-level table starts at the first character.
- // The region corresponds to the top-level table will be generated at
- // `parse_toml_file` function.
- // It also assumes that the top-level table size is just one and
- // the line number is `1`. It is always satisfied. And those conditions
- // are satisfied only if the table is the top-level table.
- //
- // 1. one-character dot-key at the first line
- // ```toml
- // a.b = "c"
- // ```
- // toml11 counts whole key as the table key. Here, `a.b` is the region
- // of the table "a". It could be counter intuitive, but it works.
- // The size of the region is 3, not 1. The above example is the shortest
- // dot-key example. The size cannot be 1.
- //
- // 2. one-character inline-table at the first line
- // ```toml
- // a = {b = "c"}
- // ```
- // toml11 considers the inline table body as the table region. Here,
- // `{b = "c"}` is the region of the table "a". The size of the region
- // is 9, not 1. The shotest inline table still has two characters, `{`
- // and `}`. The size cannot be 1.
- //
- // 3. one-character table declaration at the first line
- // ```toml
- // [a]
- // ```
- // toml11 considers the whole table key as the table region. Here,
- // `[a]` is the table region. The size is 3, not 1.
- //
- throw std::out_of_range(format_underline(concat_to_string(
- "key \"", ky, "\" not found in the top-level table"), {
- {loc, "the top-level table starts here"}
- }));
- }
- else
- {
- // normal table.
- throw std::out_of_range(format_underline(concat_to_string(
- "key \"", ky, "\" not found"), { {loc, "in this table"} }));
- }
-}
-
-// switch by `value_t` at the compile time.
-template<value_t T>
-struct switch_cast {};
-#define TOML11_GENERATE_SWITCH_CASTER(TYPE) \
- template<> \
- struct switch_cast<value_t::TYPE> \
- { \
- template<typename Value> \
- static typename Value::TYPE##_type& invoke(Value& v) \
- { \
- return v.as_##TYPE(); \
- } \
- template<typename Value> \
- static typename Value::TYPE##_type const& invoke(const Value& v) \
- { \
- return v.as_##TYPE(); \
- } \
- template<typename Value> \
- static typename Value::TYPE##_type&& invoke(Value&& v) \
- { \
- return std::move(v).as_##TYPE(); \
- } \
- }; \
- /**/
-TOML11_GENERATE_SWITCH_CASTER(boolean)
-TOML11_GENERATE_SWITCH_CASTER(integer)
-TOML11_GENERATE_SWITCH_CASTER(floating)
-TOML11_GENERATE_SWITCH_CASTER(string)
-TOML11_GENERATE_SWITCH_CASTER(offset_datetime)
-TOML11_GENERATE_SWITCH_CASTER(local_datetime)
-TOML11_GENERATE_SWITCH_CASTER(local_date)
-TOML11_GENERATE_SWITCH_CASTER(local_time)
-TOML11_GENERATE_SWITCH_CASTER(array)
-TOML11_GENERATE_SWITCH_CASTER(table)
-
-#undef TOML11_GENERATE_SWITCH_CASTER
-
-}// detail
-
-template<typename Comment, // discard/preserve_comment
- template<typename ...> class Table = std::unordered_map,
- template<typename ...> class Array = std::vector>
-class basic_value
-{
- template<typename T, typename U>
- static void assigner(T& dst, U&& v)
- {
- const auto tmp = ::new(std::addressof(dst)) T(std::forward<U>(v));
- assert(tmp == std::addressof(dst));
- (void)tmp;
- }
-
- using region_base = detail::region_base;
-
- template<typename C, template<typename ...> class T,
- template<typename ...> class A>
- friend class basic_value;
-
- public:
-
- using comment_type = Comment;
- using key_type = ::toml::key;
- using value_type = basic_value<comment_type, Table, Array>;
- using boolean_type = ::toml::boolean;
- using integer_type = ::toml::integer;
- using floating_type = ::toml::floating;
- using string_type = ::toml::string;
- using local_time_type = ::toml::local_time;
- using local_date_type = ::toml::local_date;
- using local_datetime_type = ::toml::local_datetime;
- using offset_datetime_type = ::toml::offset_datetime;
- using array_type = Array<value_type>;
- using table_type = Table<key_type, value_type>;
-
- public:
-
- basic_value() noexcept
- : type_(value_t::empty),
- region_info_(std::make_shared<region_base>(region_base{}))
- {}
- ~basic_value() noexcept {this->cleanup();}
-
- basic_value(const basic_value& v)
- : type_(v.type()), region_info_(v.region_info_), comments_(v.comments_)
- {
- switch(v.type())
- {
- case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
- case value_t::integer : assigner(integer_ , v.integer_ ); break;
- case value_t::floating : assigner(floating_ , v.floating_ ); break;
- case value_t::string : assigner(string_ , v.string_ ); break;
- case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
- case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
- case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
- case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
- case value_t::array : assigner(array_ , v.array_ ); break;
- case value_t::table : assigner(table_ , v.table_ ); break;
- default: break;
- }
- }
- basic_value(basic_value&& v)
- : type_(v.type()), region_info_(std::move(v.region_info_)),
- comments_(std::move(v.comments_))
- {
- switch(this->type_) // here this->type_ is already initialized
- {
- case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
- case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
- case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
- case value_t::string : assigner(string_ , std::move(v.string_ )); break;
- case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
- case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
- case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
- case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
- case value_t::array : assigner(array_ , std::move(v.array_ )); break;
- case value_t::table : assigner(table_ , std::move(v.table_ )); break;
- default: break;
- }
- }
- basic_value& operator=(const basic_value& v)
- {
- this->cleanup();
- this->region_info_ = v.region_info_;
- this->comments_ = v.comments_;
- this->type_ = v.type();
- switch(this->type_)
- {
- case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
- case value_t::integer : assigner(integer_ , v.integer_ ); break;
- case value_t::floating : assigner(floating_ , v.floating_ ); break;
- case value_t::string : assigner(string_ , v.string_ ); break;
- case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
- case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
- case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
- case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
- case value_t::array : assigner(array_ , v.array_ ); break;
- case value_t::table : assigner(table_ , v.table_ ); break;
- default: break;
- }
- return *this;
- }
- basic_value& operator=(basic_value&& v)
- {
- this->cleanup();
- this->region_info_ = std::move(v.region_info_);
- this->comments_ = std::move(v.comments_);
- this->type_ = v.type();
- switch(this->type_)
- {
- case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
- case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
- case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
- case value_t::string : assigner(string_ , std::move(v.string_ )); break;
- case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
- case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
- case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
- case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
- case value_t::array : assigner(array_ , std::move(v.array_ )); break;
- case value_t::table : assigner(table_ , std::move(v.table_ )); break;
- default: break;
- }
- return *this;
- }
-
- // overwrite comments ----------------------------------------------------
-
- basic_value(const basic_value& v, std::vector<std::string> com)
- : type_(v.type()), region_info_(v.region_info_),
- comments_(std::move(com))
- {
- switch(v.type())
- {
- case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
- case value_t::integer : assigner(integer_ , v.integer_ ); break;
- case value_t::floating : assigner(floating_ , v.floating_ ); break;
- case value_t::string : assigner(string_ , v.string_ ); break;
- case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
- case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
- case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
- case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
- case value_t::array : assigner(array_ , v.array_ ); break;
- case value_t::table : assigner(table_ , v.table_ ); break;
- default: break;
- }
- }
-
- basic_value(basic_value&& v, std::vector<std::string> com)
- : type_(v.type()), region_info_(std::move(v.region_info_)),
- comments_(std::move(com))
- {
- switch(this->type_) // here this->type_ is already initialized
- {
- case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
- case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
- case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
- case value_t::string : assigner(string_ , std::move(v.string_ )); break;
- case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
- case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
- case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
- case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
- case value_t::array : assigner(array_ , std::move(v.array_ )); break;
- case value_t::table : assigner(table_ , std::move(v.table_ )); break;
- default: break;
- }
- }
-
- // -----------------------------------------------------------------------
- // conversion between different basic_values.
- template<typename C,
- template<typename ...> class T,
- template<typename ...> class A>
- basic_value(const basic_value<C, T, A>& v)
- : type_(v.type()), region_info_(v.region_info_), comments_(v.comments())
- {
- switch(v.type())
- {
- case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
- case value_t::integer : assigner(integer_ , v.integer_ ); break;
- case value_t::floating : assigner(floating_ , v.floating_ ); break;
- case value_t::string : assigner(string_ , v.string_ ); break;
- case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
- case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
- case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
- case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
- case value_t::array :
- {
- array_type tmp(v.as_array(std::nothrow).begin(),
- v.as_array(std::nothrow).end());
- assigner(array_, std::move(tmp));
- break;
- }
- case value_t::table :
- {
- table_type tmp(v.as_table(std::nothrow).begin(),
- v.as_table(std::nothrow).end());
- assigner(table_, std::move(tmp));
- break;
- }
- default: break;
- }
- }
- template<typename C,
- template<typename ...> class T,
- template<typename ...> class A>
- basic_value(const basic_value<C, T, A>& v, std::vector<std::string> com)
- : type_(v.type()), region_info_(v.region_info_),
- comments_(std::move(com))
- {
- switch(v.type())
- {
- case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
- case value_t::integer : assigner(integer_ , v.integer_ ); break;
- case value_t::floating : assigner(floating_ , v.floating_ ); break;
- case value_t::string : assigner(string_ , v.string_ ); break;
- case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
- case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
- case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
- case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
- case value_t::array :
- {
- array_type tmp(v.as_array(std::nothrow).begin(),
- v.as_array(std::nothrow).end());
- assigner(array_, std::move(tmp));
- break;
- }
- case value_t::table :
- {
- table_type tmp(v.as_table(std::nothrow).begin(),
- v.as_table(std::nothrow).end());
- assigner(table_, std::move(tmp));
- break;
- }
- default: break;
- }
- }
- template<typename C,
- template<typename ...> class T,
- template<typename ...> class A>
- basic_value& operator=(const basic_value<C, T, A>& v)
- {
- this->region_info_ = v.region_info_;
- this->comments_ = comment_type(v.comments());
- this->type_ = v.type();
- switch(v.type())
- {
- case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
- case value_t::integer : assigner(integer_ , v.integer_ ); break;
- case value_t::floating : assigner(floating_ , v.floating_ ); break;
- case value_t::string : assigner(string_ , v.string_ ); break;
- case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
- case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
- case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
- case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
- case value_t::array :
- {
- array_type tmp(v.as_array(std::nothrow).begin(),
- v.as_array(std::nothrow).end());
- assigner(array_, std::move(tmp));
- break;
- }
- case value_t::table :
- {
- table_type tmp(v.as_table(std::nothrow).begin(),
- v.as_table(std::nothrow).end());
- assigner(table_, std::move(tmp));
- break;
- }
- default: break;
- }
- return *this;
- }
-
- // boolean ==============================================================
-
- basic_value(boolean b)
- : type_(value_t::boolean),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->boolean_, b);
- }
- basic_value& operator=(boolean b)
- {
- this->cleanup();
- this->type_ = value_t::boolean;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->boolean_, b);
- return *this;
- }
- basic_value(boolean b, std::vector<std::string> com)
- : type_(value_t::boolean),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->boolean_, b);
- }
-
- // integer ==============================================================
-
- template<typename T, typename std::enable_if<detail::conjunction<
- std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
- std::nullptr_t>::type = nullptr>
- basic_value(T i)
- : type_(value_t::integer),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->integer_, static_cast<integer>(i));
- }
-
- template<typename T, typename std::enable_if<detail::conjunction<
- std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
- std::nullptr_t>::type = nullptr>
- basic_value& operator=(T i)
- {
- this->cleanup();
- this->type_ = value_t::integer;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->integer_, static_cast<integer>(i));
- return *this;
- }
-
- template<typename T, typename std::enable_if<detail::conjunction<
- std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
- std::nullptr_t>::type = nullptr>
- basic_value(T i, std::vector<std::string> com)
- : type_(value_t::integer),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->integer_, static_cast<integer>(i));
- }
-
- // floating =============================================================
-
- template<typename T, typename std::enable_if<
- std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
- basic_value(T f)
- : type_(value_t::floating),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->floating_, static_cast<floating>(f));
- }
-
-
- template<typename T, typename std::enable_if<
- std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
- basic_value& operator=(T f)
- {
- this->cleanup();
- this->type_ = value_t::floating;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->floating_, static_cast<floating>(f));
- return *this;
- }
-
- template<typename T, typename std::enable_if<
- std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
- basic_value(T f, std::vector<std::string> com)
- : type_(value_t::floating),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->floating_, f);
- }
-
- // string ===============================================================
-
- basic_value(toml::string s)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->string_, std::move(s));
- }
- basic_value& operator=(toml::string s)
- {
- this->cleanup();
- this->type_ = value_t::string ;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->string_, s);
- return *this;
- }
- basic_value(toml::string s, std::vector<std::string> com)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->string_, std::move(s));
- }
-
- basic_value(std::string s)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->string_, toml::string(std::move(s)));
- }
- basic_value& operator=(std::string s)
- {
- this->cleanup();
- this->type_ = value_t::string ;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->string_, toml::string(std::move(s)));
- return *this;
- }
- basic_value(std::string s, string_t kind)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->string_, toml::string(std::move(s), kind));
- }
- basic_value(std::string s, std::vector<std::string> com)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->string_, toml::string(std::move(s)));
- }
- basic_value(std::string s, string_t kind, std::vector<std::string> com)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->string_, toml::string(std::move(s), kind));
- }
-
- basic_value(const char* s)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->string_, toml::string(std::string(s)));
- }
- basic_value& operator=(const char* s)
- {
- this->cleanup();
- this->type_ = value_t::string ;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->string_, toml::string(std::string(s)));
- return *this;
- }
- basic_value(const char* s, string_t kind)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->string_, toml::string(std::string(s), kind));
- }
- basic_value(const char* s, std::vector<std::string> com)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->string_, toml::string(std::string(s)));
- }
- basic_value(const char* s, string_t kind, std::vector<std::string> com)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->string_, toml::string(std::string(s), kind));
- }
-
-#if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0
- basic_value(std::string_view s)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->string_, toml::string(s));
- }
- basic_value& operator=(std::string_view s)
- {
- this->cleanup();
- this->type_ = value_t::string ;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->string_, toml::string(s));
- return *this;
- }
- basic_value(std::string_view s, std::vector<std::string> com)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->string_, toml::string(s));
- }
- basic_value(std::string_view s, string_t kind)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->string_, toml::string(s, kind));
- }
- basic_value(std::string_view s, string_t kind, std::vector<std::string> com)
- : type_(value_t::string),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->string_, toml::string(s, kind));
- }
-#endif
-
- // local date ===========================================================
-
- basic_value(const local_date& ld)
- : type_(value_t::local_date),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->local_date_, ld);
- }
- basic_value& operator=(const local_date& ld)
- {
- this->cleanup();
- this->type_ = value_t::local_date;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->local_date_, ld);
- return *this;
- }
- basic_value(const local_date& ld, std::vector<std::string> com)
- : type_(value_t::local_date),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->local_date_, ld);
- }
-
- // local time ===========================================================
-
- basic_value(const local_time& lt)
- : type_(value_t::local_time),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->local_time_, lt);
- }
- basic_value(const local_time& lt, std::vector<std::string> com)
- : type_(value_t::local_time),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->local_time_, lt);
- }
- basic_value& operator=(const local_time& lt)
- {
- this->cleanup();
- this->type_ = value_t::local_time;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->local_time_, lt);
- return *this;
- }
-
- template<typename Rep, typename Period>
- basic_value(const std::chrono::duration<Rep, Period>& dur)
- : type_(value_t::local_time),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->local_time_, local_time(dur));
- }
- template<typename Rep, typename Period>
- basic_value(const std::chrono::duration<Rep, Period>& dur,
- std::vector<std::string> com)
- : type_(value_t::local_time),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->local_time_, local_time(dur));
- }
- template<typename Rep, typename Period>
- basic_value& operator=(const std::chrono::duration<Rep, Period>& dur)
- {
- this->cleanup();
- this->type_ = value_t::local_time;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->local_time_, local_time(dur));
- return *this;
- }
-
- // local datetime =======================================================
-
- basic_value(const local_datetime& ldt)
- : type_(value_t::local_datetime),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->local_datetime_, ldt);
- }
- basic_value(const local_datetime& ldt, std::vector<std::string> com)
- : type_(value_t::local_datetime),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->local_datetime_, ldt);
- }
- basic_value& operator=(const local_datetime& ldt)
- {
- this->cleanup();
- this->type_ = value_t::local_datetime;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->local_datetime_, ldt);
- return *this;
- }
-
- // offset datetime ======================================================
-
- basic_value(const offset_datetime& odt)
- : type_(value_t::offset_datetime),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->offset_datetime_, odt);
- }
- basic_value(const offset_datetime& odt, std::vector<std::string> com)
- : type_(value_t::offset_datetime),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->offset_datetime_, odt);
- }
- basic_value& operator=(const offset_datetime& odt)
- {
- this->cleanup();
- this->type_ = value_t::offset_datetime;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->offset_datetime_, odt);
- return *this;
- }
- basic_value(const std::chrono::system_clock::time_point& tp)
- : type_(value_t::offset_datetime),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->offset_datetime_, offset_datetime(tp));
- }
- basic_value(const std::chrono::system_clock::time_point& tp,
- std::vector<std::string> com)
- : type_(value_t::offset_datetime),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->offset_datetime_, offset_datetime(tp));
- }
- basic_value& operator=(const std::chrono::system_clock::time_point& tp)
- {
- this->cleanup();
- this->type_ = value_t::offset_datetime;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->offset_datetime_, offset_datetime(tp));
- return *this;
- }
-
- // array ================================================================
-
- basic_value(const array_type& ary)
- : type_(value_t::array),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->array_, ary);
- }
- basic_value(const array_type& ary, std::vector<std::string> com)
- : type_(value_t::array),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->array_, ary);
- }
- basic_value& operator=(const array_type& ary)
- {
- this->cleanup();
- this->type_ = value_t::array ;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->array_, ary);
- return *this;
- }
-
- // array (initializer_list) ----------------------------------------------
-
- template<typename T, typename std::enable_if<
- std::is_convertible<T, value_type>::value,
- std::nullptr_t>::type = nullptr>
- basic_value(std::initializer_list<T> list)
- : type_(value_t::array),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- array_type ary(list.begin(), list.end());
- assigner(this->array_, std::move(ary));
- }
- template<typename T, typename std::enable_if<
- std::is_convertible<T, value_type>::value,
- std::nullptr_t>::type = nullptr>
- basic_value(std::initializer_list<T> list, std::vector<std::string> com)
- : type_(value_t::array),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- array_type ary(list.begin(), list.end());
- assigner(this->array_, std::move(ary));
- }
- template<typename T, typename std::enable_if<
- std::is_convertible<T, value_type>::value,
- std::nullptr_t>::type = nullptr>
- basic_value& operator=(std::initializer_list<T> list)
- {
- this->cleanup();
- this->type_ = value_t::array;
- this->region_info_ = std::make_shared<region_base>(region_base{});
-
- array_type ary(list.begin(), list.end());
- assigner(this->array_, std::move(ary));
- return *this;
- }
-
- // array (STL Containers) ------------------------------------------------
-
- template<typename T, typename std::enable_if<detail::conjunction<
- detail::negation<std::is_same<T, array_type>>,
- detail::is_container<T>
- >::value, std::nullptr_t>::type = nullptr>
- basic_value(const T& list)
- : type_(value_t::array),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- static_assert(std::is_convertible<typename T::value_type, value_type>::value,
- "elements of a container should be convertible to toml::value");
-
- array_type ary(list.size());
- std::copy(list.begin(), list.end(), ary.begin());
- assigner(this->array_, std::move(ary));
- }
- template<typename T, typename std::enable_if<detail::conjunction<
- detail::negation<std::is_same<T, array_type>>,
- detail::is_container<T>
- >::value, std::nullptr_t>::type = nullptr>
- basic_value(const T& list, std::vector<std::string> com)
- : type_(value_t::array),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- static_assert(std::is_convertible<typename T::value_type, value_type>::value,
- "elements of a container should be convertible to toml::value");
-
- array_type ary(list.size());
- std::copy(list.begin(), list.end(), ary.begin());
- assigner(this->array_, std::move(ary));
- }
- template<typename T, typename std::enable_if<detail::conjunction<
- detail::negation<std::is_same<T, array_type>>,
- detail::is_container<T>
- >::value, std::nullptr_t>::type = nullptr>
- basic_value& operator=(const T& list)
- {
- static_assert(std::is_convertible<typename T::value_type, value_type>::value,
- "elements of a container should be convertible to toml::value");
-
- this->cleanup();
- this->type_ = value_t::array;
- this->region_info_ = std::make_shared<region_base>(region_base{});
-
- array_type ary(list.size());
- std::copy(list.begin(), list.end(), ary.begin());
- assigner(this->array_, std::move(ary));
- return *this;
- }
-
- // table ================================================================
-
- basic_value(const table_type& tab)
- : type_(value_t::table),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- assigner(this->table_, tab);
- }
- basic_value(const table_type& tab, std::vector<std::string> com)
- : type_(value_t::table),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- assigner(this->table_, tab);
- }
- basic_value& operator=(const table_type& tab)
- {
- this->cleanup();
- this->type_ = value_t::table;
- this->region_info_ = std::make_shared<region_base>(region_base{});
- assigner(this->table_, tab);
- return *this;
- }
-
- // initializer-list ------------------------------------------------------
-
- basic_value(std::initializer_list<std::pair<key, basic_value>> list)
- : type_(value_t::table),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- table_type tab;
- for(const auto& elem : list) {tab[elem.first] = elem.second;}
- assigner(this->table_, std::move(tab));
- }
-
- basic_value(std::initializer_list<std::pair<key, basic_value>> list,
- std::vector<std::string> com)
- : type_(value_t::table),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- table_type tab;
- for(const auto& elem : list) {tab[elem.first] = elem.second;}
- assigner(this->table_, std::move(tab));
- }
- basic_value& operator=(std::initializer_list<std::pair<key, basic_value>> list)
- {
- this->cleanup();
- this->type_ = value_t::table;
- this->region_info_ = std::make_shared<region_base>(region_base{});
-
- table_type tab;
- for(const auto& elem : list) {tab[elem.first] = elem.second;}
- assigner(this->table_, std::move(tab));
- return *this;
- }
-
- // other table-like -----------------------------------------------------
-
- template<typename Map, typename std::enable_if<detail::conjunction<
- detail::negation<std::is_same<Map, table_type>>,
- detail::is_map<Map>
- >::value, std::nullptr_t>::type = nullptr>
- basic_value(const Map& mp)
- : type_(value_t::table),
- region_info_(std::make_shared<region_base>(region_base{}))
- {
- table_type tab;
- for(const auto& elem : mp) {tab[elem.first] = elem.second;}
- assigner(this->table_, std::move(tab));
- }
- template<typename Map, typename std::enable_if<detail::conjunction<
- detail::negation<std::is_same<Map, table_type>>,
- detail::is_map<Map>
- >::value, std::nullptr_t>::type = nullptr>
- basic_value(const Map& mp, std::vector<std::string> com)
- : type_(value_t::table),
- region_info_(std::make_shared<region_base>(region_base{})),
- comments_(std::move(com))
- {
- table_type tab;
- for(const auto& elem : mp) {tab[elem.first] = elem.second;}
- assigner(this->table_, std::move(tab));
- }
- template<typename Map, typename std::enable_if<detail::conjunction<
- detail::negation<std::is_same<Map, table_type>>,
- detail::is_map<Map>
- >::value, std::nullptr_t>::type = nullptr>
- basic_value& operator=(const Map& mp)
- {
- this->cleanup();
- this->type_ = value_t::table;
- this->region_info_ = std::make_shared<region_base>(region_base{});
-
- table_type tab;
- for(const auto& elem : mp) {tab[elem.first] = elem.second;}
- assigner(this->table_, std::move(tab));
- return *this;
- }
-
- // user-defined =========================================================
-
- // convert using into_toml() method -------------------------------------
-
- template<typename T, typename std::enable_if<
- detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
- basic_value(const T& ud): basic_value(ud.into_toml()) {}
-
- template<typename T, typename std::enable_if<
- detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
- basic_value(const T& ud, std::vector<std::string> com)
- : basic_value(ud.into_toml(), std::move(com))
- {}
- template<typename T, typename std::enable_if<
- detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
- basic_value& operator=(const T& ud)
- {
- *this = ud.into_toml();
- return *this;
- }
-
- // convert using into<T> struct -----------------------------------------
-
- template<typename T, std::size_t S = sizeof(::toml::into<T>)>
- basic_value(const T& ud): basic_value(::toml::into<T>::into_toml(ud)) {}
- template<typename T, std::size_t S = sizeof(::toml::into<T>)>
- basic_value(const T& ud, std::vector<std::string> com)
- : basic_value(::toml::into<T>::into_toml(ud), std::move(com))
- {}
- template<typename T, std::size_t S = sizeof(::toml::into<T>)>
- basic_value& operator=(const T& ud)
- {
- *this = ::toml::into<T>::into_toml(ud);
- return *this;
- }
-
- // for internal use ------------------------------------------------------
- //
- // Those constructors take detail::region that contains parse result.
-
- basic_value(boolean b, detail::region reg, std::vector<std::string> cm)
- : type_(value_t::boolean),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->boolean_, b);
- }
- template<typename T, typename std::enable_if<
- detail::conjunction<
- std::is_integral<T>, detail::negation<std::is_same<T, boolean>>
- >::value, std::nullptr_t>::type = nullptr>
- basic_value(T i, detail::region reg, std::vector<std::string> cm)
- : type_(value_t::integer),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->integer_, static_cast<integer>(i));
- }
- template<typename T, typename std::enable_if<
- std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
- basic_value(T f, detail::region reg, std::vector<std::string> cm)
- : type_(value_t::floating),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->floating_, static_cast<floating>(f));
- }
- basic_value(toml::string s, detail::region reg,
- std::vector<std::string> cm)
- : type_(value_t::string),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->string_, std::move(s));
- }
- basic_value(const local_date& ld, detail::region reg,
- std::vector<std::string> cm)
- : type_(value_t::local_date),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->local_date_, ld);
- }
- basic_value(const local_time& lt, detail::region reg,
- std::vector<std::string> cm)
- : type_(value_t::local_time),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->local_time_, lt);
- }
- basic_value(const local_datetime& ldt, detail::region reg,
- std::vector<std::string> cm)
- : type_(value_t::local_datetime),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->local_datetime_, ldt);
- }
- basic_value(const offset_datetime& odt, detail::region reg,
- std::vector<std::string> cm)
- : type_(value_t::offset_datetime),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->offset_datetime_, odt);
- }
- basic_value(const array_type& ary, detail::region reg,
- std::vector<std::string> cm)
- : type_(value_t::array),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->array_, ary);
- }
- basic_value(const table_type& tab, detail::region reg,
- std::vector<std::string> cm)
- : type_(value_t::table),
- region_info_(std::make_shared<detail::region>(std::move(reg))),
- comments_(std::move(cm))
- {
- assigner(this->table_, tab);
- }
-
- template<typename T, typename std::enable_if<
- detail::is_exact_toml_type<T, value_type>::value,
- std::nullptr_t>::type = nullptr>
- basic_value(std::pair<T, detail::region> parse_result, std::vector<std::string> com)
- : basic_value(std::move(parse_result.first),
- std::move(parse_result.second),
- std::move(com))
- {}
-
- // type checking and casting ============================================
-
- template<typename T, typename std::enable_if<
- detail::is_exact_toml_type<T, value_type>::value,
- std::nullptr_t>::type = nullptr>
- bool is() const noexcept
- {
- return detail::type_to_enum<T, value_type>::value == this->type_;
- }
- bool is(value_t t) const noexcept {return t == this->type_;}
-
- bool is_uninitialized() const noexcept {return this->is(value_t::empty );}
- bool is_boolean() const noexcept {return this->is(value_t::boolean );}
- bool is_integer() const noexcept {return this->is(value_t::integer );}
- bool is_floating() const noexcept {return this->is(value_t::floating );}
- bool is_string() const noexcept {return this->is(value_t::string );}
- bool is_offset_datetime() const noexcept {return this->is(value_t::offset_datetime);}
- bool is_local_datetime() const noexcept {return this->is(value_t::local_datetime );}
- bool is_local_date() const noexcept {return this->is(value_t::local_date );}
- bool is_local_time() const noexcept {return this->is(value_t::local_time );}
- bool is_array() const noexcept {return this->is(value_t::array );}
- bool is_table() const noexcept {return this->is(value_t::table );}
-
- value_t type() const noexcept {return type_;}
-
- template<value_t T>
- typename detail::enum_to_type<T, value_type>::type& cast() &
- {
- if(this->type_ != T)
- {
- detail::throw_bad_cast<T>("toml::value::cast: ", this->type_, *this);
- }
- return detail::switch_cast<T>::invoke(*this);
- }
- template<value_t T>
- typename detail::enum_to_type<T, value_type>::type const& cast() const&
- {
- if(this->type_ != T)
- {
- detail::throw_bad_cast<T>("toml::value::cast: ", this->type_, *this);
- }
- return detail::switch_cast<T>::invoke(*this);
- }
- template<value_t T>
- typename detail::enum_to_type<T, value_type>::type&& cast() &&
- {
- if(this->type_ != T)
- {
- detail::throw_bad_cast<T>("toml::value::cast: ", this->type_, *this);
- }
- return detail::switch_cast<T>::invoke(std::move(*this));
- }
-
- // ------------------------------------------------------------------------
- // nothrow version
-
- boolean const& as_boolean (const std::nothrow_t&) const& noexcept {return this->boolean_;}
- integer const& as_integer (const std::nothrow_t&) const& noexcept {return this->integer_;}
- floating const& as_floating (const std::nothrow_t&) const& noexcept {return this->floating_;}
- string const& as_string (const std::nothrow_t&) const& noexcept {return this->string_;}
- offset_datetime const& as_offset_datetime(const std::nothrow_t&) const& noexcept {return this->offset_datetime_;}
- local_datetime const& as_local_datetime (const std::nothrow_t&) const& noexcept {return this->local_datetime_;}
- local_date const& as_local_date (const std::nothrow_t&) const& noexcept {return this->local_date_;}
- local_time const& as_local_time (const std::nothrow_t&) const& noexcept {return this->local_time_;}
- array_type const& as_array (const std::nothrow_t&) const& noexcept {return this->array_.value();}
- table_type const& as_table (const std::nothrow_t&) const& noexcept {return this->table_.value();}
-
- boolean & as_boolean (const std::nothrow_t&) & noexcept {return this->boolean_;}
- integer & as_integer (const std::nothrow_t&) & noexcept {return this->integer_;}
- floating & as_floating (const std::nothrow_t&) & noexcept {return this->floating_;}
- string & as_string (const std::nothrow_t&) & noexcept {return this->string_;}
- offset_datetime& as_offset_datetime(const std::nothrow_t&) & noexcept {return this->offset_datetime_;}
- local_datetime & as_local_datetime (const std::nothrow_t&) & noexcept {return this->local_datetime_;}
- local_date & as_local_date (const std::nothrow_t&) & noexcept {return this->local_date_;}
- local_time & as_local_time (const std::nothrow_t&) & noexcept {return this->local_time_;}
- array_type & as_array (const std::nothrow_t&) & noexcept {return this->array_.value();}
- table_type & as_table (const std::nothrow_t&) & noexcept {return this->table_.value();}
-
- boolean && as_boolean (const std::nothrow_t&) && noexcept {return std::move(this->boolean_);}
- integer && as_integer (const std::nothrow_t&) && noexcept {return std::move(this->integer_);}
- floating && as_floating (const std::nothrow_t&) && noexcept {return std::move(this->floating_);}
- string && as_string (const std::nothrow_t&) && noexcept {return std::move(this->string_);}
- offset_datetime&& as_offset_datetime(const std::nothrow_t&) && noexcept {return std::move(this->offset_datetime_);}
- local_datetime && as_local_datetime (const std::nothrow_t&) && noexcept {return std::move(this->local_datetime_);}
- local_date && as_local_date (const std::nothrow_t&) && noexcept {return std::move(this->local_date_);}
- local_time && as_local_time (const std::nothrow_t&) && noexcept {return std::move(this->local_time_);}
- array_type && as_array (const std::nothrow_t&) && noexcept {return std::move(this->array_.value());}
- table_type && as_table (const std::nothrow_t&) && noexcept {return std::move(this->table_.value());}
-
- // ========================================================================
- // throw version
- // ------------------------------------------------------------------------
- // const reference {{{
-
- boolean const& as_boolean() const&
- {
- if(this->type_ != value_t::boolean)
- {
- detail::throw_bad_cast<value_t::boolean>(
- "toml::value::as_boolean(): ", this->type_, *this);
- }
- return this->boolean_;
- }
- integer const& as_integer() const&
- {
- if(this->type_ != value_t::integer)
- {
- detail::throw_bad_cast<value_t::integer>(
- "toml::value::as_integer(): ", this->type_, *this);
- }
- return this->integer_;
- }
- floating const& as_floating() const&
- {
- if(this->type_ != value_t::floating)
- {
- detail::throw_bad_cast<value_t::floating>(
- "toml::value::as_floating(): ", this->type_, *this);
- }
- return this->floating_;
- }
- string const& as_string() const&
- {
- if(this->type_ != value_t::string)
- {
- detail::throw_bad_cast<value_t::string>(
- "toml::value::as_string(): ", this->type_, *this);
- }
- return this->string_;
- }
- offset_datetime const& as_offset_datetime() const&
- {
- if(this->type_ != value_t::offset_datetime)
- {
- detail::throw_bad_cast<value_t::offset_datetime>(
- "toml::value::as_offset_datetime(): ", this->type_, *this);
- }
- return this->offset_datetime_;
- }
- local_datetime const& as_local_datetime() const&
- {
- if(this->type_ != value_t::local_datetime)
- {
- detail::throw_bad_cast<value_t::local_datetime>(
- "toml::value::as_local_datetime(): ", this->type_, *this);
- }
- return this->local_datetime_;
- }
- local_date const& as_local_date() const&
- {
- if(this->type_ != value_t::local_date)
- {
- detail::throw_bad_cast<value_t::local_date>(
- "toml::value::as_local_date(): ", this->type_, *this);
- }
- return this->local_date_;
- }
- local_time const& as_local_time() const&
- {
- if(this->type_ != value_t::local_time)
- {
- detail::throw_bad_cast<value_t::local_time>(
- "toml::value::as_local_time(): ", this->type_, *this);
- }
- return this->local_time_;
- }
- array_type const& as_array() const&
- {
- if(this->type_ != value_t::array)
- {
- detail::throw_bad_cast<value_t::array>(
- "toml::value::as_array(): ", this->type_, *this);
- }
- return this->array_.value();
- }
- table_type const& as_table() const&
- {
- if(this->type_ != value_t::table)
- {
- detail::throw_bad_cast<value_t::table>(
- "toml::value::as_table(): ", this->type_, *this);
- }
- return this->table_.value();
- }
- // }}}
- // ------------------------------------------------------------------------
- // nonconst reference {{{
-
- boolean & as_boolean() &
- {
- if(this->type_ != value_t::boolean)
- {
- detail::throw_bad_cast<value_t::boolean>(
- "toml::value::as_boolean(): ", this->type_, *this);
- }
- return this->boolean_;
- }
- integer & as_integer() &
- {
- if(this->type_ != value_t::integer)
- {
- detail::throw_bad_cast<value_t::integer>(
- "toml::value::as_integer(): ", this->type_, *this);
- }
- return this->integer_;
- }
- floating & as_floating() &
- {
- if(this->type_ != value_t::floating)
- {
- detail::throw_bad_cast<value_t::floating>(
- "toml::value::as_floating(): ", this->type_, *this);
- }
- return this->floating_;
- }
- string & as_string() &
- {
- if(this->type_ != value_t::string)
- {
- detail::throw_bad_cast<value_t::string>(
- "toml::value::as_string(): ", this->type_, *this);
- }
- return this->string_;
- }
- offset_datetime & as_offset_datetime() &
- {
- if(this->type_ != value_t::offset_datetime)
- {
- detail::throw_bad_cast<value_t::offset_datetime>(
- "toml::value::as_offset_datetime(): ", this->type_, *this);
- }
- return this->offset_datetime_;
- }
- local_datetime & as_local_datetime() &
- {
- if(this->type_ != value_t::local_datetime)
- {
- detail::throw_bad_cast<value_t::local_datetime>(
- "toml::value::as_local_datetime(): ", this->type_, *this);
- }
- return this->local_datetime_;
- }
- local_date & as_local_date() &
- {
- if(this->type_ != value_t::local_date)
- {
- detail::throw_bad_cast<value_t::local_date>(
- "toml::value::as_local_date(): ", this->type_, *this);
- }
- return this->local_date_;
- }
- local_time & as_local_time() &
- {
- if(this->type_ != value_t::local_time)
- {
- detail::throw_bad_cast<value_t::local_time>(
- "toml::value::as_local_time(): ", this->type_, *this);
- }
- return this->local_time_;
- }
- array_type & as_array() &
- {
- if(this->type_ != value_t::array)
- {
- detail::throw_bad_cast<value_t::array>(
- "toml::value::as_array(): ", this->type_, *this);
- }
- return this->array_.value();
- }
- table_type & as_table() &
- {
- if(this->type_ != value_t::table)
- {
- detail::throw_bad_cast<value_t::table>(
- "toml::value::as_table(): ", this->type_, *this);
- }
- return this->table_.value();
- }
-
- // }}}
- // ------------------------------------------------------------------------
- // rvalue reference {{{
-
- boolean && as_boolean() &&
- {
- if(this->type_ != value_t::boolean)
- {
- detail::throw_bad_cast<value_t::boolean>(
- "toml::value::as_boolean(): ", this->type_, *this);
- }
- return std::move(this->boolean_);
- }
- integer && as_integer() &&
- {
- if(this->type_ != value_t::integer)
- {
- detail::throw_bad_cast<value_t::integer>(
- "toml::value::as_integer(): ", this->type_, *this);
- }
- return std::move(this->integer_);
- }
- floating && as_floating() &&
- {
- if(this->type_ != value_t::floating)
- {
- detail::throw_bad_cast<value_t::floating>(
- "toml::value::as_floating(): ", this->type_, *this);
- }
- return std::move(this->floating_);
- }
- string && as_string() &&
- {
- if(this->type_ != value_t::string)
- {
- detail::throw_bad_cast<value_t::string>(
- "toml::value::as_string(): ", this->type_, *this);
- }
- return std::move(this->string_);
- }
- offset_datetime && as_offset_datetime() &&
- {
- if(this->type_ != value_t::offset_datetime)
- {
- detail::throw_bad_cast<value_t::offset_datetime>(
- "toml::value::as_offset_datetime(): ", this->type_, *this);
- }
- return std::move(this->offset_datetime_);
- }
- local_datetime && as_local_datetime() &&
- {
- if(this->type_ != value_t::local_datetime)
- {
- detail::throw_bad_cast<value_t::local_datetime>(
- "toml::value::as_local_datetime(): ", this->type_, *this);
- }
- return std::move(this->local_datetime_);
- }
- local_date && as_local_date() &&
- {
- if(this->type_ != value_t::local_date)
- {
- detail::throw_bad_cast<value_t::local_date>(
- "toml::value::as_local_date(): ", this->type_, *this);
- }
- return std::move(this->local_date_);
- }
- local_time && as_local_time() &&
- {
- if(this->type_ != value_t::local_time)
- {
- detail::throw_bad_cast<value_t::local_time>(
- "toml::value::as_local_time(): ", this->type_, *this);
- }
- return std::move(this->local_time_);
- }
- array_type && as_array() &&
- {
- if(this->type_ != value_t::array)
- {
- detail::throw_bad_cast<value_t::array>(
- "toml::value::as_array(): ", this->type_, *this);
- }
- return std::move(this->array_.value());
- }
- table_type && as_table() &&
- {
- if(this->type_ != value_t::table)
- {
- detail::throw_bad_cast<value_t::table>(
- "toml::value::as_table(): ", this->type_, *this);
- }
- return std::move(this->table_.value());
- }
- // }}}
-
- // accessors =============================================================
- //
- // may throw type_error or out_of_range
- //
- value_type& at(const key& k)
- {
- if(!this->is_table())
- {
- detail::throw_bad_cast<value_t::table>(
- "toml::value::at(key): ", this->type_, *this);
- }
- if(this->as_table(std::nothrow).count(k) == 0)
- {
- detail::throw_key_not_found_error(*this, k);
- }
- return this->as_table(std::nothrow).at(k);
- }
- value_type const& at(const key& k) const
- {
- if(!this->is_table())
- {
- detail::throw_bad_cast<value_t::table>(
- "toml::value::at(key): ", this->type_, *this);
- }
- if(this->as_table(std::nothrow).count(k) == 0)
- {
- detail::throw_key_not_found_error(*this, k);
- }
- return this->as_table(std::nothrow).at(k);
- }
- value_type& operator[](const key& k)
- {
- if(this->is_uninitialized())
- {
- *this = table_type{};
- }
- else if(!this->is_table()) // initialized, but not a table
- {
- detail::throw_bad_cast<value_t::table>(
- "toml::value::operator[](key): ", this->type_, *this);
- }
- return this->as_table(std::nothrow)[k];
- }
-
- value_type& at(const std::size_t idx)
- {
- if(!this->is_array())
- {
- detail::throw_bad_cast<value_t::array>(
- "toml::value::at(idx): ", this->type_, *this);
- }
- if(this->as_array(std::nothrow).size() <= idx)
- {
- throw std::out_of_range(detail::format_underline(
- "toml::value::at(idx): no element corresponding to the index", {
- {this->location(), concat_to_string("the length is ",
- this->as_array(std::nothrow).size(),
- ", and the specified index is ", idx)}
- }));
- }
- return this->as_array().at(idx);
- }
- value_type const& at(const std::size_t idx) const
- {
- if(!this->is_array())
- {
- detail::throw_bad_cast<value_t::array>(
- "toml::value::at(idx): ", this->type_, *this);
- }
- if(this->as_array(std::nothrow).size() <= idx)
- {
- throw std::out_of_range(detail::format_underline(
- "toml::value::at(idx): no element corresponding to the index", {
- {this->location(), concat_to_string("the length is ",
- this->as_array(std::nothrow).size(),
- ", and the specified index is ", idx)}
- }));
- }
- return this->as_array(std::nothrow).at(idx);
- }
-
- value_type& operator[](const std::size_t idx) noexcept
- {
- // no check...
- return this->as_array(std::nothrow)[idx];
- }
- value_type const& operator[](const std::size_t idx) const noexcept
- {
- // no check...
- return this->as_array(std::nothrow)[idx];
- }
-
- void push_back(const value_type& x)
- {
- if(!this->is_array())
- {
- detail::throw_bad_cast<value_t::array>(
- "toml::value::push_back(value): ", this->type_, *this);
- }
- this->as_array(std::nothrow).push_back(x);
- return;
- }
- void push_back(value_type&& x)
- {
- if(!this->is_array())
- {
- detail::throw_bad_cast<value_t::array>(
- "toml::value::push_back(value): ", this->type_, *this);
- }
- this->as_array(std::nothrow).push_back(std::move(x));
- return;
- }
-
- template<typename ... Ts>
- value_type& emplace_back(Ts&& ... args)
- {
- if(!this->is_array())
- {
- detail::throw_bad_cast<value_t::array>(
- "toml::value::emplace_back(...): ", this->type_, *this);
- }
- this->as_array(std::nothrow).emplace_back(std::forward<Ts>(args) ...);
- return this->as_array(std::nothrow).back();
- }
-
- std::size_t size() const
- {
- switch(this->type_)
- {
- case value_t::array:
- {
- return this->as_array(std::nothrow).size();
- }
- case value_t::table:
- {
- return this->as_table(std::nothrow).size();
- }
- case value_t::string:
- {
- return this->as_string(std::nothrow).str.size();
- }
- default:
- {
- throw type_error(detail::format_underline(
- "toml::value::size(): bad_cast to container types", {
- {this->location(),
- concat_to_string("the actual type is ", this->type_)}
- }), this->location());
- }
- }
- }
-
- std::size_t count(const key_type& k) const
- {
- if(!this->is_table())
- {
- detail::throw_bad_cast<value_t::table>(
- "toml::value::count(key): ", this->type_, *this);
- }
- return this->as_table(std::nothrow).count(k);
- }
-
- bool contains(const key_type& k) const
- {
- if(!this->is_table())
- {
- detail::throw_bad_cast<value_t::table>(
- "toml::value::contains(key): ", this->type_, *this);
- }
- return (this->as_table(std::nothrow).count(k) != 0);
- }
-
- source_location location() const
- {
- return source_location(this->region_info_.get());
- }
-
- comment_type const& comments() const noexcept {return this->comments_;}
- comment_type& comments() noexcept {return this->comments_;}
-
- private:
-
- void cleanup() noexcept
- {
- switch(this->type_)
- {
- case value_t::string : {string_.~string(); return;}
- case value_t::array : {array_.~array_storage(); return;}
- case value_t::table : {table_.~table_storage(); return;}
- default : return;
- }
- }
-
- // for error messages
- template<typename Value>
- friend region_base const* detail::get_region(const Value& v);
-
- template<typename Value>
- friend void detail::change_region(Value& v, detail::region reg);
-
- private:
-
- using array_storage = detail::storage<array_type>;
- using table_storage = detail::storage<table_type>;
-
- value_t type_;
- union
- {
- boolean boolean_;
- integer integer_;
- floating floating_;
- string string_;
- offset_datetime offset_datetime_;
- local_datetime local_datetime_;
- local_date local_date_;
- local_time local_time_;
- array_storage array_;
- table_storage table_;
- };
- std::shared_ptr<region_base> region_info_;
- comment_type comments_;
-};
-
-// default toml::value and default array/table.
-// TOML11_DEFAULT_COMMENT_STRATEGY is defined in comments.hpp
-using value = basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>;
-using array = typename value::array_type;
-using table = typename value::table_type;
-
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-inline bool
-operator==(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
-{
- if(lhs.type() != rhs.type()) {return false;}
- if(lhs.comments() != rhs.comments()) {return false;}
-
- switch(lhs.type())
- {
- case value_t::boolean :
- {
- return lhs.as_boolean() == rhs.as_boolean();
- }
- case value_t::integer :
- {
- return lhs.as_integer() == rhs.as_integer();
- }
- case value_t::floating :
- {
- return lhs.as_floating() == rhs.as_floating();
- }
- case value_t::string :
- {
- return lhs.as_string() == rhs.as_string();
- }
- case value_t::offset_datetime:
- {
- return lhs.as_offset_datetime() == rhs.as_offset_datetime();
- }
- case value_t::local_datetime:
- {
- return lhs.as_local_datetime() == rhs.as_local_datetime();
- }
- case value_t::local_date:
- {
- return lhs.as_local_date() == rhs.as_local_date();
- }
- case value_t::local_time:
- {
- return lhs.as_local_time() == rhs.as_local_time();
- }
- case value_t::array :
- {
- return lhs.as_array() == rhs.as_array();
- }
- case value_t::table :
- {
- return lhs.as_table() == rhs.as_table();
- }
- case value_t::empty : {return true; }
- default: {return false;}
- }
-}
-
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-inline bool operator!=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
-{
- return !(lhs == rhs);
-}
-
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-typename std::enable_if<detail::conjunction<
- detail::is_comparable<typename basic_value<C, T, A>::array_type>,
- detail::is_comparable<typename basic_value<C, T, A>::table_type>
- >::value, bool>::type
-operator<(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
-{
- if(lhs.type() != rhs.type()){return (lhs.type() < rhs.type());}
- switch(lhs.type())
- {
- case value_t::boolean :
- {
- return lhs.as_boolean() < rhs.as_boolean() ||
- (lhs.as_boolean() == rhs.as_boolean() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::integer :
- {
- return lhs.as_integer() < rhs.as_integer() ||
- (lhs.as_integer() == rhs.as_integer() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::floating :
- {
- return lhs.as_floating() < rhs.as_floating() ||
- (lhs.as_floating() == rhs.as_floating() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::string :
- {
- return lhs.as_string() < rhs.as_string() ||
- (lhs.as_string() == rhs.as_string() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::offset_datetime:
- {
- return lhs.as_offset_datetime() < rhs.as_offset_datetime() ||
- (lhs.as_offset_datetime() == rhs.as_offset_datetime() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::local_datetime:
- {
- return lhs.as_local_datetime() < rhs.as_local_datetime() ||
- (lhs.as_local_datetime() == rhs.as_local_datetime() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::local_date:
- {
- return lhs.as_local_date() < rhs.as_local_date() ||
- (lhs.as_local_date() == rhs.as_local_date() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::local_time:
- {
- return lhs.as_local_time() < rhs.as_local_time() ||
- (lhs.as_local_time() == rhs.as_local_time() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::array :
- {
- return lhs.as_array() < rhs.as_array() ||
- (lhs.as_array() == rhs.as_array() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::table :
- {
- return lhs.as_table() < rhs.as_table() ||
- (lhs.as_table() == rhs.as_table() &&
- lhs.comments() < rhs.comments());
- }
- case value_t::empty :
- {
- return lhs.comments() < rhs.comments();
- }
- default:
- {
- return lhs.comments() < rhs.comments();
- }
- }
-}
-
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-typename std::enable_if<detail::conjunction<
- detail::is_comparable<typename basic_value<C, T, A>::array_type>,
- detail::is_comparable<typename basic_value<C, T, A>::table_type>
- >::value, bool>::type
-operator<=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
-{
- return (lhs < rhs) || (lhs == rhs);
-}
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-typename std::enable_if<detail::conjunction<
- detail::is_comparable<typename basic_value<C, T, A>::array_type>,
- detail::is_comparable<typename basic_value<C, T, A>::table_type>
- >::value, bool>::type
-operator>(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
-{
- return !(lhs <= rhs);
-}
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-typename std::enable_if<detail::conjunction<
- detail::is_comparable<typename basic_value<C, T, A>::array_type>,
- detail::is_comparable<typename basic_value<C, T, A>::table_type>
- >::value, bool>::type
-operator>=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
-{
- return !(lhs < rhs);
-}
-
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-inline std::string format_error(const std::string& err_msg,
- const basic_value<C, T, A>& v, const std::string& comment,
- std::vector<std::string> hints = {},
- const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
-{
- return detail::format_underline(err_msg, {{v.location(), comment}},
- std::move(hints), colorize);
-}
-
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-inline std::string format_error(const std::string& err_msg,
- const toml::basic_value<C, T, A>& v1, const std::string& comment1,
- const toml::basic_value<C, T, A>& v2, const std::string& comment2,
- std::vector<std::string> hints = {},
- const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
-{
- return detail::format_underline(err_msg, {
- {v1.location(), comment1}, {v2.location(), comment2}
- }, std::move(hints), colorize);
-}
-
-template<typename C, template<typename ...> class T, template<typename ...> class A>
-inline std::string format_error(const std::string& err_msg,
- const toml::basic_value<C, T, A>& v1, const std::string& comment1,
- const toml::basic_value<C, T, A>& v2, const std::string& comment2,
- const toml::basic_value<C, T, A>& v3, const std::string& comment3,
- std::vector<std::string> hints = {},
- const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
-{
- return detail::format_underline(err_msg, {{v1.location(), comment1},
- {v2.location(), comment2}, {v3.location(), comment3}
- }, std::move(hints), colorize);
-}
-
-template<typename Visitor, typename C,
- template<typename ...> class T, template<typename ...> class A>
-detail::return_type_of_t<Visitor, const toml::boolean&>
-visit(Visitor&& visitor, const toml::basic_value<C, T, A>& v)
-{
- switch(v.type())
- {
- case value_t::boolean : {return visitor(v.as_boolean ());}
- case value_t::integer : {return visitor(v.as_integer ());}
- case value_t::floating : {return visitor(v.as_floating ());}
- case value_t::string : {return visitor(v.as_string ());}
- case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
- case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
- case value_t::local_date : {return visitor(v.as_local_date ());}
- case value_t::local_time : {return visitor(v.as_local_time ());}
- case value_t::array : {return visitor(v.as_array ());}
- case value_t::table : {return visitor(v.as_table ());}
- case value_t::empty : break;
- default: break;
- }
- throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
- "does not have any valid basic_value.", v, "here"));
-}
-
-template<typename Visitor, typename C,
- template<typename ...> class T, template<typename ...> class A>
-detail::return_type_of_t<Visitor, toml::boolean&>
-visit(Visitor&& visitor, toml::basic_value<C, T, A>& v)
-{
- switch(v.type())
- {
- case value_t::boolean : {return visitor(v.as_boolean ());}
- case value_t::integer : {return visitor(v.as_integer ());}
- case value_t::floating : {return visitor(v.as_floating ());}
- case value_t::string : {return visitor(v.as_string ());}
- case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
- case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
- case value_t::local_date : {return visitor(v.as_local_date ());}
- case value_t::local_time : {return visitor(v.as_local_time ());}
- case value_t::array : {return visitor(v.as_array ());}
- case value_t::table : {return visitor(v.as_table ());}
- case value_t::empty : break;
- default: break;
- }
- throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
- "does not have any valid basic_value.", v, "here"));
-}
-
-template<typename Visitor, typename C,
- template<typename ...> class T, template<typename ...> class A>
-detail::return_type_of_t<Visitor, toml::boolean&&>
-visit(Visitor&& visitor, toml::basic_value<C, T, A>&& v)
-{
- switch(v.type())
- {
- case value_t::boolean : {return visitor(std::move(v.as_boolean ()));}
- case value_t::integer : {return visitor(std::move(v.as_integer ()));}
- case value_t::floating : {return visitor(std::move(v.as_floating ()));}
- case value_t::string : {return visitor(std::move(v.as_string ()));}
- case value_t::offset_datetime: {return visitor(std::move(v.as_offset_datetime()));}
- case value_t::local_datetime : {return visitor(std::move(v.as_local_datetime ()));}
- case value_t::local_date : {return visitor(std::move(v.as_local_date ()));}
- case value_t::local_time : {return visitor(std::move(v.as_local_time ()));}
- case value_t::array : {return visitor(std::move(v.as_array ()));}
- case value_t::table : {return visitor(std::move(v.as_table ()));}
- case value_t::empty : break;
- default: break;
- }
- throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
- "does not have any valid basic_value.", v, "here"));
-}
-
-}// toml
-#endif// TOML11_VALUE