MiKTeX 26.5-next
A scalable TeX distribution
Loading...
Searching...
No Matches
CharBuffer.h
Go to the documentation of this file.
1
13
14#pragma once
15
16#include <miktex/Util/config.h>
17
18#include <cstddef>
19#include <cwchar>
20
21#include <string>
22
23#include "StringUtil.h"
24#include "inliners.h"
25
26MIKTEX_UTIL_BEGIN_NAMESPACE;
27
29template<typename CharType, int BUFSIZE = 512> class CharBuffer
30{
31
32public:
33
34 CharBuffer() = default;
35
36 CharBuffer(const CharBuffer& other)
37 {
38 Set(other);
39 }
40
41 CharBuffer(CharBuffer&& other) noexcept
42 {
43 if (other.buffer == other.smallBuffer)
44 {
45 memcpy(this->smallBuffer, other.smallBuffer, BUFSIZE);
46 this->buffer = this->smallBuffer;
47 }
48 else
49 {
50 this->buffer = other.buffer;
51 }
52 this->capacity = other.capacity;
53 other.buffer = other.smallBuffer;
54 other.capacity = BUFSIZE;
55 other.Clear();
56 }
57
58 CharBuffer& operator=(const CharBuffer& other)
59 {
60 Set(other);
61 return *this;
62 }
63
64 CharBuffer& operator=(CharBuffer&& other) noexcept
65 {
66 if (this != &other)
67 {
68 Reset();
69 if (other.buffer == other.smallBuffer)
70 {
71 memcpy(this->smallBuffer, other.smallBuffer, BUFSIZE);
72 this->buffer = this->smallBuffer;
73 }
74 else
75 {
76 this->buffer = other.buffer;
77 }
78 this->capacity = other.capacity;
79 other.buffer = other.smallBuffer;
80 other.capacity = BUFSIZE;
81 other.Clear();
82 }
83 return *this;
84 }
85
86 virtual ~CharBuffer() noexcept
87 {
88 try
89 {
90 Reset();
91 }
92 catch (const std::exception&)
93 {
94 }
95 }
96
97 explicit CharBuffer(const char* s)
98 {
99 Set(s);
100 }
101
102 explicit CharBuffer(const char16_t* s)
103 {
104 Set(s);
105 }
106
107 explicit CharBuffer(const wchar_t* s)
108 {
109 Set(s);
110 }
111
112 explicit CharBuffer(const std::basic_string<char>& other)
113 {
114 Set(other);
115 }
116
117 explicit CharBuffer(const std::basic_string<char16_t>& other)
118 {
119 Set(other);
120 }
121
122 explicit CharBuffer(const std::basic_string<wchar_t>& other)
123 {
124 Set(other);
125 }
126
127 explicit CharBuffer(std::size_t n)
128 {
129 Clear();
130 Reserve(n);
131 }
132
133 void Set(const CharBuffer& other)
134 {
135 if (this != &other)
136 {
137 Reserve(other.capacity);
138 memcpy(this->buffer, other.buffer, other.capacity * sizeof(CharType));
139 }
140 }
141
142 template<typename OtherCharType> void Set(const OtherCharType* s)
143 {
144 // TODO: MIKTEX_ASSERT_STRING_OR_NIL(s);
145 if (s == nullptr)
146 {
147 Reset();
148 }
149 else
150 {
151 std::size_t requiredSize;
152 if (sizeof(CharType) < sizeof(OtherCharType))
153 {
154 requiredSize = StrLen(s) * 4 + 1; // worst case: wchar_t to UTF-8
155 }
156 else
157 {
158 requiredSize = StrLen(s) + 1;
159 }
160 Reserve(requiredSize);
161 StringUtil::CopyCeeString(buffer, GetCapacity(), s);
162 }
163 }
164
165 template<typename OtherCharType> void Set(const std::basic_string<OtherCharType>& s)
166 {
167 Set(s.c_str());
168 }
169
170 void Append(const std::basic_string<CharType>& s)
171 {
172 Reserve(GetLength() + s.length() + 1);
173 StringUtil::AppendCeeString(buffer, GetCapacity(), s.c_str());
174 }
175
176 void Append(const CharType* s)
177 {
178 // TODO: MIKTEX_ASSERT_STRING(s);
179 Reserve(GetLength() + StrLen(s) + 1);
180 StringUtil::AppendCeeString(buffer, GetCapacity(), s);
181 }
182
183 void Append(const CharType* s, std::size_t len)
184 {
185 std::size_t idx = GetLength();
186 Reserve(idx + len + 1);
187 for (; len > 0; --len, ++idx, ++s)
188 {
189 buffer[idx] = *s;
190 }
191 buffer[idx] = 0;
192 }
193
194 void Append(CharType ch)
195 {
196 std::size_t len = GetLength();
197 Reserve(len + 2);
198 buffer[len] = ch;
199 buffer[len + 1] = 0;
200 }
201
202 void Clear()
203 {
204 buffer[0] = 0;
205 }
206
209 bool Empty() const
210 {
211 return buffer[0] == 0;
212 }
213
214 void Reset()
215 {
216 if (buffer != smallBuffer)
217 {
218 delete[] buffer;
219 buffer = smallBuffer;
220 capacity = BUFSIZE;
221 }
222 Clear();
223 }
224
225 void Reserve(std::size_t newSize)
226 {
227 if (newSize > BUFSIZE && newSize > capacity)
228 {
229 CharType* newBuffer = new CharType[newSize];
230 memcpy(newBuffer, buffer, capacity * sizeof(CharType));
231 if (buffer != smallBuffer)
232 {
233 delete[] buffer;
234 }
235 buffer = newBuffer;
236 capacity = newSize;
237 }
238 }
239
242 std::basic_string<CharType> ToString() const
243 {
244 return std::basic_string<CharType>(buffer);
245 }
246
247 const CharType* GetData() const
248 {
249 return buffer;
250 }
251
252 CharType* GetData()
253 {
254 return buffer;
255 }
256
257 std::size_t GetLength() const
258 {
259 std::size_t idx;
260 for (idx = 0; idx < capacity && buffer[idx] != 0; ++idx)
261 {
262 ;
263 }
264 return idx;
265 }
266
267 std::size_t GetCapacity() const
268 {
269 return capacity;
270 }
271
272 const CharType& operator[](std::size_t idx) const
273 {
274 // TODO: MIKTEX_ASSERT(idx < GetCapacity());
275 return buffer[idx];
276 }
277
278 CharType& operator[](std::size_t idx)
279 {
280 // TODO: MIKTEX_ASSERT(idx < GetCapacity());
281 return buffer[idx];
282 }
283
284 template<typename OtherCharType> CharBuffer& operator=(const OtherCharType* s)
285 {
286 Set(s);
287 return *this;
288 }
289
290 template<typename OtherCharType> CharBuffer& operator=(const std::basic_string<OtherCharType>& s)
291 {
292 Set(s);
293 return *this;
294 }
295
296 CharBuffer& operator+=(const CharType* s)
297 {
298 Append(s);
299 return *this;
300 }
301
302 CharBuffer& operator+=(const std::basic_string<CharType>& s)
303 {
304 Append(s);
305 return *this;
306 }
307
308 CharBuffer& operator+=(CharType ch)
309 {
310 Append(ch);
311 return *this;
312 }
313
314private:
315
316 CharType* buffer = smallBuffer;
317 std::size_t capacity = BUFSIZE;
318 CharType smallBuffer[BUFSIZE] = { 0 };
319};
320
321MIKTEX_UTIL_END_NAMESPACE;
StringUtil class.
bool Empty() const
Definition CharBuffer.h:209
std::basic_string< CharType > ToString() const
Definition CharBuffer.h:242
Inline functions.
@ Append
Definition File.h:59