123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- /*!
- @file
- Defines `boost::hana::string`.
- Copyright Louis Dionne 2013-2022
- 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 <boost/hana/fwd/string.hpp>
- #include <boost/hana/bool.hpp>
- #include <boost/hana/concept/constant.hpp>
- #include <boost/hana/config.hpp>
- #include <boost/hana/core/make.hpp>
- #include <boost/hana/detail/algorithm.hpp>
- #include <boost/hana/detail/operators/adl.hpp>
- #include <boost/hana/detail/operators/comparable.hpp>
- #include <boost/hana/detail/operators/iterable.hpp>
- #include <boost/hana/detail/operators/orderable.hpp>
- #include <boost/hana/fwd/at.hpp>
- #include <boost/hana/fwd/contains.hpp>
- #include <boost/hana/fwd/core/tag_of.hpp>
- #include <boost/hana/fwd/core/to.hpp>
- #include <boost/hana/fwd/drop_front.hpp>
- #include <boost/hana/fwd/equal.hpp>
- #include <boost/hana/fwd/find.hpp>
- #include <boost/hana/fwd/front.hpp>
- #include <boost/hana/fwd/hash.hpp>
- #include <boost/hana/fwd/is_empty.hpp>
- #include <boost/hana/fwd/length.hpp>
- #include <boost/hana/fwd/less.hpp>
- #include <boost/hana/fwd/plus.hpp>
- #include <boost/hana/fwd/unpack.hpp>
- #include <boost/hana/fwd/zero.hpp>
- #include <boost/hana/if.hpp>
- #include <boost/hana/integral_constant.hpp>
- #include <boost/hana/optional.hpp>
- #include <boost/hana/type.hpp>
- #include <utility>
- #include <cstddef>
- #include <type_traits>
- namespace boost { namespace hana {
- //////////////////////////////////////////////////////////////////////////
- // string<>
- //////////////////////////////////////////////////////////////////////////
- //! @cond
- namespace detail {
- template <char ...s>
- constexpr char const string_storage[sizeof...(s) + 1] = {s..., '\0'};
- }
- template <char ...s>
- struct string
- : detail::operators::adl<string<s...>>
- , detail::iterable_operators<string<s...>>
- {
- static constexpr char const* c_str() {
- return &detail::string_storage<s...>[0];
- }
- };
- //! @endcond
- template <char ...s>
- struct tag_of<string<s...>> {
- using type = string_tag;
- };
- //////////////////////////////////////////////////////////////////////////
- // make<string_tag>
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct make_impl<string_tag> {
- template <typename ...Chars>
- static constexpr auto apply(Chars const& ...) {
- return hana::string<hana::value<Chars>()...>{};
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // BOOST_HANA_STRING
- //////////////////////////////////////////////////////////////////////////
- namespace string_detail {
- template <typename S, std::size_t ...N>
- constexpr string<S::get()[N]...>
- prepare_impl(S, std::index_sequence<N...>)
- { return {}; }
- template <typename S>
- constexpr decltype(auto) prepare(S s) {
- return prepare_impl(s,
- std::make_index_sequence<sizeof(S::get()) - 1>{});
- }
- }
- #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 <typename CharT, CharT ...s>
- constexpr auto operator"" _s() {
- static_assert(std::is_same<CharT, char>::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<s...>;
- }
- }
- #endif
- //////////////////////////////////////////////////////////////////////////
- // Operators
- //////////////////////////////////////////////////////////////////////////
- namespace detail {
- template <>
- struct comparable_operators<string_tag> {
- static constexpr bool value = true;
- };
- template <>
- struct orderable_operators<string_tag> {
- static constexpr bool value = true;
- };
- }
- //////////////////////////////////////////////////////////////////////////
- // to<char const*>
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct to_impl<char const*, string_tag> {
- template <char ...c>
- static constexpr char const* apply(string<c...> const&)
- { return string<c...>::c_str(); }
- };
- //////////////////////////////////////////////////////////////////////////
- // to<string_tag>
- //////////////////////////////////////////////////////////////////////////
- namespace detail {
- constexpr std::size_t cx_strlen(char const* s) {
- std::size_t n = 0u;
- while (*s != '\0')
- ++s, ++n;
- return n;
- }
- template <typename S, std::size_t ...I>
- constexpr hana::string<hana::value<S>()[I]...> expand(std::index_sequence<I...>)
- { return {}; }
- }
- template <typename IC>
- struct to_impl<hana::string_tag, IC, hana::when<
- hana::Constant<IC>::value &&
- std::is_convertible<typename IC::value_type, char const*>::value
- >> {
- template <typename S>
- static constexpr auto apply(S const&) {
- constexpr char const* s = hana::value<S>();
- constexpr std::size_t len = detail::cx_strlen(s);
- return detail::expand<S>(std::make_index_sequence<len>{});
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Comparable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct equal_impl<string_tag, string_tag> {
- template <typename S>
- static constexpr auto apply(S const&, S const&)
- { return hana::true_c; }
- template <typename S1, typename S2>
- static constexpr auto apply(S1 const&, S2 const&)
- { return hana::false_c; }
- };
- //////////////////////////////////////////////////////////////////////////
- // Orderable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct less_impl<string_tag, string_tag> {
- template <char ...s1, char ...s2>
- static constexpr auto
- apply(string<s1...> const&, string<s2...> 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<detail::lexicographical_compare(
- c_str1, c_str1 + sizeof...(s1),
- c_str2, c_str2 + sizeof...(s2)
- )>;
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Monoid
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct plus_impl<string_tag, string_tag> {
- template <char ...s1, char ...s2>
- static constexpr auto
- apply(string<s1...> const&, string<s2...> const&) {
- return string<s1..., s2...>{};
- }
- };
- template <>
- struct zero_impl<string_tag> {
- static constexpr auto apply() {
- return string<>{};
- }
- };
- template <char ...s1, char ...s2>
- constexpr auto operator+(string<s1...> const&, string<s2...> const&) {
- return hana::string<s1..., s2...>{};
- }
- //////////////////////////////////////////////////////////////////////////
- // Foldable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct unpack_impl<string_tag> {
- template <char ...s, typename F>
- static constexpr decltype(auto) apply(string<s...> const&, F&& f)
- { return static_cast<F&&>(f)(char_<s>{}...); }
- };
- template <>
- struct length_impl<string_tag> {
- template <char ...s>
- static constexpr auto apply(string<s...> const&)
- { return hana::size_c<sizeof...(s)>; }
- };
- //////////////////////////////////////////////////////////////////////////
- // Iterable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct front_impl<string_tag> {
- template <char x, char ...xs>
- static constexpr auto apply(string<x, xs...> const&)
- { return hana::char_c<x>; }
- };
- template <>
- struct drop_front_impl<string_tag> {
- template <std::size_t N, char ...xs, std::size_t ...i>
- static constexpr auto helper(string<xs...> const&, std::index_sequence<i...>) {
- constexpr char s[] = {xs...};
- return hana::string_c<s[i + N]...>;
- }
- template <char ...xs, typename N>
- static constexpr auto apply(string<xs...> const& s, N const&) {
- return helper<N::value>(s, std::make_index_sequence<
- (N::value < sizeof...(xs)) ? sizeof...(xs) - N::value : 0
- >{});
- }
- template <typename N>
- static constexpr auto apply(string<> const& s, N const&)
- { return s; }
- };
- template <>
- struct is_empty_impl<string_tag> {
- template <char ...s>
- static constexpr auto apply(string<s...> const&)
- { return hana::bool_c<sizeof...(s) == 0>; }
- };
- template <>
- struct at_impl<string_tag> {
- template <char ...s, typename N>
- static constexpr auto apply(string<s...> 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<characters[n]>;
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Searchable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct contains_impl<string_tag> {
- template <char ...s, typename C>
- static constexpr auto
- helper(string<s...> const&, C const&, hana::true_) {
- constexpr char const characters[] = {s..., '\0'};
- constexpr char c = hana::value<C>();
- return hana::bool_c<
- detail::find(characters, characters + sizeof...(s), c)
- != characters + sizeof...(s)
- >;
- }
- template <typename S, typename C>
- static constexpr auto helper(S const&, C const&, hana::false_)
- { return hana::false_c; }
- template <typename S, typename C>
- static constexpr auto apply(S const& s, C const& c)
- { return helper(s, c, hana::bool_c<hana::Constant<C>::value>); }
- };
- template <>
- struct find_impl<string_tag> {
- template <char ...s, typename Char>
- static constexpr auto apply(string<s...> const& str, Char const& c) {
- return hana::if_(contains_impl<string_tag>::apply(str, c),
- hana::just(c),
- hana::nothing
- );
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Hashable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct hash_impl<string_tag> {
- template <typename String>
- static constexpr auto apply(String const&) {
- return hana::type_c<String>;
- }
- };
- }} // end namespace boost::hana
- #endif // !BOOST_HANA_STRING_HPP
|