Welcome to mirror list, hosted at ThFree Co, Russian Federation.

string.h « core « asmjit « src - github.com/asmjit/asmjit.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b58725ea10b2acdd0feec46002d7eace066471d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
// AsmJit - Machine code generation for C++
//
//  * Official AsmJit Home Page: https://asmjit.com
//  * Official Github Repository: https://github.com/asmjit/asmjit
//
// Copyright (c) 2008-2020 The AsmJit Authors
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

#ifndef ASMJIT_CORE_STRING_H_INCLUDED
#define ASMJIT_CORE_STRING_H_INCLUDED

#include "../core/support.h"
#include "../core/zone.h"

ASMJIT_BEGIN_NAMESPACE

//! \addtogroup asmjit_utilities
//! \{

// ============================================================================
// [asmjit::FixedString]
// ============================================================================

//! A fixed string - only useful for strings that would never exceed `N - 1`
//! characters; always null-terminated.
template<size_t N>
union FixedString {
  enum : uint32_t {
    kNumU32 = uint32_t((N + sizeof(uint32_t) - 1) / sizeof(uint32_t))
  };

  char str[kNumU32 * sizeof(uint32_t)];
  uint32_t u32[kNumU32];

  //! \name Utilities
  //! \{

  inline bool eq(const char* other) const noexcept {
    return strcmp(str, other) == 0;
  }

  //! \}
};
// ============================================================================
// [asmjit::String]
// ============================================================================

//! A simple non-reference counted string that uses small string optimization (SSO).
//!
//! This string has 3 allocation possibilities:
//!
//!   1. Small    - embedded buffer is used for up to `kSSOCapacity` characters.
//!                 This should handle most small strings and thus avoid dynamic
//!                 memory allocation for most use-cases.
//!
//!   2. Large    - string that doesn't fit into an embedded buffer (or string
//!                 that was truncated from a larger buffer) and is owned by
//!                 AsmJit. When you destroy the string AsmJit would automatically
//!                 release the large buffer.
//!
//!   3. External - like Large (2), however, the large buffer is not owned by
//!                 AsmJit and won't be released when the string is destroyed
//!                 or reallocated. This is mostly useful for working with
//!                 larger temporary strings allocated on stack or with immutable
//!                 strings.
class String {
public:
  ASMJIT_NONCOPYABLE(String)

  //! String operation.
  enum Op : uint32_t {
    //! Assignment - a new content replaces the current one.
    kOpAssign = 0,
    //! Append - a new content is appended to the string.
    kOpAppend = 1
  };

  //! String format flags.
  enum FormatFlags : uint32_t {
    kFormatShowSign  = 0x00000001u,
    kFormatShowSpace = 0x00000002u,
    kFormatAlternate = 0x00000004u,
    kFormatSigned    = 0x80000000u
  };

  //! \cond INTERNAL
  enum : uint32_t {
    kLayoutSize = 32,
    kSSOCapacity = kLayoutSize - 2
  };

  //! String type.
  enum Type : uint8_t {
    kTypeLarge    = 0x1Fu, //!< Large string (owned by String).
    kTypeExternal = 0x20u  //!< External string (zone allocated or not owned by String).
  };

  union Raw {
    uint8_t u8[kLayoutSize];
    uint64_t u64[kLayoutSize / sizeof(uint64_t)];
    uintptr_t uptr[kLayoutSize / sizeof(uintptr_t)];
  };

  struct Small {
    uint8_t type;
    char data[kSSOCapacity + 1u];
  };

  struct Large {
    uint8_t type;
    uint8_t reserved[sizeof(uintptr_t) - 1];
    size_t size;
    size_t capacity;
    char* data;
  };

  union {
    uint8_t _type;
    Raw _raw;
    Small _small;
    Large _large;
  };
  //! \endcond

  //! \name Construction & Destruction
  //! \{

  //! Creates a default-initialized string if zero length.
  inline String() noexcept
    : _small {} {}

  //! Creates a string that takes ownership of the content of the `other` string.
  inline String(String&& other) noexcept {
    _raw = other._raw;
    other._resetInternal();
  }

  inline ~String() noexcept {
    reset();
  }

  //! Reset the string into a construction state.
  ASMJIT_API Error reset() noexcept;

  //! \}

  //! \name Overloaded Operators
  //! \{

