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_STACK_HPP
10  
#ifndef BOOST_JSON_DETAIL_STACK_HPP
11  
#define BOOST_JSON_DETAIL_STACK_HPP
11  
#define BOOST_JSON_DETAIL_STACK_HPP
12  

12  

13  
#include <boost/json/detail/config.hpp>
13  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/storage_ptr.hpp>
14  
#include <boost/json/storage_ptr.hpp>
15  
#include <boost/mp11/integral.hpp>
15  
#include <boost/mp11/integral.hpp>
16  
#include <cstring>
16  
#include <cstring>
17  
#include <type_traits>
17  
#include <type_traits>
18  

18  

19  
namespace boost {
19  
namespace boost {
20  
namespace json {
20  
namespace json {
21  
namespace detail {
21  
namespace detail {
22  

22  

23  
#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000
23  
#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000
24  

24  

25  
template<class T>
25  
template<class T>
26  
struct is_trivially_copy_assignable
26  
struct is_trivially_copy_assignable
27  
    : mp11::mp_bool<
27  
    : mp11::mp_bool<
28  
        std::is_copy_assignable<T>::value &&
28  
        std::is_copy_assignable<T>::value &&
29  
          std::has_trivial_copy_assign<T>::value >
29  
          std::has_trivial_copy_assign<T>::value >
30  
{};
30  
{};
31  

31  

32  
#else
32  
#else
33  

33  

34  
using std::is_trivially_copy_assignable;
34  
using std::is_trivially_copy_assignable;
35  

35  

36  
#endif
36  
#endif
37  

37  

38  
class stack
38  
class stack
39  
{
39  
{
40  
    template< class T = void >
40  
    template< class T = void >
41  
    struct non_trivial;
41  
    struct non_trivial;
42  

42  

43  
    storage_ptr sp_;
43  
    storage_ptr sp_;
44  
    std::size_t cap_ = 0;
44  
    std::size_t cap_ = 0;
45  
    std::size_t size_ = 0;
45  
    std::size_t size_ = 0;
46  
    non_trivial<>* head_ = nullptr;
46  
    non_trivial<>* head_ = nullptr;
47  
    unsigned char* base_ = nullptr;
47  
    unsigned char* base_ = nullptr;
48  
    unsigned char* buf_ = nullptr;
48  
    unsigned char* buf_ = nullptr;
49  

49  

50  
public:
50  
public:
51  
    BOOST_JSON_DECL
51  
    BOOST_JSON_DECL
52  
    ~stack();
52  
    ~stack();
53  

53  

54  
    stack() = default;
54  
    stack() = default;
55  

55  

56  
    stack(
56  
    stack(
57  
        storage_ptr sp,
57  
        storage_ptr sp,
58  
        unsigned char* buf,
58  
        unsigned char* buf,
59  
        std::size_t buf_size) noexcept;
59  
        std::size_t buf_size) noexcept;
60  

60  

61  
    bool
61  
    bool
62  
    empty() const noexcept
62  
    empty() const noexcept
63  
    {
63  
    {
64  
        return size_ == 0;
64  
        return size_ == 0;
65  
    }
65  
    }
66  

66  

67  
    BOOST_JSON_DECL
67  
    BOOST_JSON_DECL
68  
    void
68  
    void
69  
    clear() noexcept;
69  
    clear() noexcept;
70  

70  

71  
    void
71  
    void
72  
    reserve(std::size_t n)
72  
    reserve(std::size_t n)
73  
    {
73  
    {
74  
        if(n > cap_)
74  
        if(n > cap_)
75  
            reserve_impl(n);
75  
            reserve_impl(n);
76  
    }
76  
    }
77  

77  

78  
    template<class T>
78  
    template<class T>
79  
    void
79  
    void
80  
    push(T&& t)
80  
    push(T&& t)
81  
    {
81  
    {
82  
        using U = remove_cvref<T>;
82  
        using U = remove_cvref<T>;
83  
        push( static_cast<T&&>(t), is_trivially_copy_assignable<U>() );
83  
        push( static_cast<T&&>(t), is_trivially_copy_assignable<U>() );
84  
    }
84  
    }
85  

85  

86  
    template<class T>
86  
    template<class T>
87  
    void
87  
    void
88  
    push_unchecked(
88  
    push_unchecked(
89  
        T const& t);
89  
        T const& t);
90  

90  

91  
    template<class T>
91  
    template<class T>
92  
    void
92  
    void
93  
    peek(T& t);
93  
    peek(T& t);
94  

94  

95  
    template<class T>
95  
    template<class T>
96  
    void
96  
    void
97  
    pop(T& t)
97  
    pop(T& t)
98  
    {
98  
    {
99  
        using U = remove_cvref<T>;
99  
        using U = remove_cvref<T>;
100  
        pop( t, is_trivially_copy_assignable<U>() );
100  
        pop( t, is_trivially_copy_assignable<U>() );
101  
    }
101  
    }
102  

102  

103  
private:
103  
private:
104  
    template<class T> void push(
104  
    template<class T> void push(
105  
        T const& t, std::true_type);
105  
        T const& t, std::true_type);
106  
    template<class T> void push(
106  
    template<class T> void push(
107  
        T&& t, std::false_type);
107  
        T&& t, std::false_type);
108  
    template<class T> void pop(
108  
    template<class T> void pop(
109  
        T& t, std::true_type);
109  
        T& t, std::true_type);
110  
    template<class T> void pop(
110  
    template<class T> void pop(
111  
        T& t, std::false_type);
111  
        T& t, std::false_type);
112  

112  

113  
    BOOST_JSON_DECL
113  
    BOOST_JSON_DECL
114  
    void
114  
    void
115  
    reserve_impl(
115  
    reserve_impl(
116  
        std::size_t n);
116  
        std::size_t n);
117  
};
117  
};
118  

118  

119  
} // detail
119  
} // detail
120  
} // namespace json
120  
} // namespace json
121  
} // namespace boost
121  
} // namespace boost
122  

122  

123  
#include <boost/json/detail/impl/stack.hpp>
123  
#include <boost/json/detail/impl/stack.hpp>
124  

124  

125  
#endif
125  
#endif