1  
//
1  
//
2  
// Copyright (c) 2020 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2020 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_STATIC_RESOURCE_HPP
10  
#ifndef BOOST_JSON_STATIC_RESOURCE_HPP
11  
#define BOOST_JSON_STATIC_RESOURCE_HPP
11  
#define BOOST_JSON_STATIC_RESOURCE_HPP
12  

12  

13  
#include <boost/container/pmr/memory_resource.hpp>
13  
#include <boost/container/pmr/memory_resource.hpp>
14  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/detail/config.hpp>
15  
#include <boost/json/is_deallocate_trivial.hpp>
15  
#include <boost/json/is_deallocate_trivial.hpp>
16  
#include <cstddef>
16  
#include <cstddef>
17  

17  

18  
namespace boost {
18  
namespace boost {
19  
namespace json {
19  
namespace json {
20  

20  

21  
#ifdef _MSC_VER
21  
#ifdef _MSC_VER
22  
#pragma warning(push)
22  
#pragma warning(push)
23  
#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class
23  
#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class
24  
#endif
24  
#endif
25  

25  

26  
//----------------------------------------------------------
26  
//----------------------------------------------------------
27  

27  

28  
/** A resource using a caller-owned buffer, with a trivial deallocate.
28  
/** A resource using a caller-owned buffer, with a trivial deallocate.
29  

29  

30  
    This memory resource is a special-purpose resource that releases allocated
30  
    This memory resource is a special-purpose resource that releases allocated
31  
    memory only when the resource is destroyed (or when @ref release is
31  
    memory only when the resource is destroyed (or when @ref release is
32  
    called). It has a trivial deallocate function; that is, the metafunction
32  
    called). It has a trivial deallocate function; that is, the metafunction
33  
    @ref is_deallocate_trivial returns `true`.
33  
    @ref is_deallocate_trivial returns `true`.
34  

34  

35  
    The resource is constructed from a caller-owned buffer from which
35  
    The resource is constructed from a caller-owned buffer from which
36  
    subsequent calls to allocate are apportioned. When a memory request cannot
36  
    subsequent calls to allocate are apportioned. When a memory request cannot
37  
    be satisfied from the free bytes remaining in the buffer, the allocation
37  
    be satisfied from the free bytes remaining in the buffer, the allocation
38  
    request fails with the exception `std::bad_alloc`.
38  
    request fails with the exception `std::bad_alloc`.
39  

39  

40  
    @par Example
40  
    @par Example
41  
    This parses a JSON text into a value which uses a local stack buffer, then
41  
    This parses a JSON text into a value which uses a local stack buffer, then
42  
    prints the result.
42  
    prints the result.
43  

43  

44  
    @code
44  
    @code
45  
    unsigned char buf[ 4000 ];
45  
    unsigned char buf[ 4000 ];
46  
    static_resource mr( buf );
46  
    static_resource mr( buf );
47  

47  

48  
    // Parse the string, using our memory resource
48  
    // Parse the string, using our memory resource
49  
    value const jv = parse( "[1,2,3]", &mr );
49  
    value const jv = parse( "[1,2,3]", &mr );
50  

50  

51  
    // Print the JSON
51  
    // Print the JSON
52  
    std::cout << jv;
52  
    std::cout << jv;
53  
    @endcode
53  
    @endcode
54  

54  

55  
    @par Thread Safety
55  
    @par Thread Safety
56  
    Members of the same instance may not be called concurrently.
56  
    Members of the same instance may not be called concurrently.
57  

57  

58  
    @see https://en.wikipedia.org/wiki/Region-based_memory_management
58  
    @see https://en.wikipedia.org/wiki/Region-based_memory_management
59  
*/
59  
*/
60  
class
60  
class
61  
    BOOST_JSON_DECL
61  
    BOOST_JSON_DECL
62  
    BOOST_SYMBOL_VISIBLE
62  
    BOOST_SYMBOL_VISIBLE
63  
static_resource final
63  
static_resource final
64  
    : public container::pmr::memory_resource
64  
    : public container::pmr::memory_resource
65  
{
65  
{
66  
    void* p_;
66  
    void* p_;
67  
    std::size_t n_;
67  
    std::size_t n_;
68  
    std::size_t size_;
68  
    std::size_t size_;
69  

69  

70  
public:
70  
public:
71  
    /** Assignment operator.
71  
    /** Assignment operator.
72  

72  

73  
        The type is neither copyable nor movable, so this operator is deleted.
73  
        The type is neither copyable nor movable, so this operator is deleted.
74  
    */
74  
    */
75  
    static_resource& operator=(
75  
    static_resource& operator=(
76  
        static_resource const&) = delete;
76  
        static_resource const&) = delete;
77  

77  

78  
    /** Constructors.
78  
    /** Constructors.
79  

79  

80  
        These construct the resource to use the specified buffer for subsequent
80  
        These construct the resource to use the specified buffer for subsequent
81  
        calls to allocate. When the buffer is exhausted, allocate will throw
81  
        calls to allocate. When the buffer is exhausted, allocate will throw
82  
        `std::bad_alloc`.
82  
        `std::bad_alloc`.
83  

83  

84  
        Ownership of `buffer` is not transferred; the caller is responsible for
84  
        Ownership of `buffer` is not transferred; the caller is responsible for
85  
        ensuring that its lifetime extends until the resource is destroyed.
85  
        ensuring that its lifetime extends until the resource is destroyed.
86  

86  

87  
        Overload **(5)** is the copy constructor. The type is neither copyable
87  
        Overload **(5)** is the copy constructor. The type is neither copyable
88  
        nor movable, so this overload is deleted.
88  
        nor movable, so this overload is deleted.
89  

89  

90  
        @par Complexity
90  
        @par Complexity
91  
        Constant.
91  
        Constant.
92  

92  

93  
        @par Exception Safety
93  
        @par Exception Safety
94  
        No-throw guarantee.
94  
        No-throw guarantee.
95  

95  

96  
        @param buffer The buffer to use.
96  
        @param buffer The buffer to use.
97  
        @param size The number of valid bytes pointed to by `buffer`.
97  
        @param size The number of valid bytes pointed to by `buffer`.
98  

98  

99  
        @{
99  
        @{
100  
    */
100  
    */
101  
    static_resource(
101  
    static_resource(
102  
        unsigned char* buffer,
102  
        unsigned char* buffer,
103  
        std::size_t size) noexcept;
103  
        std::size_t size) noexcept;
104  

104  

105  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
105  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
106  
    static_resource(
106  
    static_resource(
107  
        std::byte* buffer,
107  
        std::byte* buffer,
108  
        std::size_t size) noexcept
108  
        std::size_t size) noexcept
109  
        : static_resource(reinterpret_cast<
109  
        : static_resource(reinterpret_cast<
110  
            unsigned char*>(buffer), size)
110  
            unsigned char*>(buffer), size)
111  
    {
111  
    {
112  
    }
112  
    }
113  
#endif
113  
#endif
114  

114  

115  
    /** Overload
115  
    /** Overload
116  

116  

117  
        @tparam N The size of `buffer`.
117  
        @tparam N The size of `buffer`.
118  
        @param buffer
118  
        @param buffer
119  
    */
119  
    */
120  
    template<std::size_t N>
120  
    template<std::size_t N>
121  
    explicit
121  
    explicit
122  
    static_resource(
122  
    static_resource(
123  
        unsigned char(&buffer)[N]) noexcept
123  
        unsigned char(&buffer)[N]) noexcept
124  
        : static_resource(&buffer[0], N)
124  
        : static_resource(&buffer[0], N)
125  
    {
125  
    {
126  
    }
126  
    }
127  

127  

128  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
128  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
129  
    /** Overload
129  
    /** Overload
130  

130  

131  
        @tparam N
131  
        @tparam N
132  
        @param buffer
132  
        @param buffer
133  
    */
133  
    */
134  
    template<std::size_t N>
134  
    template<std::size_t N>
135  
    explicit
135  
    explicit
136  
    static_resource(
136  
    static_resource(
137  
        std::byte(&buffer)[N]) noexcept
137  
        std::byte(&buffer)[N]) noexcept
138  
        : static_resource(&buffer[0], N)
138  
        : static_resource(&buffer[0], N)
139  
    {
139  
    {
140  
    }
140  
    }
141  
#endif
141  
#endif
142  

142  

143  
#ifndef BOOST_JSON_DOCS
143  
#ifndef BOOST_JSON_DOCS
144  
    // Safety net for accidental buffer overflows
144  
    // Safety net for accidental buffer overflows
145  
    template<std::size_t N>
145  
    template<std::size_t N>
146  
    static_resource(
146  
    static_resource(
147  
        unsigned char(&buffer)[N], std::size_t n) noexcept
147  
        unsigned char(&buffer)[N], std::size_t n) noexcept
148  
        : static_resource(&buffer[0], n)
148  
        : static_resource(&buffer[0], n)
149  
    {
149  
    {
150  
        // If this goes off, check your parameters
150  
        // If this goes off, check your parameters
151  
        // closely, chances are you passed an array
151  
        // closely, chances are you passed an array
152  
        // thinking it was a pointer.
152  
        // thinking it was a pointer.
153  
        BOOST_ASSERT(n <= N);
153  
        BOOST_ASSERT(n <= N);
154  
    }
154  
    }
155  

155  

156  
#ifdef __cpp_lib_byte
156  
#ifdef __cpp_lib_byte
157  
    // Safety net for accidental buffer overflows
157  
    // Safety net for accidental buffer overflows
158  
    template<std::size_t N>
158  
    template<std::size_t N>
159  
    static_resource(
159  
    static_resource(
160  
        std::byte(&buffer)[N], std::size_t n) noexcept
160  
        std::byte(&buffer)[N], std::size_t n) noexcept
161  
        : static_resource(&buffer[0], n)
161  
        : static_resource(&buffer[0], n)
162  
    {
162  
    {
163  
        // If this goes off, check your parameters
163  
        // If this goes off, check your parameters
164  
        // closely, chances are you passed an array
164  
        // closely, chances are you passed an array
165  
        // thinking it was a pointer.
165  
        // thinking it was a pointer.
166  
        BOOST_ASSERT(n <= N);
166  
        BOOST_ASSERT(n <= N);
167  
    }
167  
    }
168  
#endif
168  
#endif
169  
#endif
169  
#endif
170  

170  

171  
    /// Overload
171  
    /// Overload
172  
    static_resource(
172  
    static_resource(
173  
        static_resource const&) = delete;
173  
        static_resource const&) = delete;
174  
    /// @}
174  
    /// @}
175  

175  

176  
    /** Release all allocated memory.
176  
    /** Release all allocated memory.
177  

177  

178  
        This function resets the buffer provided upon construction so that all
178  
        This function resets the buffer provided upon construction so that all
179  
        of the valid bytes are available for subsequent allocation.
179  
        of the valid bytes are available for subsequent allocation.
180  

180  

181  
        @par Complexity
181  
        @par Complexity
182  
        Constant
182  
        Constant
183  

183  

184  
        @par Exception Safety
184  
        @par Exception Safety
185  
        No-throw guarantee.
185  
        No-throw guarantee.
186  
    */
186  
    */
187  
    void
187  
    void
188  
    release() noexcept;
188  
    release() noexcept;
189  

189  

190  
protected:
190  
protected:
191  
#ifndef BOOST_JSON_DOCS
191  
#ifndef BOOST_JSON_DOCS
192  
    void*
192  
    void*
193  
    do_allocate(
193  
    do_allocate(
194  
        std::size_t n,
194  
        std::size_t n,
195  
        std::size_t align) override;
195  
        std::size_t align) override;
196  

196  

197  
    void
197  
    void
198  
    do_deallocate(
198  
    do_deallocate(
199  
        void* p,
199  
        void* p,
200  
        std::size_t n,
200  
        std::size_t n,
201  
        std::size_t align) override;
201  
        std::size_t align) override;
202  

202  

203  
    bool
203  
    bool
204  
    do_is_equal(
204  
    do_is_equal(
205  
        memory_resource const& mr
205  
        memory_resource const& mr
206  
            ) const noexcept override;
206  
            ) const noexcept override;
207  
#endif
207  
#endif
208  
};
208  
};
209  

209  

210  
#ifdef _MSC_VER
210  
#ifdef _MSC_VER
211  
#pragma warning(pop)
211  
#pragma warning(pop)
212  
#endif
212  
#endif
213  

213  

214  
template<>
214  
template<>
215  
struct is_deallocate_trivial<
215  
struct is_deallocate_trivial<
216  
    static_resource>
216  
    static_resource>
217  
{
217  
{
218  
    static constexpr bool value = true;
218  
    static constexpr bool value = true;
219  
};
219  
};
220  

220  

221  
} // namespace json
221  
} // namespace json
222  
} // namespace boost
222  
} // namespace boost
223  

223  

224  
#endif
224  
#endif