  inline String& operator=(String&& other) noexcept {
    swap(other);
    other.reset();
    return *this;
  }

  inline bool operator==(const char* other) const noexcept { return  eq(other); }
  inline bool operator!=(const char* other) const noexcept { return !eq(other); }

  inline bool operator==(const String& other) const noexcept { return  eq(other); }
  inline bool operator!=(const String& other) const noexcept { return !eq(other); }

  //! \}

  //! \name Accessors
  //! \{

  inline bool isLarge() const noexcept { return _type >= kTypeLarge; }
  inline bool isExternal() const noexcept { return _type == kTypeExternal; }

  //! Tests whether the string is empty.
  inline bool empty() const noexcept { return size() == 0; }
  //! Returns the size of the string.
  inline size_t size() const noexcept { return isLarge() ? size_t(_large.size) : size_t(_type); }
  //! Returns the capacity of the string.
  inline size_t capacity() const noexcept { return isLarge() ? _large.capacity : size_t(kSSOCapacity); }

  //! Returns the data of the string.
  inline char* data() noexcept { return isLarge() ? _large.data : _small.data; }
  //! \overload
  inline const char* data() const noexcept { return isLarge() ? _large.data : _small.data; }

  inline char* start() noexcept { return data(); }
  inline const char* start() const noexcept { return data(); }

  inline char* end() noexcept { return data() + size(); }
  inline const char* end() const noexcept { return data() + size(); }

  //! \}

  //! \name String Operations
  //! \{

  //! Swaps the content of this string with `other`.
  inline void swap(String& other) noexcept {
    std::swap(_raw, other._raw);
  }

  //! Clears the content of the string.
  ASMJIT_API Error clear() noexcept;

  ASMJIT_API char* prepare(uint32_t op, size_t size) noexcept;

