libs/capy/include/boost/capy/buffers/string_dynamic_buffer.hpp

100.0% Lines (53/53) 100.0% Functions (10/10) 100.0% Branches (15/15)
libs/capy/include/boost/capy/buffers/string_dynamic_buffer.hpp
Line Branch Hits 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/capy
8 //
9
10 #ifndef BOOST_CAPY_BUFFERS_STRING_DYNAMIC_BUFFER_HPP
11 #define BOOST_CAPY_BUFFERS_STRING_DYNAMIC_BUFFER_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/buffers.hpp>
15 #include <boost/capy/detail/except.hpp>
16 #include <string>
17
18 namespace boost {
19 namespace capy {
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_dynamic_buffer
28 {
29 std::basic_string<
30 CharT, Traits, Allocator>* s_;
31 std::size_t max_size_;
32
33 std::size_t in_size_ = 0;
34 std::size_t out_size_ = 0;
35
36 public:
37 using is_dynamic_buffer_adapter = void;
38 using string_type = std::basic_string<
39 CharT, Traits, Allocator>;
40 using const_buffers_type = const_buffer;
41 using mutable_buffers_type = mutable_buffer;
42
43 ~basic_string_dynamic_buffer() = default;
44
45 /** Constructor.
46 */
47 266 basic_string_dynamic_buffer(
48 basic_string_dynamic_buffer&& other) noexcept
49 266 : s_(other.s_)
50 266 , max_size_(other.max_size_)
51 266 , in_size_(other.in_size_)
52 266 , out_size_(other.out_size_)
53 {
54 266 other.s_ = nullptr;
55 266 }
56
57 /** Constructor.
58 */
59 explicit
60 433 basic_string_dynamic_buffer(
61 string_type* s,
62 std::size_t max_size =
63 std::size_t(-1)) noexcept
64 433 : s_(s)
65 433 , max_size_(
66 433 max_size > s_->max_size()
67
2/2
✓ Branch 0 taken 418 times.
✓ Branch 1 taken 15 times.
433 ? s_->max_size()
68 433 : max_size)
69 {
70
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 432 times.
433 if(s_->size() > max_size_)
71 1 s_->resize(max_size_);
72 433 in_size_ = s_->size();
73 433 }
74
75 /** Assignment.
76 */
77 basic_string_dynamic_buffer& operator=(
78 basic_string_dynamic_buffer const&) = delete;
79
80 std::size_t
81 1280 size() const noexcept
82 {
83 1280 return in_size_;
84 }
85
86 std::size_t
87 410 max_size() const noexcept
88 {
89 410 return max_size_;
90 }
91
92 std::size_t
93 2 capacity() const noexcept
94 {
95
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
2 if(s_->capacity() <= max_size_)
96 1 return s_->capacity() - in_size_;
97 1 return max_size_ - in_size_;
98 }
99
100 const_buffers_type
101 387 data() const noexcept
102 {
103 387 return const_buffers_type(
104 774 s_->data(), in_size_);
105 }
106
107 mutable_buffers_type
108 557 prepare(std::size_t n)
109 {
110 // n exceeds available space
111
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 556 times.
557 if(n > max_size_ - in_size_)
112 1 detail::throw_invalid_argument();
113
114
2/2
✓ Branch 1 taken 555 times.
✓ Branch 2 taken 1 time.
556 if( s_->size() < in_size_ + n)
115 555 s_->resize(in_size_ + n);
116 556 out_size_ = n;
117 556 return mutable_buffers_type(
118
1/1
✓ Branch 1 taken 186 times.
1112 &(*s_)[in_size_], out_size_);
119 }
120
121 455 void commit(std::size_t n) noexcept
122 {
123
2/2
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 198 times.
455 if(n < out_size_)
124 257 in_size_ += n;
125 else
126 198 in_size_ += out_size_;
127 455 out_size_ = 0;
128 455 s_->resize(in_size_);
129 455 }
130
131 168 void consume(std::size_t n) noexcept
132 {
133
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 165 times.
168 if(n < in_size_)
134 {
135 3 s_->erase(0, n);
136 3 in_size_ -= n;
137 }
138 else
139 {
140 165 s_->clear();
141 165 in_size_ = 0;
142 }
143 168 out_size_ = 0;
144 168 }
145 };
146
147 using string_dynamic_buffer = basic_string_dynamic_buffer<char>;
148
149 /** Create a dynamic buffer from a string.
150
151 @param s The string to wrap.
152 @param max_size Optional maximum size limit.
153 @return A string_dynamic_buffer wrapping the string.
154 */
155 template<class CharT, class Traits, class Allocator>
156 basic_string_dynamic_buffer<CharT, Traits, Allocator>
157 132 dynamic_buffer(
158 std::basic_string<CharT, Traits, Allocator>& s,
159 std::size_t max_size = std::size_t(-1))
160 {
161 132 return basic_string_dynamic_buffer<CharT, Traits, Allocator>(&s, max_size);
162 }
163
164 } // capy
165 } // boost
166
167 #endif
168