Line data Source code
1 : //
2 : // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
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)
6 : //
7 : // Official repository: https://github.com/cppalliance/buffers
8 : //
9 :
10 : #ifndef BOOST_BUFFERS_STRING_BUFFER_HPP
11 : #define BOOST_BUFFERS_STRING_BUFFER_HPP
12 :
13 : #include <boost/buffers/buffer.hpp>
14 : #include <boost/buffers/detail/except.hpp>
15 : #include <boost/assert.hpp>
16 : #include <string>
17 :
18 : namespace boost {
19 : namespace buffers {
20 :
21 : /** A dynamic buffer using an underlying string
22 : */
23 : template<
24 : class CharT,
25 : class Traits = std::char_traits<CharT>,
26 : class Allocator = std::allocator<CharT>>
27 : class basic_string_buffer
28 : {
29 : std::basic_string<
30 : CharT, Traits, Allocator>* s_;
31 : std::size_t max_size_;
32 :
33 : public:
34 : using string_type = std::basic_string<
35 : CharT, Traits, Allocator>;
36 :
37 : unsigned char* data_ = nullptr;
38 : std::size_t in_size_ = 0;
39 : std::size_t out_size_ = 0;
40 :
41 : public:
42 : using const_buffers_type = const_buffer;
43 : using mutable_buffers_type = mutable_buffer;
44 :
45 15 : ~basic_string_buffer()
46 : {
47 15 : if(s_)
48 14 : s_->resize(in_size_);
49 15 : }
50 :
51 : /** Constructor.
52 : */
53 1 : basic_string_buffer(
54 : basic_string_buffer&& other) noexcept
55 1 : : s_(other.s_)
56 1 : , max_size_(other.max_size_)
57 : {
58 1 : other.s_ = nullptr;
59 1 : }
60 :
61 : /** Constructor.
62 : */
63 : explicit
64 14 : basic_string_buffer(
65 : string_type* s,
66 : std::size_t max_size =
67 : std::size_t(-1)) noexcept
68 14 : : s_(s)
69 14 : , max_size_(
70 14 : max_size > s_->max_size()
71 14 : ? s_->max_size()
72 14 : : max_size)
73 : {
74 14 : if(s_->size() > max_size_)
75 1 : s_->resize(max_size_);
76 14 : in_size_ = s_->size();
77 14 : }
78 :
79 : /** Assignment.
80 : */
81 : basic_string_buffer& operator=(
82 : basic_string_buffer const&) = delete;
83 :
84 : std::size_t
85 2 : size() const noexcept
86 : {
87 2 : return in_size_;
88 : }
89 :
90 : std::size_t
91 2 : max_size() const noexcept
92 : {
93 2 : return max_size_;
94 : }
95 :
96 : std::size_t
97 2 : capacity() const noexcept
98 : {
99 2 : if(s_->capacity() <= max_size_)
100 1 : return s_->capacity() - in_size_;
101 1 : return max_size_ - in_size_;
102 : }
103 :
104 : const_buffers_type
105 2 : data() const noexcept
106 : {
107 2 : return const_buffers_type(
108 4 : s_->data(), in_size_);
109 : }
110 :
111 : mutable_buffers_type
112 6 : prepare(std::size_t n)
113 : {
114 : // n exceeds available space
115 6 : if(n > max_size_ - in_size_)
116 1 : detail::throw_invalid_argument();
117 :
118 5 : if( s_->size() < in_size_ + n)
119 4 : s_->resize(in_size_ + n);
120 5 : out_size_ = n;
121 5 : return mutable_buffers_type(
122 10 : &(*s_)[in_size_], out_size_);
123 : }
124 :
125 2 : void commit(std::size_t n) noexcept
126 : {
127 2 : if(n < out_size_)
128 1 : in_size_ += n;
129 : else
130 1 : in_size_ += out_size_;
131 2 : out_size_ = 0;
132 2 : }
133 :
134 2 : void consume(std::size_t n) noexcept
135 : {
136 2 : if(n < in_size_)
137 : {
138 1 : s_->erase(0, n);
139 1 : in_size_ -= n;
140 : }
141 : else
142 : {
143 1 : in_size_ = 0;
144 : }
145 2 : out_size_ = 0;
146 2 : }
147 : };
148 :
149 : using string_buffer = basic_string_buffer<char>;
150 :
151 : } // buffers
152 : } // boost
153 :
154 : #endif
|