mirror of
https://github.com/ToruNiina/toml11.git
synced 2024-11-08 13:50:06 +00:00
add type storage to avoid recursive type
This commit is contained in:
parent
6ffd233bce
commit
f3276b8b09
605
toml.hpp
605
toml.hpp
@ -27,10 +27,16 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
@ -48,7 +54,7 @@ using Float = double;
|
||||
using String = std::string;
|
||||
using Datetime = std::chrono::system_clock::time_point;
|
||||
using Array = std::vector<value>;
|
||||
using Table = std::map<key, value>;
|
||||
using Table = std::unordered_map<key, value>;
|
||||
|
||||
enum class value_t
|
||||
{
|
||||
@ -59,6 +65,7 @@ enum class value_t
|
||||
Datetime,
|
||||
Array,
|
||||
Table,
|
||||
Empty,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
@ -75,8 +82,9 @@ operator<<(std::basic_ostream<charT, traits>& os, value_t t)
|
||||
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;
|
||||
case toml::value_t::Unknown : os << "Unknown"; return os;
|
||||
default : os << "Nothing"; return os;
|
||||
default : os << "Nothing"; return os;
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +102,7 @@ stringize(value_t t)
|
||||
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";
|
||||
case toml::value_t::Unknown : return "Unknown";
|
||||
default : return "Nothing";
|
||||
}
|
||||
@ -105,50 +114,71 @@ namespace detail
|
||||
template<typename T>
|
||||
using unwrap_t = typename std::decay<T>::type;
|
||||
|
||||
template<typename T>
|
||||
struct is_std_array : std::false_type {};
|
||||
template<typename T, std::size_t N>
|
||||
struct is_std_array<std::array<T, N>> : std::true_type{};
|
||||
template<typename T>
|
||||
struct is_std_vector : std::false_type{};
|
||||
template<typename T>
|
||||
struct is_std_vector<std::vector<T>> : std::true_type{};
|
||||
template<typename T>
|
||||
struct is_array : std::integral_constant<bool, is_std_array<T>::value ||
|
||||
is_std_vector<T>::value || std::is_array<T>::value>{};
|
||||
|
||||
template<typename T>
|
||||
struct is_table : std::false_type {};
|
||||
template<typename cT, typename aT>
|
||||
struct is_table<std::map<toml::key, toml::value, cT, aT>> : std::true_type{};
|
||||
template<typename hT, typename pT, typename aT>
|
||||
struct is_table<std::unordered_map<toml::key, toml::value, hT, pT, aT>> : std::true_type{};
|
||||
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 {};
|
||||
|
||||
template<typename T>
|
||||
constexpr inline value_t check_type()
|
||||
{
|
||||
return std::is_same<unwrap_t<T>, bool>::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_same<unwrap_t<T>, std::string>::value ? value_t::String :
|
||||
std::is_same<unwrap_t<T>, const char*>::value ? value_t::String :
|
||||
toml::detail::is_array<unwrap_t<T>>::value ? value_t::Array :
|
||||
toml::detail::is_table<unwrap_t<T>>::value ? value_t::Table :
|
||||
return std::is_same<unwrap_t<T>, bool>::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_same<unwrap_t<T>, String>::value ? value_t::String :
|
||||
std::is_same<unwrap_t<T>, const char*>::value ? value_t::String :
|
||||
toml::detail::is_toml_array<unwrap_t<T>>::value ? value_t::Array :
|
||||
toml::detail::is_toml_table<unwrap_t<T>>::value ? value_t::Table :
|
||||
value_t::Unknown;
|
||||
}
|
||||
|
||||
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;};
|
||||
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;};
|
||||
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::Unknown>{ typedef void 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;};
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
};
|
||||
} // 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)...));
|
||||
}
|
||||
|
||||
struct exception : public std::exception
|
||||
{
|
||||
public:
|
||||
@ -159,204 +189,98 @@ struct exception : public std::exception
|
||||
struct syntax_error : public toml::exception
|
||||
{
|
||||
public:
|
||||
explicit syntax_error(const std::string& what_arg) : what_arg_(what_arg){}
|
||||
explicit syntax_error(const char* what_arg) : what_arg_(what_arg){}
|
||||
explicit syntax_error(const std::string& what_arg) : what_(what_arg){}
|
||||
explicit syntax_error(const char* what_arg) : what_(what_arg){}
|
||||
virtual ~syntax_error() override = default;
|
||||
virtual const char* what() const noexcept override {return what_arg_.c_str();}
|
||||
virtual const char* what() const noexcept override {return what_.c_str();}
|
||||
|
||||
protected:
|
||||
std::string what_arg_;
|
||||
std::string what_;
|
||||
};
|
||||
|
||||
struct type_error : public toml::exception
|
||||
{
|
||||
public:
|
||||
explicit type_error(const std::string& what_arg) : what_arg_(what_arg){}
|
||||
explicit type_error(const char* what_arg) : what_arg_(what_arg){}
|
||||
explicit type_error(const std::string& what_arg) : what_(what_arg){}
|
||||
explicit type_error(const char* what_arg) : what_(what_arg){}
|
||||
virtual ~type_error() override = default;
|
||||
virtual const char* what() const noexcept override {return what_arg_.c_str();}
|
||||
virtual const char* what() const noexcept override {return what_.c_str();}
|
||||
|
||||
protected:
|
||||
std::string what_arg_;
|
||||
std::string what_;
|
||||
};
|
||||
|
||||
struct internal_error : public toml::exception
|
||||
{
|
||||
public:
|
||||
explicit internal_error(const std::string& what_arg) : what_arg_(what_arg){}
|
||||
explicit internal_error(const char* what_arg) : what_arg_(what_arg){}
|
||||
explicit internal_error(const std::string& what_arg) : what_(what_arg){}
|
||||
explicit internal_error(const char* what_arg) : what_(what_arg){}
|
||||
virtual ~internal_error() override = default;
|
||||
virtual const char* what() const noexcept override {return what_arg_.c_str();}
|
||||
virtual const char* what() const noexcept override {return what_.c_str();}
|
||||
protected:
|
||||
std::string what_arg_;
|
||||
std::string what_;
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
template<typename T>
|
||||
struct value_traits
|
||||
{
|
||||
constexpr static value_t type_index = detail::check_type<T>();
|
||||
constexpr static bool is_toml_value = (type_index != value_t::Unknown);
|
||||
constexpr static bool is_toml_type = (type_index != value_t::Unknown);
|
||||
typedef typename detail::toml_default_type<type_index>::type type;
|
||||
};
|
||||
|
||||
class value
|
||||
{
|
||||
typedef std::unique_ptr<detail::storage_base> storage_ptr;
|
||||
|
||||
public:
|
||||
|
||||
value() : type_(value_t::Unknown){}
|
||||
value() : type_(value_t::Empty){}
|
||||
~value();
|
||||
|
||||
value(const value& v);
|
||||
value(value&& v);
|
||||
value& operator=(const value& v);
|
||||
value& operator=(value&& v);
|
||||
|
||||
template<typename T, typename std::enable_if<
|
||||
value_traits<T>::is_toml_value, std::nullptr_t>::type = nullptr>
|
||||
value(T&& v)
|
||||
: type_(toml::detail::check_type<T>())
|
||||
{
|
||||
switch_assign<toml::detail::check_type<T>()>::invoke(
|
||||
*this, std::forward<T>(v));
|
||||
}
|
||||
~value()
|
||||
{
|
||||
switch_clean(this->type_);
|
||||
}
|
||||
|
||||
value(const value& v)
|
||||
: type_(v.type())
|
||||
{
|
||||
switch(v.type())
|
||||
{
|
||||
case value_t::Boolean : boolean_ = v.cast<value_t::Boolean>(); break;
|
||||
case value_t::Integer : integer_ = v.cast<value_t::Integer>(); break;
|
||||
case value_t::Float : float_ = v.cast<value_t::Float>(); break;
|
||||
case value_t::String : string_ = v.cast<value_t::String>(); break;
|
||||
case value_t::Datetime: datetime_ = v.cast<value_t::Datetime>(); break;
|
||||
case value_t::Array : array_ = v.cast<value_t::Array>(); break;
|
||||
case value_t::Table : table_ = v.cast<value_t::Table>(); break;
|
||||
case value_t::Unknown : break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
value(value&& v)
|
||||
: type_(std::move(v.type_))
|
||||
{
|
||||
switch(v.type())
|
||||
{
|
||||
case value_t::Boolean : boolean_ = std::move(v.cast<value_t::Boolean>()); break;
|
||||
case value_t::Integer : integer_ = std::move(v.cast<value_t::Integer>()); break;
|
||||
case value_t::Float : float_ = std::move(v.cast<value_t::Float>()); break;
|
||||
case value_t::String : string_ = std::move(v.cast<value_t::String>()); break;
|
||||
case value_t::Datetime: datetime_ = std::move(v.cast<value_t::Datetime>()); break;
|
||||
case value_t::Array : array_ = std::move(v.cast<value_t::Array>()); break;
|
||||
case value_t::Table : table_ = std::move(v.cast<value_t::Table>()); break;
|
||||
case value_t::Unknown : break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
value& operator=(const value& v)
|
||||
{
|
||||
if(this->type_ != value_t::Unknown) this->switch_clean(this->type_);
|
||||
|
||||
this->type_ = v.type();
|
||||
switch(v.type())
|
||||
{
|
||||
case value_t::Boolean : boolean_ = v.cast<value_t::Boolean>(); break;
|
||||
case value_t::Integer : integer_ = v.cast<value_t::Integer>(); break;
|
||||
case value_t::Float : float_ = v.cast<value_t::Float>(); break;
|
||||
case value_t::String : string_ = v.cast<value_t::String>(); break;
|
||||
case value_t::Datetime: datetime_ = v.cast<value_t::Datetime>(); break;
|
||||
case value_t::Array : array_ = v.cast<value_t::Array>(); break;
|
||||
case value_t::Table : table_ = v.cast<value_t::Table>(); break;
|
||||
case value_t::Unknown : break;
|
||||
default: break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
value& operator=(value&& v)
|
||||
{
|
||||
if(this->type_ != value_t::Unknown) this->switch_clean(this->type_);
|
||||
|
||||
this->type_ = std::move(v.type_);
|
||||
switch(v.type())
|
||||
{
|
||||
case value_t::Boolean : boolean_ = std::move(v.cast<value_t::Boolean>()); break;
|
||||
case value_t::Integer : integer_ = std::move(v.cast<value_t::Integer>()); break;
|
||||
case value_t::Float : float_ = std::move(v.cast<value_t::Float>()); break;
|
||||
case value_t::String : string_ = std::move(v.cast<value_t::String>()); break;
|
||||
case value_t::Datetime: datetime_ = std::move(v.cast<value_t::Datetime>()); break;
|
||||
case value_t::Array : array_ = std::move(v.cast<value_t::Array>()); break;
|
||||
case value_t::Table : table_ = std::move(v.cast<value_t::Table>()); break;
|
||||
case value_t::Unknown : break;
|
||||
default: break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_traits<T>::is_toml_type, std::nullptr_t>::type = nullptr>
|
||||
value(T&& v);
|
||||
template<typename T, typename std::enable_if<
|
||||
value_traits<T>::is_toml_type, std::nullptr_t>::type = nullptr>
|
||||
value& operator=(T&& v);
|
||||
|
||||
value_t type() const {return type_;}
|
||||
|
||||
template<value_t T>
|
||||
typename detail::toml_default_type<T>::type const& cast() const
|
||||
{
|
||||
if(T != type_)
|
||||
throw type_error(std::string("value type is ") +
|
||||
stringize<char>(type_) + std::string(", not ") +
|
||||
stringize<char>(T));
|
||||
return switch_cast<T>::invoke(*this);
|
||||
}
|
||||
|
||||
typename detail::toml_default_type<T>::type const& cast() const;
|
||||
template<value_t T>
|
||||
typename detail::toml_default_type<T>::type& cast()
|
||||
{
|
||||
if(T != type_)
|
||||
throw type_error(std::string("value type is ") +
|
||||
stringize<char>(type_) + std::string(", not ") +
|
||||
stringize<char>(T));
|
||||
return switch_cast<T>::invoke(*this);
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<
|
||||
value_traits<T>::is_toml_value, std::nullptr_t>::type = nullptr>
|
||||
void reset(T&& v)
|
||||
{
|
||||
switch_clean(this->type_);
|
||||
type_ = toml::detail::check_type<T>();
|
||||
switch_assign<toml::detail::check_type<T>()>::invoke(*this, std::forward<T>(v));
|
||||
}
|
||||
typename detail::toml_default_type<T>::type& cast();
|
||||
|
||||
private:
|
||||
|
||||
void 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 : array_.~Array(); return;
|
||||
case value_t::Table : table_.~Table(); return;
|
||||
case value_t::Unknown : return;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void switch_clean(value_t t);
|
||||
template<value_t t> struct switch_assign;
|
||||
template<value_t t> struct switch_cast;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
value_t type_;
|
||||
union
|
||||
{
|
||||
Boolean boolean_;
|
||||
Integer integer_;
|
||||
Float float_;
|
||||
String string_;
|
||||
Datetime datetime_;
|
||||
Array array_;
|
||||
Table table_;
|
||||
Boolean boolean_;
|
||||
Integer integer_;
|
||||
Float float_;
|
||||
String string_;
|
||||
Datetime datetime_;
|
||||
storage_ptr storage_; //ptr to table or array
|
||||
};
|
||||
};
|
||||
|
||||
@ -365,7 +289,7 @@ template<> struct value::switch_assign<value_t::Boolean>
|
||||
template<typename valT>
|
||||
static void invoke(value& v, valT&& val)
|
||||
{
|
||||
v.boolean_ = std::forward<Boolean>(val);
|
||||
v.boolean_ = static_cast<Boolean>(val);
|
||||
}
|
||||
};
|
||||
template<> struct value::switch_assign<value_t::Integer>
|
||||
@ -373,7 +297,7 @@ template<> struct value::switch_assign<value_t::Integer>
|
||||
template<typename valT>
|
||||
static void invoke(value& v, valT&& val)
|
||||
{
|
||||
v.integer_ = std::forward<Integer>(val);
|
||||
v.integer_ = static_cast<Integer>(val);
|
||||
}
|
||||
};
|
||||
template<> struct value::switch_assign<value_t::Float>
|
||||
@ -381,7 +305,7 @@ template<> struct value::switch_assign<value_t::Float>
|
||||
template<typename valT>
|
||||
static void invoke(value& v, valT&& val)
|
||||
{
|
||||
v.float_ = std::forward<Float>(val);
|
||||
v.float_ = static_cast<Float>(val);
|
||||
}
|
||||
};
|
||||
template<> struct value::switch_assign<value_t::String>
|
||||
@ -405,7 +329,8 @@ template<> struct value::switch_assign<value_t::Array>
|
||||
template<typename valT>
|
||||
static void invoke(value& v, valT&& val)
|
||||
{
|
||||
new(&v.array_) Array(val);
|
||||
new(&v.storage_) storage_ptr(
|
||||
toml::make_unique<detail::storage<Array>>(val));
|
||||
}
|
||||
};
|
||||
template<> struct value::switch_assign<value_t::Table>
|
||||
@ -413,7 +338,8 @@ template<> struct value::switch_assign<value_t::Table>
|
||||
template<typename valT>
|
||||
static void invoke(value& v, valT&& val)
|
||||
{
|
||||
new(&v.table_) Table(val);
|
||||
new(&v.storage_) storage_ptr(
|
||||
toml::make_unique<detail::storage<Table>>(val));
|
||||
}
|
||||
};
|
||||
|
||||
@ -444,16 +370,311 @@ template<> struct value::switch_cast<value_t::Datetime>
|
||||
};
|
||||
template<> struct value::switch_cast<value_t::Array>
|
||||
{
|
||||
static Array& invoke(value& v) {return v.array_;}
|
||||
static Array const& invoke(value const& v) {return v.array_;}
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
template<> struct value::switch_cast<value_t::Table>
|
||||
{
|
||||
static Table& invoke(value& v) {return v.table_;}
|
||||
static Table const& invoke(value const& v) {return v.table_;}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
inline value::~value()
|
||||
{
|
||||
switch_clean(this->type_);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template<value_t T>
|
||||
inline typename detail::toml_default_type<T>::type const&
|
||||
value::cast() const
|
||||
{
|
||||
if(T != this->type_)
|
||||
throw type_error("current type: " + stringize<char>(this->type_) +
|
||||
std::string(" is not query type: ") + stringize<char>(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_)
|
||||
throw type_error("current type: " + stringize<char>(this->type_) +
|
||||
std::string(" is not query type: ") + stringize<char>(T));
|
||||
return switch_cast<T>::invoke(*this);
|
||||
}
|
||||
}// toml
|
||||
#endif// TOML_FOR_MODERN_CPP
|
||||
|
Loading…
Reference in New Issue
Block a user