290 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			290 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // | ||
|  | // Copyright (c) Antony Polukhin, 2012-2016. | ||
|  | // | ||
|  | // | ||
|  | // 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) | ||
|  | // | ||
|  | 
 | ||
|  | #ifndef BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP | ||
|  | #define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP | ||
|  | 
 | ||
|  | /// \file compile_time_type_info.hpp | ||
|  | /// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index. | ||
|  | /// Not intended for inclusion from user's code.  | ||
|  | 
 | ||
|  | #include <boost/config.hpp> | ||
|  | #include <boost/static_assert.hpp> | ||
|  | #include <boost/mpl/bool.hpp> | ||
|  | 
 | ||
|  | #ifdef BOOST_HAS_PRAGMA_ONCE | ||
|  | # pragma once | ||
|  | #endif | ||
|  | 
 | ||
|  | /// @cond | ||
|  | #define BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(begin_skip, end_skip, runtime_skip, runtime_skip_until)   \ | ||
|  |     namespace boost { namespace typeindex { namespace detail {                                                  \ | ||
|  |         BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_begin  = begin_skip;                               \ | ||
|  |         BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_end    = end_skip;                                 \ | ||
|  |         BOOST_STATIC_CONSTEXPR bool ctti_skip_more_at_runtime       = runtime_skip;                             \ | ||
|  |         BOOST_STATIC_CONSTEXPR char ctti_skip_until_runtime[]       = runtime_skip_until;                       \ | ||
|  |     }}} /* namespace boost::typeindex::detail */                                                                \ | ||
|  |     /**/ | ||
|  | /// @endcond | ||
|  | 
 | ||
|  | 
 | ||
|  | #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) | ||
|  |     /* Nothing to document. All the macro docs are moved to <boost/type_index.hpp> */ | ||
|  | #elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING) | ||
|  | #   include <boost/preprocessor/facilities/expand.hpp> | ||
|  |     BOOST_PP_EXPAND( BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING ) | ||
|  | #elif defined(_MSC_VER) && defined (BOOST_NO_CXX11_NOEXCEPT) | ||
|  |     // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1 | ||
|  |     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 10, false, "") | ||
|  | #elif defined(_MSC_VER) && !defined (BOOST_NO_CXX11_NOEXCEPT) | ||
|  |     // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1 | ||
|  |     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 19, false, "") | ||
|  | #elif defined(__clang__) && defined(__APPLE__) | ||
|  |     // Someone made __clang_major__ equal to LLVM version rather than compiler version | ||
|  |     // on APPLE platform. | ||
|  |     // | ||
|  |     // Using less efficient solution because there is no good way to detect real version of Clang. | ||
|  |     // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int" | ||
|  |     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ") | ||
|  | #elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0)) | ||
|  |     // sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1 | ||
|  |     // note: checked on 3.0 | ||
|  |     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 6, false, "") | ||
|  | #elif defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ > 0)) | ||
|  |     // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int" | ||
|  |     // note: checked on 3.1, 3.4 | ||
|  |     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ") | ||
|  | #elif defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) | ||
|  |     // sizeof("static contexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0u; T = ") - 1, sizeof("]") - 1 | ||
|  |     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(81, 1, false, "") | ||
|  | #elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR) | ||
|  |     // sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1 | ||
|  |     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "") | ||
|  | #else | ||
|  |     // Deafult code for other platforms... Just skip nothing! | ||
|  |     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(0, 0, false, "") | ||
|  | #endif | ||
|  | 
 | ||
|  | #undef BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS | ||
|  | 
 | ||
