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_STREAM_HPP
10  
#ifndef BOOST_JSON_DETAIL_STREAM_HPP
11  
#define BOOST_JSON_DETAIL_STREAM_HPP
11  
#define BOOST_JSON_DETAIL_STREAM_HPP
12  

12  

13  
namespace boost {
13  
namespace boost {
14  
namespace json {
14  
namespace json {
15  
namespace detail {
15  
namespace detail {
16  

16  

17  
class const_stream
17  
class const_stream
18  
{
18  
{
19  
    friend class local_const_stream;
19  
    friend class local_const_stream;
20  

20  

21  
    char const* p_;
21  
    char const* p_;
22  
    char const* end_;
22  
    char const* end_;
23  

23  

24  
public:
24  
public:
25  
    const_stream() = default;
25  
    const_stream() = default;
26  

26  

27  
    const_stream(
27  
    const_stream(
28  
        char const* data,
28  
        char const* data,
29  
        std::size_t size) noexcept
29  
        std::size_t size) noexcept
30  
        : p_(data)
30  
        : p_(data)
31  
        , end_(data + size)
31  
        , end_(data + size)
32  
    {
32  
    {
33  
    }
33  
    }
34  

34  

35  
    size_t
35  
    size_t
36  
    used(char const* begin) const noexcept
36  
    used(char const* begin) const noexcept
37  
    {
37  
    {
38  
        return static_cast<
38  
        return static_cast<
39  
            size_t>(p_ - begin);
39  
            size_t>(p_ - begin);
40  
    }
40  
    }
41  

41  

42  
    size_t
42  
    size_t
43  
    remain() const noexcept
43  
    remain() const noexcept
44  
    {
44  
    {
45  
        return end_ - p_;
45  
        return end_ - p_;
46  
    }
46  
    }
47  

47  

48  
    char const*
48  
    char const*
49  
    data() const noexcept
49  
    data() const noexcept
50  
    {
50  
    {
51  
        return p_;
51  
        return p_;
52  
    }
52  
    }
53  

53  

54  
    operator bool() const noexcept
54  
    operator bool() const noexcept
55  
    {
55  
    {
56  
        return p_ < end_;
56  
        return p_ < end_;
57  
    }
57  
    }
58  

58  

59  
    // unchecked
59  
    // unchecked
60  
    char
60  
    char
61  
    operator*() const noexcept
61  
    operator*() const noexcept
62  
    {
62  
    {
63  
        BOOST_ASSERT(p_ < end_);
63  
        BOOST_ASSERT(p_ < end_);
64  
        return *p_;
64  
        return *p_;
65  
    }
65  
    }
66  

66  

67  
    // unchecked
67  
    // unchecked
68  
    const_stream&
68  
    const_stream&
69  
    operator++() noexcept
69  
    operator++() noexcept
70  
    {
70  
    {
71  
        BOOST_ASSERT(p_ < end_);
71  
        BOOST_ASSERT(p_ < end_);
72  
        ++p_;
72  
        ++p_;
73  
        return *this;
73  
        return *this;
74  
    }
74  
    }
75  

75  

76  
    void
76  
    void
77  
    skip(std::size_t n) noexcept
77  
    skip(std::size_t n) noexcept
78  
    {
78  
    {
79  
        BOOST_ASSERT(n <= remain());
79  
        BOOST_ASSERT(n <= remain());
80  
        p_ += n;
80  
        p_ += n;
81  
    }
81  
    }
82  

82  

83  
    void
83  
    void
84  
    skip_to(const char* p) noexcept
84  
    skip_to(const char* p) noexcept
85  
    {
85  
    {
86  
        BOOST_ASSERT(p <= end_ && p >= p_);
86  
        BOOST_ASSERT(p <= end_ && p >= p_);
87  
        p_ = p;
87  
        p_ = p;
88  
    }
88  
    }
89  
};
89  
};
90  

90  

91  
class local_const_stream
91  
class local_const_stream
92  
    : public const_stream
92  
    : public const_stream
93  
{
93  
{
94  
    const_stream& src_;
94  
    const_stream& src_;
95  

95  

96  
public:
96  
public:
97  
    explicit
97  
    explicit
98  
    local_const_stream(
98  
    local_const_stream(
99  
        const_stream& src) noexcept
99  
        const_stream& src) noexcept
100  
        : const_stream(src)
100  
        : const_stream(src)
101  
        , src_(src)
101  
        , src_(src)
102  
    {
102  
    {
103  
    }
103  
    }
104  

104  

105  
    ~local_const_stream()
105  
    ~local_const_stream()
106  
    {
106  
    {
107  
        src_.p_ = p_;
107  
        src_.p_ = p_;
108  
    }
108  
    }
109  

109  

110  
    void
110  
    void
111  
    clip(std::size_t n) noexcept
111  
    clip(std::size_t n) noexcept
112  
    {
112  
    {
113  
        if(static_cast<std::size_t>(
113  
        if(static_cast<std::size_t>(
114  
            src_.end_ - p_) > n)
114  
            src_.end_ - p_) > n)
115  
            end_ = p_ + n;
115  
            end_ = p_ + n;
116  
        else
116  
        else
117  
            end_ = src_.end_;
117  
            end_ = src_.end_;
118  
    }
118  
    }
119  
};
119  
};
120  

120  

121  
class const_stream_wrapper
121  
class const_stream_wrapper
122  
{
122  
{
123  
    const char*& p_;
123  
    const char*& p_;
124  
    const char* const end_;
124  
    const char* const end_;
125  

125  

126  
    friend class clipped_const_stream;
126  
    friend class clipped_const_stream;
127  
public:
127  
public:
128  
    const_stream_wrapper(
128  
    const_stream_wrapper(
129  
        const char*& p,
129  
        const char*& p,
130  
        const char* end)
130  
        const char* end)
131  
        : p_(p)
131  
        : p_(p)
132  
        , end_(end)
132  
        , end_(end)
133  
    {
133  
    {
134  
    }
134  
    }
135  

135  

136  
    void operator++() noexcept
136  
    void operator++() noexcept
137  
    {
137  
    {
138  
        ++p_;
138  
        ++p_;
139  
    }
139  
    }
140  

140  

141  
    void operator+=(std::size_t n) noexcept
141  
    void operator+=(std::size_t n) noexcept
142  
    {
142  
    {
143  
        p_ += n;
143  
        p_ += n;
144  
    }
144  
    }
145  

145  

146  
    void operator=(const char* p) noexcept
146  
    void operator=(const char* p) noexcept
147  
    {
147  
    {
148  
        p_ = p;
148  
        p_ = p;
149  
    }
149  
    }
150  

150  

151  
    char operator*() const noexcept
151  
    char operator*() const noexcept
152  
    {
152  
    {
153  
        return *p_;
153  
        return *p_;
154  
    }
154  
    }
155  

155  

156  
    operator bool() const noexcept
156  
    operator bool() const noexcept
157  
    {
157  
    {
158  
        return p_ < end_;
158  
        return p_ < end_;
159  
    }
159  
    }
160  

160  

161  
    const char* begin() const noexcept
161  
    const char* begin() const noexcept
162  
    {
162  
    {
163  
        return p_;
163  
        return p_;
164  
    }
164  
    }
165  

165  

166  
    const char* end() const noexcept
166  
    const char* end() const noexcept
167  
    {
167  
    {
168  
        return end_;
168  
        return end_;
169  
    }
169  
    }
170  

170  

171  
    std::size_t remain() const noexcept
171  
    std::size_t remain() const noexcept
172  
    {
172  
    {
173  
        return end_ - p_;
173  
        return end_ - p_;
174  
    }
174  
    }
175  

175  

176  
    std::size_t remain(const char* p) const noexcept
176  
    std::size_t remain(const char* p) const noexcept
177  
    {
177  
    {
178  
        return end_ - p;
178  
        return end_ - p;
179  
    }
179  
    }
180  

180  

181  
    std::size_t used(const char* p) const noexcept
181  
    std::size_t used(const char* p) const noexcept
182  
    {
182  
    {
183  
        return p_ - p;
183  
        return p_ - p;
184  
    }
184  
    }
185  
};
185  
};
186  

186  

187  
class clipped_const_stream
187  
class clipped_const_stream
188  
    : public const_stream_wrapper
188  
    : public const_stream_wrapper
189  
{
189  
{
190  
    const char* clip_;
190  
    const char* clip_;
191  

191  

192  
public:
192  
public:
193  
    clipped_const_stream(
193  
    clipped_const_stream(
194  
        const char*& p,
194  
        const char*& p,
195  
        const char* end)
195  
        const char* end)
196  
        : const_stream_wrapper(p, end)
196  
        : const_stream_wrapper(p, end)
197  
        , clip_(end)
197  
        , clip_(end)
198  
    {
198  
    {
199  
    }
199  
    }
200  

200  

201  
    void operator=(const char* p)
201  
    void operator=(const char* p)
202  
    {
202  
    {
203  
        p_ = p;
203  
        p_ = p;
204  
    }
204  
    }
205  

205  

206  
    const char* end() const noexcept
206  
    const char* end() const noexcept
207  
    {
207  
    {
208  
        return clip_;
208  
        return clip_;
209  
    }
209  
    }
210  

210  

211  
    operator bool() const noexcept
211  
    operator bool() const noexcept
212  
    {
212  
    {
213  
        return p_ < clip_;
213  
        return p_ < clip_;
214  
    }
214  
    }
215  

215  

216  
    std::size_t remain() const noexcept
216  
    std::size_t remain() const noexcept
217  
    {
217  
    {
218  
        return clip_ - p_;
218  
        return clip_ - p_;
219  
    }
219  
    }
220  

220  

221  
    std::size_t remain(const char* p) const noexcept
221  
    std::size_t remain(const char* p) const noexcept
222  
    {
222  
    {
223  
        return clip_ - p;
223  
        return clip_ - p;
224  
    }
224  
    }
225  

225  

226  
    void
226  
    void
227  
    clip(std::size_t n) noexcept
227  
    clip(std::size_t n) noexcept
228  
    {
228  
    {
229  
        if(static_cast<std::size_t>(
229  
        if(static_cast<std::size_t>(
230  
            end_ - p_) > n)
230  
            end_ - p_) > n)
231  
            clip_ = p_ + n;
231  
            clip_ = p_ + n;
232  
        else
232  
        else
233  
            clip_ = end_;
233  
            clip_ = end_;
234  
    }
234  
    }
235  
};
235  
};
236  

236  

237  
//--------------------------------------
237  
//--------------------------------------
238  

238  

239  
class stream
239  
class stream
240  
{
240  
{
241  
    friend class local_stream;
241  
    friend class local_stream;
242  

242  

243  
    char* p_;
243  
    char* p_;
244  
    char* end_;
244  
    char* end_;
245  

245  

246  
public:
246  
public:
247  
    stream(
247  
    stream(
248  
        char* data,
248  
        char* data,
249  
        std::size_t size) noexcept
249  
        std::size_t size) noexcept
250  
        : p_(data)
250  
        : p_(data)
251  
        , end_(data + size)
251  
        , end_(data + size)
252  
    {
252  
    {
253  
    }
253  
    }
254  

254  

255  
    size_t
255  
    size_t
256  
    used(char* begin) const noexcept
256  
    used(char* begin) const noexcept
257  
    {
257  
    {
258  
        return static_cast<
258  
        return static_cast<
259  
            size_t>(p_ - begin);
259  
            size_t>(p_ - begin);
260  
    }
260  
    }
261  

261  

262  
    size_t
262  
    size_t
263  
    remain() const noexcept
263  
    remain() const noexcept
264  
    {
264  
    {
265  
        return end_ - p_;
265  
        return end_ - p_;
266  
    }
266  
    }
267  

267  

268  
    char*
268  
    char*
269  
    data() noexcept
269  
    data() noexcept
270  
    {
270  
    {
271  
        return p_;
271  
        return p_;
272  
    }
272  
    }
273  

273  

274  
    operator bool() const noexcept
274  
    operator bool() const noexcept
275  
    {
275  
    {
276  
        return p_ < end_;
276  
        return p_ < end_;
277  
    }
277  
    }
278  

278  

279  
    // unchecked
279  
    // unchecked
280  
    char&
280  
    char&
281  
    operator*() noexcept
281  
    operator*() noexcept
282  
    {
282  
    {
283  
        BOOST_ASSERT(p_ < end_);
283  
        BOOST_ASSERT(p_ < end_);
284  
        return *p_;
284  
        return *p_;
285  
    }
285  
    }
286  

286  

287  
    // unchecked
287  
    // unchecked
288  
    stream&
288  
    stream&
289  
    operator++() noexcept
289  
    operator++() noexcept
290  
    {
290  
    {
291  
        BOOST_ASSERT(p_ < end_);
291  
        BOOST_ASSERT(p_ < end_);
292  
        ++p_;
292  
        ++p_;
293  
        return *this;
293  
        return *this;
294  
    }
294  
    }
295  

295  

296  
    // unchecked
296  
    // unchecked
297  
    void
297  
    void
298  
    append(
298  
    append(
299  
        char const* src,
299  
        char const* src,
300  
        std::size_t n) noexcept
300  
        std::size_t n) noexcept
301  
    {
301  
    {
302  
        BOOST_ASSERT(remain() >= n);
302  
        BOOST_ASSERT(remain() >= n);
303  
        std::memcpy(p_, src, n);
303  
        std::memcpy(p_, src, n);
304  
        p_ += n;
304  
        p_ += n;
305  
    }
305  
    }
306  

306  

307  
    // unchecked
307  
    // unchecked
308  
    void
308  
    void
309  
    append(char c) noexcept
309  
    append(char c) noexcept
310  
    {
310  
    {
311  
        BOOST_ASSERT(p_ < end_);
311  
        BOOST_ASSERT(p_ < end_);
312  
        *p_++ = c;
312  
        *p_++ = c;
313  
    }
313  
    }
314  

314  

315  
    void
315  
    void
316  
    advance(std::size_t n) noexcept
316  
    advance(std::size_t n) noexcept
317  
    {
317  
    {
318  
        BOOST_ASSERT(remain() >= n);
318  
        BOOST_ASSERT(remain() >= n);
319  
        p_ += n;
319  
        p_ += n;
320  
    }
320  
    }
321  
};
321  
};
322  

322  

323  
class local_stream
323  
class local_stream
324  
    : public stream
324  
    : public stream
325  
{
325  
{
326  
    stream& src_;
326  
    stream& src_;
327  

327  

328  
public:
328  
public:
329  
    explicit
329  
    explicit
330  
    local_stream(
330  
    local_stream(
331  
        stream& src)
331  
        stream& src)
332  
        : stream(src)
332  
        : stream(src)
333  
        , src_(src)
333  
        , src_(src)
334  
    {
334  
    {
335  
    }
335  
    }
336  

336  

337  
    ~local_stream()
337  
    ~local_stream()
338  
    {
338  
    {
339  
        src_.p_ = p_;
339  
        src_.p_ = p_;
340  
    }
340  
    }
341  
};
341  
};
342  

342  

343  
} // detail
343  
} // detail
344  
} // namespace json
344  
} // namespace json
345  
} // namespace boost
345  
} // namespace boost
346  

346  

347  
#endif
347  
#endif