toml11/toml/toml.hpp

886 lines
27 KiB
C++
Raw Normal View History

2017-04-16 06:12:39 +00:00
/*
* The MIT License (MIT)
*
* Copyright (c) 2017 Toru Niina
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef TOML_FOR_MODERN_CPP
#define TOML_FOR_MODERN_CPP
#include <type_traits>
#include <utility>
#include <stdexcept>
#include <memory>
2017-04-16 06:12:39 +00:00
#include <string>
#include <vector>
#include <unordered_map>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <cassert>
namespace toml
{
class value;
using key = std::string;
using Boolean = bool;
using Integer = std::int64_t;
using Float = double;
using String = std::string;
using Datetime = std::chrono::system_clock::time_point;
using Array = std::vector<value>;
using Table = std::unordered_map<key, value>;
2017-04-16 06:12:39 +00:00
2017-04-16 07:37:19 +00:00
enum class value_t
2017-04-16 06:12:39 +00:00
{
Boolean,
Integer,
Float,
String,
Datetime,
Array,
Table,
Empty,
2017-04-16 06:12:39 +00:00
Unknown,
};
template<typename charT, typename traits>
inline std::basic_ostream<charT, traits>&
2017-04-16 07:37:19 +00:00
operator<<(std::basic_ostream<charT, traits>& os, value_t t)
2017-04-16 06:12:39 +00:00
{
switch(t)
{
2017-04-16 07:37:19 +00:00
case toml::value_t::Boolean : os << "Boolean"; return os;
case toml::value_t::Integer : os << "Integer"; return os;
case toml::value_t::Float : os << "Float"; return os;
case toml::value_t::String : os << "String"; return os;
case toml::value_t::Datetime: os << "Datetime"; return os;
case toml::value_t::Array : os << "Array"; return os;
case toml::value_t::Table : os << "Table"; return os;
case toml::value_t::Empty : os << "Empty"; return os;
2017-04-16 07:37:19 +00:00
case toml::value_t::Unknown : os << "Unknown"; return os;
default : os << "Nothing"; return os;
2017-04-16 06:12:39 +00:00
}
}
2017-04-20 03:49:36 +00:00
template<typename charT = char, typename traits = std::char_traits<charT>,
2017-04-16 06:12:39 +00:00
typename alloc = std::allocator<charT>>
inline std::basic_string<charT, traits, alloc>
2017-04-16 07:37:19 +00:00
stringize(value_t t)
2017-04-16 06:12:39 +00:00
{
switch(t)
{
2017-04-16 07:37:19 +00:00
case toml::value_t::Boolean : return "Boolean";
case toml::value_t::Integer : return "Integer";
case toml::value_t::Float : return "Float";
case toml::value_t::String : return "String";
case toml::value_t::Datetime: return "Datetime";
case toml::value_t::Array : return "Array";
case toml::value_t::Table : return "Table";
case toml::value_t::Empty : return "Empty";
2017-04-16 07:37:19 +00:00
case toml::value_t::Unknown : return "Unknown";
default : return "Nothing";
2017-04-16 06:12:39 +00:00
}
}
namespace detail
{
template<typename T>
using unwrap_t = typename std::decay<T>::type;
template<typename T>
2017-04-16 07:37:19 +00:00
constexpr inline value_t check_type()
2017-04-16 06:12:39 +00:00
{
2017-04-19 11:18:16 +00:00
return std::is_same<unwrap_t<T>, toml::Boolean >::value ? value_t::Boolean :
std::is_integral<unwrap_t<T>>::value ? value_t::Integer :
std::is_floating_point<unwrap_t<T>>::value ? value_t::Float :
std::is_convertible<unwrap_t<T>, toml::String >::value ? value_t::String :
std::is_convertible<unwrap_t<T>, toml::Datetime>::value ? value_t::Datetime:
std::is_convertible<unwrap_t<T>, toml::Array >::value ? value_t::Array :
std::is_convertible<unwrap_t<T>, toml::Table >::value ? value_t::Table :
2017-04-16 07:37:19 +00:00
value_t::Unknown;
2017-04-16 06:12:39 +00:00
}
2017-04-19 11:18:16 +00:00
template<typename T> struct is_toml_array : std::false_type{};
template<> struct is_toml_array<toml::Array> : std::true_type {};
template<typename T> struct is_toml_table : std::false_type{};
template<> struct is_toml_table<toml::Table> : std::true_type {};
2017-04-16 07:37:19 +00:00
template<value_t t> struct toml_default_type{};
template<> struct toml_default_type<value_t::Boolean >{typedef Boolean type;};
template<> struct toml_default_type<value_t::Integer >{typedef Integer type;};
template<> struct toml_default_type<value_t::Float >{typedef Float type;};
template<> struct toml_default_type<value_t::String >{typedef String type;};
2017-04-16 07:37:19 +00:00
template<> struct toml_default_type<value_t::Datetime>{typedef Datetime type;};
template<> struct toml_default_type<value_t::Array >{typedef Array type;};
template<> struct toml_default_type<value_t::Table >{typedef Table type;};
template<> struct toml_default_type<value_t::Empty >{typedef void type;};
template<> struct toml_default_type<value_t::Unknown >{typedef void type;};
2017-04-19 11:18:16 +00:00
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(...);
};
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 is_container : std::integral_constant<bool,
has_iterator<T>::value && has_value_type<T>::value>{};
template<typename T>
struct is_map : std::integral_constant<bool,
has_iterator<T>::value && has_key_type<T>::value &&
has_mapped_type<T>::value>{};
struct is_key_convertible_impl
{
template<typename T>
static std::is_convertible<typename T::key_type, toml::key>
check(typename T::key_type*);
template<typename T> static std::false_type check(...);
};
template<typename T>
struct is_key_convertible : decltype(is_key_convertible_impl::check<T>(nullptr)){};
struct storage_base
{
storage_base(): type(toml::value_t::Empty){}
storage_base(toml::value_t t): type(t){}
virtual ~storage_base() = default;
toml::value_t type;
};
template<typename T>
struct storage : public storage_base
{
static_assert(is_toml_array<T>::value || is_toml_table<T>::value,
"toml::detail::storage is for toml::Array or toml::Table!");
typedef T value_type;
2017-04-16 06:12:39 +00:00
storage() = default;
~storage() override = default;
storage(storage const&) = default;
storage(storage&&) = default;
storage& operator=(storage const&) = default;
storage& operator=(storage&&) = default;
storage(value_type const& v) : value(v){}
storage(value_type&& v) : value(std::move(v)){}
value_type value;
};
2017-04-16 06:12:39 +00:00
} // detail
/* -------------------------------------------------------------------------- */
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)...));
}
2017-04-16 06:12:39 +00:00
struct exception : public std::exception
{
public:
virtual ~exception() override = default;
virtual const char* what() const noexcept override {return "";}
};
struct syntax_error : public toml::exception
{
public:
explicit syntax_error(const std::string& what_arg) : what_(what_arg){}
explicit syntax_error(const char* what_arg) : what_(what_arg){}
2017-04-16 06:12:39 +00:00
virtual ~syntax_error() override = default;
virtual const char* what() const noexcept override {return what_.c_str();}
2017-04-16 06:12:39 +00:00
protected:
std::string what_;
2017-04-16 06:12:39 +00:00
};
struct type_error : public toml::exception
{
public:
explicit type_error(const std::string& what_arg) : what_(what_arg){}
explicit type_error(const char* what_arg) : what_(what_arg){}
2017-04-16 06:12:39 +00:00
virtual ~type_error() override = default;
virtual const char* what() const noexcept override {return what_.c_str();}
2017-04-16 06:12:39 +00:00
protected:
std::string what_;
2017-04-16 06:12:39 +00:00
};
struct internal_error : public toml::exception
{
public:
explicit internal_error(const std::string& what_arg) : what_(what_arg){}
explicit internal_error(const char* what_arg) : what_(what_arg){}
2017-04-16 06:12:39 +00:00
virtual ~internal_error() override = default;
virtual const char* what() const noexcept override {return what_.c_str();}
2017-04-16 06:12:39 +00:00
protected:
std::string what_;
2017-04-16 06:12:39 +00:00
};
/* -------------------------------------------------------------------------- */
2017-04-16 06:12:39 +00:00
template<typename T>
struct value_traits
{
2017-04-16 07:37:19 +00:00
constexpr static value_t type_index = detail::check_type<T>();
constexpr static bool is_toml_type = (type_index != value_t::Unknown);
2017-04-16 07:37:19 +00:00
typedef typename detail::toml_default_type<type_index>::type type;
2017-04-16 06:12:39 +00:00
};
class value
{
typedef std::unique_ptr<detail::storage_base> storage_ptr;
2017-04-16 07:37:45 +00:00
public:
2017-04-16 07:37:45 +00:00
value() : type_(value_t::Empty){}
~value();
2017-04-16 07:37:45 +00:00
value(const value& v);
value(value&& v);
value& operator=(const value& v);
value& operator=(value&& v);
2017-04-16 07:37:45 +00:00
template<typename T, typename std::enable_if<
value_traits<T>::is_toml_type, std::nullptr_t>::type = nullptr>
value(T&& v);
2017-04-19 11:18:16 +00:00
template<typename T, typename std::enable_if<
value_traits<T>::is_toml_type, std::nullptr_t>::type = nullptr>
value& operator=(T&& v);
2017-04-16 07:37:45 +00:00
2017-04-20 01:44:11 +00:00
template<typename T, typename std::enable_if<
value_traits<T>::is_toml_type, std::nullptr_t>::type = nullptr>
value(std::initializer_list<T> init);
value(std::initializer_list<std::pair<toml::key, toml::value>> init);
2017-04-16 07:37:45 +00:00
value_t type() const {return type_;}
2017-04-16 06:12:39 +00:00
2017-04-16 07:37:19 +00:00
template<value_t T>
typename detail::toml_default_type<T>::type const& cast() const;
2017-04-16 07:37:19 +00:00
template<value_t T>
typename detail::toml_default_type<T>::type& cast();
2017-04-16 06:12:39 +00:00
private:
void switch_clean(value_t t);
2017-04-16 07:37:19 +00:00
template<value_t t> struct switch_assign;
template<value_t t> struct switch_cast;
2017-04-16 06:12:39 +00:00
static bool should_be_cleaned(value_t vt)
{
return (vt == value_t::String) || (vt == value_t::Array) ||
(vt == value_t::Table) || (vt == value_t::Datetime);
}
2017-04-16 06:12:39 +00:00
private:
2017-04-16 07:37:19 +00:00
value_t type_;
2017-04-16 06:12:39 +00:00
union
{
Boolean boolean_;
Integer integer_;
Float float_;
String string_;
Datetime datetime_;
storage_ptr storage_; //ptr to table or array
2017-04-16 06:12:39 +00:00
};
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_assign<value_t::Boolean>
2017-04-16 06:12:39 +00:00
{
template<typename valT>
static void invoke(value& v, valT&& val)
{
v.boolean_ = static_cast<Boolean>(val);
2017-04-16 06:12:39 +00:00
}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_assign<value_t::Integer>
2017-04-16 06:12:39 +00:00
{
template<typename valT>
static void invoke(value& v, valT&& val)
{
v.integer_ = static_cast<Integer>(val);
2017-04-16 06:12:39 +00:00
}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_assign<value_t::Float>
2017-04-16 06:12:39 +00:00
{
template<typename valT>
static void invoke(value& v, valT&& val)
{
v.float_ = static_cast<Float>(val);
2017-04-16 06:12:39 +00:00
}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_assign<value_t::String>
2017-04-16 06:12:39 +00:00
{
template<typename valT>
static void invoke(value& v, valT&& val)
{
new(&v.string_) String(val);
}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_assign<value_t::Datetime>
2017-04-16 06:12:39 +00:00
{
template<typename valT>
static void invoke(value& v, valT&& val)
{
new(&v.datetime_) Datetime(val);
}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_assign<value_t::Array>
2017-04-16 06:12:39 +00:00
{
template<typename valT>
static void invoke(value& v, valT&& val)
{
new(&v.storage_) storage_ptr(
toml::make_unique<detail::storage<Array>>(val));
2017-04-16 06:12:39 +00:00
}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_assign<value_t::Table>
2017-04-16 06:12:39 +00:00
{
template<typename valT>
static void invoke(value& v, valT&& val)
{
new(&v.storage_) storage_ptr(
toml::make_unique<detail::storage<Table>>(val));
2017-04-16 06:12:39 +00:00
}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_cast<value_t::Boolean>
2017-04-16 06:12:39 +00:00
{
static Boolean& invoke(value& v) {return v.boolean_;}
static Boolean const& invoke(value const& v) {return v.boolean_;}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_cast<value_t::Integer>
2017-04-16 06:12:39 +00:00
{
static Integer& invoke(value& v) {return v.integer_;}
static Integer const& invoke(value const& v) {return v.integer_;}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_cast<value_t::Float>
2017-04-16 06:12:39 +00:00
{
static Float& invoke(value& v) {return v.float_;}
static Float const& invoke(value const& v) {return v.float_;}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_cast<value_t::String>
2017-04-16 06:12:39 +00:00
{
static String& invoke(value& v) {return v.string_;}
static String const& invoke(value const& v) {return v.string_;}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_cast<value_t::Datetime>
2017-04-16 06:12:39 +00:00
{
static Datetime& invoke(value& v) {return v.datetime_;}
static Datetime const& invoke(value const& v) {return v.datetime_;}
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_cast<value_t::Array>
2017-04-16 06:12:39 +00:00
{
// switch_cast assumes tmeplate argument is correct.
// if not, the behaviour is undefined.
static Array& invoke(value& v)
{
return static_cast<detail::storage<Array>*>(v.storage_.get())->value;
}
static Array const& invoke(value const& v)
{
return static_cast<detail::storage<Array>*>(v.storage_.get())->value;
}
2017-04-16 06:12:39 +00:00
};
2017-04-16 07:37:19 +00:00
template<> struct value::switch_cast<value_t::Table>
2017-04-16 06:12:39 +00:00
{
static Table& invoke(value& v)
{
return static_cast<detail::storage<Table>*>(v.storage_.get())->value;
}
static Table const& invoke(value const& v)
{
return static_cast<detail::storage<Table>*>(v.storage_.get())->value;
}
2017-04-16 06:12:39 +00:00
};
inline void value::switch_clean(value_t t)
{
switch(t)
{
case value_t::Boolean : {boolean_.~Boolean(); return;}
case value_t::Integer : {integer_.~Integer(); return;}
case value_t::Float : {float_.~Float(); return;}
case value_t::String : {string_.~String(); return;}
case value_t::Datetime : {datetime_.~Datetime(); return;}
case value_t::Array : {storage_.~storage_ptr(); return;}
case value_t::Table : {storage_.~storage_ptr(); return;}
case value_t::Empty : return;
case value_t::Unknown : assert(false);
default : assert(false);
}
}
2017-04-16 06:12:39 +00:00
inline value::~value()
{
switch_clean(this->type_);
}
2017-04-16 06:12:39 +00:00
inline value::value(const value& v) : type_(v.type())
{
switch(v.type())
{
case value_t::Boolean :
{
switch_assign<value_t::Boolean>::invoke(
*this, v.cast<value_t::Boolean>());
break;
}
case value_t::Integer :
{
switch_assign<value_t::Integer>::invoke(
*this, v.cast<value_t::Integer>());
break;
}
case value_t::Float :
{
switch_assign<value_t::Float>::invoke(
*this, v.cast<value_t::Float>());
break;
}
case value_t::String :
{
switch_assign<value_t::String>::invoke(
*this, v.cast<value_t::String>());
break;
}
case value_t::Datetime:
{
switch_assign<value_t::Datetime>::invoke(
*this, v.cast<value_t::Datetime>());
break;
}
case value_t::Array :
{
switch_assign<value_t::Array>::invoke(
*this, v.cast<value_t::Array>());
break;
}
case value_t::Table :
{
switch_assign<value_t::Table>::invoke(
*this, v.cast<value_t::Table>());
break;
}
case value_t::Empty : break;
case value_t::Unknown : assert(false);
default: assert(false);
}
}
inline value::value(value&& v)
{
this->type_ = v.type_;
switch(this->type_)
{
case value_t::Boolean :
{
switch_assign<value_t::Boolean>::invoke(*this,
std::move(v.cast<value_t::Boolean>()));
break;
}
case value_t::Integer :
{
switch_assign<value_t::Integer>::invoke(*this,
std::move(v.cast<value_t::Integer>()));
break;
}
case value_t::Float :
{
switch_assign<value_t::Float>::invoke(*this,
std::move(v.cast<value_t::Float>()));
break;
}
case value_t::String :
{
switch_assign<value_t::String>::invoke(*this,
std::move(v.cast<value_t::String>()));
break;
}
case value_t::Datetime:
{
switch_assign<value_t::Datetime>::invoke(*this,
std::move(v.cast<value_t::Datetime>()));
break;
}
case value_t::Array :
{
new(&this->storage_) storage_ptr(std::move(v.storage_));
break;
}
case value_t::Table :
{
new(&this->storage_) storage_ptr(std::move(v.storage_));
break;
}
case value_t::Empty : break;
case value_t::Unknown : assert(false);
default: assert(false);
}
}
inline value& value::operator=(const value& v)
{
if(should_be_cleaned(this->type_))
{
this->switch_clean(this->type_);
}
this->type_ = v.type();
switch(this->type_)
{
case value_t::Boolean :
{
switch_assign<value_t::Boolean>::invoke(*this,
v.cast<value_t::Boolean>());
break;
}
case value_t::Integer :
{
switch_assign<value_t::Integer>::invoke(*this,
v.cast<value_t::Integer>());
break;
}
case value_t::Float :
{
switch_assign<value_t::Float>::invoke(*this,
v.cast<value_t::Float>());
break;
}
case value_t::String :
{
switch_assign<value_t::String>::invoke(*this,
v.cast<value_t::String>());
break;
}
case value_t::Datetime:
{
switch_assign<value_t::Datetime>::invoke(*this,
v.cast<value_t::Datetime>());
break;
}
case value_t::Array :
{
switch_assign<value_t::Array>::invoke(*this,
v.cast<value_t::Array>());
break;
}
case value_t::Table :
{
switch_assign<value_t::Table>::invoke(*this,
v.cast<value_t::Table>());
break;
}
case value_t::Empty : break;
case value_t::Unknown : assert(false);
default: assert(false);
}
return *this;
}
inline value& value::operator=(value&& v)
{
if(should_be_cleaned(this->type_))
{
this->switch_clean(this->type_);
}
this->type_ = v.type_;
switch(this->type_)
{
case value_t::Boolean :
{
switch_assign<value_t::Boolean>::invoke(*this,
std::move(v.cast<value_t::Boolean>()));
break;
}
case value_t::Integer :
{
switch_assign<value_t::Integer>::invoke(*this,
std::move(v.cast<value_t::Integer>()));
break;
}
case value_t::Float :
{
switch_assign<value_t::Float>::invoke(*this,
std::move(v.cast<value_t::Float>()));
break;
}
case value_t::String :
{
switch_assign<value_t::String>::invoke(*this,
std::move(v.cast<value_t::String>()));
break;
}
case value_t::Datetime:
{
switch_assign<value_t::Datetime>::invoke(*this,
std::move(v.cast<value_t::Datetime>()));
break;
}
case value_t::Array :
{
switch_assign<value_t::Array>::invoke(*this,
std::move(v.cast<value_t::Array>()));
break;
}
case value_t::Table :
{
switch_assign<value_t::Table>::invoke(*this,
std::move(v.cast<value_t::Table>()));
break;
}
case value_t::Empty : break;
case value_t::Unknown : assert(false);
default: assert(false);
}
return *this;
}
template<typename T, typename std::enable_if<
value_traits<T>::is_toml_type, std::nullptr_t>::type>
value::value(T&& v) : type_(toml::detail::check_type<T>())
{
switch_assign<toml::detail::check_type<T>()>::invoke(
*this, std::forward<T>(v));
}
template<typename T, typename std::enable_if<
value_traits<T>::is_toml_type, std::nullptr_t>::type>
value& value::operator=(T&& v)
{
if(should_be_cleaned(this->type_))
{
switch_clean(this->type_);
}
this->type_ = toml::detail::check_type<T>();
switch_assign<toml::detail::check_type<T>()>::invoke(
*this, std::forward<T>(v));
return *this;
}
2017-04-20 01:44:11 +00:00
template<typename T, typename std::enable_if<
value_traits<T>::is_toml_type, std::nullptr_t>::type>
value::value(std::initializer_list<T> init)
: type_(toml::value_t::Array)
{
toml::Array arr; arr.reserve(init.size());
for(auto&& item : init)
arr.emplace_back(std::move(item));
switch_assign<toml::value_t::Array>::invoke(*this, std::move(arr));
}
inline value::value(
std::initializer_list<std::pair<toml::key, toml::value>> init)
: type_(toml::value_t::Table)
{
toml::Table tmp;
for(auto&& item : init)
tmp.emplace(std::move(item.first), std::move(item.second));
switch_assign<toml::value_t::Table>::invoke(*this, std::move(tmp));
}
template<value_t T>
inline typename detail::toml_default_type<T>::type const&
value::cast() const
{
if(T != this->type_)
2017-04-20 03:49:36 +00:00
throw type_error("current type: " + stringize(this->type_) +
std::string(" is not query type: ") + stringize(T));
return switch_cast<T>::invoke(*this);
}
template<value_t T>
inline typename detail::toml_default_type<T>::type&
value::cast()
{
if(T != this->type_)
2017-04-20 03:49:36 +00:00
throw type_error("current type: " + stringize(this->type_) +
std::string(" is not query type: ") + stringize(T));
return switch_cast<T>::invoke(*this);
}
2017-04-19 04:37:39 +00:00
2017-04-20 03:49:36 +00:00
/* ------------------------------- to_toml ---------------------------------- */
2017-04-19 04:37:39 +00:00
2017-04-19 15:13:58 +00:00
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT != toml::value_t::Unknown &&
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
inline toml::value to_toml(T&& x)
{
return toml::value(std::forward<T>(x));
}
2017-04-19 04:37:39 +00:00
2017-04-19 15:13:58 +00:00
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT == toml::value_t::Unknown) &&
(!toml::detail::is_map<T>::value) &&
toml::detail::is_container<T>::value, std::nullptr_t>::type = nullptr>
2017-04-20 03:05:10 +00:00
toml::value to_toml(T&& x)
2017-04-19 15:13:58 +00:00
{
toml::Array tmp; tmp.reserve(std::distance(std::begin(x), std::end(x)));
for(auto iter = std::begin(x); iter != std::end(x); ++iter)
tmp.emplace_back(*iter);
return toml::value(std::move(tmp));
}
2017-04-19 04:37:39 +00:00
2017-04-19 15:13:58 +00:00
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT == toml::value_t::Unknown) &&
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
2017-04-20 03:05:10 +00:00
toml::value to_toml(T&& x)
2017-04-19 15:13:58 +00:00
{
toml::Table tmp;
for(auto iter = std::begin(x); iter != std::end(x); ++iter)
tmp.emplace(iter->first, to_toml(iter->second));
return toml::value(std::move(tmp));
}
2017-04-19 04:37:39 +00:00
2017-04-20 03:05:10 +00:00
template<typename T>
inline toml::value to_toml(std::initializer_list<T> init)
{
return toml::value(std::move(init));
}
inline toml::value
to_toml(std::initializer_list<std::pair<std::string, toml::value>> init)
{
return toml::value(std::move(init));
}
2017-04-20 03:49:36 +00:00
/* ------------------------------ from_toml --------------------------------- */
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT != toml::value_t::Unknown &&
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
void from_toml(T& x, const toml::value& v)
{
if(v.type() != vT)
throw type_error("from_toml: value type: " + stringize(v.type()) +
2017-04-20 04:30:01 +00:00
std::string(" is not arguemnt type: ") + stringize(vT));
2017-04-20 03:49:36 +00:00
x = v.cast<vT>();
return;
}
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT == toml::value_t::Unknown) &&
(!toml::detail::is_map<T>::value) &&
toml::detail::is_container<T>::value, std::nullptr_t>::type = nullptr>
void from_toml(T& x, const toml::value& v)
{
// TODO the case of x is not dynamic container case
if(v.type() != value_t::Array)
throw type_error("from_toml: value type: " + stringize(v.type()) +
2017-04-20 04:30:01 +00:00
std::string(" is not argument type: Array"));
2017-04-20 03:49:36 +00:00
const auto& ar = v.cast<value_t::Array>();
for(const auto& val : ar)
{
typename T::value_type v;
from_toml(v, val);
x.push_back(std::move(v));
}
return;
}
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT == toml::value_t::Unknown) &&
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
void from_toml(T& x, const toml::value& v)
{
if(v.type() != value_t::Table)
throw type_error("from_toml: value type: " + stringize(v.type()) +
2017-04-20 04:30:01 +00:00
std::string(" is not argument type: Table"));
2017-04-20 03:49:36 +00:00
x.clear();
const auto& tb = v.cast<value_t::Table>();
for(const auto& kv : tb)
{
x.insert(kv);
}
return;
}
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT != toml::value_t::Unknown &&
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
inline T get(const toml::value& v)
{
return static_cast<T>(v.cast<vT>());
}
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT == toml::value_t::Unknown) &&
(!toml::detail::is_map<T>::value) &&
toml::detail::is_container<T>::value, std::nullptr_t>::type = nullptr>
T get(const toml::value& v)
{
if(v.type() != value_t::Array)
throw type_error("from_toml: value type: " + stringize(v.type()) +
2017-04-20 04:30:01 +00:00
std::string(" is not argument type: Array"));
2017-04-20 03:49:36 +00:00
T tmp;
from_toml(tmp, v);
return tmp;
}
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
typename std::enable_if<(vT == toml::value_t::Unknown) &&
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
T get(const toml::value& v)
{
if(v.type() != value_t::Table)
throw type_error("from_toml: value type: " + stringize(v.type()) +
2017-04-20 04:30:01 +00:00
std::string(" is not argument type: Table"));
2017-04-20 03:49:36 +00:00
T tmp;
from_toml(tmp, v);
return tmp;
}
2017-04-16 06:12:39 +00:00
}// toml
#endif// TOML_FOR_MODERN_CPP