string.h 11.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.

// [Guard]
#ifndef _ASMJIT_BASE_STRING_H
#define _ASMJIT_BASE_STRING_H

11
// [Dependencies]
12
13
14
#include "../base/globals.h"

// [Api-Begin]
15
#include "../asmjit_apibegin.h"
16
17
18

namespace asmjit {

19
//! \addtogroup asmjit_base
20
21
22
//! \{

// ============================================================================
23
// [asmjit::SmallString]
24
25
// ============================================================================

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//! Small string is a template that helps to create strings that can be either
//! statically allocated if they are small, or externally allocated in case
//! their length exceed the limit. The `WholeSize` represents the size of the
//! whole `SmallString` structure, based on that size the maximum size of the
//! internal buffer is determined.
template<size_t WholeSize>
class SmallString {
public:
  enum { kMaxEmbeddedLength = WholeSize - 5 };

  ASMJIT_INLINE SmallString() noexcept { reset(); }
  ASMJIT_INLINE void reset() noexcept { ::memset(this, 0, sizeof(*this)); }

  ASMJIT_INLINE bool isEmpty() const noexcept { return _length == 0; }
  ASMJIT_INLINE bool isEmbedded() const noexcept { return _length <= kMaxEmbeddedLength; }
  ASMJIT_INLINE bool mustEmbed(size_t len) const noexcept { return len <= kMaxEmbeddedLength; }

  ASMJIT_INLINE uint32_t getLength() const noexcept { return _length; }
  ASMJIT_INLINE char* getData() const noexcept {
    return _length <= kMaxEmbeddedLength ? const_cast<char*>(_embedded) : _external[1];
  }
47

48
49
  ASMJIT_INLINE void setEmbedded(const char* data, size_t len) noexcept {
    ASMJIT_ASSERT(len <= kMaxEmbeddedLength);
50

51
52
53
54
    _length = static_cast<uint32_t>(len);
    ::memcpy(_embedded, data, len);
    _embedded[len] = '\0';
  }
55

56
57
58
  ASMJIT_INLINE void setExternal(const char* data, size_t len) noexcept {
    ASMJIT_ASSERT(len > kMaxEmbeddedLength);
    ASMJIT_ASSERT(len <= ~static_cast<uint32_t>(0));
59

60
61
    _length = static_cast<uint32_t>(len);
    _external[1] = const_cast<char*>(data);
62
  }
63
64
65
66
67
68
69
70

  union {
    struct {
      uint32_t _length;
      char _embedded[WholeSize - 4];
    };
    char* _external[2];
  };
71
72
73
74
75
76
77
78
79
80
81
82
83
84
};

// ============================================================================
// [asmjit::StringBuilder]
// ============================================================================

//! String builder.
//!
//! String builder was designed to be able to build a string using append like
//! operation to append numbers, other strings, or signle characters. It can
//! allocate it's own buffer or use a buffer created on the stack.
//!
//! String builder contains method specific to AsmJit functionality, used for
//! logging or HTML output.
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
class StringBuilder {
public:
  ASMJIT_NONCOPYABLE(StringBuilder)

  //! \internal
  //!
  //! String operation.
  ASMJIT_ENUM(OpType) {
    kStringOpSet = 0,                    //!< Replace the current string by a given content.
    kStringOpAppend = 1                  //!< Append a given content to the current string.
  };

  //! \internal
  //!
  //! String format flags.
  ASMJIT_ENUM(StringFormatFlags) {
    kStringFormatShowSign  = 0x00000001,
    kStringFormatShowSpace = 0x00000002,
    kStringFormatAlternate = 0x00000004,
    kStringFormatSigned    = 0x80000000
  };
106
107
108
109
110

  // --------------------------------------------------------------------------
  // [Construction / Destruction]
  // --------------------------------------------------------------------------

111
112
  ASMJIT_API StringBuilder() noexcept;
  ASMJIT_API ~StringBuilder() noexcept;
113

114
  ASMJIT_INLINE StringBuilder(const _NoInit&) noexcept {}
115
116
117
118
119
120

