123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- //
- // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
- // Copyright (c) 2022 Alan de Freitas ([email protected])
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // Official repository: https://github.com/boostorg/url
- //
- #ifndef BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP
- #define BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP
- #include <boost/core/detail/string_view.hpp>
- #include <boost/assert.hpp>
- #include <cstdint>
- #include <iterator>
- #include <type_traits>
- namespace boost {
- namespace urls {
- namespace grammar {
- namespace detail {
- template<class T, class = void>
- struct is_char_iter : std::false_type {};
- template<class T>
- struct is_char_iter<T, void_t<
- decltype(std::declval<char&>() =
- *std::declval<T const&>()),
- decltype(std::declval<T&>() =
- ++std::declval<T&>()),
- decltype(std::declval<bool&>() =
- std::declval<T const&>() ==
- std::declval<T const&>())
- > > : std::integral_constant<bool,
- std::is_copy_constructible<T>::value>
- {
- };
- template<class T, class = void>
- struct is_char_range : std::false_type {};
- template<class T>
- struct is_char_range<T, void_t<
- decltype(std::declval<T const&>().begin()),
- decltype(std::declval<T const&>().end())
- > > : std::integral_constant<bool,
- is_char_iter<decltype(
- std::declval<T const&>(
- ).begin())>::value &&
- is_char_iter<decltype(
- std::declval<T const&>(
- ).end())>::value>
- {
- };
- template<class T>
- struct type_id_impl
- {
- static
- constexpr
- char cid = 0;
- };
- template<class T>
- constexpr
- char
- type_id_impl<T>::cid;
- template<class T>
- constexpr
- std::uintptr_t
- type_id() noexcept
- {
- return std::uintptr_t(
- &type_id_impl<T>::cid);
- }
- //------------------------------------------------
- constexpr
- char
- to_lower(char c) noexcept
- {
- return
- (c >= 'A' &&
- c <= 'Z')
- ? c + 'a' - 'A'
- : c;
- }
- constexpr
- char
- to_upper(char c) noexcept
- {
- return
- (c >= 'a' &&
- c <= 'z')
- ? c - ('a' - 'A')
- : c;
- }
- //------------------------------------------------
- template<class S0, class S1>
- auto
- ci_is_equal(
- S0 const& s0,
- S1 const& s1) ->
- typename std::enable_if<
- ! std::is_convertible<
- S0, core::string_view>::value ||
- ! std::is_convertible<
- S1, core::string_view>::value,
- bool>::type
- {
- /* If you get a compile error here, it
- means that a range you passed does
- not meet the requirements stated
- in the documentation.
- */
- static_assert(
- is_char_range<S0>::value,
- "Type requirements not met");
- static_assert(
- is_char_range<S1>::value,
- "Type requirements not met");
- // Arguments are sorted by type to
- // reduce the number of function
- // template instantiations. This
- // works because:
- //
- // ci_is_equal(s0,s1) == ci_is_equal(s1,s0)
- //
- BOOST_ASSERT(
- detail::type_id<S0>() <=
- detail::type_id<S1>());
- auto it0 = s0.begin();
- auto it1 = s1.begin();
- auto const end0 = s0.end();
- auto const end1 = s1.end();
- for(;;)
- {
- if(it0 == end0)
- return it1 == end1;
- if(it1 == end1)
- return false;
- if( to_lower(*it0) !=
- to_lower(*it1))
- return false;
- ++it0;
- ++it1;
- }
- }
- //------------------------------------------------
- BOOST_URL_DECL
- bool
- ci_is_equal(
- core::string_view s0,
- core::string_view s1) noexcept;
- BOOST_URL_DECL
- bool
- ci_is_less(
- core::string_view s0,
- core::string_view s1) noexcept;
- } // detail
- } // grammar
- } // urls
- } // boost
- #endif
|