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/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 433 : ? s_->max_size()
68 433 : : max_size)
69 : {
70 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 : 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 557 : if(n > max_size_ - in_size_)
112 1 : detail::throw_invalid_argument();
113 :
114 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 1112 : &(*s_)[in_size_], out_size_);
119 : }
120 :
121 455 : void commit(std::size_t n) noexcept
122 : {
123 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 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
|