  // --------------------------------------------------------------------------
  // [Accessors]
  // --------------------------------------------------------------------------

  //! Get string builder capacity.
121
  ASMJIT_INLINE size_t getCapacity() const noexcept { return _capacity; }
122
  //! Get length.
123
  ASMJIT_INLINE size_t getLength() const noexcept { return _length; }
124
125

  //! Get null-terminated string data.
126
  ASMJIT_INLINE char* getData() noexcept { return _data; }
127
  //! Get null-terminated string data (const).
128
  ASMJIT_INLINE const char* getData() const noexcept { return _data; }
129
130
131
132
133
134

  // --------------------------------------------------------------------------
  // [Prepare / Reserve]
  // --------------------------------------------------------------------------

  //! Prepare to set/append.
135
  ASMJIT_API char* prepare(uint32_t op, size_t len) noexcept;
136
137

  //! Reserve `to` bytes in string builder.
138
  ASMJIT_API Error reserve(size_t to) noexcept;
139
140
141
142
143
144

  // --------------------------------------------------------------------------
  // [Clear]
  // --------------------------------------------------------------------------

  //! Clear the content in String builder.
145
  ASMJIT_API void clear() noexcept;
146
147
148
149
150

  // --------------------------------------------------------------------------
  // [Op]
  // --------------------------------------------------------------------------

151
152
153
154
155
156
  ASMJIT_API Error _opString(uint32_t op, const char* str, size_t len = Globals::kInvalidIndex) noexcept;
  ASMJIT_API Error _opVFormat(uint32_t op, const char* fmt, va_list ap) 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 len) noexcept;
157
158
159
160
161

  // --------------------------------------------------------------------------
  // [Set]
  // --------------------------------------------------------------------------

162
163
164
165
166
167
  //! Replace the current string with `str` having `len` characters (or `kInvalidIndex` if it's null terminated).
  ASMJIT_INLINE Error setString(const char* str, size_t len = Globals::kInvalidIndex) noexcept { return _opString(kStringOpSet, str, len); }
  //! Replace the current content by a formatted string `fmt`.
  ASMJIT_API Error setFormat(const char* fmt, ...) noexcept;
  //! Replace the current content by a formatted string `fmt` (va_list version).
  ASMJIT_INLINE Error setFormatVA(const char* fmt, va_list ap) noexcept { return _opVFormat(kStringOpSet, fmt, ap); }
168

169
170
171
172
  //! Replace the current content by a single `c` character.
  ASMJIT_INLINE Error setChar(char c) noexcept { return _opChar(kStringOpSet, c); }
  //! Replace the current content by `c` character `n` times.
  ASMJIT_INLINE Error setChars(char c, size_t n) noexcept { return _opChars(kStringOpSet, c, n); }
173

174
175
  //! Replace the current content by a formatted integer `i` (signed).
  ASMJIT_INLINE Error setInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept {
176
177
178
    return _opNumber(kStringOpSet, i, base, width, flags | kStringFormatSigned);
  }

179
180
  //! Replace the current content by a formatted integer `i` (unsigned).
  ASMJIT_INLINE Error setUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept {
181
182
183
184
    return _opNumber(kStringOpSet, i, base, width, flags);
  }

  //! Replace the current content by the given `data` converted to a HEX string.
185
  ASMJIT_INLINE Error setHex(const void* data, size_t len) noexcept {
186
187
188
189
190
191
192
    return _opHex(kStringOpSet, data, len);
  }

