Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:06

0001 /*!
0002 @file
0003 Defines `boost::hana::string`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_STRING_HPP
0011 #define BOOST_HANA_STRING_HPP
0012 
0013 #include <boost/hana/fwd/string.hpp>
0014 
0015 #include <boost/hana/bool.hpp>
0016 #include <boost/hana/concept/constant.hpp>
0017 #include <boost/hana/config.hpp>
0018 #include <boost/hana/core/make.hpp>
0019 #include <boost/hana/detail/algorithm.hpp>
0020 #include <boost/hana/detail/operators/adl.hpp>
0021 #include <boost/hana/detail/operators/comparable.hpp>
0022 #include <boost/hana/detail/operators/iterable.hpp>
0023 #include <boost/hana/detail/operators/orderable.hpp>
0024 #include <boost/hana/fwd/at.hpp>
0025 #include <boost/hana/fwd/contains.hpp>
0026 #include <boost/hana/fwd/core/tag_of.hpp>
0027 #include <boost/hana/fwd/core/to.hpp>
0028 #include <boost/hana/fwd/drop_front.hpp>
0029 #include <boost/hana/fwd/equal.hpp>
0030 #include <boost/hana/fwd/find.hpp>
0031 #include <boost/hana/fwd/front.hpp>
0032 #include <boost/hana/fwd/hash.hpp>
0033 #include <boost/hana/fwd/is_empty.hpp>
0034 #include <boost/hana/fwd/length.hpp>
0035 #include <boost/hana/fwd/less.hpp>
0036 #include <boost/hana/fwd/plus.hpp>
0037 #include <boost/hana/fwd/unpack.hpp>
0038 #include <boost/hana/fwd/zero.hpp>
0039 #include <boost/hana/if.hpp>
0040 #include <boost/hana/integral_constant.hpp>
0041 #include <boost/hana/optional.hpp>
0042 #include <boost/hana/type.hpp>
0043 
0044 #include <utility>
0045 #include <cstddef>
0046 #include <type_traits>
0047 
0048 
0049 namespace boost { namespace hana {
0050     //////////////////////////////////////////////////////////////////////////
0051     // string<>
0052     //////////////////////////////////////////////////////////////////////////
0053     //! @cond
0054     namespace detail {
0055         template <char ...s>
0056         constexpr char const string_storage[sizeof...(s) + 1] = {s..., '\0'};
0057     }
0058 
0059     template <char ...s>
0060     struct string
0061         : detail::operators::adl<string<s...>>
0062         , detail::iterable_operators<string<s...>>
0063     {
0064         static constexpr char const* c_str() {
0065             return &detail::string_storage<s...>[0];
0066         }
0067     };
0068     //! @endcond
0069 
0070     template <char ...s>
0071     struct tag_of<string<s...>> {
0072         using type = string_tag;
0073     };
0074 
0075     //////////////////////////////////////////////////////////////////////////
0076     // make<string_tag>
0077     //////////////////////////////////////////////////////////////////////////
0078     template <>
0079     struct make_impl<string_tag> {
0080         template <typename ...Chars>
0081         static constexpr auto apply(Chars const& ...) {
0082             return hana::string<hana::value<Chars>()...>{};
0083         }
0084     };
0085 
0086     //////////////////////////////////////////////////////////////////////////
0087     // BOOST_HANA_STRING
0088     //////////////////////////////////////////////////////////////////////////
0089     namespace string_detail {
0090         template <typename S, std::size_t ...N>
0091         constexpr string<S::get()[N]...>
0092         prepare_impl(S, std::index_sequence<N...>)
0093         { return {}; }
0094 
0095         template <typename S>
0096         constexpr decltype(auto) prepare(S s) {
0097             return prepare_impl(s,
0098                 std::make_index_sequence<sizeof(S::get()) - 1>{});
0099         }
0100     }
0101 
0102 #define BOOST_HANA_STRING(s)                                                \
0103     (::boost::hana::string_detail::prepare([]{                              \
0104         struct tmp {                                                        \
0105             static constexpr decltype(auto) get() { return s; }             \
0106         };                                                                  \
0107         return tmp{};                                                       \
0108     }()))                                                                   \
0109 /**/
0110 
0111 #ifdef BOOST_HANA_CONFIG_ENABLE_STRING_UDL
0112     //////////////////////////////////////////////////////////////////////////
0113     // _s user-defined literal
0114     //////////////////////////////////////////////////////////////////////////
0115     namespace literals {
0116         template <typename CharT, CharT ...s>
0117         constexpr auto operator"" _s() {
0118             static_assert(std::is_same<CharT, char>::value,
0119             "hana::string: Only narrow string literals are supported with "
0120             "the _s string literal right now. See https://github.com/boostorg/hana/issues/80 "
0121             "if you need support for fancier types of compile-time strings.");
0122             return hana::string_c<s...>;
0123         }
0124     }
0125 #endif
0126 
0127     //////////////////////////////////////////////////////////////////////////
0128     // Operators
0129     //////////////////////////////////////////////////////////////////////////
0130     namespace detail {
0131         template <>
0132         struct comparable_operators<string_tag> {
0133             static constexpr bool value = true;
0134         };
0135         template <>
0136         struct orderable_operators<string_tag> {
0137             static constexpr bool value = true;
0138         };
0139     }
0140 
0141     //////////////////////////////////////////////////////////////////////////
0142     // to<char const*>
0143     //////////////////////////////////////////////////////////////////////////
0144     template <>
0145     struct to_impl<char const*, string_tag> {
0146         template <char ...c>
0147         static constexpr char const* apply(string<c...> const&)
0148         { return string<c...>::c_str(); }
0149     };
0150 
0151     //////////////////////////////////////////////////////////////////////////
0152     // to<string_tag>
0153     //////////////////////////////////////////////////////////////////////////
0154     namespace detail {
0155         constexpr std::size_t cx_strlen(char const* s) {
0156           std::size_t n = 0u;
0157           while (*s != '\0')
0158             ++s, ++n;
0159           return n;
0160         }
0161 
0162         template <typename S, std::size_t ...I>
0163         constexpr hana::string<hana::value<S>()[I]...> expand(std::index_sequence<I...>)
0164         { return {}; }
0165     }
0166 
0167     template <typename IC>
0168     struct to_impl<hana::string_tag, IC, hana::when<
0169         hana::Constant<IC>::value &&
0170         std::is_convertible<typename IC::value_type, char const*>::value
0171     >> {
0172         template <typename S>
0173         static constexpr auto apply(S const&) {
0174             constexpr char const* s = hana::value<S>();
0175             constexpr std::size_t len = detail::cx_strlen(s);
0176             return detail::expand<S>(std::make_index_sequence<len>{});
0177         }
0178     };
0179 
0180     //////////////////////////////////////////////////////////////////////////
0181     // Comparable
0182     //////////////////////////////////////////////////////////////////////////
0183     template <>
0184     struct equal_impl<string_tag, string_tag> {
0185         template <typename S>
0186         static constexpr auto apply(S const&, S const&)
0187         { return hana::true_c; }
0188 
0189         template <typename S1, typename S2>
0190         static constexpr auto apply(S1 const&, S2 const&)
0191         { return hana::false_c; }
0192     };
0193 
0194     //////////////////////////////////////////////////////////////////////////
0195     // Orderable
0196     //////////////////////////////////////////////////////////////////////////
0197     template <>
0198     struct less_impl<string_tag, string_tag> {
0199         template <char ...s1, char ...s2>
0200         static constexpr auto
0201         apply(string<s1...> const&, string<s2...> const&) {
0202             // We put a '\0' at the end only to avoid empty arrays.
0203             constexpr char const c_str1[] = {s1..., '\0'};
0204             constexpr char const c_str2[] = {s2..., '\0'};
0205             return hana::bool_c<detail::lexicographical_compare(
0206                 c_str1, c_str1 + sizeof...(s1),
0207                 c_str2, c_str2 + sizeof...(s2)
0208             )>;
0209         }
0210     };
0211 
0212     //////////////////////////////////////////////////////////////////////////
0213     // Monoid
0214     //////////////////////////////////////////////////////////////////////////
0215     template <>
0216     struct plus_impl<string_tag, string_tag> {
0217         template <char ...s1, char ...s2>
0218         static constexpr auto
0219         apply(string<s1...> const&, string<s2...> const&) {
0220             return string<s1..., s2...>{};
0221         }
0222     };
0223 
0224     template <>
0225     struct zero_impl<string_tag> {
0226         static constexpr auto apply() {
0227             return string<>{};
0228         }
0229     };
0230 
0231     template <char ...s1, char ...s2>
0232     constexpr auto operator+(string<s1...> const&, string<s2...> const&) {
0233         return hana::string<s1..., s2...>{};
0234     }
0235 
0236     //////////////////////////////////////////////////////////////////////////
0237     // Foldable
0238     //////////////////////////////////////////////////////////////////////////
0239     template <>
0240     struct unpack_impl<string_tag> {
0241         template <char ...s, typename F>
0242         static constexpr decltype(auto) apply(string<s...> const&, F&& f)
0243         { return static_cast<F&&>(f)(char_<s>{}...); }
0244     };
0245 
0246     template <>
0247     struct length_impl<string_tag> {
0248         template <char ...s>
0249         static constexpr auto apply(string<s...> const&)
0250         { return hana::size_c<sizeof...(s)>; }
0251     };
0252 
0253     //////////////////////////////////////////////////////////////////////////
0254     // Iterable
0255     //////////////////////////////////////////////////////////////////////////
0256     template <>
0257     struct front_impl<string_tag> {
0258         template <char x, char ...xs>
0259         static constexpr auto apply(string<x, xs...> const&)
0260         { return hana::char_c<x>; }
0261     };
0262 
0263     template <>
0264     struct drop_front_impl<string_tag> {
0265         template <std::size_t N, char ...xs, std::size_t ...i>
0266         static constexpr auto helper(string<xs...> const&, std::index_sequence<i...>) {
0267             constexpr char s[] = {xs...};
0268             return hana::string_c<s[i + N]...>;
0269         }
0270 
0271         template <char ...xs, typename N>
0272         static constexpr auto apply(string<xs...> const& s, N const&) {
0273             return helper<N::value>(s, std::make_index_sequence<
0274                 (N::value < sizeof...(xs)) ? sizeof...(xs) - N::value : 0
0275             >{});
0276         }
0277 
0278         template <typename N>
0279         static constexpr auto apply(string<> const& s, N const&)
0280         { return s; }
0281     };
0282 
0283     template <>
0284     struct is_empty_impl<string_tag> {
0285         template <char ...s>
0286         static constexpr auto apply(string<s...> const&)
0287         { return hana::bool_c<sizeof...(s) == 0>; }
0288     };
0289 
0290     template <>
0291     struct at_impl<string_tag> {
0292         template <char ...s, typename N>
0293         static constexpr auto apply(string<s...> const&, N const&) {
0294             // We put a '\0' at the end to avoid an empty array.
0295             constexpr char characters[] = {s..., '\0'};
0296             constexpr auto n = N::value;
0297             return hana::char_c<characters[n]>;
0298         }
0299     };
0300 
0301     //////////////////////////////////////////////////////////////////////////
0302     // Searchable
0303     //////////////////////////////////////////////////////////////////////////
0304     template <>
0305     struct contains_impl<string_tag> {
0306         template <char ...s, typename C>
0307         static constexpr auto
0308         helper(string<s...> const&, C const&, hana::true_) {
0309             constexpr char const characters[] = {s..., '\0'};
0310             constexpr char c = hana::value<C>();
0311             return hana::bool_c<
0312                 detail::find(characters, characters + sizeof...(s), c)
0313                     != characters + sizeof...(s)
0314             >;
0315         }
0316 
0317         template <typename S, typename C>
0318         static constexpr auto helper(S const&, C const&, hana::false_)
0319         { return hana::false_c; }
0320 
0321         template <typename S, typename C>
0322         static constexpr auto apply(S const& s, C const& c)
0323         { return helper(s, c, hana::bool_c<hana::Constant<C>::value>); }
0324     };
0325 
0326     template <>
0327     struct find_impl<string_tag> {
0328         template <char ...s, typename Char>
0329         static constexpr auto apply(string<s...> const& str, Char const& c) {
0330             return hana::if_(contains_impl<string_tag>::apply(str, c),
0331                 hana::just(c),
0332                 hana::nothing
0333             );
0334         }
0335     };
0336 
0337     //////////////////////////////////////////////////////////////////////////
0338     // Hashable
0339     //////////////////////////////////////////////////////////////////////////
0340     template <>
0341     struct hash_impl<string_tag> {
0342         template <typename String>
0343         static constexpr auto apply(String const&) {
0344             return hana::type_c<String>;
0345         }
0346     };
0347 }} // end namespace boost::hana
0348 
0349 #endif // !BOOST_HANA_STRING_HPP