summaryrefslogtreecommitdiff
path: root/boost/hana/string.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hana/string.hpp')
-rw-r--r--boost/hana/string.hpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/boost/hana/string.hpp b/boost/hana/string.hpp
new file mode 100644
index 0000000000..836a92be6a
--- /dev/null
+++ b/boost/hana/string.hpp
@@ -0,0 +1,290 @@
+/*!
+@file
+Defines `boost::hana::string`.
+
+@copyright Louis Dionne 2013-2016
+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/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/unpack.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>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //////////////////////////////////////////////////////////////////////////
+ // string<>
+ //////////////////////////////////////////////////////////////////////////
+ //! @cond
+ template <char ...s>
+ struct string
+ : detail::operators::adl<string<s...>>
+ , detail::iterable_operators<string<s...>>
+ { };
+ //! @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://goo.gl/fBbKD7 "
+ "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 c_string[sizeof...(c) + 1] = {c..., '\0'};
+
+ template <char ...c>
+ static constexpr char const* apply(string<c...> const&)
+ { return c_string<c...>; }
+ };
+
+ template <char ...c>
+ constexpr char const to_impl<char const*, string_tag>::c_string[sizeof...(c) + 1];
+
+ //////////////////////////////////////////////////////////////////////////
+ // 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)
+ )>;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // 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>;
+ }
+ };
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_STRING_HPP