  // --------------------------------------------------------------------------
  // [Append]
  // --------------------------------------------------------------------------

193
194
195
196
197
198
  //! Append string `str` having `len` characters (or `kInvalidIndex` if it's null terminated).
  ASMJIT_INLINE Error appendString(const char* str, size_t len = Globals::kInvalidIndex) noexcept { return _opString(kStringOpAppend, str, len); }
  //! Append a formatted string `fmt`.
  ASMJIT_API Error appendFormat(const char* fmt, ...) noexcept;
  //! Append a formatted string `fmt` (va_list version).
  ASMJIT_INLINE Error appendFormatVA(const char* fmt, va_list ap) noexcept { return _opVFormat(kStringOpAppend, fmt, ap); }
199

200
201
202
203
  //! Append a single `c` character.
  ASMJIT_INLINE Error appendChar(char c) noexcept { return _opChar(kStringOpAppend, c); }
  //! Append `c` character `n` times.
  ASMJIT_INLINE Error appendChars(char c, size_t n) noexcept { return _opChars(kStringOpAppend, c, n); }
204
205

  //! Append `i`.
206
  ASMJIT_INLINE Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept {
207
208
209
210
    return _opNumber(kStringOpAppend, static_cast<uint64_t>(i), base, width, flags | kStringFormatSigned);
  }

  //! Append `i`.
211
  ASMJIT_INLINE Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept {
212
213
214
215
    return _opNumber(kStringOpAppend, i, base, width, flags);
  }

  //! Append the given `data` converted to a HEX string.
216
  ASMJIT_INLINE Error appendHex(const void* data, size_t len) noexcept {
217
218
219
220
221
222
223
    return _opHex(kStringOpAppend, data, len);
  }

  // --------------------------------------------------------------------------
  // [Eq]
  // --------------------------------------------------------------------------

224
225
  //! Check for equality with other `str` of length `len`.
  ASMJIT_API bool eq(const char* str, size_t len = Globals::kInvalidIndex) const noexcept;
226
  //! Check for equality with `other`.
227
  ASMJIT_INLINE bool eq(const StringBuilder& other) const noexcept { return eq(other._data, other._length); }
228
229
230
231
232

  // --------------------------------------------------------------------------
  // [Operator Overload]
  // --------------------------------------------------------------------------

233
234
  ASMJIT_INLINE bool operator==(const StringBuilder& other) const noexcept { return  eq(other); }
  ASMJIT_INLINE bool operator!=(const StringBuilder& other) const noexcept { return !eq(other); }
235

236
237
  ASMJIT_INLINE bool operator==(const char* str) const noexcept { return  eq(str); }
  ASMJIT_INLINE bool operator!=(const char* str) const noexcept { return !eq(str); }
238
239
240
241
242

  // --------------------------------------------------------------------------
  // [Members]
  // --------------------------------------------------------------------------

243
244
245
246
  char* _data;                           //!< String data.
  size_t _length;                        //!< String length.
  size_t _capacity;                      //!< String capacity.
  size_t _canFree;                       //!< If the string data can be freed.
247
248
249
};

// ============================================================================
250
// [asmjit::StringBuilderTmp]
251
252
// ============================================================================

253
//! Temporary string builder, has statically allocated `N` bytes.
254
template<size_t N>
255
256
257
class StringBuilderTmp : public StringBuilder {
public:
  ASMJIT_NONCOPYABLE(StringBuilderTmp<N>)
258
259
260
261
262

  // --------------------------------------------------------------------------
  // [Construction / Destruction]
  // --------------------------------------------------------------------------

263
  ASMJIT_INLINE StringBuilderTmp() noexcept : StringBuilder(NoInit) {
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
    _data = _embeddedData;
    _data[0] = 0;

    _length = 0;
    _capacity = N;
    _canFree = false;
  }

  // --------------------------------------------------------------------------
  // [Members]
  // --------------------------------------------------------------------------

  //! Embedded data.
  char _embeddedData[static_cast<size_t>(
    N + 1 + sizeof(intptr_t)) & ~static_cast<size_t>(sizeof(intptr_t) - 1)];
};

//! \}

} // asmjit namespace

// [Api-End]
286
#include "../asmjit_apiend.h"
287
288
289

// [Guard]
#endif // _ASMJIT_BASE_STRING_H