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_BUFFER_HPP
11 : #define BOOST_CAPY_BUFFERS_STRING_BUFFER_HPP
12 :
13 : #include <boost/capy/detail/config.hpp>
14 : #include <boost/capy/buffers.hpp>
15 : #include <boost/capy/buffers/detail/except.hpp>
16 : #include <boost/assert.hpp>
17 : #include <string>
18 :
19 : namespace boost {
20 : namespace capy {
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 = const_buffer;
44 : using mutable_buffers_type = mutable_buffer;
45 :
46 15 : ~basic_string_buffer()
47 : {
48 15 : if(s_)
49 14 : s_->resize(in_size_);
50 15 : }
51 :
52 : /** Constructor.
53 : */
54 1 : basic_string_buffer(
55 : basic_string_buffer&& other) noexcept
56 1 : : s_(other.s_)
57 1 : , max_size_(other.max_size_)
58 : {
59 1 : other.s_ = nullptr;
60 1 : }
61 :
62 : /** Constructor.
63 : */
64 : explicit
65 14 : basic_string_buffer(
66 : string_type* s,
67 : std::size_t max_size =
68 : std::size_t(-1)) noexcept
69 14 : : s_(s)
70 14 : , max_size_(
71 14 : max_size > s_->max_size()
72 14 : ? s_->max_size()
73 14 : : max_size)
74 : {
75 14 : if(s_->size() > max_size_)
76 1 : s_->resize(max_size_);
77 14 : in_size_ = s_->size();
78 14 : }
79 :
80 : /** Assignment.
81 : */
82 : basic_string_buffer& operator=(
83 : basic_string_buffer const&) = delete;
84 :
85 : std::size_t
86 2 : size() const noexcept
87 : {
88 2 : return in_size_;
89 : }
90 :
91 : std::size_t
92 2 : max_size() const noexcept
93 : {
94 2 : return max_size_;
95 : }
96 :
97 : std::size_t
98 2 : capacity() const noexcept
99 : {
100 2 : if(s_->capacity() <= max_size_)
101 1 : return s_->capacity() - in_size_;
102 1 : return max_size_ - in_size_;
103 : }
104 :
105 : const_buffers_type
106 2 : data() const noexcept
107 : {
108 2 : return const_buffers_type(
109 4 : s_->data(), in_size_);
110 : }
111 :
112 : mutable_buffers_type
113 6 : prepare(std::size_t n)
114 : {
115 : // n exceeds available space
116 6 : if(n > max_size_ - in_size_)
117 1 : detail::throw_invalid_argument();
118 :
119 5 : if( s_->size() < in_size_ + n)
120 4 : s_->resize(in_size_ + n);
121 5 : out_size_ = n;
122 5 : return mutable_buffers_type(
123 10 : &(*s_)[in_size_], out_size_);
124 : }
125 :
126 2 : void commit(std::size_t n) noexcept
127 : {
128 2 : if(n < out_size_)
129 1 : in_size_ += n;
130 : else
131 1 : in_size_ += out_size_;
132 2 : out_size_ = 0;
133 2 : }
134 :
135 2 : void consume(std::size_t n) noexcept
136 : {
137 2 : if(n < in_size_)
138 : {
139 1 : s_->erase(0, n);
140 1 : in_size_ -= n;
141 : }
142 : else
143 : {
144 1 : in_size_ = 0;
145 : }
146 2 : out_size_ = 0;
147 2 : }
148 : };
149 :
150 : using string_buffer = basic_string_buffer<char>;
151 :
152 : } // capy
153 : } // boost
154 :
155 : #endif
|