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 -

 
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
 
32 -
    called). It has a trivial deallocate function; that is, the metafunction
 
33 -
    @ref is_deallocate_trivial returns `true`.
 
34  

29  

35 -
    The resource is constructed from a caller-owned buffer from which
30 +
    This memory resource is a special-purpose resource
36 -
    subsequent calls to allocate are apportioned. When a memory request cannot
31 +
    that releases allocated memory only when the resource
37 -
    be satisfied from the free bytes remaining in the buffer, the allocation
32 +
    is destroyed (or when @ref release is called).
 
33 +
    It has a trivial deallocate function; that is, the
 
34 +
    metafunction @ref is_deallocate_trivial returns `true`.
 
35 +
\n
 
36 +
    The resource is constructed from a caller-owned buffer
 
37 +
    from which subsequent calls to allocate are apportioned.
 
38 +
    When a memory request cannot be satisfied from the
 
39 +
    free bytes remaining in the buffer, the allocation
38  
    request fails with the exception `std::bad_alloc`.
40  
    request fails with the exception `std::bad_alloc`.
39 -

41 +
\n
40  
    @par Example
42  
    @par Example
41 -
    This parses a JSON text into a value which uses a local stack buffer, then
43 +

42 -
    prints the result.
44 +
    This parses a JSON text into a value which uses a local
 
45 +
    stack buffer, then prints the result.
43  

46  

44  
    @code
47  
    @code
 
48 +

45  
    unsigned char buf[ 4000 ];
49  
    unsigned char buf[ 4000 ];
46  
    static_resource mr( buf );
50  
    static_resource mr( buf );
47  

51  

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

54  

51  
    // Print the JSON
55  
    // Print the JSON
52  
    std::cout << jv;
56  
    std::cout << jv;
 
57 +

53  
    @endcode
58  
    @endcode
54  

59  

55  
    @par Thread Safety
60  
    @par Thread Safety
56 -
    Members of the same instance may not be called concurrently.
61 +
    Members of the same instance may not be
 
62 +
    called concurrently.
57  

63  

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

76  

70  
public:
77  
public:
71 -
    /** Assignment operator.
78 +
    /// Copy constructor (deleted)
 
79 +
    static_resource(
 
80 +
        static_resource const&) = delete;
72  

81  

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

85  

78 -
    /** Constructors.
86 +
    /** Constructor
79  

87  

80 -
        These construct the resource to use the specified buffer for subsequent
88 +
        This constructs the resource to use the specified
81 -
        calls to allocate. When the buffer is exhausted, allocate will throw
89 +
        buffer for subsequent calls to allocate. When the
 
90 +
        buffer is exhausted, allocate will throw
82  
        `std::bad_alloc`.
91  
        `std::bad_alloc`.
83 -
        Ownership of `buffer` is not transferred; the caller is responsible for
 
84 -
        ensuring that its lifetime extends until the resource is destroyed.
 
85 -

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

 
89  

92  

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

95  

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

98  

96  
        @param buffer The buffer to use.
99  
        @param buffer The buffer to use.
97 -
        @param size The number of valid bytes pointed to by `buffer`.
100 +
        Ownership is not transferred; the caller is
 
101 +
        responsible for ensuring that the lifetime of
 
102 +
        the buffer extends until the resource is destroyed.
98  

103  

99 -
        @{
104 +
        @param size The number of valid bytes pointed
 
105 +
        to by `buffer`.
100  
    */
106  
    */
 
107 +
    /** @{ */
101  
    static_resource(
108  
    static_resource(
102  
        unsigned char* buffer,
109  
        unsigned char* buffer,
103  
        std::size_t size) noexcept;
110  
        std::size_t size) noexcept;
104  

111  

105  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
112  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
106  
    static_resource(
113  
    static_resource(
107  
        std::byte* buffer,
114  
        std::byte* buffer,
108  
        std::size_t size) noexcept
115  
        std::size_t size) noexcept
109  
        : static_resource(reinterpret_cast<
116  
        : static_resource(reinterpret_cast<
110  
            unsigned char*>(buffer), size)
117  
            unsigned char*>(buffer), size)
111  
    {
118  
    {
112  
    }
119  
    }
