1  
//
1  
//
2  
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/http
7  
// Official repository: https://github.com/cppalliance/http
8  
//
8  
//
9  

9  

10  
#include <boost/http/core/polystore.hpp>
10  
#include <boost/http/core/polystore.hpp>
11  
#include <utility>
11  
#include <utility>
12  

12  

13  
namespace boost {
13  
namespace boost {
14  
namespace http {
14  
namespace http {
15  

15  

16  
polystore::
16  
polystore::
17  
~polystore()
17  
~polystore()
18  
{
18  
{
19  
    destroy();
19  
    destroy();
20  
}
20  
}
21  

21  

22  
polystore::
22  
polystore::
23  
polystore(
23  
polystore(
24  
    polystore&& other) noexcept
24  
    polystore&& other) noexcept
25  
{
25  
{
26  
    using std::swap;
26  
    using std::swap;
27  
    swap(v_, other.v_);
27  
    swap(v_, other.v_);
28  
    swap(m_, other.m_);
28  
    swap(m_, other.m_);
29  
}
29  
}
30  

30  

31  
polystore&
31  
polystore&
32  
polystore::
32  
polystore::
33  
operator=(
33  
operator=(
34  
    polystore&& other) noexcept
34  
    polystore&& other) noexcept
35  
{
35  
{
36  
    if(this != &other)
36  
    if(this != &other)
37  
    {
37  
    {
38  
        using std::swap;
38  
        using std::swap;
39  
        polystore tmp(std::move(*this));
39  
        polystore tmp(std::move(*this));
40  
        swap(v_, tmp.v_);
40  
        swap(v_, tmp.v_);
41  
        swap(m_, tmp.m_);
41  
        swap(m_, tmp.m_);
42  
        swap(v_, other.v_);
42  
        swap(v_, other.v_);
43  
        swap(m_, other.m_);
43  
        swap(m_, other.m_);
44  
    }
44  
    }
45  
    return *this;
45  
    return *this;
46  
}
46  
}
47  

47  

48  
void
48  
void
49  
polystore::
49  
polystore::
50  
clear() noexcept
50  
clear() noexcept
51  
{
51  
{
52  
    destroy();
52  
    destroy();
53  
    m_.clear();
53  
    m_.clear();
54  
}
54  
}
55  

55  

56  
auto
56  
auto
57  
polystore::
57  
polystore::
58  
get_elements() noexcept ->
58  
get_elements() noexcept ->
59  
    elements
59  
    elements
60  
{
60  
{
61  
    return elements(v_.size(), *this);
61  
    return elements(v_.size(), *this);
62  
}
62  
}
63  

63  

64  
void
64  
void
65  
polystore::
65  
polystore::
66  
destroy() noexcept
66  
destroy() noexcept
67  
{
67  
{
68  
    // destroy in reverse order
68  
    // destroy in reverse order
69  
    for(auto n = v_.size(); n--;)
69  
    for(auto n = v_.size(); n--;)
70  
        v_.resize(n);
70  
        v_.resize(n);
71  
}
71  
}
72  

72  

73  
auto
73  
auto
74  
polystore::
74  
polystore::
75  
get(std::size_t i) -> any&
75  
get(std::size_t i) -> any&
76  
{
76  
{
77  
    return *v_[i];
77  
    return *v_[i];
78  
}
78  
}
79  

79  

80  
void*
80  
void*
81  
polystore::
81  
polystore::
82  
find(
82  
find(
83  
    core::typeinfo const& ti) const noexcept
83  
    core::typeinfo const& ti) const noexcept
84  
{
84  
{
85  
    auto const it = m_.find(ti);
85  
    auto const it = m_.find(ti);
86  
    if(it == m_.end())
86  
    if(it == m_.end())
87  
        return nullptr;
87  
        return nullptr;
88  
    return it->second;
88  
    return it->second;
89  
}
89  
}
90  

90  

91  
void*
91  
void*
92  
polystore::
92  
polystore::
93  
insert_impl(
93  
insert_impl(
94  
    any_ptr p, key const* k, std::size_t n)
94  
    any_ptr p, key const* k, std::size_t n)
95  
{
95  
{
96  
    struct do_insert
96  
    struct do_insert
97  
    {
97  
    {
98  
        any_ptr p;
98  
        any_ptr p;
99  
        key const* k;
99  
        key const* k;
100  
        std::size_t n;
100  
        std::size_t n;
101  
        polystore& ps;
101  
        polystore& ps;
102  
        std::size_t i = 0;
102  
        std::size_t i = 0;
103  

103  

104  
        do_insert(
104  
        do_insert(
105  
            any_ptr p_,
105  
            any_ptr p_,
106  
            key const* k_,
106  
            key const* k_,
107  
            std::size_t n_,
107  
            std::size_t n_,
108  
            polystore& ps_)
108  
            polystore& ps_)
109  
            : p(std::move(p_)), k(k_), n(n_), ps(ps_)
109  
            : p(std::move(p_)), k(k_), n(n_), ps(ps_)
110  
        {
110  
        {
111  
            // ensure emplace_back can't fail
111  
            // ensure emplace_back can't fail
112  
            ps.v_.reserve(ps.v_.size() + 1);
112  
            ps.v_.reserve(ps.v_.size() + 1);
113  

113  

114  
            for(;i < n;++i)
114  
            for(;i < n;++i)
115  
                if(! ps.m_.emplace(k[i].ti, k[i].p).second)
115  
                if(! ps.m_.emplace(k[i].ti, k[i].p).second)
116  
                    detail::throw_invalid_argument(
116  
                    detail::throw_invalid_argument(
117  
                        "polystore: duplicate key");
117  
                        "polystore: duplicate key");
118  

118  

119  
            ps.v_.emplace_back(std::move(p));
119  
            ps.v_.emplace_back(std::move(p));
120  
        }
120  
        }
121  

121  

122  
        ~do_insert()
122  
        ~do_insert()
123  
        {
123  
        {
124  
            if(i == n)
124  
            if(i == n)
125  
                return;
125  
                return;
126  
            while(i--)
126  
            while(i--)
127  
                ps.m_.erase(k[i].ti);
127  
                ps.m_.erase(k[i].ti);
128  
        }
128  
        }
129  
    };
129  
    };
130  

130  

131  
    auto const pt = p->get();
131  
    auto const pt = p->get();
132  
    do_insert(std::move(p), k, n, *this);
132  
    do_insert(std::move(p), k, n, *this);
133  
    return pt;
133  
    return pt;
134  
}
134  
}
135  

135  

136  
} // http
136  
} // http
137  
} // boost
137  
} // boost