aboutsummaryrefslogtreecommitdiff
path: root/src/toml11/toml
diff options
context:
space:
mode:
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