mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-09-16 16:28:09 +08:00
Merge branch 'u8string' into v4_1_0
This commit is contained in:
@@ -109,16 +109,32 @@ get(const basic_value<TC>& v)
|
||||
return static_cast<T>(v.as_floating());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::string with different char/trait/allocator
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_not_toml_type<T, basic_value<TC>>,
|
||||
detail::is_1byte_std_basic_string<T>
|
||||
>::value, T>
|
||||
get(const basic_value<TC>& v)
|
||||
{
|
||||
using value_type = typename cxx::remove_cvref_t<T>::value_type;
|
||||
using traits_type = typename cxx::remove_cvref_t<T>::traits_type;
|
||||
using allocator_type = typename cxx::remove_cvref_t<T>::allocator_type;
|
||||
return detail::to_string_of<value_type, traits_type, allocator_type>(v.as_string());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::string_view
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<std::is_same<T, std::string_view>::value, std::string_view>
|
||||
cxx::enable_if_t<detail::is_string_view_of<T, typename basic_value<TC>::string_type>::value, T>
|
||||
get(const basic_value<TC>& v)
|
||||
{
|
||||
return std::string_view(v.as_string());
|
||||
return T(v.as_string());
|
||||
}
|
||||
|
||||
#endif // string_view
|
||||
@@ -175,6 +191,10 @@ cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::has_push_back_method<T>, // .push_back() works
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::array
|
||||
cxx::negation<detail::is_std_basic_string<T>>, // but not std::basic_string<CharT>
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
cxx::negation<detail::is_std_basic_string_view<T>>, // but not std::basic_string_view<CharT>
|
||||
#endif
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
@@ -245,6 +265,10 @@ cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::has_push_back_method<T>, // .push_back() works
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::array
|
||||
cxx::negation<detail::is_std_basic_string<T>>, // but not std::basic_string<CharT>
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
cxx::negation<detail::is_std_basic_string_view<T>>, // but not std::basic_string_view<CharT>
|
||||
#endif
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
|
@@ -1701,21 +1701,7 @@ parse_simple_key(location& loc, const context<TC>& ctx)
|
||||
|
||||
if(const auto bare = syntax::unquoted_key(spec).scan(loc))
|
||||
{
|
||||
const auto reg = bare.as_string();
|
||||
// here we cannot use `if constexpr` because it is C++11.
|
||||
if(std::is_same<key_type, std::string>::value)
|
||||
{
|
||||
return ok(reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
key_type k;
|
||||
for(const auto c : reg)
|
||||
{
|
||||
k += typename key_type::value_type(c);
|
||||
}
|
||||
return ok(k);
|
||||
}
|
||||
return ok(to_string_of<typename key_type::value_type>(bare.as_string()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -162,6 +162,32 @@ struct is_std_forward_list_impl<std::forward_list<T>> : std::true_type{};
|
||||
template<typename T>
|
||||
using is_std_forward_list = is_std_forward_list_impl<cxx::remove_cvref_t<T>>;
|
||||
|
||||
template<typename T> struct is_std_basic_string_impl : std::false_type{};
|
||||
template<typename C, typename T, typename A>
|
||||
struct is_std_basic_string_impl<std::basic_string<C, T, A>> : std::true_type{};
|
||||
template<typename T>
|
||||
using is_std_basic_string = is_std_basic_string_impl<cxx::remove_cvref_t<T>>;
|
||||
|
||||
template<typename T> struct is_1byte_std_basic_string_impl : std::false_type{};
|
||||
template<typename C, typename T, typename A>
|
||||
struct is_1byte_std_basic_string_impl<std::basic_string<C, T, A>>
|
||||
: std::integral_constant<bool, sizeof(C) == sizeof(char)> {};
|
||||
template<typename T>
|
||||
using is_1byte_std_basic_string = is_std_basic_string_impl<cxx::remove_cvref_t<T>>;
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
template<typename T> struct is_std_basic_string_view_impl : std::false_type{};
|
||||
template<typename C, typename T>
|
||||
struct is_std_basic_string_view_impl<std::basic_string_view<C, T>> : std::true_type{};
|
||||
template<typename T>
|
||||
using is_std_basic_string_view = is_std_basic_string_view_impl<cxx::remove_cvref_t<T>>;
|
||||
|
||||
template<typename V, typename S>
|
||||
struct is_string_view_of : std::false_type {};
|
||||
template<typename C, typename T>
|
||||
struct is_string_view_of<std::basic_string_view<C, T>, std::basic_string<C, T>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
template<typename T> struct is_chrono_duration_impl: std::false_type{};
|
||||
template<typename Rep, typename Period>
|
||||
struct is_chrono_duration_impl<std::chrono::duration<Rep, Period>>: std::true_type{};
|
||||
|
@@ -99,6 +99,66 @@ inline std::string make_string(std::size_t len, char c)
|
||||
return std::string(len, c);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<typename Char, typename Traits, typename Alloc,
|
||||
typename Char2, typename Traits2, typename Alloc2>
|
||||
struct to_string_of_impl
|
||||
{
|
||||
static_assert(sizeof(Char) == sizeof(char), "");
|
||||
static_assert(sizeof(Char2) == sizeof(char), "");
|
||||
|
||||
static std::basic_string<Char, Traits, Alloc> invoke(std::basic_string<Char2, Traits2, Alloc2> s)
|
||||
{
|
||||
std::basic_string<Char, Traits, Alloc> retval;
|
||||
std::transform(s.begin(), s.end(), std::back_inserter(retval),
|
||||
[](const Char2 c) {return static_cast<Char>(c);});
|
||||
return retval;
|
||||
}
|
||||
template<std::size_t N>
|
||||
static std::basic_string<Char, Traits, Alloc> invoke(const Char2 (&s)[N])
|
||||
{
|
||||
std::basic_string<Char, Traits, Alloc> retval;
|
||||
std::transform(std::begin(s), std::end(s), std::back_inserter(retval),
|
||||
[](const char c) {return static_cast<Char>(c);});
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Char, typename Traits, typename Alloc>
|
||||
struct to_string_of_impl<Char, Traits, Alloc, Char, Traits, Alloc>
|
||||
{
|
||||
static_assert(sizeof(Char) == sizeof(char), "");
|
||||
|
||||
static std::basic_string<Char, Traits, Alloc> invoke(std::basic_string<Char, Traits, Alloc> s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
template<std::size_t N>
|
||||
static std::basic_string<Char, Traits, Alloc> invoke(const Char (&s)[N])
|
||||
{
|
||||
return std::basic_string<Char, Traits, Alloc>(s);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Char,
|
||||
typename Traits = std::char_traits<Char>,
|
||||
typename Alloc = std::allocator<Char>,
|
||||
typename Char2, typename Traits2, typename Alloc2>
|
||||
std::basic_string<Char, Traits, Alloc>
|
||||
to_string_of(std::basic_string<Char2, Traits2, Alloc2> s)
|
||||
{
|
||||
return to_string_of_impl<Char, Traits, Alloc, Char2, Traits2, Alloc2>::invoke(std::move(s));
|
||||
}
|
||||
template<typename Char,
|
||||
typename Traits = std::char_traits<Char>,
|
||||
typename Alloc = std::allocator<Char>,
|
||||
typename Char2, typename Traits2, typename Alloc2, std::size_t N>
|
||||
std::basic_string<Char, Traits, Alloc> to_string_of(const char (&s)[N])
|
||||
{
|
||||
return to_string_of_impl<Char, Traits, Alloc, Char2, Traits2, Alloc2>::template invoke<N>(s);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace toml
|
||||
#endif // TOML11_UTILITY_HPP
|
||||
|
@@ -48,7 +48,7 @@ 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&);
|
||||
error_info make_not_found_error(const basic_value<TC>&, const std::string&, const typename basic_value<TC>::key_type&);
|
||||
|
||||
template<typename TC>
|
||||
void change_region_of_value(basic_value<TC>&, const basic_value<TC>&);
|
||||
@@ -76,6 +76,7 @@ class basic_value
|
||||
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;
|
||||
using char_type = typename string_type::value_type;
|
||||
|
||||
private:
|
||||
|
||||
@@ -643,6 +644,63 @@ class basic_value
|
||||
}
|
||||
|
||||
#endif // TOML11_HAS_STRING_VIEW
|
||||
|
||||
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
||||
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, string_type>>,
|
||||
detail::is_1byte_std_basic_string<T>
|
||||
>::value, std::nullptr_t> = nullptr>
|
||||
basic_value(const T& x)
|
||||
: basic_value(x, string_format_info{}, std::vector<std::string>{}, region_type{})
|
||||
{}
|
||||
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
||||
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, string_type>>,
|
||||
detail::is_1byte_std_basic_string<T>
|
||||
>::value, std::nullptr_t> = nullptr>
|
||||
basic_value(const T& x, string_format_info fmt)
|
||||
: basic_value(x, std::move(fmt), std::vector<std::string>{}, region_type{})
|
||||
{}
|
||||
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
||||
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, string_type>>,
|
||||
detail::is_1byte_std_basic_string<T>
|
||||
>::value, std::nullptr_t> = nullptr>
|
||||
basic_value(const T& x, std::vector<std::string> com)
|
||||
: basic_value(x, string_format_info{}, std::move(com), region_type{})
|
||||
{}
|
||||
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
||||
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, string_type>>,
|
||||
detail::is_1byte_std_basic_string<T>
|
||||
>::value, std::nullptr_t> = nullptr>
|
||||
basic_value(const T& x, string_format_info fmt, std::vector<std::string> com)
|
||||
: basic_value(x, std::move(fmt), std::move(com), region_type{})
|
||||
{}
|
||||
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
||||
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, string_type>>,
|
||||
detail::is_1byte_std_basic_string<T>
|
||||
>::value, std::nullptr_t> = nullptr>
|
||||
basic_value(const T& x, string_format_info fmt,
|
||||
std::vector<std::string> com, region_type reg)
|
||||
: type_(value_t::string),
|
||||
string_(string_storage(detail::to_string_of<char_type>(x), std::move(fmt))),
|
||||
region_(std::move(reg)), comments_(std::move(com))
|
||||
{}
|
||||
template<typename T, cxx::enable_if_t<cxx::conjunction<
|
||||
cxx::negation<std::is_same<cxx::remove_cvref_t<T>, string_type>>,
|
||||
detail::is_1byte_std_basic_string<T>
|
||||
>::value, std::nullptr_t> = nullptr>
|
||||
basic_value& operator=(const T& 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(detail::to_string_of<char_type>(x), std::move(fmt)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
// constructor (local_date) =========================================== {{{
|
||||
@@ -893,8 +951,14 @@ class basic_value
|
||||
|
||||
template<typename T>
|
||||
using enable_if_array_like_t = cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_container<T>,
|
||||
cxx::negation<std::is_same<T, array_type>>,
|
||||
detail::is_container<T>
|
||||
cxx::negation<detail::is_std_basic_string<T>>,
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
cxx::negation<detail::is_std_basic_string_view<T>>,
|
||||
#endif
|
||||
cxx::negation<detail::has_from_toml_method<T, config_type>>,
|
||||
cxx::negation<detail::has_specialized_from<T>>
|
||||
>::value, std::nullptr_t>;
|
||||
|
||||
public:
|
||||
@@ -988,7 +1052,9 @@ class basic_value
|
||||
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>
|
||||
detail::is_map<T>,
|
||||
cxx::negation<detail::has_from_toml_method<T, config_type>>,
|
||||
cxx::negation<detail::has_specialized_from<T>>
|
||||
>::value, std::nullptr_t>;
|
||||
|
||||
public:
|
||||
@@ -2062,10 +2128,10 @@ error_info make_type_error(const basic_value<TC>& v, const std::string& fname, c
|
||||
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)
|
||||
error_info make_not_found_error(const basic_value<TC>& v, const std::string& fname, const typename basic_value<TC>::key_type& key)
|
||||
{
|
||||
const auto loc = v.location();
|
||||
const std::string title = fname + ": key \"" + key + "\" not found";
|
||||
const std::string title = fname + ": key \"" + to_string_of<char>(key) + "\" not found";
|
||||
|
||||
std::vector<std::pair<source_location, std::string>> locs;
|
||||
if( ! loc.is_ok())
|
||||
|
@@ -627,14 +627,29 @@ TEST_CASE("testing toml::find string conversion")
|
||||
toml::find<std::string>(v, "key") += "bar";
|
||||
CHECK_EQ("foobar", toml::find<std::string>(v, "key"));
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
#if defined(TOML11_HAS_CHAR8_T)
|
||||
TEST_CASE("testing toml::find<string-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v = toml::table{{"key", "foo"}};
|
||||
CHECK_EQ("foo", toml::find<std::string_view>(v, "key"));
|
||||
CHECK_EQ(u8"foo", toml::find<std::u8string>(v, "key"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
TEST_CASE("testing toml::get<string_view>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v("foo");
|
||||
CHECK_EQ("foo", toml::get<std::string_view>(v));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("testing toml::find array conversion")
|
||||
{
|
||||
|
@@ -240,8 +240,19 @@ TEST_CASE("testing toml::get<floating-like>")
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
#if defined(TOML11_HAS_CHAR8_T)
|
||||
TEST_CASE("testing toml::get<string-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v("foo");
|
||||
CHECK_EQ(u8"foo", toml::get<std::u8string>(v));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
TEST_CASE("testing toml::get<string_view>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
|
@@ -587,6 +587,105 @@ TEST_CASE("testing constructor (string_view)")
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TOML11_HAS_CHAR8_T
|
||||
TEST_CASE("testing constructor (u8string)")
|
||||
{
|
||||
toml::string_format_info fmt;
|
||||
fmt.fmt = toml::string_format::basic;
|
||||
|
||||
const std::string eq("hoge");
|
||||
const std::string ne("fuga");
|
||||
|
||||
const std::u8string ref(u8"hoge");
|
||||
|
||||
{
|
||||
toml::value x(ref);
|
||||
test_is_type(x, toml::value_t::string);
|
||||
test_as_type_throws(x, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x, toml::value_t::string);
|
||||
|
||||
test_as_type<toml::value_t::string>(x, "hoge", "fuga");
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_with_comments(ref, std::vector<std::string>{"foo", "bar"});
|
||||
|
||||
test_is_type (x_with_comments, toml::value_t::string);
|
||||
test_as_type_throws (x_with_comments, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_with_comments, toml::value_t::string);
|
||||
|
||||
test_as_type<toml::value_t::string>(x_with_comments, eq, ne);
|
||||
|
||||
CHECK_EQ(x_with_comments.comments().size(), 2);
|
||||
CHECK_EQ(x_with_comments.comments().at(0), "foo");
|
||||
CHECK_EQ(x_with_comments.comments().at(1), "bar");
|
||||
|
||||
CHECK_EQ(x_with_comments.location().is_ok(), false);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_with_format(eq, fmt);
|
||||
|
||||
test_is_type (x_with_format, toml::value_t::string);
|
||||
test_as_type_throws (x_with_format, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_with_format, toml::value_t::string);
|
||||
|
||||
test_as_type <toml::value_t::string>(x_with_format, eq, ne);
|
||||
test_as_type_fmt<toml::value_t::string>(x_with_format, fmt);
|
||||
|
||||
CHECK_EQ(x_with_format.comments().size(), 0);
|
||||
CHECK_EQ(x_with_format.location().is_ok(), false);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_with_com_fmt(ref, fmt,
|
||||
std::vector<std::string>{"foo", "bar"});
|
||||
|
||||
test_is_type (x_with_com_fmt, toml::value_t::string);
|
||||
test_as_type_throws (x_with_com_fmt, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_with_com_fmt, toml::value_t::string);
|
||||
|
||||
test_as_type <toml::value_t::string>(x_with_com_fmt, eq, ne);
|
||||
test_as_type_fmt<toml::value_t::string>(x_with_com_fmt, fmt);
|
||||
|
||||
CHECK_EQ(x_with_com_fmt.comments().size(), 2);
|
||||
CHECK_EQ(x_with_com_fmt.comments().at(0), "foo");
|
||||
CHECK_EQ(x_with_com_fmt.comments().at(1), "bar");
|
||||
|
||||
CHECK_EQ(x_with_com_fmt.location().is_ok(), false);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_assign(ne, fmt);
|
||||
x_assign = ref;
|
||||
|
||||
test_is_type (x_assign, toml::value_t::string);
|
||||
test_as_type_throws (x_assign, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_assign, toml::value_t::string);
|
||||
|
||||
test_as_type <toml::value_t::string>(x_assign, eq, ne);
|
||||
test_as_type_fmt<toml::value_t::string>(x_assign, fmt);
|
||||
|
||||
CHECK_EQ(x_assign.comments().size(), 0);
|
||||
CHECK_EQ(x_assign.location().is_ok(), false);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_assign_different_type(true);
|
||||
x_assign_different_type = ref;
|
||||
|
||||
test_is_type (x_assign_different_type, toml::value_t::string);
|
||||
test_as_type_throws (x_assign_different_type, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_assign_different_type, toml::value_t::string);
|
||||
|
||||
test_as_type<toml::value_t::string>(x_assign_different_type, eq, ne);
|
||||
|
||||
CHECK_EQ(x_assign_different_type.comments().size(), 0);
|
||||
CHECK_EQ(x_assign_different_type.location().is_ok(), false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("testing constructor (local_date)")
|
||||
{
|
||||
toml::local_date_format_info fmt;
|
||||
|
Reference in New Issue
Block a user