Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2008-2017, Petr Kobalicek
3 :
4 : This software is provided 'as-is', without any express or implied
5 : warranty. In no event will the authors be held liable for any damages
6 : arising from the use of this software.
7 :
8 : Permission is granted to anyone to use this software for any purpose,
9 : including commercial applications, and to alter it and redistribute it
10 : freely, subject to the following restrictions:
11 :
12 : 1. The origin of this software must not be misrepresented; you must not
13 : claim that you wrote the original software. If you use this software
14 : in a product, an acknowledgment in the product documentation would be
15 : appreciated but is not required.
16 : 2. Altered source versions must be plainly marked as such, and must not be
17 : misrepresented as being the original software.
18 : 3. This notice may not be removed or altered from any source distribution.
19 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
20 : #ifdef __PLUMED_HAS_ASMJIT
21 : #pragma GCC diagnostic push
22 : #pragma GCC diagnostic ignored "-Wpedantic"
23 : // [AsmJit]
24 : // Complete x86/x64 JIT and Remote Assembler for C++.
25 : //
26 : // [License]
27 : // Zlib - See LICENSE.md file in the package.
28 :
29 : // [Export]
30 : #define ASMJIT_EXPORTS
31 :
32 : // [Dependencies]
33 : #include "./moved_string.h"
34 : #include "./utils.h"
35 :
36 : // [Api-Begin]
37 : #include "./asmjit_apibegin.h"
38 :
39 : namespace PLMD {
40 : namespace asmjit {
41 :
42 : // ============================================================================
43 : // [asmjit::StringBuilder - Construction / Destruction]
44 : // ============================================================================
45 :
46 : // Should be placed in read-only memory.
47 : static const char StringBuilder_empty[4] = { 0 };
48 :
49 0 : StringBuilder::StringBuilder() noexcept
50 0 : : _data(const_cast<char*>(StringBuilder_empty)),
51 0 : _length(0),
52 0 : _capacity(0),
53 0 : _canFree(false) {}
54 :
55 0 : StringBuilder::~StringBuilder() noexcept {
56 0 : if (_canFree)
57 0 : Internal::releaseMemory(_data);
58 0 : }
59 :
60 : // ============================================================================
61 : // [asmjit::StringBuilder - Prepare / Reserve]
62 : // ============================================================================
63 :
64 0 : ASMJIT_FAVOR_SIZE char* StringBuilder::prepare(uint32_t op, size_t len) noexcept {
65 0 : if (op == kStringOpSet) {
66 : // We don't care here, but we can't return a null pointer since it indicates
67 : // failure in memory allocation.
68 0 : if (len == 0) {
69 0 : if (_data != StringBuilder_empty)
70 0 : _data[0] = 0;
71 :
72 0 : _length = 0;
73 0 : return _data;
74 : }
75 :
76 0 : if (_capacity < len) {
77 0 : if (len >= IntTraits<size_t>::maxValue() - sizeof(intptr_t) * 2)
78 : return nullptr;
79 :
80 : size_t to = Utils::alignTo<size_t>(len, sizeof(intptr_t));
81 : if (to < 256 - sizeof(intptr_t))
82 : to = 256 - sizeof(intptr_t);
83 :
84 0 : char* newData = static_cast<char*>(Internal::allocMemory(to + sizeof(intptr_t)));
85 0 : if (!newData) {
86 0 : clear();
87 0 : return nullptr;
88 : }
89 :
90 0 : if (_canFree)
91 0 : Internal::releaseMemory(_data);
92 :
93 0 : _data = newData;
94 0 : _capacity = to + sizeof(intptr_t) - 1;
95 0 : _canFree = true;
96 : }
97 :
98 0 : _data[len] = 0;
99 0 : _length = len;
100 :
101 : ASMJIT_ASSERT(_length <= _capacity);
102 0 : return _data;
103 : }
104 : else {
105 : // We don't care here, but we can't return a null pointer since it indicates
106 : // failure of memory allocation.
107 0 : if (len == 0)
108 0 : return _data + _length;
109 :
110 : // Overflow.
111 0 : if (IntTraits<size_t>::maxValue() - sizeof(intptr_t) * 2 - _length < len)
112 : return nullptr;
113 :
114 0 : size_t after = _length + len;
115 0 : if (_capacity < after) {
116 : size_t to = _capacity;
117 :
118 : if (to < 256)
119 : to = 256;
120 :
121 0 : while (to < 1024 * 1024 && to < after)
122 0 : to *= 2;
123 :
124 0 : if (to < after) {
125 : to = after;
126 0 : if (to < (IntTraits<size_t>::maxValue() - 1024 * 32))
127 : to = Utils::alignTo<size_t>(to, 1024 * 32);
128 : }
129 :
130 : to = Utils::alignTo<size_t>(to, sizeof(intptr_t));
131 0 : char* newData = static_cast<char*>(Internal::allocMemory(to + sizeof(intptr_t)));
132 0 : if (!newData) return nullptr;
133 :
134 0 : ::memcpy(newData, _data, _length);
135 0 : if (_canFree)
136 : Internal::releaseMemory(_data);
137 :
138 0 : _data = newData;
139 0 : _capacity = to + sizeof(intptr_t) - 1;
140 0 : _canFree = true;
141 : }
142 :
143 0 : char* ret = _data + _length;
144 0 : _data[after] = 0;
145 0 : _length = after;
146 :
147 : ASMJIT_ASSERT(_length <= _capacity);
148 0 : return ret;
149 : }
150 : }
151 :
152 0 : ASMJIT_FAVOR_SIZE Error StringBuilder::reserve(size_t to) noexcept {
153 0 : if (_capacity >= to)
154 : return kErrorOk;
155 :
156 0 : if (to >= IntTraits<size_t>::maxValue() - sizeof(intptr_t) * 2)
157 : return DebugUtils::errored(kErrorNoHeapMemory);
158 :
159 : to = Utils::alignTo<size_t>(to, sizeof(intptr_t));
160 0 : char* newData = static_cast<char*>(Internal::allocMemory(to + sizeof(intptr_t)));
161 :
162 0 : if (!newData)
163 : return DebugUtils::errored(kErrorNoHeapMemory);
164 :
165 0 : ::memcpy(newData, _data, _length + 1);
166 0 : if (_canFree)
167 : Internal::releaseMemory(_data);
168 :
169 0 : _data = newData;
170 0 : _capacity = to + sizeof(intptr_t) - 1;
171 0 : _canFree = true;
172 0 : return kErrorOk;
173 : }
174 :
175 : // ============================================================================
176 : // [asmjit::StringBuilder - Clear]
177 : // ============================================================================
178 :
179 0 : void StringBuilder::clear() noexcept {
180 0 : if (_data != StringBuilder_empty)
181 0 : _data[0] = 0;
182 0 : _length = 0;
183 0 : }
184 :
185 : // ============================================================================
186 : // [asmjit::StringBuilder - Methods]
187 : // ============================================================================
188 :
189 0 : Error StringBuilder::_opString(uint32_t op, const char* str, size_t len) noexcept {
190 0 : if (len == Globals::kInvalidIndex)
191 0 : len = str ? ::strlen(str) : static_cast<size_t>(0);
192 :
193 0 : char* p = prepare(op, len);
194 0 : if (!p) return DebugUtils::errored(kErrorNoHeapMemory);
195 :
196 : ::memcpy(p, str, len);
197 0 : return kErrorOk;
198 : }
199 :
200 0 : Error StringBuilder::_opChar(uint32_t op, char c) noexcept {
201 0 : char* p = prepare(op, 1);
202 0 : if (!p) return DebugUtils::errored(kErrorNoHeapMemory);
203 :
204 0 : *p = c;
205 0 : return kErrorOk;
206 : }
207 :
208 0 : Error StringBuilder::_opChars(uint32_t op, char c, size_t n) noexcept {
209 0 : char* p = prepare(op, n);
210 0 : if (!p) return DebugUtils::errored(kErrorNoHeapMemory);
211 :
212 0 : ::memset(p, c, n);
213 0 : return kErrorOk;
214 : }
215 :
216 : static const char StringBuilder_numbers[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
217 :
218 0 : Error StringBuilder::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, uint32_t flags) noexcept {
219 0 : if (base < 2 || base > 36)
220 : base = 10;
221 :
222 : char buf[128];
223 : char* p = buf + ASMJIT_ARRAY_SIZE(buf);
224 :
225 : uint64_t orig = i;
226 : char sign = '\0';
227 :
228 : // --------------------------------------------------------------------------
229 : // [Sign]
230 : // --------------------------------------------------------------------------
231 :
232 0 : if ((flags & kStringFormatSigned) != 0 && static_cast<int64_t>(i) < 0) {
233 0 : i = static_cast<uint64_t>(-static_cast<int64_t>(i));
234 : sign = '-';
235 : }
236 0 : else if ((flags & kStringFormatShowSign) != 0) {
237 : sign = '+';
238 : }
239 0 : else if ((flags & kStringFormatShowSpace) != 0) {
240 : sign = ' ';
241 : }
242 :
243 : // --------------------------------------------------------------------------
244 : // [Number]
245 : // --------------------------------------------------------------------------
246 :
247 : do {
248 0 : uint64_t d = i / base;
249 0 : uint64_t r = i % base;
250 :
251 0 : *--p = StringBuilder_numbers[r];
252 : i = d;
253 0 : } while (i);
254 :
255 0 : size_t numberLength = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p);
256 :
257 : // --------------------------------------------------------------------------
258 : // [Alternate Form]
259 : // --------------------------------------------------------------------------
260 :
261 0 : if ((flags & kStringFormatAlternate) != 0) {
262 0 : if (base == 8) {
263 0 : if (orig != 0)
264 0 : *--p = '0';
265 : }
266 0 : if (base == 16) {
267 0 : *--p = 'x';
268 0 : *--p = '0';
269 : }
270 : }
271 :
272 : // --------------------------------------------------------------------------
273 : // [Width]
274 : // --------------------------------------------------------------------------
275 :
276 0 : if (sign != 0)
277 0 : *--p = sign;
278 :
279 : if (width > 256)
280 : width = 256;
281 :
282 0 : if (width <= numberLength)
283 : width = 0;
284 : else
285 0 : width -= numberLength;
286 :
287 : // --------------------------------------------------------------------------
288 : // Write]
289 : // --------------------------------------------------------------------------
290 :
291 0 : size_t prefixLength = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p) - numberLength;
292 0 : char* data = prepare(op, prefixLength + width + numberLength);
293 :
294 0 : if (!data)
295 : return DebugUtils::errored(kErrorNoHeapMemory);
296 :
297 : ::memcpy(data, p, prefixLength);
298 0 : data += prefixLength;
299 :
300 : ::memset(data, '0', width);
301 0 : data += width;
302 :
303 0 : ::memcpy(data, p + prefixLength, numberLength);
304 0 : return kErrorOk;
305 : }
306 :
307 0 : Error StringBuilder::_opHex(uint32_t op, const void* data, size_t len) noexcept {
308 : char* dst;
309 :
310 0 : if (len >= IntTraits<size_t>::maxValue() / 2 || !(dst = prepare(op, len * 2)))
311 : return DebugUtils::errored(kErrorNoHeapMemory);;
312 :
313 : const char* src = static_cast<const char*>(data);
314 0 : for (size_t i = 0; i < len; i++, dst += 2, src++) {
315 0 : dst[0] = StringBuilder_numbers[(src[0] >> 4) & 0xF];
316 0 : dst[1] = StringBuilder_numbers[(src[0] ) & 0xF];
317 : }
318 : return kErrorOk;
319 : }
320 :
321 0 : Error StringBuilder::_opVFormat(uint32_t op, const char* fmt, va_list ap) noexcept {
322 : char buf[1024];
323 :
324 : vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap);
325 0 : buf[ASMJIT_ARRAY_SIZE(buf) - 1] = '\0';
326 :
327 0 : return _opString(op, buf);
328 : }
329 :
330 0 : Error StringBuilder::setFormat(const char* fmt, ...) noexcept {
331 : bool result;
332 :
333 : va_list ap;
334 0 : va_start(ap, fmt);
335 0 : result = _opVFormat(kStringOpSet, fmt, ap);
336 0 : va_end(ap);
337 :
338 0 : return result;
339 : }
340 :
341 0 : Error StringBuilder::appendFormat(const char* fmt, ...) noexcept {
342 : bool result;
343 :
344 : va_list ap;
345 0 : va_start(ap, fmt);
346 0 : result = _opVFormat(kStringOpAppend, fmt, ap);
347 0 : va_end(ap);
348 :
349 0 : return result;
350 : }
351 :
352 0 : bool StringBuilder::eq(const char* str, size_t len) const noexcept {
353 0 : const char* aData = _data;
354 : const char* bData = str;
355 :
356 0 : size_t aLength = _length;
357 : size_t bLength = len;
358 :
359 0 : if (bLength == Globals::kInvalidIndex) {
360 : size_t i;
361 0 : for (i = 0; i < aLength; i++)
362 0 : if (aData[i] != bData[i] || bData[i] == 0)
363 : return false;
364 0 : return bData[i] == 0;
365 : }
366 : else {
367 0 : if (aLength != bLength)
368 : return false;
369 0 : return ::memcmp(aData, bData, aLength) == 0;
370 : }
371 : }
372 :
373 : } // asmjit namespace
374 : } // namespace PLMD
375 :
376 : // [Api-End]
377 : #include "./asmjit_apiend.h"
378 : #pragma GCC diagnostic pop
379 : #endif // __PLUMED_HAS_ASMJIT
|