2018-12-13 11:44:10 +00:00
|
|
|
// Copyright Toru Niina 2017.
|
|
|
|
// Distributed under the MIT License.
|
2019-03-16 05:19:47 +00:00
|
|
|
#ifndef TOML11_VALUE_HPP
|
|
|
|
#define TOML11_VALUE_HPP
|
2017-04-21 04:14:53 +00:00
|
|
|
#include "traits.hpp"
|
2019-03-16 05:44:04 +00:00
|
|
|
#include "into.hpp"
|
2017-04-21 04:14:53 +00:00
|
|
|
#include "utility.hpp"
|
|
|
|
#include "exception.hpp"
|
2018-12-09 07:41:45 +00:00
|
|
|
#include "storage.hpp"
|
|
|
|
#include "region.hpp"
|
2018-12-05 11:55:25 +00:00
|
|
|
#include "types.hpp"
|
2017-04-16 06:12:39 +00:00
|
|
|
#include <vector>
|
2017-04-20 07:13:06 +00:00
|
|
|
#include <tuple>
|
2017-04-16 06:12:39 +00:00
|
|
|
#include <unordered_map>
|
|
|
|
#include <cassert>
|
2017-04-21 03:56:39 +00:00
|
|
|
#include <cstdint>
|
2019-04-26 07:33:09 +00:00
|
|
|
#if __cplusplus >= 201703L
|
|
|
|
#include <string_view>
|
|
|
|
#endif
|
2017-04-16 06:12:39 +00:00
|
|
|
|
|
|
|
namespace toml
|
|
|
|
{
|
|
|
|
|
2018-12-10 06:06:28 +00:00
|
|
|
namespace detail
|
|
|
|
{
|
2018-12-13 07:13:05 +00:00
|
|
|
// to show error messages. not recommended for users.
|
|
|
|
region_base const& get_region(const value&);
|
2019-03-04 06:01:28 +00:00
|
|
|
template<typename Region>
|
|
|
|
void change_region(value&, Region&&);
|
2018-12-10 06:06:28 +00:00
|
|
|
}// detail
|
|
|
|
|
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>();
|
2017-06-12 13:04:59 +00:00
|
|
|
constexpr static bool is_toml_type = detail::is_valid(detail::check_type<T>());
|
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
|
|
|
};
|
2018-07-08 09:58:38 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr value_t value_traits<T>::type_index;
|
|
|
|
template<typename T>
|
|
|
|
constexpr bool value_traits<T>::is_toml_type;
|
2017-04-16 06:12:39 +00:00
|
|
|
|
|
|
|
class value
|
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
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));
|
2019-05-10 11:58:22 +00:00
|
|
|
(void)tmp;
|
2018-12-09 09:03:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
using region_base = detail::region_base;
|
2017-04-16 07:37:45 +00:00
|
|
|
|
2017-04-19 04:37:02 +00:00
|
|
|
public:
|
2017-04-16 07:37:45 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
value() noexcept
|
|
|
|
: type_(value_t::Empty),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
|
|
|
{}
|
2017-04-16 07:37:45 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
~value() noexcept {this->cleanup();}
|
2017-04-16 07:37:45 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
value(const value& v): type_(v.type()), region_info_(v.region_info_)
|
|
|
|
{
|
|
|
|
switch(v.type())
|
|
|
|
{
|
|
|
|
case value_t::Boolean : assigner(boolean_ , v.boolean_ ); break;
|
|
|
|
case value_t::Integer : assigner(integer_ , v.integer_ ); break;
|
|
|
|
case value_t::Float : assigner(floating_ , v.floating_ ); break;
|
|
|
|
case value_t::String : assigner(string_ , v.string_ ); break;
|
|
|
|
case value_t::OffsetDatetime: assigner(offset_datetime_, v.offset_datetime_); break;
|
|
|
|
case value_t::LocalDatetime : assigner(local_datetime_ , v.local_datetime_ ); break;
|
|
|
|
case value_t::LocalDate : assigner(local_date_ , v.local_date_ ); break;
|
|
|
|
case value_t::LocalTime : 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
value(value&& v): type_(v.type()), region_info_(std::move(v.region_info_))
|
|
|
|
{
|
|
|
|
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::Float : assigner(floating_ , std::move(v.floating_ )); break;
|
|
|
|
case value_t::String : assigner(string_ , std::move(v.string_ )); break;
|
|
|
|
case value_t::OffsetDatetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
|
|
|
|
case value_t::LocalDatetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
|
|
|
|
case value_t::LocalDate : assigner(local_date_ , std::move(v.local_date_ )); break;
|
|
|
|
case value_t::LocalTime : 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
value& operator=(const value& v)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->region_info_ = v.region_info_;
|
|
|
|
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::Float : assigner(floating_ , v.floating_ ); break;
|
|
|
|
case value_t::String : assigner(string_ , v.string_ ); break;
|
|
|
|
case value_t::OffsetDatetime: assigner(offset_datetime_, v.offset_datetime_); break;
|
|
|
|
case value_t::LocalDatetime : assigner(local_datetime_ , v.local_datetime_ ); break;
|
|
|
|
case value_t::LocalDate : assigner(local_date_ , v.local_date_ ); break;
|
|
|
|
case value_t::LocalTime : 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;
|
|
|
|
}
|
|
|
|
value& operator=(value&& v)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->region_info_ = std::move(v.region_info_);
|
|
|
|
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::Float : assigner(floating_ , std::move(v.floating_ )); break;
|
|
|
|
case value_t::String : assigner(string_ , std::move(v.string_ )); break;
|
|
|
|
case value_t::OffsetDatetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
|
|
|
|
case value_t::LocalDatetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
|
|
|
|
case value_t::LocalDate : assigner(local_date_ , std::move(v.local_date_ )); break;
|
|
|
|
case value_t::LocalTime : 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;
|
|
|
|
}
|
2017-04-19 11:18:16 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// boolean ==============================================================
|
2017-04-16 07:37:45 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
value(boolean b)
|
|
|
|
: type_(value_t::Boolean),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
|
|
|
{
|
|
|
|
assigner(this->boolean_, b);
|
|
|
|
}
|
2017-04-20 01:44:11 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-04-20 01:44:11 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
template<typename Container>
|
|
|
|
value(boolean b, detail::region<Container> reg)
|
|
|
|
: type_(value_t::Boolean),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
|
|
|
assigner(this->boolean_, b);
|
|
|
|
}
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// integer ==============================================================
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
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>
|
|
|
|
value(T i)
|
|
|
|
: type_(value_t::Integer),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
|
|
|
{
|
|
|
|
assigner(this->integer_, static_cast<integer>(i));
|
|
|
|
}
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
template<typename T, typename Container, typename std::enable_if<
|
|
|
|
detail::conjunction<std::is_integral<T>,
|
|
|
|
detail::negation<std::is_same<T, boolean>>
|
|
|
|
>::value, std::nullptr_t>::type = nullptr>
|
|
|
|
value(T i, detail::region<Container> reg)
|
|
|
|
: type_(value_t::Integer),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
|
|
|
assigner(this->integer_, static_cast<integer>(i));
|
|
|
|
}
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
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>
|
|
|
|
value& operator=(T i)
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
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;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// floating =============================================================
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
template<typename T, typename std::enable_if<
|
|
|
|
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
|
|
|
value(T f)
|
|
|
|
: type_(value_t::Float),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-16 06:12:39 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->floating_, f);
|
|
|
|
}
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
template<typename T, typename Container, typename std::enable_if<
|
|
|
|
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
|
|
|
value(T f, detail::region<Container> reg)
|
|
|
|
: type_(value_t::Float),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2017-04-16 06:12:39 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->floating_, f);
|
2017-04-16 06:12:39 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
|
|
|
|
template<typename T, typename std::enable_if<
|
|
|
|
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
|
|
|
value& operator=(T f)
|
2017-04-16 06:12:39 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::Float;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->floating_, f);
|
|
|
|
return *this;
|
2017-04-16 06:12:39 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
|
|
|
|
// string ===============================================================
|
|
|
|
|
|
|
|
value(toml::string s)
|
|
|
|
: type_(value_t::String),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-16 06:12:39 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->string_, std::move(s));
|
2017-04-16 06:12:39 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
template<typename Container>
|
|
|
|
value(toml::string s, detail::region<Container> reg)
|
|
|
|
: type_(value_t::String),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2017-04-16 06:12:39 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->string_, std::move(s));
|
2017-04-16 06:12:39 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
value& operator=(toml::string s)
|
2017-04-16 06:12:39 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::String;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->string_, s);
|
|
|
|
return *this;
|
2017-04-16 06:12:39 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
|
|
|
|
value(std::string s)
|
|
|
|
: type_(value_t::String),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-16 06:12:39 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->string_, toml::string(std::move(s)));
|
2017-04-16 06:12:39 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
value& operator=(std::string s)
|
2017-04-16 06:12:39 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
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));
|
2017-04-16 06:12:39 +00:00
|
|
|
}
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
value(const char* s)
|
|
|
|
: type_(value_t::String),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->string_, toml::string(std::string(s)));
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
value& operator=(const char* s)
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
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;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
value(const char* s, string_t kind)
|
|
|
|
: type_(value_t::String),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->string_, toml::string(std::string(s), kind));
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
|
2019-04-26 07:33:09 +00:00
|
|
|
#if __cplusplus >= 201703L
|
|
|
|
value(std::string_view s)
|
|
|
|
: type_(value_t::String),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
|
|
|
{
|
|
|
|
assigner(this->string_, toml::string(s));
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// local date ===========================================================
|
|
|
|
|
|
|
|
value(const local_date& ld)
|
|
|
|
: type_(value_t::LocalDate),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->local_date_, ld);
|
|
|
|
}
|
|
|
|
template<typename Container>
|
|
|
|
value(const local_date& ld, detail::region<Container> reg)
|
|
|
|
: type_(value_t::LocalDate),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
|
|
|
assigner(this->local_date_, ld);
|
|
|
|
}
|
|
|
|
value& operator=(const local_date& ld)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::LocalDate;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->local_date_, ld);
|
|
|
|
return *this;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// local time ===========================================================
|
|
|
|
|
|
|
|
value(const local_time& lt)
|
|
|
|
: type_(value_t::LocalTime),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
|
|
|
{
|
|
|
|
assigner(this->local_time_, lt);
|
|
|
|
}
|
|
|
|
template<typename Container>
|
|
|
|
value(const local_time& lt, detail::region<Container> reg)
|
|
|
|
: type_(value_t::LocalTime),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
|
|
|
assigner(this->local_time_, lt);
|
|
|
|
}
|
|
|
|
value& operator=(const local_time& lt)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::LocalTime;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->local_time_, lt);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
template<typename Rep, typename Period>
|
|
|
|
value(const std::chrono::duration<Rep, Period>& dur)
|
|
|
|
: type_(value_t::LocalTime),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
|
|
|
{
|
|
|
|
assigner(this->local_time_, local_time(dur));
|
|
|
|
}
|
|
|
|
template<typename Rep, typename Period>
|
|
|
|
value& operator=(const std::chrono::duration<Rep, Period>& dur)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::LocalTime;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->local_time_, local_time(dur));
|
|
|
|
return *this;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// local datetime =======================================================
|
2017-04-16 06:12:39 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
value(const local_datetime& ldt)
|
|
|
|
: type_(value_t::LocalDatetime),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->local_datetime_, ldt);
|
|
|
|
}
|
|
|
|
template<typename Container>
|
|
|
|
value(const local_datetime& ldt, detail::region<Container> reg)
|
|
|
|
: type_(value_t::LocalDatetime),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
|
|
|
assigner(this->local_datetime_, ldt);
|
|
|
|
}
|
|
|
|
value& operator=(const local_datetime& ldt)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::LocalDatetime;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->local_datetime_, ldt);
|
|
|
|
return *this;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// offset datetime ======================================================
|
|
|
|
|
|
|
|
value(const offset_datetime& odt)
|
|
|
|
: type_(value_t::OffsetDatetime),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->offset_datetime_, odt);
|
|
|
|
}
|
|
|
|
template<typename Container>
|
|
|
|
value(const offset_datetime& odt, detail::region<Container> reg)
|
|
|
|
: type_(value_t::OffsetDatetime),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
|
|
|
assigner(this->offset_datetime_, odt);
|
|
|
|
}
|
|
|
|
value& operator=(const offset_datetime& odt)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::OffsetDatetime;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->offset_datetime_, odt);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
value(const std::chrono::system_clock::time_point& tp)
|
|
|
|
: type_(value_t::OffsetDatetime),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
|
|
|
{
|
|
|
|
assigner(this->offset_datetime_, offset_datetime(tp));
|
|
|
|
}
|
|
|
|
value& operator=(const std::chrono::system_clock::time_point& tp)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::OffsetDatetime;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->offset_datetime_, offset_datetime(tp));
|
|
|
|
return *this;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// array ================================================================
|
|
|
|
|
|
|
|
value(const array& ary)
|
|
|
|
: type_(value_t::Array),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->array_, ary);
|
|
|
|
}
|
|
|
|
template<typename Container>
|
|
|
|
value(const array& ary, detail::region<Container> reg)
|
|
|
|
: type_(value_t::Array),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
|
|
|
assigner(this->array_, ary);
|
|
|
|
}
|
|
|
|
value& operator=(const array& ary)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::Array;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->array_, ary);
|
|
|
|
return *this;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
|
|
|
|
2018-12-09 09:03:20 +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> list)
|
|
|
|
: type_(value_t::Array),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
array ary; ary.reserve(list.size());
|
|
|
|
for(auto& elem : list) {ary.emplace_back(std::move(elem));}
|
|
|
|
assigner(this->array_, std::move(ary));
|
|
|
|
}
|
|
|
|
template<typename T, typename std::enable_if<value_traits<T>::is_toml_type,
|
|
|
|
std::nullptr_t>::type = nullptr>
|
|
|
|
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 ary; ary.reserve(list.size());
|
|
|
|
for(auto& elem : list) {ary.emplace_back(std::move(elem));}
|
|
|
|
assigner(this->array_, std::move(ary));
|
|
|
|
return *this;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
template<typename T, typename std::enable_if<detail::is_container<T>::value,
|
|
|
|
std::nullptr_t>::type = nullptr>
|
|
|
|
value(T&& list)
|
|
|
|
: type_(value_t::Array),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
array ary; ary.reserve(list.size());
|
2019-03-17 17:05:55 +00:00
|
|
|
for(const auto& elem : list) {ary.emplace_back(elem);}
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->array_, std::move(ary));
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
template<typename T, typename std::enable_if<detail::is_container<T>::value,
|
|
|
|
std::nullptr_t>::type = nullptr>
|
|
|
|
value& operator=(T&& list)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::Array;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
|
|
|
|
array ary; ary.reserve(list.size());
|
2019-03-17 17:05:55 +00:00
|
|
|
for(const auto& elem : list) {ary.emplace_back(elem);}
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->array_, std::move(ary));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// table ================================================================
|
2017-04-19 04:37:02 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
value(const table& tab)
|
|
|
|
: type_(value_t::Table),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
assigner(this->table_, tab);
|
|
|
|
}
|
|
|
|
template<typename Container>
|
|
|
|
value(const table& tab, detail::region<Container> reg)
|
|
|
|
: type_(value_t::Table),
|
2018-12-10 06:25:27 +00:00
|
|
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg)))
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
|
|
|
assigner(this->table_, tab);
|
|
|
|
}
|
|
|
|
value& operator=(const table& tab)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::Table;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
assigner(this->table_, tab);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
value(std::initializer_list<std::pair<key, value>> list)
|
|
|
|
: type_(value_t::Table),
|
|
|
|
region_info_(std::make_shared<region_base>(region_base{}))
|
|
|
|
{
|
|
|
|
table tab;
|
|
|
|
for(const auto& elem : list) {tab[elem.first] = elem.second;}
|
|
|
|
assigner(this->table_, std::move(tab));
|
|
|
|
}
|
|
|
|
value& operator=(std::initializer_list<std::pair<key, value>> list)
|
|
|
|
{
|
|
|
|
this->cleanup();
|
|
|
|
this->type_ = value_t::Array;
|
|
|
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
|
|
|
|
|
|
|
table tab;
|
|
|
|
for(const auto& elem : list) {tab[elem.first] = elem.second;}
|
|
|
|
assigner(this->table_, std::move(tab));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2019-03-16 05:44:04 +00:00
|
|
|
// user-defined =========================================================
|
|
|
|
|
|
|
|
// convert using into_toml() method -------------------------------------
|
|
|
|
|
|
|
|
template<typename T, typename std::enable_if<detail::conjunction<
|
|
|
|
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
|
|
|
|
detail::has_into_toml_method<T> // but has `into_toml` method
|
|
|
|
>::value, std::nullptr_t>::type = nullptr>
|
|
|
|
value(const T& ud): value(ud.into_toml()) {}
|
|
|
|
|
|
|
|
template<typename T, typename std::enable_if<detail::conjunction<
|
|
|
|
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
|
|
|
|
detail::has_into_toml_method<T> // but has `into_toml` method
|
|
|
|
>::value, std::nullptr_t>::type = nullptr>
|
|
|
|
value& operator=(const T& ud)
|
|
|
|
{
|
|
|
|
*this = ud.into_toml();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert using into<T> struct -----------------------------------------
|
|
|
|
|
|
|
|
template<typename T, typename std::enable_if<
|
|
|
|
detail::negation<detail::is_exact_toml_type<T>>::value,
|
|
|
|
std::nullptr_t>::type = nullptr,
|
|
|
|
std::size_t S = sizeof(::toml::into<T>)>
|
|
|
|
value(const T& ud): value(::toml::into<T>::into_toml(ud)) {}
|
|
|
|
|
|
|
|
template<typename T, typename std::enable_if<
|
|
|
|
detail::negation<detail::is_exact_toml_type<T>>::value,
|
|
|
|
std::nullptr_t>::type = nullptr,
|
|
|
|
std::size_t S = sizeof(::toml::into<T>)>
|
|
|
|
value& operator=(const T& ud)
|
|
|
|
{
|
|
|
|
*this = ::toml::into<T>::into_toml(ud);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2019-04-17 14:43:42 +00:00
|
|
|
// for internal use ------------------------------------------------------
|
|
|
|
|
|
|
|
template<typename T, typename Container, typename std::enable_if<
|
|
|
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
|
|
|
value(std::pair<T, detail::region<Container>> parse_result)
|
|
|
|
: value(std::move(parse_result.first), std::move(parse_result.second))
|
|
|
|
{}
|
|
|
|
|
2019-03-16 05:44:04 +00:00
|
|
|
// type checking and casting ============================================
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
template<typename T>
|
|
|
|
bool is() const noexcept {return value_traits<T>::type_index == this->type_;}
|
|
|
|
bool is(value_t t) const noexcept {return t == this->type_;}
|
|
|
|
|
2019-03-12 11:43:07 +00:00
|
|
|
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_float() const noexcept {return this->is(value_t::Float );}
|
|
|
|
bool is_string() const noexcept {return this->is(value_t::String );}
|
|
|
|
bool is_offset_datetime() const noexcept {return this->is(value_t::OffsetDatetime);}
|
|
|
|
bool is_local_datetime() const noexcept {return this->is(value_t::LocalDatetime );}
|
|
|
|
bool is_local_date() const noexcept {return this->is(value_t::LocalDate );}
|
|
|
|
bool is_local_time() const noexcept {return this->is(value_t::LocalTime );}
|
|
|
|
bool is_array() const noexcept {return this->is(value_t::Array );}
|
|
|
|
bool is_table() const noexcept {return this->is(value_t::Table );}
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
value_t type() const {return type_;}
|
|
|
|
|
|
|
|
template<value_t T>
|
|
|
|
typename detail::toml_default_type<T>::type& cast() &;
|
|
|
|
template<value_t T>
|
|
|
|
typename detail::toml_default_type<T>::type const& cast() const&;
|
|
|
|
template<value_t T>
|
|
|
|
typename detail::toml_default_type<T>::type&& cast() &&;
|
|
|
|
|
2019-05-29 11:18:15 +00:00
|
|
|
boolean const& as_boolean() const& noexcept {return this->boolean_;}
|
|
|
|
integer const& as_integer() const& noexcept {return this->integer_;}
|
|
|
|
floating const& as_float() const& noexcept {return this->floating_;}
|
|
|
|
string const& as_string() const& noexcept {return this->string_;}
|
|
|
|
offset_datetime const& as_offset_datetime() const& noexcept {return this->offset_datetime_;}
|
|
|
|
local_datetime const& as_local_datetime() const& noexcept {return this->local_datetime_;}
|
|
|
|
local_date const& as_local_date() const& noexcept {return this->local_date_;}
|
|
|
|
local_time const& as_local_time() const& noexcept {return this->local_time_;}
|
|
|
|
array const& as_array() const& noexcept {return this->array_.value();}
|
|
|
|
table const& as_table() const& noexcept {return this->table_.value();}
|
|
|
|
|
|
|
|
boolean & as_boolean() & noexcept {return this->boolean_;}
|
|
|
|
integer & as_integer() & noexcept {return this->integer_;}
|
|
|
|
floating & as_float() & noexcept {return this->floating_;}
|
|
|
|
string & as_string() & noexcept {return this->string_;}
|
|
|
|
offset_datetime& as_offset_datetime() & noexcept {return this->offset_datetime_;}
|
|
|
|
local_datetime & as_local_datetime() & noexcept {return this->local_datetime_;}
|
|
|
|
local_date & as_local_date() & noexcept {return this->local_date_;}
|
|
|
|
local_time & as_local_time() & noexcept {return this->local_time_;}
|
|
|
|
array & as_array() & noexcept {return this->array_.value();}
|
|
|
|
table & as_table() & noexcept {return this->table_.value();}
|
|
|
|
|
|
|
|
boolean && as_boolean() && noexcept {return std::move(this->boolean_);}
|
|
|
|
integer && as_integer() && noexcept {return std::move(this->integer_);}
|
|
|
|
floating && as_float() && noexcept {return std::move(this->floating_);}
|
|
|
|
string && as_string() && noexcept {return std::move(this->string_);}
|
|
|
|
offset_datetime&& as_offset_datetime() && noexcept {return std::move(this->offset_datetime_);}
|
|
|
|
local_datetime && as_local_datetime() && noexcept {return std::move(this->local_datetime_);}
|
|
|
|
local_date && as_local_date() && noexcept {return std::move(this->local_date_);}
|
|
|
|
local_time && as_local_time() && noexcept {return std::move(this->local_time_);}
|
|
|
|
array && as_array() && noexcept {return std::move(this->array_.value());}
|
|
|
|
table && as_table() && noexcept {return std::move(this->table_.value());}
|
2019-04-27 07:22:23 +00:00
|
|
|
|
2019-04-25 13:32:39 +00:00
|
|
|
std::string comment() const
|
|
|
|
{
|
|
|
|
return this->region_info_->comment();
|
|
|
|
}
|
|
|
|
std::string comment_before() const
|
|
|
|
{
|
|
|
|
return this->region_info_->comment_before();
|
|
|
|
}
|
|
|
|
std::string comment_inline() const
|
|
|
|
{
|
|
|
|
return this->region_info_->comment_inline();
|
|
|
|
}
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
private:
|
|
|
|
|
|
|
|
void cleanup() noexcept
|
|
|
|
{
|
|
|
|
switch(this->type_)
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
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;
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-13 07:13:05 +00:00
|
|
|
// for error messages
|
|
|
|
friend region_base const& detail::get_region(const value&);
|
2018-12-10 06:06:28 +00:00
|
|
|
|
2019-03-04 06:01:28 +00:00
|
|
|
template<typename Region>
|
|
|
|
friend void detail::change_region(value&, Region&&);
|
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
private:
|
|
|
|
|
|
|
|
using array_storage = detail::storage<array>;
|
|
|
|
using table_storage = detail::storage<table>;
|
|
|
|
|
|
|
|
value_t type_;
|
2017-04-20 01:44:11 +00:00
|
|
|
|
2018-12-09 09:03:20 +00:00
|
|
|
// for error message information.
|
|
|
|
std::shared_ptr<region_base> region_info_;
|
|
|
|
|
|
|
|
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_;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2018-12-10 06:06:28 +00:00
|
|
|
namespace detail
|
|
|
|
{
|
2018-12-13 07:13:05 +00:00
|
|
|
inline region_base const& get_region(const value& v)
|
2018-12-10 06:06:28 +00:00
|
|
|
{
|
2018-12-13 07:13:05 +00:00
|
|
|
return *(v.region_info_);
|
2018-12-10 06:06:28 +00:00
|
|
|
}
|
2019-03-04 06:01:28 +00:00
|
|
|
|
|
|
|
template<typename Region>
|
|
|
|
void change_region(value& v, Region&& reg)
|
|
|
|
{
|
|
|
|
using region_type = typename std::remove_reference<
|
|
|
|
typename std::remove_cv<Region>::type
|
|
|
|
>::type;
|
|
|
|
|
|
|
|
std::shared_ptr<region_base> new_reg =
|
|
|
|
std::make_shared<region_type>(std::forward<region_type>(reg));
|
|
|
|
v.region_info_ = new_reg;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-29 11:53:49 +00:00
|
|
|
template<value_t Expected>
|
|
|
|
[[noreturn]] inline void throw_bad_cast(value_t actual, const ::toml::value& v)
|
|
|
|
{
|
|
|
|
throw type_error(detail::format_underline(concat_to_string(
|
|
|
|
"[error] toml::value bad_cast to ", Expected), {
|
|
|
|
{std::addressof(get_region(v)),
|
|
|
|
concat_to_string("the actual type is ", actual)}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2019-05-29 11:18:15 +00:00
|
|
|
template<value_t T>
|
|
|
|
struct switch_cast;
|
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::Boolean>
|
2017-04-20 01:44:11 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::boolean& invoke(value& v) {return v.as_boolean();}
|
|
|
|
static ::toml::boolean const& invoke(value const& v) {return v.as_boolean();}
|
|
|
|
static ::toml::boolean&& invoke(value&& v) {return std::move(v).as_boolean();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::Integer>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::integer& invoke(value& v) {return v.as_integer();}
|
|
|
|
static ::toml::integer const& invoke(value const& v) {return v.as_integer();}
|
|
|
|
static ::toml::integer&& invoke(value&& v) {return std::move(v).as_integer();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::Float>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::floating& invoke(value& v) {return v.as_float();}
|
|
|
|
static ::toml::floating const& invoke(value const& v) {return v.as_float();}
|
|
|
|
static ::toml::floating&& invoke(value&& v) {return std::move(v).as_float();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::String>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::string& invoke(value& v) {return v.as_string();}
|
|
|
|
static ::toml::string const& invoke(value const& v) {return v.as_string();}
|
|
|
|
static ::toml::string&& invoke(value&& v) {return std::move(v).as_string();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::OffsetDatetime>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::offset_datetime& invoke(value& v) {return v.as_offset_datetime();}
|
|
|
|
static ::toml::offset_datetime const& invoke(value const& v) {return v.as_offset_datetime();}
|
|
|
|
static ::toml::offset_datetime&& invoke(value&& v) {return std::move(v).as_offset_datetime();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::LocalDatetime>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::local_datetime& invoke(value& v) {return v.as_local_datetime();}
|
|
|
|
static ::toml::local_datetime const& invoke(value const& v) {return v.as_local_datetime();}
|
|
|
|
static ::toml::local_datetime&& invoke(value&& v) {return std::move(v).as_local_datetime();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::LocalDate>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::local_date& invoke(value& v) {return v.as_local_date();}
|
|
|
|
static ::toml::local_date const& invoke(value const& v) {return v.as_local_date();}
|
|
|
|
static ::toml::local_date&& invoke(value&& v) {return std::move(v).as_local_date();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::LocalTime>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::local_time& invoke(value& v) {return v.as_local_time();}
|
|
|
|
static ::toml::local_time const& invoke(value const& v) {return v.as_local_time();}
|
|
|
|
static ::toml::local_time&& invoke(value&& v) {return std::move(v).as_local_time();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::Array>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::array& invoke(value& v) {return v.as_array();}
|
|
|
|
static ::toml::array const& invoke(value const& v) {return v.as_array();}
|
|
|
|
static ::toml::array&& invoke(value&& v) {return std::move(v).as_array();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
template<>
|
|
|
|
struct switch_cast<value_t::Table>
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-30 05:39:15 +00:00
|
|
|
static ::toml::table& invoke(value& v) {return v.as_table();}
|
|
|
|
static ::toml::table const& invoke(value const& v) {return v.as_table();}
|
|
|
|
static ::toml::table&& invoke(value&& v) {return std::move(v).as_table();}
|
2018-12-09 09:03:20 +00:00
|
|
|
};
|
2019-05-29 11:18:15 +00:00
|
|
|
}// detail
|
2017-04-20 01:44:11 +00:00
|
|
|
|
2017-04-19 04:37:02 +00:00
|
|
|
template<value_t T>
|
2018-12-09 09:03:20 +00:00
|
|
|
typename detail::toml_default_type<T>::type& value::cast() &
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
|
|
|
if(T != this->type_)
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-29 11:53:49 +00:00
|
|
|
detail::throw_bad_cast<T>(this->type_, *this);
|
2018-12-09 09:03:20 +00:00
|
|
|
}
|
2019-05-29 11:18:15 +00:00
|
|
|
return detail::switch_cast<T>::invoke(*this);
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
|
|
|
template<value_t T>
|
2018-12-09 09:03:20 +00:00
|
|
|
typename detail::toml_default_type<T>::type const& value::cast() const&
|
2017-04-19 04:37:02 +00:00
|
|
|
{
|
|
|
|
if(T != this->type_)
|
2018-12-09 09:03:20 +00:00
|
|
|
{
|
2019-05-29 11:53:49 +00:00
|
|
|
detail::throw_bad_cast<T>(this->type_, *this);
|
2018-12-09 09:03:20 +00:00
|
|
|
}
|
2019-05-29 11:18:15 +00:00
|
|
|
return detail::switch_cast<T>::invoke(*this);
|
2017-04-19 04:37:02 +00:00
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
template<value_t T>
|
|
|
|
typename detail::toml_default_type<T>::type&& value::cast() &&
|
|
|
|
{
|
|
|
|
if(T != this->type_)
|
|
|
|
{
|
2019-05-29 11:53:49 +00:00
|
|
|
detail::throw_bad_cast<T>(this->type_, *this);
|
2018-12-09 09:03:20 +00:00
|
|
|
}
|
2019-05-29 11:18:15 +00:00
|
|
|
return detail::switch_cast<T>::invoke(std::move(*this));
|
2018-12-09 09:03:20 +00:00
|
|
|
}
|
2017-04-19 04:37:39 +00:00
|
|
|
|
2017-04-20 05:22:22 +00:00
|
|
|
inline bool operator==(const toml::value& lhs, const toml::value& rhs)
|
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
if(lhs.type() != rhs.type()){return false;}
|
2017-04-20 05:22:22 +00:00
|
|
|
switch(lhs.type())
|
|
|
|
{
|
|
|
|
case value_t::Boolean :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_boolean() == rhs.as_boolean();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::Integer :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_integer() == rhs.as_integer();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::Float :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_float() == rhs.as_float();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::String :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_string() == rhs.as_string();
|
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
case value_t::OffsetDatetime:
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_offset_datetime() == rhs.as_offset_datetime();
|
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
case value_t::LocalDatetime:
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_local_datetime() == rhs.as_local_datetime();
|
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
case value_t::LocalDate:
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_local_date() == rhs.as_local_date();
|
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
case value_t::LocalTime:
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_local_time() == rhs.as_local_time();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::Array :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_array() == rhs.as_array();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::Table :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_table() == rhs.as_table();
|
|
|
|
}
|
|
|
|
case value_t::Empty : {return true; }
|
|
|
|
case value_t::Unknown : {return false;}
|
|
|
|
default: {return false;}
|
2017-04-20 05:22:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
inline bool operator<(const toml::value& lhs, const toml::value& rhs)
|
|
|
|
{
|
2018-12-09 09:03:20 +00:00
|
|
|
if(lhs.type() != rhs.type()){return (lhs.type() < rhs.type());}
|
2017-04-20 05:22:22 +00:00
|
|
|
switch(lhs.type())
|
|
|
|
{
|
|
|
|
case value_t::Boolean :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_boolean() < rhs.as_boolean();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::Integer :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_integer() < rhs.as_integer();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::Float :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_float() < rhs.as_float();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::String :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_string() < rhs.as_string();
|
|
|
|
}
|
2019-02-13 04:34:26 +00:00
|
|
|
case value_t::OffsetDatetime:
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_offset_datetime() < rhs.as_offset_datetime();
|
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
case value_t::LocalDatetime:
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_local_datetime() < rhs.as_local_datetime();
|
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
case value_t::LocalDate:
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_local_date() < rhs.as_local_date();
|
|
|
|
}
|
2018-12-09 09:03:20 +00:00
|
|
|
case value_t::LocalTime:
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_local_time() < rhs.as_local_time();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::Array :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_array() < rhs.as_array();
|
|
|
|
}
|
2017-04-20 05:22:22 +00:00
|
|
|
case value_t::Table :
|
2019-05-29 11:18:15 +00:00
|
|
|
{
|
|
|
|
return lhs.as_table() < rhs.as_table();
|
|
|
|
}
|
|
|
|
case value_t::Empty : {return false;}
|
|
|
|
case value_t::Unknown : {return false;}
|
|
|
|
default: {return false;}
|
2017-04-20 05:22:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator!=(const toml::value& lhs, const toml::value& rhs)
|
|
|
|
{
|
|
|
|
return !(lhs == rhs);
|
|
|
|
}
|
|
|
|
inline bool operator<=(const toml::value& lhs, const toml::value& rhs)
|
|
|
|
{
|
|
|
|
return (lhs < rhs) || (lhs == rhs);
|
|
|
|
}
|
|
|
|
inline bool operator>(const toml::value& lhs, const toml::value& rhs)
|
|
|
|
{
|
|
|
|
return !(lhs <= rhs);
|
|
|
|
}
|
|
|
|
inline bool operator>=(const toml::value& lhs, const toml::value& rhs)
|
|
|
|
{
|
|
|
|
return !(lhs < rhs);
|
|
|
|
}
|
|
|
|
|
2019-03-20 11:46:22 +00:00
|
|
|
inline std::string format_error(const std::string& err_msg,
|
|
|
|
const toml::value& v, const std::string& comment,
|
|
|
|
std::vector<std::string> hints = {})
|
2019-03-15 03:38:37 +00:00
|
|
|
{
|
2019-03-20 11:46:22 +00:00
|
|
|
return detail::format_underline(err_msg,
|
|
|
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
|
|
|
{std::addressof(detail::get_region(v)), comment}
|
|
|
|
}, std::move(hints));
|
2019-03-15 03:38:37 +00:00
|
|
|
}
|
|
|
|
|
2019-03-20 11:46:22 +00:00
|
|
|
inline std::string format_error(const std::string& err_msg,
|
|
|
|
const toml::value& v1, const std::string& comment1,
|
|
|
|
const toml::value& v2, const std::string& comment2,
|
|
|
|
std::vector<std::string> hints = {})
|
2018-12-16 12:46:32 +00:00
|
|
|
{
|
2019-03-20 11:46:22 +00:00
|
|
|
return detail::format_underline(err_msg,
|
|
|
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
|
|
|
{std::addressof(detail::get_region(v1)), comment1},
|
|
|
|
{std::addressof(detail::get_region(v2)), comment2}
|
|
|
|
}, std::move(hints));
|
2018-12-16 12:50:18 +00:00
|
|
|
}
|
|
|
|
|
2019-03-20 11:46:22 +00:00
|
|
|
inline std::string format_error(const std::string& err_msg,
|
|
|
|
const toml::value& v1, const std::string& comment1,
|
|
|
|
const toml::value& v2, const std::string& comment2,
|
|
|
|
const toml::value& v3, const std::string& comment3,
|
|
|
|
std::vector<std::string> hints = {})
|
2018-12-16 12:50:18 +00:00
|
|
|
{
|
2019-03-20 11:46:22 +00:00
|
|
|
return detail::format_underline(err_msg,
|
|
|
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
|
|
|
{std::addressof(detail::get_region(v1)), comment1},
|
|
|
|
{std::addressof(detail::get_region(v2)), comment2},
|
|
|
|
{std::addressof(detail::get_region(v3)), comment3}
|
|
|
|
}, std::move(hints));
|
2018-12-16 12:46:32 +00:00
|
|
|
}
|
|
|
|
|
2019-02-13 04:36:55 +00:00
|
|
|
template<typename Visitor>
|
|
|
|
detail::return_type_of_t<Visitor, const toml::boolean&>
|
|
|
|
visit(Visitor&& visitor, const toml::value& v)
|
|
|
|
{
|
|
|
|
switch(v.type())
|
|
|
|
{
|
2019-05-29 11:18:15 +00:00
|
|
|
case value_t::Boolean : {return visitor(v.as_boolean ());}
|
|
|
|
case value_t::Integer : {return visitor(v.as_integer ());}
|
|
|
|
case value_t::Float : {return visitor(v.as_float ());}
|
|
|
|
case value_t::String : {return visitor(v.as_string ());}
|
|
|
|
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
|
|
|
|
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
|
|
|
|
case value_t::LocalDate : {return visitor(v.as_local_date ());}
|
|
|
|
case value_t::LocalTime : {return visitor(v.as_local_time ());}
|
|
|
|
case value_t::Array : {return visitor(v.as_array ());}
|
|
|
|
case value_t::Table : {return visitor(v.as_table ());}
|
2019-02-13 04:50:33 +00:00
|
|
|
case value_t::Empty : break;
|
|
|
|
case value_t::Unknown : break;
|
|
|
|
default: break;
|
2019-02-13 04:36:55 +00:00
|
|
|
}
|
|
|
|
throw std::runtime_error(format_error("[error] toml::visit: toml::value "
|
|
|
|
"does not have any valid value.", v, "here"));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Visitor>
|
|
|
|
detail::return_type_of_t<Visitor, toml::boolean&>
|
|
|
|
visit(Visitor&& visitor, toml::value& v)
|
|
|
|
{
|
|
|
|
switch(v.type())
|
|
|
|
{
|
2019-05-29 11:18:15 +00:00
|
|
|
case value_t::Boolean : {return visitor(v.as_boolean ());}
|
|
|
|
case value_t::Integer : {return visitor(v.as_integer ());}
|
|
|
|
case value_t::Float : {return visitor(v.as_float ());}
|
|
|
|
case value_t::String : {return visitor(v.as_string ());}
|
|
|
|
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
|
|
|
|
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
|
|
|
|
case value_t::LocalDate : {return visitor(v.as_local_date ());}
|
|
|
|
case value_t::LocalTime : {return visitor(v.as_local_time ());}
|
|
|
|
case value_t::Array : {return visitor(v.as_array ());}
|
|
|
|
case value_t::Table : {return visitor(v.as_table ());}
|
2019-02-13 04:50:33 +00:00
|
|
|
case value_t::Empty : break;
|
|
|
|
case value_t::Unknown : break;
|
|
|
|
default: break;
|
2019-02-13 04:36:55 +00:00
|
|
|
}
|
|
|
|
throw std::runtime_error(format_error("[error] toml::visit: toml::value "
|
|
|
|
"does not have any valid value.", v, "here"));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Visitor>
|
2019-03-18 01:53:04 +00:00
|
|
|
detail::return_type_of_t<Visitor, toml::boolean&&>
|
2019-02-13 04:36:55 +00:00
|
|
|
visit(Visitor&& visitor, toml::value&& v)
|
|
|
|
{
|
|
|
|
switch(v.type())
|
|
|
|
{
|
2019-05-29 11:18:15 +00:00
|
|
|
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::Float : {return visitor(std::move(v.as_float ()));}
|
|
|
|
case value_t::String : {return visitor(std::move(v.as_string ()));}
|
|
|
|
case value_t::OffsetDatetime: {return visitor(std::move(v.as_offset_datetime()));}
|
|
|
|
case value_t::LocalDatetime : {return visitor(std::move(v.as_local_datetime ()));}
|
|
|
|
case value_t::LocalDate : {return visitor(std::move(v.as_local_date ()));}
|
|
|
|
case value_t::LocalTime : {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 ()));}
|
2019-02-13 04:50:33 +00:00
|
|
|
case value_t::Empty : break;
|
|
|
|
case value_t::Unknown : break;
|
|
|
|
default: break;
|
2019-02-13 04:36:55 +00:00
|
|
|
}
|
|
|
|
throw std::runtime_error(format_error("[error] toml::visit: toml::value "
|
|
|
|
"does not have any valid value.", v, "here"));
|
|
|
|
}
|
|
|
|
|
2017-04-16 06:12:39 +00:00
|
|
|
}// toml
|
2017-04-21 04:14:53 +00:00
|
|
|
#endif// TOML11_VALUE
|