113  
#endif
120  
#endif
 
121 +
    /** @} */
114  

122  

115 -
    /** Overload
123 +
    /** Constructor
116  

124  

117 -
        @tparam N The size of `buffer`.
125 +
        This constructs the resource to use the specified
118 -
        @param buffer
126 +
        buffer for subsequent calls to allocate. When the
 
127 +
        buffer is exhausted, allocate will throw
 
128 +
        `std::bad_alloc`.
 
129 +

 
130 +
        @par Complexity
 
131 +
        Constant.
 
132 +

 
133 +
        @par Exception Safety
 
134 +
        No-throw guarantee.
 
135 +

 
136 +
        @param buffer The buffer to use.
 
137 +
        Ownership is not transferred; the caller is
 
138 +
        responsible for ensuring that the lifetime of
 
139 +
        the buffer extends until the resource is destroyed.
119  
    */
140  
    */
 
141 +
    /** @{ */
120  
    template<std::size_t N>
142  
    template<std::size_t N>
121  
    explicit
143  
    explicit
122  
    static_resource(
144  
    static_resource(
123  
        unsigned char(&buffer)[N]) noexcept
145  
        unsigned char(&buffer)[N]) noexcept
124  
        : static_resource(&buffer[0], N)
146  
        : static_resource(&buffer[0], N)
125  
    {
147  
    {
126  
    }
148  
    }
127  

149  

128 -
    /** Overload
 
129 -

 
130 -
        @tparam N
 
131 -
        @param buffer
 
132 -
    */
 
133  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
150  
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
134  
    template<std::size_t N>
151  
    template<std::size_t N>
135  
    explicit
152  
    explicit
136  
    static_resource(
153  
    static_resource(
137  
        std::byte(&buffer)[N]) noexcept
154  
        std::byte(&buffer)[N]) noexcept
138  
        : static_resource(&buffer[0], N)
155  
        : static_resource(&buffer[0], N)
139  
    {
156  
    {
140  
    }
157  
    }
141  
#endif
158  
#endif
 
159 +
    /** @} */
142  

160  

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

173  

156  
#ifdef __cpp_lib_byte
174  
#ifdef __cpp_lib_byte
157  
    // Safety net for accidental buffer overflows
175  
    // Safety net for accidental buffer overflows
158  
    template<std::size_t N>
176  
    template<std::size_t N>
159  
    static_resource(
177  
    static_resource(
160  
        std::byte(&buffer)[N], std::size_t n) noexcept
178  
        std::byte(&buffer)[N], std::size_t n) noexcept
161  
        : static_resource(&buffer[0], n)
179  
        : static_resource(&buffer[0], n)
162  
    {
180  
    {
163  
        // If this goes off, check your parameters
181  
        // If this goes off, check your parameters
164  
        // closely, chances are you passed an array
182  
        // closely, chances are you passed an array
165  
        // thinking it was a pointer.
183  
        // thinking it was a pointer.
166  
        BOOST_ASSERT(n <= N);
184  
        BOOST_ASSERT(n <= N);
167  
    }
185  
    }
168  
#endif
186  
#endif
169  
#endif
187  
#endif
170 -
    /// Overload
 
171 -
    static_resource(
 
172 -
        static_resource const&) = delete;
 
173 -
    /// @}
 
174 -

 
175  

188  

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

190  

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

194  

181  
        @par Complexity
195  
        @par Complexity
182  
        Constant
196  
        Constant
183  

197  

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

203  

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

210  

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

216  

203  
    bool
217  
    bool
204  
    do_is_equal(
218  
    do_is_equal(
205  
        memory_resource const& mr
219  
        memory_resource const& mr
206  
            ) const noexcept override;
220  
            ) const noexcept override;
207  
#endif
221  
#endif
208  
};
222  
};
209  

223  

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

227  

214  
template<>
228  
template<>
215  
struct is_deallocate_trivial<
229  
struct is_deallocate_trivial<
216  
    static_resource>
230  
    static_resource>
217  
{
231  
{
218  
    static constexpr bool value = true;
232  
    static constexpr bool value = true;
219  
};
233  
};
220  

234  

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

237  

224  
#endif
238  
#endif