mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-09-17 00:38:08 +08:00
2164 lines
86 KiB
C++
2164 lines
86 KiB
C++
#ifndef TOML11_VALUE_HPP
|
|
#define TOML11_VALUE_HPP
|
|
|
|
#include "color.hpp"
|
|
#include "datetime.hpp"
|
|
#include "exception.hpp"
|
|
#include "error_info.hpp"
|
|
#include "format.hpp"
|
|
#include "region.hpp"
|
|
#include "source_location.hpp"
|
|
#include "storage.hpp"
|
|
#include "traits.hpp"
|
|
#include "value_t.hpp"
|
|
#include "version.hpp" // IWYU pragma: keep < TOML11_HAS_STRING_VIEW
|
|
|
|
#ifdef TOML11_HAS_STRING_VIEW
|
|
#include <string_view>
|
|
#endif
|
|
|
|
#include <cassert>
|
|
|
|
namespace toml
|
|
{
|
|
template<typename TypeConfig>
|
|
class basic_value;
|
|
|
|
struct type_error final : public ::toml::exception
|
|
{
|
|
public:
|
|
type_error(std::string what_arg, source_location loc)
|
|
: what_(std::move(what_arg)), loc_(std::move(loc))
|
|
{}
|
|
~type_error() noexcept override = default;
|
|
|
|
const char* what() const noexcept override {return what_.c_str();}
|
|
|
|
source_location const& location() const noexcept {return loc_;}
|
|
|
|
private:
|
|
std::string what_;
|
|
source_location loc_;
|
|
};
|
|
|
|
// only for internal use
|
|
namespace detail
|
|
{
|
|
template<typename TC>
|
|
error_info make_type_error(const basic_value<TC>&, const std::string&, const value_t);
|
|
|
|
template<typename TC>
|
|
error_info make_not_found_error(const basic_value<TC>&, const std::string&, const std::string&);
|
|
|
|
template<typename TC>
|
|
void change_region_of_value(basic_value<TC>&, const basic_value<TC>&);
|
|
|
|
template<typename TC, value_t V>
|
|
struct getter;
|
|
} // detail
|
|
|
|
template<typename TypeConfig>
|
|
class basic_value
|
|
{
|
|
public:
|
|
|
|
using config_type = TypeConfig;
|
|
using key_type = typename config_type::string_type;
|
|
using value_type = basic_value<config_type>;
|
|
using boolean_type = typename config_type::boolean_type;
|
|
using integer_type = typename config_type::integer_type;
|
|
using floating_type = typename config_type::floating_type;
|
|
using string_type = typename config_type::string_type;
|
|
using local_time_type = ::toml::local_time;
|
|
using local_date_type = ::toml::local_date;
|
|
using local_datetime_type = ::toml::local_datetime;
|
|
using offset_datetime_type = ::toml::offset_datetime;
|
|
using array_type = typename config_type::template array_type<value_type>;
|
|
using table_type = typename config_type::template table_type<key_type, value_type>;
|
|
using comment_type = typename config_type::comment_type;
|
|
|
|
private:
|
|
|
|
using region_type = detail::region;
|
|
|
|
public:
|
|
|
|
basic_value() noexcept
|
|
: type_(value_t::empty), empty_('\0'), region_{}, comments_{}
|
|
{}
|
|
~basic_value() noexcept {this->cleanup();}
|
|
|
|
// copy/move constructor/assigner ===================================== {{{
|
|
|
|
basic_value(const basic_value& v)
|
|
: type_(v.type_), region_(v.region_), comments_(v.comments_)
|
|
{
|
|
switch(this->type_)
|
|
{
|
|
case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
|
|
case value_t::integer : assigner(integer_ , v.integer_ ); break;
|
|
case value_t::floating : assigner(floating_ , v.floating_ ); break;
|
|
case value_t::string : assigner(string_ , v.string_ ); break;
|
|
case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
|
|
case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
|
|
case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
|
|
case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
|
|
case value_t::array : assigner(array_ , v.array_ ); break;
|
|
case value_t::table : assigner(table_ , v.table_ ); break;
|
|
default : assigner(empty_ , '\0' ); break;
|
|
}
|
|
}
|
|
basic_value(basic_value&& v)
|
|
: type_(v.type()), region_(std::move(v.region_)),
|
|
comments_(std::move(v.comments_))
|
|
{
|
|
switch(this->type_)
|
|
{
|
|
case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
|
|
case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
|
|
case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
|
|
case value_t::string : assigner(string_ , std::move(v.string_ )); break;
|
|
case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
|
|
case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
|
|
case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
|
|
case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
|
|
case value_t::array : assigner(array_ , std::move(v.array_ )); break;
|
|
case value_t::table : assigner(table_ , std::move(v.table_ )); break;
|
|
default : assigner(empty_ , '\0' ); break;
|
|
}
|
|
}
|
|
|
|
basic_value& operator=(const basic_value& v)
|
|
{
|
|
if(this == std::addressof(v)) {return *this;}
|
|
|
|
this->cleanup();
|
|
this->type_ = v.type_;
|
|
this->region_ = v.region_;
|
|
this->comments_ = v.comments_;
|
|
switch(this->type_)
|
|
{
|
|
case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
|
|
case value_t::integer : assigner(integer_ , v.integer_ ); break;
|
|
case value_t::floating : assigner(floating_ , v.floating_ ); break;
|
|
case value_t::string : assigner(string_ , v.string_ ); break;
|
|
case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
|
|
case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
|
|
case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
|
|
case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
|
|
case value_t::array : assigner(array_ , v.array_ ); break;
|
|
case value_t::table : assigner(table_ , v.table_ ); break;
|
|
default : assigner(empty_ , '\0' ); break;
|
|
}
|
|
return *this;
|
|
}
|
|
basic_value& operator=(basic_value&& v)
|
|
{
|
|
if(this == std::addressof(v)) {return *this;}
|
|
|
|
this->cleanup();
|
|
this->type_ = v.type_;
|
|
this->region_ = std::move(v.region_);
|
|
this->comments_ = std::move(v.comments_);
|
|
switch(this->type_)
|
|
{
|
|
case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
|
|
case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
|
|
case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
|
|
case value_t::string : assigner(string_ , std::move(v.string_ )); break;
|
|
case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
|
|
case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
|
|
case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
|
|
case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
|
|
case value_t::array : assigner(array_ , std::move(v.array_ )); break;
|
|
case value_t::table : assigner(table_ , std::move(v.table_ )); break;
|
|
default : assigner(empty_ , '\0' ); break;
|
|
}
|
|
return *this;
|
|
}
|
|
// }}}
|
|
|
|
// constructor to overwrite commnets ================================== {{{
|
|
|
|
basic_value(basic_value v, std::vector<std::string> com)
|
|
: type_(v.type()), region_(std::move(v.region_)),
|
|
comments_(std::move(com))
|
|
{
|
|
switch(this->type_)
|
|
{
|
|
case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
|
|
case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
|
|
case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
|
|
case value_t::string : assigner(string_ , std::move(v.string_ )); break;
|
|
case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
|
|
case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
|
|
case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
|
|
case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
|
|
case value_t::array : assigner(array_ , std::move(v.array_ )); break;
|
|
case value_t::table : assigner(table_ , std::move(v.table_ )); break;
|
|
default : assigner(empty_ , '\0' ); break;
|
|
}
|
|
}
|
|
// }}}
|
|
|
|
// conversion between different basic_values ========================== {{{
|
|
|
|
template<typename TI>
|
|
basic_value(basic_value<TI> other)
|
|
: type_(other.type_),
|
|
region_(std::move(other.region_)),
|
|
comments_(std::move(other.comments_))
|
|
{
|
|
switch(other.type_)
|
|
{
|
|
// use auto-convert in constructor
|
|
case value_t::boolean : assigner(boolean_ , std::move(other.boolean_ )); break;
|
|
case value_t::integer : assigner(integer_ , std::move(other.integer_ )); break;
|
|
case value_t::floating : assigner(floating_ , std::move(other.floating_ )); break;
|
|
case value_t::string : assigner(string_ , std::move(other.string_ )); break;
|
|
case value_t::offset_datetime: assigner(offset_datetime_, std::move(other.offset_datetime_)); break;
|
|
case value_t::local_datetime : assigner(local_datetime_ , std::move(other.local_datetime_ )); break;
|
|
case value_t::local_date : assigner(local_date_ , std::move(other.local_date_ )); break;
|
|
case value_t::local_time : assigner(local_time_ , std::move(other.local_time_ )); break;
|
|
|
|
// may have different container type
|
|
case value_t::array :
|
|
{
|
|
array_type tmp(
|
|
std::make_move_iterator(other.array_.value.get().begin()),
|
|
std::make_move_iterator(other.array_.value.get().end()));
|
|
assigner(array_, array_storage(
|
|
detail::storage<array_type>(std::move(tmp)),
|
|
other.array_.format
|
|
));
|
|
break;
|
|
}
|
|
case value_t::table :
|
|
{
|
|
table_type tmp(
|
|
std::make_move_iterator(other.table_.value.get().begin()),
|
|
std::make_move_iterator(other.table_.value.get().end()));
|
|
assigner(table_, table_storage(
|
|
detail::storage<table_type>(std::move(tmp)),
|
|
other.table_.format
|
|
));
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
template<typename TI>
|
|
basic_value(basic_value<TI> other, std::vector<std::string> com)
|
|
: type_(other.type_),
|
|
region_(std::move(other.region_)),
|
|
comments_(std::move(com))
|
|
{
|
|
switch(other.type_)
|
|
{
|
|
// use auto-convert in constructor
|
|
case value_t::boolean : assigner(boolean_ , std::move(other.boolean_ )); break;
|
|
case value_t::integer : assigner(integer_ , std::move(other.integer_ )); break;
|
|
case value_t::floating : assigner(floating_ , std::move(other.floating_ )); break;
|
|
case value_t::string : assigner(string_ , std::move(other.string_ )); break;
|
|
case value_t::offset_datetime: assigner(offset_datetime_, std::move(other.offset_datetime_)); break;
|
|
case value_t::local_datetime : assigner(local_datetime_ , std::move(other.local_datetime_ )); break;
|
|
case value_t::local_date : assigner(local_date_ , std::move(other.local_date_ )); break;
|
|
case value_t::local_time : assigner(local_time_ , std::move(other.local_time_ )); break;
|
|
|
|
// may have different container type
|
|
case value_t::array :
|
|
{
|
|
array_type tmp(
|
|
std::make_move_iterator(other.array_.value.get().begin()),
|
|
std::make_move_iterator(other.array_.value.get().end()));
|
|
assigner(array_, array_storage(
|
|
detail::storage<array_type>(std::move(tmp)),
|
|
other.array_.format
|
|
));
|
|
break;
|
|
}
|
|
case value_t::table :
|
|
{
|
|
table_type tmp(
|
|
std::make_move_iterator(other.table_.value.get().begin()),
|
|
std::make_move_iterator(other.table_.value.get().end()));
|
|
assigner(table_, table_storage(
|
|
detail::storage<table_type>(std::move(tmp)),
|
|
other.table_.format
|
|
));
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
template<typename TI>
|
|
basic_value& operator=(basic_value<TI> other)
|
|
{
|
|
this->cleanup();
|
|
this->region_ = other.region_;
|
|
this->comments_ = comment_type(other.comments_);
|
|
this->type_ = other.type_;
|
|
switch(other.type_)
|
|
{
|
|
// use auto-convert in constructor
|
|
case value_t::boolean : assigner(boolean_ , std::move(other.boolean_ )); break;
|
|
case value_t::integer : assigner(integer_ , std::move(other.integer_ )); break;
|
|
case value_t::floating : assigner(floating_ , std::move(other.floating_ )); break;
|
|
case value_t::string : assigner(string_ , std::move(other.string_ )); break;
|
|
case value_t::offset_datetime: assigner(offset_datetime_, std::move(other.offset_datetime_)); break;
|
|
case value_t::local_datetime : assigner(local_datetime_ , std::move(other.local_datetime_ )); break;
|
|
case value_t::local_date : assigner(local_date_ , std::move(other.local_date_ )); break;
|
|
case value_t::local_time : assigner(local_time_ , std::move(other.local_time_ )); break;
|
|
|
|
// may have different container type
|
|
case value_t::array :
|
|
{
|
|
array_type tmp(
|
|
std::make_move_iterator(other.array_.value.get().begin()),
|
|
std::make_move_iterator(other.array_.value.get().end()));
|
|
assigner(array_, array_storage(
|
|
detail::storage<array_type>(std::move(tmp)),
|
|
other.array_.format
|
|
));
|
|
break;
|
|
}
|
|
case value_t::table :
|
|
{
|
|
table_type tmp(
|
|
std::make_move_iterator(other.table_.value.get().begin()),
|
|
std::make_move_iterator(other.table_.value.get().end()));
|
|
assigner(table_, table_storage(
|
|
detail::storage<table_type>(std::move(tmp)),
|
|
other.table_.format
|
|
));
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
return *this;
|
|
}
|
|
// }}}
|
|
|
|
// constructor (boolean) ============================================== {{{
|
|
|
|
basic_value(boolean_type x)
|
|
: basic_value(x, boolean_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(boolean_type x, boolean_format_info fmt)
|
|
: basic_value(x, fmt, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(boolean_type x, std::vector<std::string> com)
|
|
: basic_value(x, boolean_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(boolean_type x, boolean_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(x, fmt, std::move(com), region_type{})
|
|
{}
|
|
basic_value(boolean_type x, boolean_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::boolean), boolean_(boolean_storage(x, fmt)),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(boolean_type x)
|
|
{
|
|
boolean_format_info fmt;
|
|
if(this->is_boolean())
|
|
{
|
|
fmt = this->as_boolean_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::boolean;
|
|
this->region_ = region_type{};
|
|
assigner(this->boolean_, boolean_storage(x, fmt));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (integer) ============================================== {{{
|
|
|
|
basic_value(integer_type x)
|
|
: basic_value(std::move(x), integer_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(integer_type x, integer_format_info fmt)
|
|
: basic_value(std::move(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(integer_type x, std::vector<std::string> com)
|
|
: basic_value(std::move(x), integer_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(integer_type x, integer_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(std::move(x), std::move(fmt), std::move(com), region_type{})
|
|
{}
|
|
basic_value(integer_type x, integer_format_info fmt, std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::integer), integer_(integer_storage(std::move(x), std::move(fmt))),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(integer_type x)
|
|
{
|
|
integer_format_info fmt;
|
|
if(this->is_integer())
|
|
{
|
|
fmt = this->as_integer_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::integer;
|
|
this->region_ = region_type{};
|
|
assigner(this->integer_, integer_storage(std::move(x), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
|
|
template<typename T>
|
|
using enable_if_integer_like_t = cxx::enable_if_t<cxx::conjunction<
|
|
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, boolean_type>>,
|
|
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, integer_type>>,
|
|
std::is_integral<cxx::remove_cvref_t<T>>
|
|
>::value, std::nullptr_t>;
|
|
|
|
public:
|
|
|
|
template<typename T, enable_if_integer_like_t<T> = nullptr>
|
|
basic_value(T x)
|
|
: basic_value(std::move(x), integer_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
template<typename T, enable_if_integer_like_t<T> = nullptr>
|
|
basic_value(T x, integer_format_info fmt)
|
|
: basic_value(std::move(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
template<typename T, enable_if_integer_like_t<T> = nullptr>
|
|
basic_value(T x, std::vector<std::string> com)
|
|
: basic_value(std::move(x), integer_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
template<typename T, enable_if_integer_like_t<T> = nullptr>
|
|
basic_value(T x, integer_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(std::move(x), std::move(fmt), std::move(com), region_type{})
|
|
{}
|
|
template<typename T, enable_if_integer_like_t<T> = nullptr>
|
|
basic_value(T x, integer_format_info fmt, std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::integer), integer_(integer_storage(std::move(x), std::move(fmt))),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
template<typename T, enable_if_integer_like_t<T> = nullptr>
|
|
basic_value& operator=(T x)
|
|
{
|
|
integer_format_info fmt;
|
|
if(this->is_integer())
|
|
{
|
|
fmt = this->as_integer_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::integer;
|
|
this->region_ = region_type{};
|
|
assigner(this->integer_, integer_storage(x, std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (floating) ============================================= {{{
|
|
|
|
basic_value(floating_type x)
|
|
: basic_value(std::move(x), floating_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(floating_type x, floating_format_info fmt)
|
|
: basic_value(std::move(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(floating_type x, std::vector<std::string> com)
|
|
: basic_value(std::move(x), floating_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(floating_type x, floating_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(std::move(x), std::move(fmt), std::move(com), region_type{})
|
|
{}
|
|
basic_value(floating_type x, floating_format_info fmt, std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::floating), floating_(floating_storage(std::move(x), std::move(fmt))),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(floating_type x)
|
|
{
|
|
floating_format_info fmt;
|
|
if(this->is_floating())
|
|
{
|
|
fmt = this->as_floating_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::floating;
|
|
this->region_ = region_type{};
|
|
assigner(this->floating_, floating_storage(std::move(x), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
|
|
template<typename T>
|
|
using enable_if_floating_like_t = cxx::enable_if_t<cxx::conjunction<
|
|
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, floating_type>>,
|
|
std::is_floating_point<cxx::remove_cvref_t<T>>
|
|
>::value, std::nullptr_t>;
|
|
|
|
public:
|
|
|
|
template<typename T, enable_if_floating_like_t<T> = nullptr>
|
|
basic_value(T x)
|
|
: basic_value(x, floating_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
|
|
template<typename T, enable_if_floating_like_t<T> = nullptr>
|
|
basic_value(T x, floating_format_info fmt)
|
|
: basic_value(x, std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
|
|
template<typename T, enable_if_floating_like_t<T> = nullptr>
|
|
basic_value(T x, std::vector<std::string> com)
|
|
: basic_value(x, floating_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
|
|
template<typename T, enable_if_floating_like_t<T> = nullptr>
|
|
basic_value(T x, floating_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(x, std::move(fmt), std::move(com), region_type{})
|
|
{}
|
|
|
|
template<typename T, enable_if_floating_like_t<T> = nullptr>
|
|
basic_value(T x, floating_format_info fmt, std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::floating), floating_(floating_storage(x, std::move(fmt))),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
|
|
template<typename T, enable_if_floating_like_t<T> = nullptr>
|
|
basic_value& operator=(T x)
|
|
{
|
|
floating_format_info fmt;
|
|
if(this->is_floating())
|
|
{
|
|
fmt = this->as_floating_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::floating;
|
|
this->region_ = region_type{};
|
|
assigner(this->floating_, floating_storage(x, std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (string) =============================================== {{{
|
|
|
|
basic_value(string_type x)
|
|
: basic_value(std::move(x), string_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(string_type x, string_format_info fmt)
|
|
: basic_value(std::move(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(string_type x, std::vector<std::string> com)
|
|
: basic_value(std::move(x), string_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(string_type x, string_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(std::move(x), std::move(fmt), std::move(com), region_type{})
|
|
{}
|
|
basic_value(string_type x, string_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::string), string_(string_storage(std::move(x), std::move(fmt))),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(string_type x)
|
|
{
|
|
string_format_info fmt;
|
|
if(this->is_string())
|
|
{
|
|
fmt = this->as_string_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::string;
|
|
this->region_ = region_type{};
|
|
assigner(this->string_, string_storage(x, std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
// "string literal"
|
|
|
|
basic_value(const typename string_type::value_type* x)
|
|
: basic_value(x, string_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(const typename string_type::value_type* x, string_format_info fmt)
|
|
: basic_value(x, std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(const typename string_type::value_type* x, std::vector<std::string> com)
|
|
: basic_value(x, string_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(const typename string_type::value_type* x, string_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(x, std::move(fmt), std::move(com), region_type{})
|
|
{}
|
|
basic_value(const typename string_type::value_type* x, string_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::string), string_(string_storage(string_type(x), std::move(fmt))),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(const typename string_type::value_type* x)
|
|
{
|
|
string_format_info fmt;
|
|
if(this->is_string())
|
|
{
|
|
fmt = this->as_string_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::string;
|
|
this->region_ = region_type{};
|
|
assigner(this->string_, string_storage(string_type(x), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
#if defined(TOML11_HAS_STRING_VIEW)
|
|
using string_view_type = std::basic_string_view<
|
|
typename string_type::value_type, typename string_type::traits_type>;
|
|
|
|
basic_value(string_view_type x)
|
|
: basic_value(x, string_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(string_view_type x, string_format_info fmt)
|
|
: basic_value(x, std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(string_view_type x, std::vector<std::string> com)
|
|
: basic_value(x, string_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(string_view_type x, string_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(x, std::move(fmt), std::move(com), region_type{})
|
|
{}
|
|
basic_value(string_view_type x, string_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::string), string_(string_storage(string_type(x), std::move(fmt))),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(string_view_type x)
|
|
{
|
|
string_format_info fmt;
|
|
if(this->is_string())
|
|
{
|
|
fmt = this->as_string_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::string;
|
|
this->region_ = region_type{};
|
|
assigner(this->string_, string_storage(string_type(x), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
#endif // TOML11_HAS_STRING_VIEW
|
|
// }}}
|
|
|
|
// constructor (local_date) =========================================== {{{
|
|
|
|
basic_value(local_date_type x)
|
|
: basic_value(x, local_date_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(local_date_type x, local_date_format_info fmt)
|
|
: basic_value(x, fmt, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(local_date_type x, std::vector<std::string> com)
|
|
: basic_value(x, local_date_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(local_date_type x, local_date_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(x, fmt, std::move(com), region_type{})
|
|
{}
|
|
basic_value(local_date_type x, local_date_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::local_date), local_date_(local_date_storage(x, fmt)),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(local_date_type x)
|
|
{
|
|
local_date_format_info fmt;
|
|
if(this->is_local_date())
|
|
{
|
|
fmt = this->as_local_date_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::local_date;
|
|
this->region_ = region_type{};
|
|
assigner(this->local_date_, local_date_storage(x, fmt));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (local_time) =========================================== {{{
|
|
|
|
basic_value(local_time_type x)
|
|
: basic_value(x, local_time_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(local_time_type x, local_time_format_info fmt)
|
|
: basic_value(x, fmt, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(local_time_type x, std::vector<std::string> com)
|
|
: basic_value(x, local_time_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(local_time_type x, local_time_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(x, fmt, std::move(com), region_type{})
|
|
{}
|
|
basic_value(local_time_type x, local_time_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::local_time), local_time_(local_time_storage(x, fmt)),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(local_time_type x)
|
|
{
|
|
local_time_format_info fmt;
|
|
if(this->is_local_time())
|
|
{
|
|
fmt = this->as_local_time_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::local_time;
|
|
this->region_ = region_type{};
|
|
assigner(this->local_time_, local_time_storage(x, fmt));
|
|
return *this;
|
|
}
|
|
|
|
template<typename Rep, typename Period>
|
|
basic_value(const std::chrono::duration<Rep, Period>& x)
|
|
: basic_value(local_time_type(x), local_time_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
template<typename Rep, typename Period>
|
|
basic_value(const std::chrono::duration<Rep, Period>& x, local_time_format_info fmt)
|
|
: basic_value(local_time_type(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
template<typename Rep, typename Period>
|
|
basic_value(const std::chrono::duration<Rep, Period>& x, std::vector<std::string> com)
|
|
: basic_value(local_time_type(x), local_time_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
template<typename Rep, typename Period>
|
|
basic_value(const std::chrono::duration<Rep, Period>& x, local_time_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(local_time_type(x), std::move(fmt), std::move(com), region_type{})
|
|
{}
|
|
template<typename Rep, typename Period>
|
|
basic_value(const std::chrono::duration<Rep, Period>& x,
|
|
local_time_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: basic_value(local_time_type(x), std::move(fmt), std::move(com), std::move(reg))
|
|
{}
|
|
template<typename Rep, typename Period>
|
|
basic_value& operator=(const std::chrono::duration<Rep, Period>& x)
|
|
{
|
|
local_time_format_info fmt;
|
|
if(this->is_local_time())
|
|
{
|
|
fmt = this->as_local_time_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::local_time;
|
|
this->region_ = region_type{};
|
|
assigner(this->local_time_, local_time_storage(local_time_type(x), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (local_datetime) =========================================== {{{
|
|
|
|
basic_value(local_datetime_type x)
|
|
: basic_value(x, local_datetime_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(local_datetime_type x, local_datetime_format_info fmt)
|
|
: basic_value(x, fmt, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(local_datetime_type x, std::vector<std::string> com)
|
|
: basic_value(x, local_datetime_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(local_datetime_type x, local_datetime_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(x, fmt, std::move(com), region_type{})
|
|
{}
|
|
basic_value(local_datetime_type x, local_datetime_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::local_datetime), local_datetime_(local_datetime_storage(x, fmt)),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(local_datetime_type x)
|
|
{
|
|
local_datetime_format_info fmt;
|
|
if(this->is_local_datetime())
|
|
{
|
|
fmt = this->as_local_datetime_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::local_datetime;
|
|
this->region_ = region_type{};
|
|
assigner(this->local_datetime_, local_datetime_storage(x, fmt));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (offset_datetime) =========================================== {{{
|
|
|
|
basic_value(offset_datetime_type x)
|
|
: basic_value(x, offset_datetime_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(offset_datetime_type x, offset_datetime_format_info fmt)
|
|
: basic_value(x, fmt, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(offset_datetime_type x, std::vector<std::string> com)
|
|
: basic_value(x, offset_datetime_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(offset_datetime_type x, offset_datetime_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(x, fmt, std::move(com), region_type{})
|
|
{}
|
|
basic_value(offset_datetime_type x, offset_datetime_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::offset_datetime), offset_datetime_(offset_datetime_storage(x, fmt)),
|
|
region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(offset_datetime_type x)
|
|
{
|
|
offset_datetime_format_info fmt;
|
|
if(this->is_offset_datetime())
|
|
{
|
|
fmt = this->as_offset_datetime_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::offset_datetime;
|
|
this->region_ = region_type{};
|
|
assigner(this->offset_datetime_, offset_datetime_storage(x, fmt));
|
|
return *this;
|
|
}
|
|
|
|
// system_clock::time_point
|
|
|
|
basic_value(std::chrono::system_clock::time_point x)
|
|
: basic_value(offset_datetime_type(x), offset_datetime_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(std::chrono::system_clock::time_point x, offset_datetime_format_info fmt)
|
|
: basic_value(offset_datetime_type(x), fmt, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(std::chrono::system_clock::time_point x, std::vector<std::string> com)
|
|
: basic_value(offset_datetime_type(x), offset_datetime_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(std::chrono::system_clock::time_point x, offset_datetime_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(offset_datetime_type(x), fmt, std::move(com), region_type{})
|
|
{}
|
|
basic_value(std::chrono::system_clock::time_point x, offset_datetime_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: basic_value(offset_datetime_type(x), std::move(fmt), std::move(com), std::move(reg))
|
|
{}
|
|
basic_value& operator=(std::chrono::system_clock::time_point x)
|
|
{
|
|
offset_datetime_format_info fmt;
|
|
if(this->is_offset_datetime())
|
|
{
|
|
fmt = this->as_offset_datetime_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::offset_datetime;
|
|
this->region_ = region_type{};
|
|
assigner(this->offset_datetime_, offset_datetime_storage(offset_datetime_type(x), fmt));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (array) ================================================ {{{
|
|
|
|
basic_value(array_type x)
|
|
: basic_value(std::move(x), array_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(array_type x, array_format_info fmt)
|
|
: basic_value(std::move(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(array_type x, std::vector<std::string> com)
|
|
: basic_value(std::move(x), array_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(array_type x, array_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(std::move(x), fmt, std::move(com), region_type{})
|
|
{}
|
|
basic_value(array_type x, array_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::array), array_(array_storage(
|
|
detail::storage<array_type>(std::move(x)), std::move(fmt)
|
|
)), region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(array_type x)
|
|
{
|
|
array_format_info fmt;
|
|
if(this->is_array())
|
|
{
|
|
fmt = this->as_array_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::array;
|
|
this->region_ = region_type{};
|
|
assigner(this->array_, array_storage(
|
|
detail::storage<array_type>(std::move(x)), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
|
|
template<typename T>
|
|
using enable_if_array_like_t = cxx::enable_if_t<cxx::conjunction<
|
|
cxx::negation<std::is_same<T, array_type>>,
|
|
detail::is_container<T>
|
|
>::value, std::nullptr_t>;
|
|
|
|
public:
|
|
|
|
template<typename T, enable_if_array_like_t<T> = nullptr>
|
|
basic_value(T x)
|
|
: basic_value(std::move(x), array_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
template<typename T, enable_if_array_like_t<T> = nullptr>
|
|
basic_value(T x, array_format_info fmt)
|
|
: basic_value(std::move(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
template<typename T, enable_if_array_like_t<T> = nullptr>
|
|
basic_value(T x, std::vector<std::string> com)
|
|
: basic_value(std::move(x), array_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
template<typename T, enable_if_array_like_t<T> = nullptr>
|
|
basic_value(T x, array_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(std::move(x), fmt, std::move(com), region_type{})
|
|
{}
|
|
template<typename T, enable_if_array_like_t<T> = nullptr>
|
|
basic_value(T x, array_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::array), array_(array_storage(
|
|
detail::storage<array_type>(array_type(
|
|
std::make_move_iterator(x.begin()),
|
|
std::make_move_iterator(x.end()))
|
|
), std::move(fmt)
|
|
)), region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
template<typename T, enable_if_array_like_t<T> = nullptr>
|
|
basic_value& operator=(T x)
|
|
{
|
|
array_format_info fmt;
|
|
if(this->is_array())
|
|
{
|
|
fmt = this->as_array_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::array;
|
|
this->region_ = region_type{};
|
|
|
|
array_type a(std::make_move_iterator(x.begin()),
|
|
std::make_move_iterator(x.end()));
|
|
assigner(this->array_, array_storage(
|
|
detail::storage<array_type>(std::move(a)), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (table) ================================================ {{{
|
|
|
|
basic_value(table_type x)
|
|
: basic_value(std::move(x), table_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(table_type x, table_format_info fmt)
|
|
: basic_value(std::move(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
basic_value(table_type x, std::vector<std::string> com)
|
|
: basic_value(std::move(x), table_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
basic_value(table_type x, table_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(std::move(x), fmt, std::move(com), region_type{})
|
|
{}
|
|
basic_value(table_type x, table_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::table), table_(table_storage(
|
|
detail::storage<table_type>(std::move(x)), std::move(fmt)
|
|
)), region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
basic_value& operator=(table_type x)
|
|
{
|
|
table_format_info fmt;
|
|
if(this->is_table())
|
|
{
|
|
fmt = this->as_table_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::table;
|
|
this->region_ = region_type{};
|
|
assigner(this->table_, table_storage(
|
|
detail::storage<table_type>(std::move(x)), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
// table-like
|
|
|
|
private:
|
|
|
|
template<typename T>
|
|
using enable_if_table_like_t = cxx::enable_if_t<cxx::conjunction<
|
|
cxx::negation<std::is_same<T, table_type>>,
|
|
detail::is_map<T>
|
|
>::value, std::nullptr_t>;
|
|
|
|
public:
|
|
|
|
template<typename T, enable_if_table_like_t<T> = nullptr>
|
|
basic_value(T x)
|
|
: basic_value(std::move(x), table_format_info{}, std::vector<std::string>{}, region_type{})
|
|
{}
|
|
template<typename T, enable_if_table_like_t<T> = nullptr>
|
|
basic_value(T x, table_format_info fmt)
|
|
: basic_value(std::move(x), std::move(fmt), std::vector<std::string>{}, region_type{})
|
|
{}
|
|
template<typename T, enable_if_table_like_t<T> = nullptr>
|
|
basic_value(T x, std::vector<std::string> com)
|
|
: basic_value(std::move(x), table_format_info{}, std::move(com), region_type{})
|
|
{}
|
|
template<typename T, enable_if_table_like_t<T> = nullptr>
|
|
basic_value(T x, table_format_info fmt, std::vector<std::string> com)
|
|
: basic_value(std::move(x), fmt, std::move(com), region_type{})
|
|
{}
|
|
template<typename T, enable_if_table_like_t<T> = nullptr>
|
|
basic_value(T x, table_format_info fmt,
|
|
std::vector<std::string> com, region_type reg)
|
|
: type_(value_t::table), table_(table_storage(
|
|
detail::storage<table_type>(table_type(
|
|
std::make_move_iterator(x.begin()),
|
|
std::make_move_iterator(x.end())
|
|
)), std::move(fmt)
|
|
)), region_(std::move(reg)), comments_(std::move(com))
|
|
{}
|
|
template<typename T, enable_if_table_like_t<T> = nullptr>
|
|
basic_value& operator=(T x)
|
|
{
|
|
table_format_info fmt;
|
|
if(this->is_table())
|
|
{
|
|
fmt = this->as_table_fmt();
|
|
}
|
|
this->cleanup();
|
|
this->type_ = value_t::table;
|
|
this->region_ = region_type{};
|
|
|
|
table_type t(std::make_move_iterator(x.begin()),
|
|
std::make_move_iterator(x.end()));
|
|
assigner(this->table_, table_storage(
|
|
detail::storage<table_type>(std::move(t)), std::move(fmt)));
|
|
return *this;
|
|
}
|
|
|
|
// }}}
|
|
|
|
// constructor (user_defined) ========================================= {{{
|
|
|
|
template<typename T, cxx::enable_if_t<
|
|
detail::has_specialized_into<T>::value, std::nullptr_t> = nullptr>
|
|
basic_value(const T& ud)
|
|
: basic_value(
|
|
into<cxx::remove_cvref_t<T>>::template into_toml<config_type>(ud))
|
|
{}
|
|
template<typename T, cxx::enable_if_t<
|
|
detail::has_specialized_into<T>::value, std::nullptr_t> = nullptr>
|
|
basic_value(const T& ud, std::vector<std::string> com)
|
|
: basic_value(
|
|
into<cxx::remove_cvref_t<T>>::template into_toml<config_type>(ud),
|
|
std::move(com))
|
|
{}
|
|
template<typename T, cxx::enable_if_t<
|
|
detail::has_specialized_into<T>::value, std::nullptr_t> = nullptr>
|
|
basic_value& operator=(const T& ud)
|
|
{
|
|
*this = into<cxx::remove_cvref_t<T>>::template into_toml<config_type>(ud);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
|
detail::has_into_toml_method<T>,
|
|
cxx::negation<detail::has_specialized_into<T>>
|
|
>::value, std::nullptr_t> = nullptr>
|
|
basic_value(const T& ud): basic_value(ud.into_toml()) {}
|
|
|
|
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
|
detail::has_into_toml_method<T>,
|
|
cxx::negation<detail::has_specialized_into<T>>
|
|
>::value, std::nullptr_t> = nullptr>
|
|
basic_value(const T& ud, std::vector<std::string> com)
|
|
: basic_value(ud.into_toml(), std::move(com))
|
|
{}
|
|
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
|
detail::has_into_toml_method<T>,
|
|
cxx::negation<detail::has_specialized_into<T>>
|
|
>::value, std::nullptr_t> = nullptr>
|
|
basic_value& operator=(const T& ud)
|
|
{
|
|
*this = ud.into_toml();
|
|
return *this;
|
|
}
|
|
// }}}
|
|
|
|
// empty value with region info ======================================= {{{
|
|
|
|
// mainly for `null` extension
|
|
basic_value(detail::none_t, region_type reg) noexcept
|
|
: type_(value_t::empty), empty_('\0'), region_(std::move(reg)), comments_{}
|
|
{}
|
|
|
|
// }}}
|
|
|
|
// type checking ====================================================== {{{
|
|
|
|
template<typename T, cxx::enable_if_t<
|
|
detail::is_exact_toml_type<cxx::remove_cvref_t<T>, value_type>::value,
|
|
std::nullptr_t> = nullptr>
|
|
bool is() const noexcept
|
|
{
|
|
return detail::type_to_enum<T, value_type>::value == this->type_;
|
|
}
|
|
bool is(value_t t) const noexcept {return t == this->type_;}
|
|
|
|
bool is_empty() const noexcept {return this->is(value_t::empty );}
|
|
bool is_boolean() const noexcept {return this->is(value_t::boolean );}
|
|
bool is_integer() const noexcept {return this->is(value_t::integer );}
|
|
bool is_floating() const noexcept {return this->is(value_t::floating );}
|
|
bool is_string() const noexcept {return this->is(value_t::string );}
|
|
bool is_offset_datetime() const noexcept {return this->is(value_t::offset_datetime);}
|
|
bool is_local_datetime() const noexcept {return this->is(value_t::local_datetime );}
|
|
bool is_local_date() const noexcept {return this->is(value_t::local_date );}
|
|
bool is_local_time() const noexcept {return this->is(value_t::local_time );}
|
|
bool is_array() const noexcept {return this->is(value_t::array );}
|
|
bool is_table() const noexcept {return this->is(value_t::table );}
|
|
|
|
bool is_array_of_tables() const noexcept
|
|
{
|
|
if( ! this->is_array()) {return false;}
|
|
const auto& a = this->as_array(std::nothrow); // already checked.
|
|
|
|
// when you define [[array.of.tables]], at least one empty table will be
|
|
// assigned. In case of array of inline tables, `array_of_tables = []`,
|
|
// there is no reason to consider this as an array of *tables*.
|
|
// So empty array is not an array-of-tables.
|
|
if(a.empty()) {return false;}
|
|
|
|
// since toml v1.0.0 allows array of heterogeneous types, we need to
|
|
// check all the elements. if any of the elements is not a table, it
|
|
// is a heterogeneous array and cannot be expressed by `[[aot]]` form.
|
|
for(const auto& e : a)
|
|
{
|
|
if( ! e.is_table()) {return false;}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
value_t type() const noexcept {return type_;}
|
|
|
|
// }}}
|
|
|
|
// as_xxx (noexcept) version ========================================== {{{
|
|
|
|
template<value_t T>
|
|
detail::enum_to_type_t<T, basic_value<config_type>> const&
|
|
as(const std::nothrow_t&) const noexcept
|
|
{
|
|
return detail::getter<config_type, T>::get_nothrow(*this);
|
|
}
|
|
template<value_t T>
|
|
detail::enum_to_type_t<T, basic_value<config_type>>&
|
|
as(const std::nothrow_t&) noexcept
|
|
{
|
|
return detail::getter<config_type, T>::get_nothrow(*this);
|
|
}
|
|
|
|
boolean_type const& as_boolean (const std::nothrow_t&) const noexcept {return this->boolean_.value;}
|
|
integer_type const& as_integer (const std::nothrow_t&) const noexcept {return this->integer_.value;}
|
|
floating_type const& as_floating (const std::nothrow_t&) const noexcept {return this->floating_.value;}
|
|
string_type const& as_string (const std::nothrow_t&) const noexcept {return this->string_.value;}
|
|
offset_datetime_type const& as_offset_datetime(const std::nothrow_t&) const noexcept {return this->offset_datetime_.value;}
|
|
local_datetime_type const& as_local_datetime (const std::nothrow_t&) const noexcept {return this->local_datetime_.value;}
|
|
local_date_type const& as_local_date (const std::nothrow_t&) const noexcept {return this->local_date_.value;}
|
|
local_time_type const& as_local_time (const std::nothrow_t&) const noexcept {return this->local_time_.value;}
|
|
array_type const& as_array (const std::nothrow_t&) const noexcept {return this->array_.value.get();}
|
|
table_type const& as_table (const std::nothrow_t&) const noexcept {return this->table_.value.get();}
|
|
|
|
boolean_type & as_boolean (const std::nothrow_t&) noexcept {return this->boolean_.value;}
|
|
integer_type & as_integer (const std::nothrow_t&) noexcept {return this->integer_.value;}
|
|
floating_type & as_floating (const std::nothrow_t&) noexcept {return this->floating_.value;}
|
|
string_type & as_string (const std::nothrow_t&) noexcept {return this->string_.value;}
|
|
offset_datetime_type& as_offset_datetime(const std::nothrow_t&) noexcept {return this->offset_datetime_.value;}
|
|
local_datetime_type & as_local_datetime (const std::nothrow_t&) noexcept {return this->local_datetime_.value;}
|
|
local_date_type & as_local_date (const std::nothrow_t&) noexcept {return this->local_date_.value;}
|
|
local_time_type & as_local_time (const std::nothrow_t&) noexcept {return this->local_time_.value;}
|
|
array_type & as_array (const std::nothrow_t&) noexcept {return this->array_.value.get();}
|
|
table_type & as_table (const std::nothrow_t&) noexcept {return this->table_.value.get();}
|
|
|
|
// }}}
|
|
|
|
// as_xxx (throw) ===================================================== {{{
|
|
|
|
template<value_t T>
|
|
detail::enum_to_type_t<T, basic_value<config_type>> const& as() const
|
|
{
|
|
return detail::getter<config_type, T>::get(*this);
|
|
}
|
|
template<value_t T>
|
|
detail::enum_to_type_t<T, basic_value<config_type>>& as()
|
|
{
|
|
return detail::getter<config_type, T>::get(*this);
|
|
}
|
|
|
|
boolean_type const& as_boolean() const
|
|
{
|
|
if(this->type_ != value_t::boolean)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_boolean()", value_t::boolean);
|
|
}
|
|
return this->boolean_.value;
|
|
}
|
|
integer_type const& as_integer() const
|
|
{
|
|
if(this->type_ != value_t::integer)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_integer()", value_t::integer);
|
|
}
|
|
return this->integer_.value;
|
|
}
|
|
floating_type const& as_floating() const
|
|
{
|
|
if(this->type_ != value_t::floating)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_floating()", value_t::floating);
|
|
}
|
|
return this->floating_.value;
|
|
}
|
|
string_type const& as_string() const
|
|
{
|
|
if(this->type_ != value_t::string)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_string()", value_t::string);
|
|
}
|
|
return this->string_.value;
|
|
}
|
|
offset_datetime_type const& as_offset_datetime() const
|
|
{
|
|
if(this->type_ != value_t::offset_datetime)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_offset_datetime()", value_t::offset_datetime);
|
|
}
|
|
return this->offset_datetime_.value;
|
|
}
|
|
local_datetime_type const& as_local_datetime() const
|
|
{
|
|
if(this->type_ != value_t::local_datetime)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_datetime()", value_t::local_datetime);
|
|
}
|
|
return this->local_datetime_.value;
|
|
}
|
|
local_date_type const& as_local_date() const
|
|
{
|
|
if(this->type_ != value_t::local_date)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_date()", value_t::local_date);
|
|
}
|
|
return this->local_date_.value;
|
|
}
|
|
local_time_type const& as_local_time() const
|
|
{
|
|
if(this->type_ != value_t::local_time)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_time()", value_t::local_time);
|
|
}
|
|
return this->local_time_.value;
|
|
}
|
|
array_type const& as_array() const
|
|
{
|
|
if(this->type_ != value_t::array)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_array()", value_t::array);
|
|
}
|
|
return this->array_.value.get();
|
|
}
|
|
table_type const& as_table() const
|
|
{
|
|
if(this->type_ != value_t::table)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_table()", value_t::table);
|
|
}
|
|
return this->table_.value.get();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------
|
|
// nonconst reference
|
|
|
|
boolean_type& as_boolean()
|
|
{
|
|
if(this->type_ != value_t::boolean)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_boolean()", value_t::boolean);
|
|
}
|
|
return this->boolean_.value;
|
|
}
|
|
integer_type& as_integer()
|
|
{
|
|
if(this->type_ != value_t::integer)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_integer()", value_t::integer);
|
|
}
|
|
return this->integer_.value;
|
|
}
|
|
floating_type& as_floating()
|
|
{
|
|
if(this->type_ != value_t::floating)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_floating()", value_t::floating);
|
|
}
|
|
return this->floating_.value;
|
|
}
|
|
string_type& as_string()
|
|
{
|
|
if(this->type_ != value_t::string)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_string()", value_t::string);
|
|
}
|
|
return this->string_.value;
|
|
}
|
|
offset_datetime_type& as_offset_datetime()
|
|
{
|
|
if(this->type_ != value_t::offset_datetime)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_offset_datetime()", value_t::offset_datetime);
|
|
}
|
|
return this->offset_datetime_.value;
|
|
}
|
|
local_datetime_type& as_local_datetime()
|
|
{
|
|
if(this->type_ != value_t::local_datetime)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_datetime()", value_t::local_datetime);
|
|
}
|
|
return this->local_datetime_.value;
|
|
}
|
|
local_date_type& as_local_date()
|
|
{
|
|
if(this->type_ != value_t::local_date)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_date()", value_t::local_date);
|
|
}
|
|
return this->local_date_.value;
|
|
}
|
|
local_time_type& as_local_time()
|
|
{
|
|
if(this->type_ != value_t::local_time)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_time()", value_t::local_time);
|
|
}
|
|
return this->local_time_.value;
|
|
}
|
|
array_type& as_array()
|
|
{
|
|
if(this->type_ != value_t::array)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_array()", value_t::array);
|
|
}
|
|
return this->array_.value.get();
|
|
}
|
|
table_type& as_table()
|
|
{
|
|
if(this->type_ != value_t::table)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_table()", value_t::table);
|
|
}
|
|
return this->table_.value.get();
|
|
}
|
|
|
|
// }}}
|
|
|
|
// format accessors (noexcept) ======================================== {{{
|
|
|
|
template<value_t T>
|
|
detail::enum_to_fmt_type_t<T> const&
|
|
as_fmt(const std::nothrow_t&) const noexcept
|
|
{
|
|
return detail::getter<config_type, T>::get_fmt_nothrow(*this);
|
|
}
|
|
template<value_t T>
|
|
detail::enum_to_fmt_type_t<T>&
|
|
as_fmt(const std::nothrow_t&) noexcept
|
|
{
|
|
return detail::getter<config_type, T>::get_fmt_nothrow(*this);
|
|
}
|
|
|
|
boolean_format_info & as_boolean_fmt (const std::nothrow_t&) noexcept {return this->boolean_.format;}
|
|
integer_format_info & as_integer_fmt (const std::nothrow_t&) noexcept {return this->integer_.format;}
|
|
floating_format_info & as_floating_fmt (const std::nothrow_t&) noexcept {return this->floating_.format;}
|
|
string_format_info & as_string_fmt (const std::nothrow_t&) noexcept {return this->string_.format;}
|
|
offset_datetime_format_info& as_offset_datetime_fmt(const std::nothrow_t&) noexcept {return this->offset_datetime_.format;}
|
|
local_datetime_format_info & as_local_datetime_fmt (const std::nothrow_t&) noexcept {return this->local_datetime_.format;}
|
|
local_date_format_info & as_local_date_fmt (const std::nothrow_t&) noexcept {return this->local_date_.format;}
|
|
local_time_format_info & as_local_time_fmt (const std::nothrow_t&) noexcept {return this->local_time_.format;}
|
|
array_format_info & as_array_fmt (const std::nothrow_t&) noexcept {return this->array_.format;}
|
|
table_format_info & as_table_fmt (const std::nothrow_t&) noexcept {return this->table_.format;}
|
|
|
|
boolean_format_info const& as_boolean_fmt (const std::nothrow_t&) const noexcept {return this->boolean_.format;}
|
|
integer_format_info const& as_integer_fmt (const std::nothrow_t&) const noexcept {return this->integer_.format;}
|
|
floating_format_info const& as_floating_fmt (const std::nothrow_t&) const noexcept {return this->floating_.format;}
|
|
string_format_info const& as_string_fmt (const std::nothrow_t&) const noexcept {return this->string_.format;}
|
|
offset_datetime_format_info const& as_offset_datetime_fmt(const std::nothrow_t&) const noexcept {return this->offset_datetime_.format;}
|
|
local_datetime_format_info const& as_local_datetime_fmt (const std::nothrow_t&) const noexcept {return this->local_datetime_.format;}
|
|
local_date_format_info const& as_local_date_fmt (const std::nothrow_t&) const noexcept {return this->local_date_.format;}
|
|
local_time_format_info const& as_local_time_fmt (const std::nothrow_t&) const noexcept {return this->local_time_.format;}
|
|
array_format_info const& as_array_fmt (const std::nothrow_t&) const noexcept {return this->array_.format;}
|
|
table_format_info const& as_table_fmt (const std::nothrow_t&) const noexcept {return this->table_.format;}
|
|
|
|
// }}}
|
|
|
|
// format accessors (throw) =========================================== {{{
|
|
|
|
template<value_t T>
|
|
detail::enum_to_fmt_type_t<T> const& as_fmt() const
|
|
{
|
|
return detail::getter<config_type, T>::get_fmt(*this);
|
|
}
|
|
template<value_t T>
|
|
detail::enum_to_fmt_type_t<T>& as_fmt()
|
|
{
|
|
return detail::getter<config_type, T>::get_fmt(*this);
|
|
}
|
|
|
|
boolean_format_info const& as_boolean_fmt() const
|
|
{
|
|
if(this->type_ != value_t::boolean)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_boolean_fmt()", value_t::boolean);
|
|
}
|
|
return this->boolean_.format;
|
|
}
|
|
integer_format_info const& as_integer_fmt() const
|
|
{
|
|
if(this->type_ != value_t::integer)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_integer_fmt()", value_t::integer);
|
|
}
|
|
return this->integer_.format;
|
|
}
|
|
floating_format_info const& as_floating_fmt() const
|
|
{
|
|
if(this->type_ != value_t::floating)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_floating_fmt()", value_t::floating);
|
|
}
|
|
return this->floating_.format;
|
|
}
|
|
string_format_info const& as_string_fmt() const
|
|
{
|
|
if(this->type_ != value_t::string)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_string_fmt()", value_t::string);
|
|
}
|
|
return this->string_.format;
|
|
}
|
|
offset_datetime_format_info const& as_offset_datetime_fmt() const
|
|
{
|
|
if(this->type_ != value_t::offset_datetime)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_offset_datetime_fmt()", value_t::offset_datetime);
|
|
}
|
|
return this->offset_datetime_.format;
|
|
}
|
|
local_datetime_format_info const& as_local_datetime_fmt() const
|
|
{
|
|
if(this->type_ != value_t::local_datetime)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_datetime_fmt()", value_t::local_datetime);
|
|
}
|
|
return this->local_datetime_.format;
|
|
}
|
|
local_date_format_info const& as_local_date_fmt() const
|
|
{
|
|
if(this->type_ != value_t::local_date)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_date_fmt()", value_t::local_date);
|
|
}
|
|
return this->local_date_.format;
|
|
}
|
|
local_time_format_info const& as_local_time_fmt() const
|
|
{
|
|
if(this->type_ != value_t::local_time)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_time_fmt()", value_t::local_time);
|
|
}
|
|
return this->local_time_.format;
|
|
}
|
|
array_format_info const& as_array_fmt() const
|
|
{
|
|
if(this->type_ != value_t::array)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_array_fmt()", value_t::array);
|
|
}
|
|
return this->array_.format;
|
|
}
|
|
table_format_info const& as_table_fmt() const
|
|
{
|
|
if(this->type_ != value_t::table)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_table_fmt()", value_t::table);
|
|
}
|
|
return this->table_.format;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------
|
|
// nonconst reference
|
|
|
|
boolean_format_info& as_boolean_fmt()
|
|
{
|
|
if(this->type_ != value_t::boolean)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_boolean_fmt()", value_t::boolean);
|
|
}
|
|
return this->boolean_.format;
|
|
}
|
|
integer_format_info& as_integer_fmt()
|
|
{
|
|
if(this->type_ != value_t::integer)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_integer_fmt()", value_t::integer);
|
|
}
|
|
return this->integer_.format;
|
|
}
|
|
floating_format_info& as_floating_fmt()
|
|
{
|
|
if(this->type_ != value_t::floating)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_floating_fmt()", value_t::floating);
|
|
}
|
|
return this->floating_.format;
|
|
}
|
|
string_format_info& as_string_fmt()
|
|
{
|
|
if(this->type_ != value_t::string)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_string_fmt()", value_t::string);
|
|
}
|
|
return this->string_.format;
|
|
}
|
|
offset_datetime_format_info& as_offset_datetime_fmt()
|
|
{
|
|
if(this->type_ != value_t::offset_datetime)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_offset_datetime_fmt()", value_t::offset_datetime);
|
|
}
|
|
return this->offset_datetime_.format;
|
|
}
|
|
local_datetime_format_info& as_local_datetime_fmt()
|
|
{
|
|
if(this->type_ != value_t::local_datetime)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_datetime_fmt()", value_t::local_datetime);
|
|
}
|
|
return this->local_datetime_.format;
|
|
}
|
|
local_date_format_info& as_local_date_fmt()
|
|
{
|
|
if(this->type_ != value_t::local_date)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_date_fmt()", value_t::local_date);
|
|
}
|
|
return this->local_date_.format;
|
|
}
|
|
local_time_format_info& as_local_time_fmt()
|
|
{
|
|
if(this->type_ != value_t::local_time)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_local_time_fmt()", value_t::local_time);
|
|
}
|
|
return this->local_time_.format;
|
|
}
|
|
array_format_info& as_array_fmt()
|
|
{
|
|
if(this->type_ != value_t::array)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_array_fmt()", value_t::array);
|
|
}
|
|
return this->array_.format;
|
|
}
|
|
table_format_info& as_table_fmt()
|
|
{
|
|
if(this->type_ != value_t::table)
|
|
{
|
|
this->throw_bad_cast("toml::value::as_table_fmt()", value_t::table);
|
|
}
|
|
return this->table_.format;
|
|
}
|
|
// }}}
|
|
|
|
// table accessors ==================================================== {{{
|
|
|
|
value_type& at(const key_type& k)
|
|
{
|
|
if(!this->is_table())
|
|
{
|
|
this->throw_bad_cast("toml::value::at(key_type)", value_t::table);
|
|
}
|
|
auto& table = this->as_table(std::nothrow);
|
|
const auto found = table.find(k);
|
|
if(found == table.end())
|
|
{
|
|
this->throw_key_not_found_error("toml::value::at", k);
|
|
}
|
|
assert(found->first == k);
|
|
return found->second;
|
|
}
|
|
value_type const& at(const key_type& k) const
|
|
{
|
|
if(!this->is_table())
|
|
{
|
|
this->throw_bad_cast("toml::value::at(key_type)", value_t::table);
|
|
}
|
|
const auto& table = this->as_table(std::nothrow);
|
|
const auto found = table.find(k);
|
|
if(found == table.end())
|
|
{
|
|
this->throw_key_not_found_error("toml::value::at", k);
|
|
}
|
|
assert(found->first == k);
|
|
return found->second;
|
|
}
|
|
value_type& operator[](const key_type& k)
|
|
{
|
|
if(this->is_empty())
|
|
{
|
|
(*this) = table_type{};
|
|
}
|
|
else if( ! this->is_table()) // initialized, but not a table
|
|
{
|
|
this->throw_bad_cast("toml::value::operator[](key_type)", value_t::table);
|
|
}
|
|
return (this->as_table(std::nothrow))[k];
|
|
}
|
|
std::size_t count(const key_type& k) const
|
|
{
|
|
if(!this->is_table())
|
|
{
|
|
this->throw_bad_cast("toml::value::count(key_type)", value_t::table);
|
|
}
|
|
return this->as_table(std::nothrow).count(k);
|
|
}
|
|
bool contains(const key_type& k) const
|
|
{
|
|
if(!this->is_table())
|
|
{
|
|
this->throw_bad_cast("toml::value::contains(key_type)", value_t::table);
|
|
}
|
|
const auto& table = this->as_table(std::nothrow);
|
|
return table.find(k) != table.end();
|
|
}
|
|
// }}}
|
|
|
|
// array accessors ==================================================== {{{
|
|
|
|
value_type& at(const std::size_t idx)
|
|
{
|
|
if(!this->is_array())
|
|
{
|
|
this->throw_bad_cast("toml::value::at(idx)", value_t::array);
|
|
}
|
|
auto& ar = this->as_array(std::nothrow);
|
|
|
|
if(ar.size() <= idx)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "actual length (" << ar.size()
|
|
<< ") is shorter than the specified index (" << idx << ").";
|
|
throw std::out_of_range(format_error(
|
|
"toml::value::at(idx): no element corresponding to the index",
|
|
this->location(), oss.str()
|
|
));
|
|
}
|
|
return ar.at(idx);
|
|
}
|
|
value_type const& at(const std::size_t idx) const
|
|
{
|
|
if(!this->is_array())
|
|
{
|
|
this->throw_bad_cast("toml::value::at(idx)", value_t::array);
|
|
}
|
|
const auto& ar = this->as_array(std::nothrow);
|
|
|
|
if(ar.size() <= idx)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << "actual length (" << ar.size()
|
|
<< ") is shorter than the specified index (" << idx << ").";
|
|
|
|
throw std::out_of_range(format_error(
|
|
"toml::value::at(idx): no element corresponding to the index",
|
|
this->location(), oss.str()
|
|
));
|
|
}
|
|
return ar.at(idx);
|
|
}
|
|
|
|
value_type& operator[](const std::size_t idx) noexcept
|
|
{
|
|
// no check...
|
|
return this->as_array(std::nothrow)[idx];
|
|
}
|
|
value_type const& operator[](const std::size_t idx) const noexcept
|
|
{
|
|
// no check...
|
|
return this->as_array(std::nothrow)[idx];
|
|
}
|
|
|
|
void push_back(const value_type& x)
|
|
{
|
|
if(!this->is_array())
|
|
{
|
|
this->throw_bad_cast("toml::value::push_back(idx)", value_t::array);
|
|
}
|
|
this->as_array(std::nothrow).push_back(x);
|
|
return;
|
|
}
|
|
void push_back(value_type&& x)
|
|
{
|
|
if(!this->is_array())
|
|
{
|
|
this->throw_bad_cast("toml::value::push_back(idx)", value_t::array);
|
|
}
|
|
this->as_array(std::nothrow).push_back(std::move(x));
|
|
return;
|
|
}
|
|
|
|
template<typename ... Ts>
|
|
value_type& emplace_back(Ts&& ... args)
|
|
{
|
|
if(!this->is_array())
|
|
{
|
|
this->throw_bad_cast("toml::value::emplace_back(idx)", value_t::array);
|
|
}
|
|
auto& ar = this->as_array(std::nothrow);
|
|
ar.emplace_back(std::forward<Ts>(args) ...);
|
|
return ar.back();
|
|
}
|
|
|
|
std::size_t size() const
|
|
{
|
|
switch(this->type_)
|
|
{
|
|
case value_t::array:
|
|
{
|
|
return this->as_array(std::nothrow).size();
|
|
}
|
|
case value_t::table:
|
|
{
|
|
return this->as_table(std::nothrow).size();
|
|
}
|
|
case value_t::string:
|
|
{
|
|
return this->as_string(std::nothrow).size();
|
|
}
|
|
default:
|
|
{
|
|
throw type_error(format_error(
|
|
"toml::value::size(): bad_cast to container types",
|
|
this->location(),
|
|
"the actual type is " + to_string(this->type_)
|
|
), this->location());
|
|
}
|
|
}
|
|
}
|
|
|
|
// }}}
|
|
|
|
source_location location() const
|
|
{
|
|
return source_location(this->region_);
|
|
}
|
|
|
|
comment_type const& comments() const noexcept {return this->comments_;}
|
|
comment_type& comments() noexcept {return this->comments_;}
|
|
|
|
private:
|
|
|
|
// private helper functions =========================================== {{{
|
|
|
|
void cleanup() noexcept
|
|
{
|
|
switch(this->type_)
|
|
{
|
|
case value_t::boolean : { boolean_ .~boolean_storage (); return; }
|
|
case value_t::integer : { integer_ .~integer_storage (); return; }
|
|
case value_t::floating : { floating_ .~floating_storage (); return; }
|
|
case value_t::string : { string_ .~string_storage (); return; }
|
|
case value_t::offset_datetime : { offset_datetime_.~offset_datetime_storage (); return; }
|
|
case value_t::local_datetime : { local_datetime_ .~local_datetime_storage (); return; }
|
|
case value_t::local_date : { local_date_ .~local_date_storage (); return; }
|
|
case value_t::local_time : { local_time_ .~local_time_storage (); return; }
|
|
case value_t::array : { array_ .~array_storage (); return; }
|
|
case value_t::table : { table_ .~table_storage (); return; }
|
|
default : { return; }
|
|
}
|
|
this->type_ = value_t::empty;
|
|
}
|
|
|
|
template<typename T, typename U>
|
|
static void assigner(T& dst, U&& v)
|
|
{
|
|
const auto tmp = ::new(std::addressof(dst)) T(std::forward<U>(v));
|
|
assert(tmp == std::addressof(dst));
|
|
(void)tmp;
|
|
}
|
|
|
|
[[noreturn]]
|
|
void throw_bad_cast(const std::string& funcname, const value_t ty) const
|
|
{
|
|
throw type_error(format_error(detail::make_type_error(*this, funcname, ty)),
|
|
this->location());
|
|
}
|
|
|
|
[[noreturn]]
|
|
void throw_key_not_found_error(const std::string& funcname, const key_type& key) const
|
|
{
|
|
throw std::out_of_range(format_error(
|
|
detail::make_not_found_error(*this, funcname, key)));
|
|
}
|
|
|
|
template<typename TC>
|
|
friend void detail::change_region_of_value(basic_value<TC>&, const basic_value<TC>&);
|
|
|
|
template<typename TC>
|
|
friend class basic_value;
|
|
|
|
// }}}
|
|
|
|
private:
|
|
|
|
using boolean_storage = detail::value_with_format<boolean_type, boolean_format_info >;
|
|
using integer_storage = detail::value_with_format<integer_type, integer_format_info >;
|
|
using floating_storage = detail::value_with_format<floating_type, floating_format_info >;
|
|
using string_storage = detail::value_with_format<string_type, string_format_info >;
|
|
using offset_datetime_storage = detail::value_with_format<offset_datetime_type, offset_datetime_format_info>;
|
|
using local_datetime_storage = detail::value_with_format<local_datetime_type, local_datetime_format_info >;
|
|
using local_date_storage = detail::value_with_format<local_date_type, local_date_format_info >;
|
|
using local_time_storage = detail::value_with_format<local_time_type, local_time_format_info >;
|
|
using array_storage = detail::value_with_format<detail::storage<array_type>, array_format_info >;
|
|
using table_storage = detail::value_with_format<detail::storage<table_type>, table_format_info >;
|
|
|
|
private:
|
|
|
|
value_t type_;
|
|
union
|
|
{
|
|
char empty_; // the smallest type
|
|
boolean_storage boolean_;
|
|
integer_storage integer_;
|
|
floating_storage floating_;
|
|
string_storage string_;
|
|
offset_datetime_storage offset_datetime_;
|
|
local_datetime_storage local_datetime_;
|
|
local_date_storage local_date_;
|
|
local_time_storage local_time_;
|
|
array_storage array_;
|
|
table_storage table_;
|
|
};
|
|
region_type region_;
|
|
comment_type comments_;
|
|
};
|
|
|
|
template<typename TC>
|
|
bool operator==(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
|
{
|
|
if(lhs.type() != rhs.type()) {return false;}
|
|
if(lhs.comments() != rhs.comments()) {return false;}
|
|
|
|
switch(lhs.type())
|
|
{
|
|
case value_t::boolean :
|
|
{
|
|
return lhs.as_boolean() == rhs.as_boolean();
|
|
}
|
|
case value_t::integer :
|
|
{
|
|
return lhs.as_integer() == rhs.as_integer();
|
|
}
|
|
case value_t::floating :
|
|
{
|
|
return lhs.as_floating() == rhs.as_floating();
|
|
}
|
|
case value_t::string :
|
|
{
|
|
return lhs.as_string() == rhs.as_string();
|
|
}
|
|
case value_t::offset_datetime:
|
|
{
|
|
return lhs.as_offset_datetime() == rhs.as_offset_datetime();
|
|
}
|
|
case value_t::local_datetime:
|
|
{
|
|
return lhs.as_local_datetime() == rhs.as_local_datetime();
|
|
}
|
|
case value_t::local_date:
|
|
{
|
|
return lhs.as_local_date() == rhs.as_local_date();
|
|
}
|
|
case value_t::local_time:
|
|
{
|
|
return lhs.as_local_time() == rhs.as_local_time();
|
|
}
|
|
case value_t::array :
|
|
{
|
|
return lhs.as_array() == rhs.as_array();
|
|
}
|
|
case value_t::table :
|
|
{
|
|
return lhs.as_table() == rhs.as_table();
|
|
}
|
|
case value_t::empty : {return true; }
|
|
default: {return false;}
|
|
}
|
|
}
|
|
|
|
template<typename TC>
|
|
bool operator!=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
template<typename TC>
|
|
cxx::enable_if_t<cxx::conjunction<
|
|
detail::is_comparable<typename basic_value<TC>::array_type>,
|
|
detail::is_comparable<typename basic_value<TC>::table_type>
|
|
>::value, bool>
|
|
operator<(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
|
{
|
|
if(lhs.type() != rhs.type())
|
|
{
|
|
return (lhs.type() < rhs.type());
|
|
}
|
|
switch(lhs.type())
|
|
{
|
|
case value_t::boolean :
|
|
{
|
|
return lhs.as_boolean() < rhs.as_boolean() ||
|
|
(lhs.as_boolean() == rhs.as_boolean() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::integer :
|
|
{
|
|
return lhs.as_integer() < rhs.as_integer() ||
|
|
(lhs.as_integer() == rhs.as_integer() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::floating :
|
|
{
|
|
return lhs.as_floating() < rhs.as_floating() ||
|
|
(lhs.as_floating() == rhs.as_floating() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::string :
|
|
{
|
|
return lhs.as_string() < rhs.as_string() ||
|
|
(lhs.as_string() == rhs.as_string() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::offset_datetime:
|
|
{
|
|
return lhs.as_offset_datetime() < rhs.as_offset_datetime() ||
|
|
(lhs.as_offset_datetime() == rhs.as_offset_datetime() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::local_datetime:
|
|
{
|
|
return lhs.as_local_datetime() < rhs.as_local_datetime() ||
|
|
(lhs.as_local_datetime() == rhs.as_local_datetime() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::local_date:
|
|
{
|
|
return lhs.as_local_date() < rhs.as_local_date() ||
|
|
(lhs.as_local_date() == rhs.as_local_date() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::local_time:
|
|
{
|
|
return lhs.as_local_time() < rhs.as_local_time() ||
|
|
(lhs.as_local_time() == rhs.as_local_time() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::array :
|
|
{
|
|
return lhs.as_array() < rhs.as_array() ||
|
|
(lhs.as_array() == rhs.as_array() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::table :
|
|
{
|
|
return lhs.as_table() < rhs.as_table() ||
|
|
(lhs.as_table() == rhs.as_table() &&
|
|
lhs.comments() < rhs.comments());
|
|
}
|
|
case value_t::empty :
|
|
{
|
|
return lhs.comments() < rhs.comments();
|
|
}
|
|
default:
|
|
{
|
|
return lhs.comments() < rhs.comments();
|
|
}
|
|
}
|
|
}
|
|
|
|
template<typename TC>
|
|
cxx::enable_if_t<cxx::conjunction<
|
|
detail::is_comparable<typename basic_value<TC>::array_type>,
|
|
detail::is_comparable<typename basic_value<TC>::table_type>
|
|
>::value, bool>
|
|
operator<=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
|
{
|
|
return (lhs < rhs) || (lhs == rhs);
|
|
}
|
|
template<typename TC>
|
|
cxx::enable_if_t<cxx::conjunction<
|
|
detail::is_comparable<typename basic_value<TC>::array_type>,
|
|
detail::is_comparable<typename basic_value<TC>::table_type>
|
|
>::value, bool>
|
|
operator>(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
|
{
|
|
return !(lhs <= rhs);
|
|
}
|
|
template<typename TC>
|
|
cxx::enable_if_t<cxx::conjunction<
|
|
detail::is_comparable<typename basic_value<TC>::array_type>,
|
|
detail::is_comparable<typename basic_value<TC>::table_type>
|
|
>::value, bool>
|
|
operator>=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
|
{
|
|
return !(lhs < rhs);
|
|
}
|
|
|
|
// error_info helper
|
|
template<typename TC, typename ... Ts>
|
|
error_info make_error_info_rec(error_info e,
|
|
const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
|
{
|
|
return make_error_info_rec(std::move(e), v.location(), std::move(msg), std::forward<Ts>(tail)...);
|
|
}
|
|
template<typename TC, typename ... Ts>
|
|
error_info make_error_info(
|
|
std::string title, const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
|
{
|
|
return make_error_info(std::move(title),
|
|
v.location(), std::move(msg), std::forward<Ts>(tail)...);
|
|
}
|
|
template<typename TC, typename ... Ts>
|
|
std::string format_error(std::string title,
|
|
const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
|
{
|
|
return format_error(std::move(title),
|
|
v.location(), std::move(msg), std::forward<Ts>(tail)...);
|
|
}
|
|
|
|
namespace detail
|
|
{
|
|
|
|
template<typename TC>
|
|
error_info make_type_error(const basic_value<TC>& v, const std::string& fname, const value_t ty)
|
|
{
|
|
return make_error_info(fname + ": bad_cast to " + to_string(ty),
|
|
v.location(), "the actual type is " + to_string(v.type()));
|
|
}
|
|
template<typename TC>
|
|
error_info make_not_found_error(const basic_value<TC>& v, const std::string& fname, const std::string& key)
|
|
{
|
|
const auto loc = v.location();
|
|
const std::string title = fname + ": key \"" + key + "\" not found";
|
|
|
|
std::vector<std::pair<source_location, std::string>> locs;
|
|
if( ! loc.is_ok())
|
|
{
|
|
return error_info(title, locs);
|
|
}
|
|
|
|
if(loc.first_line_number() == 1 && loc.first_column_number() == 1 && loc.length() == 1)
|
|
{
|
|
// The top-level table has its region at the 0th character of the file.
|
|
// That means that, in the case when a key is not found in the top-level
|
|
// table, the error message points to the first character. If the file has
|
|
// the first table at the first line, the error message would be like this.
|
|
// ```console
|
|
// [error] key "a" not found
|
|
// --> example.toml
|
|
// |
|
|
// 1 | [table]
|
|
// | ^------ in this table
|
|
// ```
|
|
// It actually points to the top-level table at the first character, not
|
|
// `[table]`. But it is too confusing. To avoid the confusion, the error
|
|
// message should explicitly say "key not found in the top-level table".
|
|
locs.emplace_back(v.location(), "at the top-level table");
|
|
}
|
|
else
|
|
{
|
|
locs.emplace_back(v.location(), "in this table");
|
|
}
|
|
return error_info(title, locs);
|
|
}
|
|
|
|
#define TOML11_DETAIL_GENERATE_COMPTIME_GETTER(ty) \
|
|
template<typename TC> \
|
|
struct getter<TC, value_t::ty> \
|
|
{ \
|
|
using value_type = basic_value<TC>; \
|
|
using result_type = enum_to_type_t<value_t::ty, value_type>; \
|
|
using format_type = enum_to_fmt_type_t<value_t::ty>; \
|
|
\
|
|
static result_type& get(value_type& v) \
|
|
{ \
|
|
return v.as_ ## ty(); \
|
|
} \
|
|
static result_type const& get(const value_type& v) \
|
|
{ \
|
|
return v.as_ ## ty(); \
|
|
} \
|
|
\
|
|
static result_type& get_nothrow(value_type& v) noexcept \
|
|
{ \
|
|
return v.as_ ## ty(std::nothrow); \
|
|
} \
|
|
static result_type const& get_nothrow(const value_type& v) noexcept \
|
|
{ \
|
|
return v.as_ ## ty(std::nothrow); \
|
|
} \
|
|
\
|
|
static format_type& get_fmt(value_type& v) \
|
|
{ \
|
|
return v.as_ ## ty ## _fmt(); \
|
|
} \
|
|
static format_type const& get_fmt(const value_type& v) \
|
|
{ \
|
|
return v.as_ ## ty ## _fmt(); \
|
|
} \
|
|
\
|
|
static format_type& get_fmt_nothrow(value_type& v) noexcept \
|
|
{ \
|
|
return v.as_ ## ty ## _fmt(std::nothrow); \
|
|
} \
|
|
static format_type const& get_fmt_nothrow(const value_type& v) noexcept \
|
|
{ \
|
|
return v.as_ ## ty ## _fmt(std::nothrow); \
|
|
} \
|
|
};
|
|
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(boolean )
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(integer )
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(floating )
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(string )
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(offset_datetime)
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(local_datetime )
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(local_date )
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(local_time )
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(array )
|
|
TOML11_DETAIL_GENERATE_COMPTIME_GETTER(table )
|
|
|
|
#undef TOML11_DETAIL_GENERATE_COMPTIME_GETTER
|
|
|
|
template<typename TC>
|
|
void change_region_of_value(basic_value<TC>& dst, const basic_value<TC>& src)
|
|
{
|
|
dst.region_ = std::move(src.region_);
|
|
return;
|
|
}
|
|
|
|
} // namespace detail
|
|
} // namespace toml
|
|
#endif // TOML11_VALUE_HPP
|