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