Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/beast2
8 : //
9 :
10 : #include <boost/beast2/polystore.hpp>
11 : #include <boost/assert.hpp>
12 : #include <unordered_map>
13 : #include <vector>
14 :
15 : namespace boost {
16 : namespace beast2 {
17 :
18 : struct polystore::impl
19 : {
20 : struct hash
21 : {
22 88 : std::size_t operator()(
23 : detail::type_info const* p) const noexcept
24 : {
25 88 : return p->hash_code();
26 : }
27 : };
28 :
29 : struct eq
30 : {
31 64 : bool operator()(
32 : detail::type_info const* p0,
33 : detail::type_info const* p1) const noexcept
34 : {
35 64 : return *p0 == *p1;
36 : }
37 : };
38 :
39 : std::vector<any_ptr> v;
40 : std::unordered_map<
41 : detail::type_info const*, void*, hash, eq> m;
42 :
43 8 : ~impl()
44 : {
45 : // destroy in reverse order
46 19 : while(! v.empty())
47 11 : v.resize(v.size() - 1);
48 8 : }
49 : };
50 :
51 15 : polystore::any::~any() = default;
52 :
53 8 : polystore::
54 : ~polystore()
55 : {
56 8 : delete impl_;
57 8 : }
58 :
59 8 : polystore::
60 8 : polystore()
61 8 : : impl_(new impl)
62 : {
63 8 : }
64 :
65 : auto
66 0 : polystore::
67 : get_elements() noexcept ->
68 : elements
69 : {
70 0 : return elements(impl_->v.size(), *this);
71 : }
72 :
73 : auto
74 0 : polystore::
75 : get(std::size_t i) -> any&
76 : {
77 0 : return *impl_->v[i];
78 : }
79 :
80 : void*
81 63 : polystore::
82 : find(
83 : detail::type_info const& ti) const noexcept
84 : {
85 63 : auto const it = impl_->m.find(&ti);
86 63 : if(it == impl_->m.end())
87 8 : return nullptr;
88 55 : return it->second;
89 : }
90 :
91 : void*
92 15 : polystore::
93 : insert_impl(
94 : any_ptr p, key const* k, std::size_t n)
95 : {
96 : struct do_insert
97 : {
98 : any_ptr p;
99 : key const* k;
100 : std::size_t n;
101 : polystore::impl* pi;
102 : std::size_t i = 0;
103 :
104 15 : do_insert(
105 : any_ptr p_,
106 : key const* k_,
107 : std::size_t n_,
108 : polystore::impl* pi_)
109 15 : : p(std::move(p_)), k(k_), n(n_), pi(pi_)
110 : {
111 : // ensure emplace_back can't fail
112 15 : pi->v.reserve(pi->v.size() + 1);
113 :
114 31 : for(;i < n;++i)
115 20 : if(! pi->m.emplace(k[i].ti, k[i].p).second)
116 4 : detail::throw_invalid_argument(
117 : "polystore: duplicate key");
118 :
119 11 : pi->v.emplace_back(std::move(p));
120 15 : }
121 :
122 11 : ~do_insert()
123 0 : {
124 11 : if(i == n)
125 11 : return;
126 0 : while(i--)
127 0 : pi->m.erase(k[i].ti);
128 11 : }
129 : };
130 :
131 15 : auto const pt = p->get();
132 19 : do_insert(std::move(p), k, n, impl_);
133 11 : return pt;
134 : }
135 :
136 : } // beast2
137 : } // boost
|