  ASMJIT_API Error _opString(uint32_t op, const char* str, size_t size = SIZE_MAX) noexcept;
  ASMJIT_API Error _opChar(uint32_t op, char c) noexcept;
  ASMJIT_API Error _opChars(uint32_t op, char c, size_t n) noexcept;
  ASMJIT_API Error _opNumber(uint32_t op, uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept;
  ASMJIT_API Error _opHex(uint32_t op, const void* data, size_t size, char separator = '\0') noexcept;
  ASMJIT_API Error _opFormat(uint32_t op, const char* fmt, ...) noexcept;
  ASMJIT_API Error _opVFormat(uint32_t op, const char* fmt, va_list ap) noexcept;

  //! Replaces the current of the string with `data` of the given `size`.
  //!
  //! Null terminated strings can set `size` to `SIZE_MAX`.
  ASMJIT_API Error assign(const char* data, size_t size = SIZE_MAX) noexcept;

  //! Replaces the current of the string with `other` string.
  inline Error assign(const String& other) noexcept {
    return assign(other.data(), other.size());
  }

  //! Replaces the current of the string by a single `c` character.
  inline Error assign(char c) noexcept {
    return _opChar(kOpAssign, c);
  }

  //! Replaces the current of the string by a `c` character, repeated `n` times.
  inline Error assignChars(char c, size_t n) noexcept {
    return _opChars(kOpAssign, c, n);
  }

  //! Replaces the current of the string by a formatted integer `i` (signed).
  inline Error assignInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept {
    return _opNumber(kOpAssign, uint64_t(i), base, width, flags | kFormatSigned);
  }

  //! Replaces the current of the string by a formatted integer `i` (unsigned).
  inline Error assignUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept {
    return _opNumber(kOpAssign, i, base, width, flags);
  }

  //! Replaces the current of the string by the given `data` converted to a HEX string.
  inline Error assignHex(const void* data, size_t size, char separator = '\0') noexcept {
    return _opHex(kOpAssign, data, size, separator);
  }

  //! Replaces the current of the string by a formatted string `fmt`.
  template<typename... Args>
  inline Error assignFormat(const char* fmt, Args&&... args) noexcept {
    return _opFormat(kOpAssign, fmt, std::forward<Args>(args)...);
  }

  //! Replaces the current of the string by a formatted string `fmt` (va_list version).
  inline Error assignVFormat(const char* fmt, va_list ap) noexcept {
    return _opVFormat(kOpAssign, fmt, ap);
  }

  //! Appends `str` having the given size `size` to the string.
  //!
  //! Null terminated strings can set `size` to `SIZE_MAX`.
  inline Error append(const char* str, size_t size = SIZE_MAX) noexcept {
    return _opString(kOpAppend, str, size);
  }

  //! Appends `other` string to this string.
  inline Error append(const String& other) noexcept {
    return append(other.data(), other.size());
  }

  //! Appends a single `c` character.
  inline Error append(char c) noexcept {
    return _opChar(kOpAppend, c);
  }

  //! Appends `c` character repeated `n` times.
  inline Error appendChars(char c, size_t n) noexcept {
    return _opChars(kOpAppend, c, n);
  }

  //! Appends a formatted integer `i` (signed).
  inline Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept {
    return _opNumber(kOpAppend, uint64_t(i), base, width, flags | kFormatSigned);
  }

  //! Appends a formatted integer `i` (unsigned).
  inline Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept {
    return _opNumber(kOpAppend, i, base, width, flags);
  }

  //! Appends the given `data` converted to a HEX string.
  inline Error appendHex(const void* data, size_t size, char separator = '\0') noexcept {
    return _opHex(kOpAppend, data, size, separator);
  }

  //! Appends a formatted string `fmt` with `args`.
  template<typename... Args>
  inline Error appendFormat(const char* fmt, Args&&... args) noexcept {
    return _opFormat(kOpAppend, fmt, std::forward<Args>(args)...);
  }

  //! Appends a formatted string `fmt` (va_list version).
  inline Error appendVFormat(const char* fmt, va_list ap) noexcept {
    return _opVFormat(kOpAppend, fmt, ap);
  }

  ASMJIT_API Error padEnd(size_t n, char c = ' ') noexcept;

  //! Truncate the string length into `newSize`.
  ASMJIT_API Error truncate(size_t newSize) noexcept;

  ASMJIT_API bool eq(const char* other, size_t size = SIZE_MAX) const noexcept;
  inline bool eq(const String& other) const noexcept { return eq(other.data(), other.size()); }

  //! \}

  //! \name Internal Functions
  //! \{

  //! Resets string to embedded and makes it empty (zero length, zero first char)
  //!
  //! \note This is always called internally after an external buffer was released
  //! as it zeroes all bytes used by String's embedded storage.
  inline void _resetInternal() noexcept {
    for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_raw.uptr); i++)
      _raw.uptr[i] = 0;
  }

  inline void _setSize(size_t newSize) noexcept {
    if (isLarge())
      _large.size = newSize;
    else
      _small.type = uint8_t(newSize);
  }

  //! \}

#ifndef ASMJIT_NO_DEPRECATED
  ASMJIT_DEPRECATED("Use assign() instead of assignString()")
  inline Error assignString(const char* data, size_t size = SIZE_MAX) noexcept { return assign(data, size); }

  ASMJIT_DEPRECATED("Use assign() instead of assignChar()")
  inline Error assignChar(char c) noexcept { return assign(c); }

  ASMJIT_DEPRECATED("Use append() instead of appendString()")
  inline Error appendString(const char* data, size_t size = SIZE_MAX) noexcept { return append(data, size); }

  ASMJIT_DEPRECATED("Use append() instead of appendChar()")
  inline Error appendChar(char c) noexcept { return append(c); }
#endif // !ASMJIT_NO_DEPRECATED
};

// ============================================================================
// [asmjit::StringTmp]
// ============================================================================

//! Temporary string builder, has statically allocated `N` bytes.
template<size_t N>
class StringTmp : public String {
public:
  ASMJIT_NONCOPYABLE(StringTmp)

  //! Embedded data.
  char _embeddedData[Support::alignUp(N + 1, sizeof(size_t))];

  //! \name Construction & Destruction
  //! \{

  inline StringTmp() noexcept {
    _resetToTemporary();
  }

  inline void _resetToTemporary() noexcept {
    _large.type = kTypeExternal;
    _large.capacity = ASMJIT_ARRAY_SIZE(_embeddedData) - 1;
    _large.data = _embeddedData;
    _embeddedData[0] = '\0';
  }

  //! \}
};

//! \}

ASMJIT_END_NAMESPACE

#endif // ASMJIT_CORE_STRING_H_INCLUDED