Line data Source code
1 : //
2 : // Copyright (c) 2023 Christian Mazakas
3 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/http_proto
9 : //
10 :
11 : #ifndef BOOST_HTTP_PROTO_DETAIL_TYPE_INDEX_HPP
12 : #define BOOST_HTTP_PROTO_DETAIL_TYPE_INDEX_HPP
13 :
14 : #include <boost/config.hpp>
15 : #include <boost/assert/source_location.hpp>
16 : #include <boost/container_hash/hash.hpp>
17 : #include <boost/core/typeinfo.hpp>
18 : #include <boost/throw_exception.hpp>
19 :
20 : namespace boost {
21 : namespace http_proto {
22 : namespace detail {
23 :
24 : struct type_index_impl
25 : {
26 : private:
27 : boost::core::typeinfo const *pdata_ = nullptr;
28 :
29 : std::size_t
30 1216 : get_raw_name_length() const noexcept
31 : {
32 : // Boost.TypeIndex has a dramatically more sophisticated implementation here
33 : // see if this eventually turns out to matter and if it does, essentially
34 : // just do more copy-paste
35 1216 : return std::strlen(raw_name());
36 : }
37 :
38 : bool
39 1095 : equal(type_index_impl const &rhs) const noexcept
40 : {
41 1095 : return raw_name() == rhs.raw_name() ||
42 1095 : !std::strcmp(raw_name(), rhs.raw_name());
43 : }
44 :
45 : public:
46 1155 : type_index_impl(
47 : boost::core::typeinfo const &type_info) noexcept
48 1155 : : pdata_(&type_info) {}
49 :
50 : type_index_impl(type_index_impl const &) = default;
51 : type_index_impl& operator=(
52 : type_index_impl const &) = default;
53 :
54 : ~type_index_impl() = default;
55 :
56 : template <class T>
57 : static
58 : type_index_impl
59 1155 : type_id() noexcept
60 : {
61 1155 : return type_index_impl(BOOST_CORE_TYPEID(T));
62 : }
63 :
64 : char const*
65 5838 : raw_name() const noexcept
66 : {
67 5838 : return pdata_->name();
68 : }
69 :
70 : std::size_t
71 1216 : hash_code() const noexcept
72 : {
73 1216 : return boost::hash_range(
74 2432 : raw_name(), raw_name() + get_raw_name_length());
75 : }
76 :
77 : bool
78 1095 : operator==(type_index_impl const &rhs) const noexcept
79 : {
80 1095 : return equal(rhs);
81 : }
82 :
83 : bool
84 : operator!=(type_index_impl const &rhs) const noexcept
85 : {
86 : return !equal(rhs);
87 : }
88 : };
89 :
90 : // like std::type_index,
91 : // but without requiring RTTI
92 : using type_index = type_index_impl;
93 :
94 : template <class T>
95 : type_index
96 1155 : get_type_index() noexcept
97 : {
98 1155 : return type_index_impl::type_id<T>();
99 : }
100 :
101 : struct type_index_hasher
102 : {
103 : std::size_t
104 1216 : operator()(type_index const &tid) const noexcept
105 : {
106 1216 : return tid.hash_code();
107 : }
108 : };
109 :
110 : BOOST_NOINLINE BOOST_NORETURN
111 : inline
112 : void
113 0 : throw_bad_cast(boost::source_location const& loc = {})
114 : {
115 0 : boost::throw_exception(std::bad_cast(), loc);
116 : }
117 :
118 : template <class U, class T>
119 : U
120 1095 : downcast(T *p)
121 : {
122 : #ifdef BOOST_NO_RTTI
123 : return static_cast<U>(p);
124 : #else
125 1095 : auto q = dynamic_cast<U>(p);
126 1095 : if(! q )
127 0 : throw_bad_cast();
128 1095 : return q;
129 : #endif
130 : }
131 :
132 : template <class U, class T>
133 : U
134 60 : downcast(T &p)
135 : {
136 : #ifdef BOOST_NO_RTTI
137 : return static_cast<U>(p);
138 : #else
139 60 : return dynamic_cast<U>(p);
140 : #endif
141 : }
142 :
143 : } // namespace detail
144 : } // namespace http_proto
145 : } // namespace boost
146 :
147 : #endif
|