include/boost/capy/buffers/string_dynamic_buffer.hpp

100.0% Lines (53/53) 100.0% Functions (10/10)
Line TLA 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 266x basic_string_dynamic_buffer(
48 basic_string_dynamic_buffer&& other) noexcept
49 266x : s_(other.s_)
50 266x , max_size_(other.max_size_)
51 266x , in_size_(other.in_size_)
52 266x , out_size_(other.out_size_)
53 {
54 266x other.s_ = nullptr;
55 266x }
56
57 /** Constructor.
58 */
59 explicit
60 427x basic_string_dynamic_buffer(
61 string_type* s,
62 std::size_t max_size =
63 std::size_t(-1)) noexcept
64 427x : s_(s)
65 427x , max_size_(
66 427x max_size > s_->max_size()
67 427x ? s_->max_size()
68 427x : max_size)
69 {
70 427x if(s_->size() > max_size_)
71 1x s_->resize(max_size_);
72 427x in_size_ = s_->size();
73 427x }
74
75 /** Assignment.
76 */
77 basic_string_dynamic_buffer& operator=(
78 basic_string_dynamic_buffer const&) = delete;
79
80 std::size_t
81 1280x size() const noexcept
82 {
83 1280x return in_size_;
84 }
85
86 std::size_t
87 410x max_size() const noexcept
88 {
89 410x return max_size_;
90 }
91
92 std::size_t
93 2x capacity() const noexcept
94 {
95 2x if(s_->capacity() <= max_size_)
96 1x return s_->capacity() - in_size_;
97 1x return max_size_ - in_size_;
98 }
99
100 const_buffers_type
101 387x data() const noexcept
102 {
103 387x return const_buffers_type(
104 774x s_->data(), in_size_);
105 }
106
107 mutable_buffers_type
108 533x prepare(std::size_t n)
109 {
110 // n exceeds available space
111 533x if(n > max_size_ - in_size_)
112 1x detail::throw_invalid_argument();
113
114 532x if( s_->size() < in_size_ + n)
115 531x s_->resize(in_size_ + n);
116 532x out_size_ = n;
117 532x return mutable_buffers_type(
118 1064x &(*s_)[in_size_], out_size_);
119 }
120
121 434x void commit(std::size_t n) noexcept
122 {
123 434x if(n < out_size_)
124 242x in_size_ += n;
125 else
126 192x in_size_ += out_size_;
127 434x out_size_ = 0;
128 434x s_->resize(in_size_);
129 434x }
130
131 168x void consume(std::size_t n) noexcept
132 {
133 168x if(n < in_size_)
134 {
135 3x s_->erase(0, n);
136 3x in_size_ -= n;
137 }
138 else
139 {
140 165x s_->clear();
141 165x in_size_ = 0;
142 }
143 168x out_size_ = 0;
144 168x }
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 132x dynamic_buffer(
158 std::basic_string<CharT, Traits, Allocator>& s,
159 std::size_t max_size = std::size_t(-1))
160 {
161 132x return basic_string_dynamic_buffer<CharT, Traits, Allocator>(&s, max_size);
162 }
163
164 } // capy
165 } // boost
166
167 #endif
168