/*! @file Defines `boost::hana::string`. @copyright Louis Dionne 2013-2017 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_STRING_HPP #define BOOST_HANA_STRING_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include BOOST_HANA_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////// // string<> ////////////////////////////////////////////////////////////////////////// //! @cond namespace detail { template constexpr char const string_storage[sizeof...(s) + 1] = {s..., '\0'}; } template struct string : detail::operators::adl> , detail::iterable_operators> { static constexpr char const* c_str() { return &detail::string_storage[0]; } }; //! @endcond template struct tag_of> { using type = string_tag; }; ////////////////////////////////////////////////////////////////////////// // make ////////////////////////////////////////////////////////////////////////// template <> struct make_impl { template static constexpr auto apply(Chars const& ...) { return hana::string()...>{}; } }; ////////////////////////////////////////////////////////////////////////// // BOOST_HANA_STRING ////////////////////////////////////////////////////////////////////////// namespace string_detail { template constexpr string prepare_impl(S, std::index_sequence) { return {}; } template constexpr decltype(auto) prepare(S s) { return prepare_impl(s, std::make_index_sequence{}); } } #define BOOST_HANA_STRING(s) \ (::boost::hana::string_detail::prepare([]{ \ struct tmp { \ static constexpr decltype(auto) get() { return s; } \ }; \ return tmp{}; \ }())) \ /**/ #ifdef BOOST_HANA_CONFIG_ENABLE_STRING_UDL ////////////////////////////////////////////////////////////////////////// // _s user-defined literal ////////////////////////////////////////////////////////////////////////// namespace literals { template constexpr auto operator"" _s() { static_assert(std::is_same::value, "hana::string: Only narrow string literals are supported with " "the _s string literal right now. See https://github.com/boostorg/hana/issues/80 " "if you need support for fancier types of compile-time strings."); return hana::string_c; } } #endif ////////////////////////////////////////////////////////////////////////// // Operators ////////////////////////////////////////////////////////////////////////// namespace detail { template <> struct comparable_operators { static constexpr bool value = true; }; template <> struct orderable_operators { static constexpr bool value = true; }; } ////////////////////////////////////////////////////////////////////////// // to ////////////////////////////////////////////////////////////////////////// template <> struct to_impl { template static constexpr char const* apply(string const&) { return string::c_str(); } }; ////////////////////////////////////////////////////////////////////////// // to ////////////////////////////////////////////////////////////////////////// namespace detail { constexpr std::size_t cx_strlen(char const* s) { std::size_t n = 0u; while (*s != '\0') ++s, ++n; return n; } template constexpr hana::string()[I]...> expand(std::index_sequence) { return {}; } } template struct to_impl::value && std::is_convertible::value >> { template static constexpr auto apply(S const&) { constexpr char const* s = hana::value(); constexpr std::size_t len = detail::cx_strlen(s); return detail::expand(std::make_index_sequence{}); } }; ////////////////////////////////////////////////////////////////////////// // Comparable ////////////////////////////////////////////////////////////////////////// template <> struct equal_impl { template static constexpr auto apply(S const&, S const&) { return hana::true_c; } template static constexpr auto apply(S1 const&, S2 const&) { return hana::false_c; } }; ////////////////////////////////////////////////////////////////////////// // Orderable ////////////////////////////////////////////////////////////////////////// template <> struct less_impl { template static constexpr auto apply(string const&, string const&) { // We put a '\0' at the end only to avoid empty arrays. constexpr char const c_str1[] = {s1..., '\0'}; constexpr char const c_str2[] = {s2..., '\0'}; return hana::bool_c; } }; ////////////////////////////////////////////////////////////////////////// // Monoid ////////////////////////////////////////////////////////////////////////// template <> struct plus_impl { template static constexpr auto apply(string const&, string const&) { return string{}; } }; template <> struct zero_impl { static constexpr auto apply() { return string<>{}; } }; template constexpr auto operator+(string const&, string const&) { return hana::string{}; } ////////////////////////////////////////////////////////////////////////// // Foldable ////////////////////////////////////////////////////////////////////////// template <> struct unpack_impl { template static constexpr decltype(auto) apply(string const&, F&& f) { return static_cast(f)(char_{}...); } }; template <> struct length_impl { template static constexpr auto apply(string const&) { return hana::size_c; } }; ////////////////////////////////////////////////////////////////////////// // Iterable ////////////////////////////////////////////////////////////////////////// template <> struct front_impl { template static constexpr auto apply(string const&) { return hana::char_c; } }; template <> struct drop_front_impl { template static constexpr auto helper(string const&, std::index_sequence) { constexpr char s[] = {xs...}; return hana::string_c; } template static constexpr auto apply(string const& s, N const&) { return helper(s, std::make_index_sequence< (N::value < sizeof...(xs)) ? sizeof...(xs) - N::value : 0 >{}); } template static constexpr auto apply(string<> const& s, N const&) { return s; } }; template <> struct is_empty_impl { template static constexpr auto apply(string const&) { return hana::bool_c; } }; template <> struct at_impl { template static constexpr auto apply(string const&, N const&) { // We put a '\0' at the end to avoid an empty array. constexpr char characters[] = {s..., '\0'}; constexpr auto n = N::value; return hana::char_c; } }; ////////////////////////////////////////////////////////////////////////// // Searchable ////////////////////////////////////////////////////////////////////////// template <> struct contains_impl { template static constexpr auto helper(string const&, C const&, hana::true_) { constexpr char const characters[] = {s..., '\0'}; constexpr char c = hana::value(); return hana::bool_c< detail::find(characters, characters + sizeof...(s), c) != characters + sizeof...(s) >; } template static constexpr auto helper(S const&, C const&, hana::false_) { return hana::false_c; } template static constexpr auto apply(S const& s, C const& c) { return helper(s, c, hana::bool_c::value>); } }; template <> struct find_impl { template static constexpr auto apply(string const& str, Char const& c) { return hana::if_(contains_impl::apply(str, c), hana::just(c), hana::nothing ); } }; ////////////////////////////////////////////////////////////////////////// // Hashable ////////////////////////////////////////////////////////////////////////// template <> struct hash_impl { template static constexpr auto apply(String const&) { return hana::type_c; } }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_STRING_HPP