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_BUFFER_HPP
10  
#ifndef BOOST_JSON_DETAIL_BUFFER_HPP
11  
#define BOOST_JSON_DETAIL_BUFFER_HPP
11  
#define BOOST_JSON_DETAIL_BUFFER_HPP
12  

12  

13  
#include <boost/json/detail/config.hpp>
13  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/string_view.hpp>
14  
#include <boost/json/string_view.hpp>
15  
#include <cstring>
15  
#include <cstring>
16  

16  

17  
namespace boost {
17  
namespace boost {
18  
namespace json {
18  
namespace json {
19  
namespace detail {
19  
namespace detail {
20  

20  

21  
// A simple string-like temporary static buffer
21  
// A simple string-like temporary static buffer
22  
template<std::size_t N>
22  
template<std::size_t N>
23  
class buffer
23  
class buffer
24  
{
24  
{
25  
public:
25  
public:
26  
    using size_type = std::size_t;
26  
    using size_type = std::size_t;
27  

27  

28  
    buffer() = default;
28  
    buffer() = default;
29  

29  

30  
    bool
30  
    bool
31  
    empty() const noexcept
31  
    empty() const noexcept
32  
    {
32  
    {
33  
        return size_ == 0;
33  
        return size_ == 0;
34  
    }
34  
    }
35  

35  

36  
    string_view
36  
    string_view
37  
    get() const noexcept
37  
    get() const noexcept
38  
    {
38  
    {
39  
        return {buf_, size_};
39  
        return {buf_, size_};
40  
    }
40  
    }
41  

41  

42  
    operator string_view() const noexcept
42  
    operator string_view() const noexcept
43  
    {
43  
    {
44  
        return get();
44  
        return get();
45  
    }
45  
    }
46  

46  

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

52  

53  
    size_type
53  
    size_type
54  
    size() const noexcept
54  
    size() const noexcept
55  
    {
55  
    {
56  
        return size_;
56  
        return size_;
57  
    }
57  
    }
58  

58  

59  
    size_type
59  
    size_type
60  
    capacity() const noexcept
60  
    capacity() const noexcept
61  
    {
61  
    {
62  
        return N - size_;
62  
        return N - size_;
63  
    }
63  
    }
64  

64  

65  
    size_type
65  
    size_type
66  
    max_size() const noexcept
66  
    max_size() const noexcept
67  
    {
67  
    {
68  
        return N;
68  
        return N;
69  
    }
69  
    }
70  

70  

71  
    void
71  
    void
72  
    clear() noexcept
72  
    clear() noexcept
73  
    {
73  
    {
74  
        size_ = 0;
74  
        size_ = 0;
75  
    }
75  
    }
76  

76  

77  
    void
77  
    void
78  
    push_back(char ch) noexcept
78  
    push_back(char ch) noexcept
79  
    {
79  
    {
80  
        BOOST_ASSERT(capacity() > 0);
80  
        BOOST_ASSERT(capacity() > 0);
81  
        buf_[size_++] = ch;
81  
        buf_[size_++] = ch;
82  
    }
82  
    }
83  

83  

84  
    // append an unescaped string
84  
    // append an unescaped string
85  
    void
85  
    void
86  
    append(
86  
    append(
87  
        char const* s,
87  
        char const* s,
88  
        size_type n)
88  
        size_type n)
89  
    {
89  
    {
90  
        BOOST_ASSERT(n <= N - size_);
90  
        BOOST_ASSERT(n <= N - size_);
91  
        std::memcpy(buf_ + size_, s, n);
91  
        std::memcpy(buf_ + size_, s, n);
92  
        size_ += n;
92  
        size_ += n;
93  
    }
93  
    }
94  

94  

95  
    // append valid 32-bit code point as utf8
95  
    // append valid 32-bit code point as utf8
96  
    void
96  
    void
97  
    append_utf8(
97  
    append_utf8(
98  
        unsigned long cp) noexcept
98  
        unsigned long cp) noexcept
99  
    {
99  
    {
100  
        auto dest = buf_ + size_;
100  
        auto dest = buf_ + size_;
101  
        if(cp < 0x80)
101  
        if(cp < 0x80)
102  
        {
102  
        {
103  
            BOOST_ASSERT(size_ <= N - 1);
103  
            BOOST_ASSERT(size_ <= N - 1);
104  
            dest[0] = static_cast<char>(cp);
104  
            dest[0] = static_cast<char>(cp);
105  
            size_ += 1;
105  
            size_ += 1;
106  
            return;
106  
            return;
107  
        }
107  
        }
108  

108  

109  
        if(cp < 0x800)
109  
        if(cp < 0x800)
110  
        {
110  
        {
111  
            BOOST_ASSERT(size_ <= N - 2);
111  
            BOOST_ASSERT(size_ <= N - 2);
112  
            dest[0] = static_cast<char>( (cp >> 6)          | 0xc0);
112  
            dest[0] = static_cast<char>( (cp >> 6)          | 0xc0);
113  
            dest[1] = static_cast<char>( (cp & 0x3f)        | 0x80);
113  
            dest[1] = static_cast<char>( (cp & 0x3f)        | 0x80);
114  
            size_ += 2;
114  
            size_ += 2;
115  
            return;
115  
            return;
116  
        }
116  
        }
117  

117  

118  
        if(cp < 0x10000)
118  
        if(cp < 0x10000)
119  
        {
119  
        {
120  
            BOOST_ASSERT(size_ <= N - 3);
120  
            BOOST_ASSERT(size_ <= N - 3);
121  
            dest[0] = static_cast<char>( (cp >> 12)         | 0xe0);
121  
            dest[0] = static_cast<char>( (cp >> 12)         | 0xe0);
122  
            dest[1] = static_cast<char>(((cp >> 6) & 0x3f)  | 0x80);
122  
            dest[1] = static_cast<char>(((cp >> 6) & 0x3f)  | 0x80);
123  
            dest[2] = static_cast<char>( (cp       & 0x3f)  | 0x80);
123  
            dest[2] = static_cast<char>( (cp       & 0x3f)  | 0x80);
124  
            size_ += 3;
124  
            size_ += 3;
125  
            return;
125  
            return;
126  
        }
126  
        }
127  

127  

128  
        {
128  
        {
129  
            BOOST_ASSERT(size_ <= N - 4);
129  
            BOOST_ASSERT(size_ <= N - 4);
130  
            dest[0] = static_cast<char>( (cp >> 18)         | 0xf0);
130  
            dest[0] = static_cast<char>( (cp >> 18)         | 0xf0);
131  
            dest[1] = static_cast<char>(((cp >> 12) & 0x3f) | 0x80);
131  
            dest[1] = static_cast<char>(((cp >> 12) & 0x3f) | 0x80);
132  
            dest[2] = static_cast<char>(((cp >> 6)  & 0x3f) | 0x80);
132  
            dest[2] = static_cast<char>(((cp >> 6)  & 0x3f) | 0x80);
133  
            dest[3] = static_cast<char>( (cp        & 0x3f) | 0x80);
133  
            dest[3] = static_cast<char>( (cp        & 0x3f) | 0x80);
134  
            size_ += 4;
134  
            size_ += 4;
135  
        }
135  
        }
136  
    }
136  
    }
137  
private:
137  
private:
138  
    char buf_[N];
138  
    char buf_[N];
139  
    size_type size_ = 0;
139  
    size_type size_ = 0;
140  
};
140  
};
141  

141  

142  
} // detail
142  
} // detail
143  
} // namespace json
143  
} // namespace json
144  
} // namespace boost
144  
} // namespace boost
145  

145  

146  
#endif
146  
#endif