File indexing completed on 2025-01-18 09:38:06
0001
0002
0003
0004
0005
0006
0007
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
0052
0053
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
0069
0070 template <char ...s>
0071 struct tag_of<string<s...>> {
0072 using type = string_tag;
0073 };
0074
0075
0076
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
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
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
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
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
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
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
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
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
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
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
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
0295 constexpr char characters[] = {s..., '\0'};
0296 constexpr auto n = N::value;
0297 return hana::char_c<characters[n]>;
0298 }
0299 };
0300
0301
0302
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
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 }}
0348
0349 #endif