|  | namespace boost { namespace typeindex { namespace detail {  | ||
|  |     template <bool Condition> | ||
|  |     BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() BOOST_NOEXCEPT { | ||
|  |         BOOST_STATIC_ASSERT_MSG( | ||
|  |             Condition, | ||
|  |             "TypeIndex library is misconfigured for your compiler. " | ||
|  |             "Please define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct values. See section " | ||
|  |             "'RTTI emulation limitations' of the documentation for more information." | ||
|  |         ); | ||
|  |     } | ||
|  | 
 | ||
|  |     template <class T> | ||
|  |     BOOST_CXX14_CONSTEXPR inline void failed_to_get_function_name() BOOST_NOEXCEPT { | ||
|  |         BOOST_STATIC_ASSERT_MSG( | ||
|  |             sizeof(T) && false, | ||
|  |             "TypeIndex library could not detect your compiler. " | ||
|  |             "Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use " | ||
|  |             "correct compiler macro for getting the whole function name. " | ||
|  |             "Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that." | ||
|  |         ); | ||
|  |     } | ||
|  | 
 | ||
|  |     template <unsigned int ArrayLength> | ||
|  |     BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::mpl::false_) BOOST_NOEXCEPT { | ||
|  |         return begin; | ||
|  |     } | ||
|  | 
 | ||
|  |     template<class ForwardIterator1, class ForwardIterator2> | ||
|  |     BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search( | ||
|  |         ForwardIterator1 first1, | ||
|  |         ForwardIterator1 last1, | ||
|  |         ForwardIterator2 first2, | ||
|  |         ForwardIterator2 last2) BOOST_NOEXCEPT | ||
|  |     { | ||
|  |         if (first2 == last2) { | ||
|  |             return first1;  // specified in C++11 | ||
|  |         } | ||
|  | 
 | ||
|  |         while (first1 != last1) { | ||
|  |             ForwardIterator1 it1 = first1; | ||
|  |             ForwardIterator2 it2 = first2; | ||
|  | 
 | ||
|  |             while (*it1 == *it2) { | ||
|  |                 ++it1; | ||
|  |                 ++it2; | ||
|  |                 if (it2 == last2) return first1; | ||
|  |                 if (it1 == last1) return last1; | ||
|  |             } | ||
|  | 
 | ||
|  |             ++first1; | ||
|  |         } | ||
|  | 
 | ||
|  |         return last1; | ||
|  |     } | ||
|  | 
 | ||
|  |     BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp(const char *v1, const char *v2) BOOST_NOEXCEPT { | ||
|  |         while (*v1 != '\0' && *v1 == *v2) { | ||
|  |             ++v1; | ||
|  |             ++v2; | ||
|  |         }; | ||
|  | 
 | ||
|  |         return static_cast<int>(*v1) - *v2; | ||
|  |     } | ||
|  | 
 | ||
|  |     template <unsigned int ArrayLength> | ||
|  |     BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::mpl::true_) BOOST_NOEXCEPT { | ||
|  |         const char* const it = constexpr_search( | ||
|  |             begin, begin + ArrayLength, | ||
|  |             ctti_skip_until_runtime, ctti_skip_until_runtime + sizeof(ctti_skip_until_runtime) - 1 | ||
|  |         ); | ||
|  |         return (it == begin + ArrayLength ? begin : it + sizeof(ctti_skip_until_runtime) - 1); | ||
|  |     } | ||
|  | 
 | ||
|  |     template <unsigned int ArrayLength> | ||
|  |     BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT { | ||
|  |         assert_compile_time_legths<(ArrayLength > ctti_skip_size_at_begin + ctti_skip_size_at_end)>(); | ||
|  |         return skip_begining_runtime<ArrayLength - ctti_skip_size_at_begin>( | ||
|  |             begin + ctti_skip_size_at_begin,  | ||
|  |             boost::mpl::bool_<ctti_skip_more_at_runtime>() | ||
|  |         ); | ||
|  |     } | ||
|  | 
 | ||
|  | #if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) | ||
|  |     template <unsigned int... I> | ||
|  |     struct index_seq {}; | ||
|  | 
 | ||
|  |     template <typename Left, typename Right> | ||
|  |     struct make_index_sequence_join; | ||
|  | 
 | ||
|  |     template <unsigned int... Left, unsigned int... Right> | ||
|  |     struct make_index_sequence_join<index_seq<Left...>, index_seq<Right...> > { | ||
|  |         typedef index_seq<Left..., Right...> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <unsigned int C, unsigned int D> | ||
|  |     struct make_index_seq_impl { | ||
|  |         typedef typename make_index_sequence_join< | ||
|  |             typename make_index_seq_impl<C, D / 2>::type, | ||
|  |             typename make_index_seq_impl<C + D / 2, (D + 1) / 2>::type | ||
|  |         >::type type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <unsigned int C> | ||
|  |     struct make_index_seq_impl<C, 0> { | ||
|  |         typedef index_seq<> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <unsigned int C> | ||
|  |     struct make_index_seq_impl<C, 1> { | ||
|  |         typedef index_seq<C> type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <char... C> | ||
|  |     struct cstring { | ||
|  |         static constexpr unsigned int size_ = sizeof...(C); | ||
|  |         static constexpr char data_[size_] = { C... }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <char... C> | ||
|  |     constexpr char cstring<C...>::data_[]; | ||
|  | #endif | ||
|  | 
 | ||
|  | }}} // namespace boost::typeindex::detail | ||
|  | 
 | ||
|  | namespace boost { namespace detail { | ||
|  | 
 | ||
|  | /// Noncopyable type_info that does not require RTTI. | ||
|  | /// CTTI == Compile Time Type Info. | ||
|  | /// This name must be as short as possible, to avoid code bloat | ||
|  | template <class T> | ||
|  | struct ctti { | ||
|  |     | ||
|  | #if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) | ||
|  |     //helper functions | ||
|  |     template <unsigned int I> | ||
|  |     constexpr static char s() BOOST_NOEXCEPT { // step | ||
|  |         constexpr unsigned int offset = | ||
|  |                   (I >= 10u      ? 1u : 0u) | ||
|  |                 + (I >= 100u     ? 1u : 0u) | ||
|  |                 + (I >= 1000u    ? 1u : 0u) | ||
|  |                 + (I >= 10000u   ? 1u : 0u) | ||
|  |                 + (I >= 100000u  ? 1u : 0u) | ||
|  |                 + (I >= 1000000u ? 1u : 0u) | ||
|  |         ; | ||
|  | 
 | ||
|  |     #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) | ||
|  |         return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE[I + offset]; | ||
|  |     #elif defined(__FUNCSIG__) | ||
|  |         return __FUNCSIG__[I + offset]; | ||
|  |     #else | ||
|  |         return __PRETTY_FUNCTION__[I + offset]; | ||
|  |     #endif | ||
|  |     } | ||
|  | 
 | ||
|  |     template <unsigned int ...Indexes> | ||
|  |     constexpr static const char* impl(::boost::typeindex::detail::index_seq<Indexes...> ) BOOST_NOEXCEPT { | ||
|  |         return ::boost::typeindex::detail::cstring<s<Indexes>()...>::data_; | ||
|  |     } | ||
|  | 
 | ||
|  |     template <unsigned int D = 0> // `D` means `Dummy` | ||
|  |     constexpr static const char* n() BOOST_NOEXCEPT { | ||
|  |     #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) | ||
|  |         constexpr unsigned int size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); | ||
|  |     #elif defined(__FUNCSIG__) | ||
|  |         constexpr unsigned int size = sizeof(__FUNCSIG__); | ||
|  |     #elif defined(__PRETTY_FUNCTION__) \ | ||
|  |                     || defined(__GNUC__) \ | ||
|  |                     || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \ | ||
|  |                     || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ | ||
|  |                     || (defined(__ICC) && (__ICC >= 600)) \ | ||
|  |                     || defined(__ghs__) \ | ||
|  |                     || defined(__DMC__) | ||
|  |         constexpr unsigned int size = sizeof(__PRETTY_FUNCTION__); | ||
|  |     #else | ||
|  |         boost::typeindex::detail::failed_to_get_function_name(); | ||
|  |     #endif | ||
|  | 
 | ||
|  |         boost::typeindex::detail::assert_compile_time_legths< | ||
|  |             (size > boost::typeindex::detail::ctti_skip_size_at_begin + boost::typeindex::detail::ctti_skip_size_at_end + sizeof("const *") - 1) | ||
|  |         >(); | ||
|  |         static_assert(!boost::typeindex::detail::ctti_skip_more_at_runtime, "Skipping for GCC in C++14 mode is unsupported"); | ||
|  | 
 | ||
|  |         typedef typename boost::typeindex::detail::make_index_seq_impl< | ||
|  |             boost::typeindex::detail::ctti_skip_size_at_begin, | ||
|  |             size - sizeof("const *") + 1 - boost::typeindex::detail::ctti_skip_size_at_begin | ||
|  |         >::type idx_seq; | ||
|  |         return impl(idx_seq()); | ||
|  |     } | ||
|  | #else | ||
|  |     /// Returns raw name. Must be as short, as possible, to avoid code bloat | ||
|  |     BOOST_CXX14_CONSTEXPR static const char* n() BOOST_NOEXCEPT { | ||
|  |     #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) | ||
|  |         return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); | ||
|  |     #elif defined(__FUNCSIG__) | ||
|  |         return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__); | ||
|  |     #elif defined(__PRETTY_FUNCTION__) \ | ||
|  |                 || defined(__GNUC__) \ | ||
|  |                 || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \ | ||
|  |                 || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ | ||
|  |                 || (defined(__ICC) && (__ICC >= 600)) \ | ||
|  |                 || defined(__ghs__) \ | ||
|  |                 || defined(__DMC__) | ||
|  |         return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__); | ||
|  |     #else | ||
|  |         boost::typeindex::detail::failed_to_get_function_name(); | ||
|  |         return ""; | ||
|  |     #endif | ||
|  |     } | ||
|  | #endif | ||
|  | }; | ||
|  | 
 | ||
|  | }} // namespace boost::detail | ||
|  | 
 | ||
|  | #endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP | ||
|  | 
 |