1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 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/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_DETAIL_IMPL_STACK_IPP
10  
#ifndef BOOST_JSON_DETAIL_IMPL_STACK_IPP
11  
#define BOOST_JSON_DETAIL_IMPL_STACK_IPP
11  
#define BOOST_JSON_DETAIL_IMPL_STACK_IPP
12  

12  

13  
#include <boost/json/detail/stack.hpp>
13  
#include <boost/json/detail/stack.hpp>
14  

14  

15  
namespace boost {
15  
namespace boost {
16  
namespace json {
16  
namespace json {
17  
namespace detail {
17  
namespace detail {
18  

18  

19  
stack::non_trivial<>*
19  
stack::non_trivial<>*
20  
stack::non_trivial<>::destroy() noexcept
20  
stack::non_trivial<>::destroy() noexcept
21  
{
21  
{
22  
    non_trivial* const result = next;
22  
    non_trivial* const result = next;
23  
    rel(this, nullptr);
23  
    rel(this, nullptr);
24  
    return result;
24  
    return result;
25  
}
25  
}
26  

26  

27  
stack::non_trivial<>*
27  
stack::non_trivial<>*
28  
stack::non_trivial<>::relocate(void* dst) noexcept
28  
stack::non_trivial<>::relocate(void* dst) noexcept
29  
{
29  
{
30  
    return rel(this, dst);
30  
    return rel(this, dst);
31  
}
31  
}
32  

32  

33  

33  

34  
stack::
34  
stack::
35  
~stack()
35  
~stack()
36  
{
36  
{
37  
    clear();
37  
    clear();
38  
    if(base_ != buf_)
38  
    if(base_ != buf_)
39  
        sp_->deallocate(
39  
        sp_->deallocate(
40  
            base_, cap_);
40  
            base_, cap_);
41  
}
41  
}
42  

42  

43  
stack::
43  
stack::
44  
stack(
44  
stack(
45  
    storage_ptr sp,
45  
    storage_ptr sp,
46  
    unsigned char* buf,
46  
    unsigned char* buf,
47  
    std::size_t buf_size) noexcept
47  
    std::size_t buf_size) noexcept
48  
    : sp_(std::move(sp))
48  
    : sp_(std::move(sp))
49  
    , cap_(buf_size)
49  
    , cap_(buf_size)
50  
    , base_(buf)
50  
    , base_(buf)
51  
    , buf_(buf)
51  
    , buf_(buf)
52  
{
52  
{
53  
}
53  
}
54  

54  

55  
void
55  
void
56  
stack::
56  
stack::
57  
clear() noexcept
57  
clear() noexcept
58  
{
58  
{
59  
    while(head_)
59  
    while(head_)
60  
        head_ = head_->destroy();
60  
        head_ = head_->destroy();
61  
    size_ = 0;
61  
    size_ = 0;
62  
}
62  
}
63  

63  

64  
void
64  
void
65  
stack::
65  
stack::
66  
reserve_impl(std::size_t n)
66  
reserve_impl(std::size_t n)
67  
{
67  
{
68  
    // caller checks this
68  
    // caller checks this
69  
    BOOST_ASSERT(n > cap_);
69  
    BOOST_ASSERT(n > cap_);
70  

70  

71  
    auto const base = static_cast<unsigned char*>( sp_->allocate(n) );
71  
    auto const base = static_cast<unsigned char*>( sp_->allocate(n) );
72  
    if(base_)
72  
    if(base_)
73  
    {
73  
    {
74  
        // copy trivials
74  
        // copy trivials
75  
        std::memcpy(base, base_, size_);
75  
        std::memcpy(base, base_, size_);
76  

76  

77  
        // copy non-trivials
77  
        // copy non-trivials
78  
        non_trivial<>* src = head_;
78  
        non_trivial<>* src = head_;
79  
        non_trivial<>** prev = &head_;
79  
        non_trivial<>** prev = &head_;
80  
        while(src)
80  
        while(src)
81  
        {
81  
        {
82  
            std::size_t const buf_offset =
82  
            std::size_t const buf_offset =
83  
                reinterpret_cast<unsigned char*>(src) - base_;
83  
                reinterpret_cast<unsigned char*>(src) - base_;
84  
            non_trivial<>* dest = src->relocate(base + buf_offset);
84  
            non_trivial<>* dest = src->relocate(base + buf_offset);
85  
            *prev = dest;
85  
            *prev = dest;
86  
            prev = &dest->next;
86  
            prev = &dest->next;
87  
            src = dest->next;
87  
            src = dest->next;
88  
        }
88  
        }
89  

89  

90  
        if(base_ != buf_)
90  
        if(base_ != buf_)
91  
            sp_->deallocate(base_, cap_);
91  
            sp_->deallocate(base_, cap_);
92  
    }
92  
    }
93  
    base_ = base;
93  
    base_ = base;
94  
    cap_ = n;
94  
    cap_ = n;
95  
}
95  
}
96  

96  

97  
} // detail
97  
} // detail
98  
} // namespace json
98  
} // namespace json
99  
} // namespace boost
99  
} // namespace boost
100  

100  

101  
#endif
101  
#endif