Zydis: include/Zydis/Internal/String.h Source File

Zydis v4.0.0

Loading...
Searching...
No Matches
String.h
Go to the documentation of this file.
1/***************************************************************************************************
2
3 Zyan Disassembler Library (Zydis)
4
5 Original Author : Florian Bernd, Joel Hoener
6
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24
25***************************************************************************************************/
26
40#ifndef ZYDIS_INTERNAL_STRING_H
41#define ZYDIS_INTERNAL_STRING_H
42
43#include <Zycore/LibC.h>
44#include <Zycore/String.h>
45#include <Zycore/Types.h>
46#include <Zycore/Format.h>
47#include <Zydis/ShortString.h>
48#include <Zycore/Defines.h>
49#include <Zycore/Status.h>
50#include <Zycore/Vector.h>
51
52#ifdef __cplusplus
53extern "C" {
54#endif
55
56/* ============================================================================================== */
57/* Enums and types */
58/* ============================================================================================== */
59
60/* ---------------------------------------------------------------------------------------------- */
61/* Letter Case */
62/* ---------------------------------------------------------------------------------------------- */
63
67 typedef enum ZydisLetterCase_
68{
72 ZYDIS_LETTER_CASE_DEFAULT,
76 ZYDIS_LETTER_CASE_LOWER,
80 ZYDIS_LETTER_CASE_UPPER,
81
85 ZYDIS_LETTER_CASE_MAX_VALUE = ZYDIS_LETTER_CASE_UPPER,
89 ZYDIS_LETTER_CASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_LETTER_CASE_MAX_VALUE)
90} ZydisLetterCase;
91
92/* ---------------------------------------------------------------------------------------------- */
93
94/* ============================================================================================== */
95/* Macros */
96/* ============================================================================================== */
97
98/* ---------------------------------------------------------------------------------------------- */
99/* Internal macros */
100/* ---------------------------------------------------------------------------------------------- */
101
105#define ZYDIS_STRING_ASSERT_NULLTERMINATION(string) \
106 ZYAN_ASSERT(*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) == '\0');
107
111#define ZYDIS_STRING_NULLTERMINATE(string) \
112 *(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) = '\0';
113
114/* ---------------------------------------------------------------------------------------------- */
115
116/* ============================================================================================== */
117/* Internal Functions */
118/* ============================================================================================== */
119
120/* ---------------------------------------------------------------------------------------------- */
121/* Appending */
122/* ---------------------------------------------------------------------------------------------- */
123
132ZYAN_INLINE ZyanStatus ZydisStringAppend(ZyanString* destination, const ZyanStringView* source)
133{
134 ZYAN_ASSERT(destination && source);
135 ZYAN_ASSERT(!destination->vector.allocator);
136 ZYAN_ASSERT(destination->vector.size && source->string.vector.size);
137
138 if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity)
139 {
140 return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
141 }
142
143 ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1,
144 source->string.vector.data, source->string.vector.size - 1);
145
146 destination->vector.size += source->string.vector.size - 1;
147 ZYDIS_STRING_NULLTERMINATE(destination);
148
149 return ZYAN_STATUS_SUCCESS;
150}
151
162ZYAN_INLINE ZyanStatus ZydisStringAppendCase(ZyanString* destination, const ZyanStringView* source,
163 ZydisLetterCase letter_case)
164{
165 ZYAN_ASSERT(destination && source);
166 ZYAN_ASSERT(!destination->vector.allocator);
167 ZYAN_ASSERT(destination->vector.size && source->string.vector.size);
168
169 if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity)
170 {
171 return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
172 }
173
174 ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1,
175 source->string.vector.data, source->string.vector.size - 1);
176
177 switch (letter_case)
178 {
179 case ZYDIS_LETTER_CASE_DEFAULT:
180 break;
181 case ZYDIS_LETTER_CASE_LOWER:
182 {
183 const ZyanUSize index = destination->vector.size - 1;
184 const ZyanUSize count = source->string.vector.size - 1;
185 char* s = (char*)destination->vector.data + index;
186 for (ZyanUSize i = index; i < index + count; ++i)
187 {
188 const char c = *s;
189 if ((c >= 'A') && (c <= 'Z'))
190 {
191 *s = c | 32;
192 }
193 ++s;
194 }
195 break;
196 }
197 case ZYDIS_LETTER_CASE_UPPER:
198 {
199 const ZyanUSize index = destination->vector.size - 1;
200 const ZyanUSize count = source->string.vector.size - 1;
201 char* s = (char*)destination->vector.data + index;
202 for (ZyanUSize i = index; i < index + count; ++i)
203 {
204 const char c = *s;
205 if ((c >= 'a') && (c <= 'z'))
206 {
207 *s = c & ~32;
208 }
209 ++s;
210 }
211 break;
212 }
213 default:
214 ZYAN_UNREACHABLE;
215 }
216
217 destination->vector.size += source->string.vector.size - 1;
218 ZYDIS_STRING_NULLTERMINATE(destination);
219
220 return ZYAN_STATUS_SUCCESS;
221}
222
231ZYAN_INLINE ZyanStatus ZydisStringAppendShort(ZyanString* destination,
232 const ZydisShortString* source)
233{
234 ZYAN_ASSERT(destination && source);
235 ZYAN_ASSERT(!destination->vector.allocator);
236 ZYAN_ASSERT(destination->vector.size && source->size);
237
238 if (destination->vector.size + source->size > destination->vector.capacity)
239 {
240 return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
241 }
242
243 ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data,
244 (ZyanUSize)source->size + 1);
245
246 destination->vector.size += source->size;
247 ZYDIS_STRING_ASSERT_NULLTERMINATION(destination);
248
249 return ZYAN_STATUS_SUCCESS;
250}
251
262ZYAN_INLINE ZyanStatus ZydisStringAppendShortCase(ZyanString* destination,
263 const ZydisShortString* source, ZydisLetterCase letter_case)
264{
265 ZYAN_ASSERT(destination && source);
266 ZYAN_ASSERT(!destination->vector.allocator);
267 ZYAN_ASSERT(destination->vector.size && source->size);
268
269 if (destination->vector.size + source->size > destination->vector.capacity)
270 {
271 return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
272 }
273
274 ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data,
275 (ZyanUSize)source->size + 1);
276
277 switch (letter_case)
278 {
279 case ZYDIS_LETTER_CASE_DEFAULT:
280 break;
281 case ZYDIS_LETTER_CASE_LOWER:
282 {
283 const ZyanUSize index = destination->vector.size - 1;
284 const ZyanUSize count = source->size;
285 char* s = (char*)destination->vector.data + index;
286 for (ZyanUSize i = index; i < index + count; ++i)
287 {
288 const char c = *s;
289 if ((c >= 'A') && (c <= 'Z'))
290 {
291 *s = c | 32;
292 }
293 ++s;
294 }
295 break;
296 }
297 case ZYDIS_LETTER_CASE_UPPER:
298 {
299 const ZyanUSize index = destination->vector.size - 1;
300 const ZyanUSize count = source->size;
301 char* s = (char*)destination->vector.data + index;
302 for (ZyanUSize i = index; i < index + count; ++i)
303 {
304 const char c = *s;
305 if ((c >= 'a') && (c <= 'z'))
306 {
307 *s = c & ~32;
308 }
309 ++s;
310 }
311 break;
312 }
313 default:
314 ZYAN_UNREACHABLE;
315 }
316
317 destination->vector.size += source->size;
318 ZYDIS_STRING_ASSERT_NULLTERMINATION(destination);
319
320 return ZYAN_STATUS_SUCCESS;
321}
322
323/* ---------------------------------------------------------------------------------------------- */
324/* Formatting */
325/* ---------------------------------------------------------------------------------------------- */
326
343ZyanStatus ZydisStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
344 const ZyanStringView* prefix, const ZyanStringView* suffix);
345
363ZYAN_INLINE ZyanStatus ZydisStringAppendDecS(ZyanString* string, ZyanI64 value,
364 ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix,
365 const ZyanStringView* suffix)
366{
367 static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+");
368 static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-");
369
370 if (value < 0)
371 {
372 ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub));
373 if (prefix)
374 {
375 ZYAN_CHECK(ZydisStringAppend(string, prefix));
376 }
377 return ZydisStringAppendDecU(string, ZyanAbsI64(value), padding_length,
378 (const ZyanStringView*)ZYAN_NULL, suffix);
379 }
380
381 if (force_sign)
382 {
383 ZYAN_ASSERT(value >= 0);
384 ZYAN_CHECK(ZydisStringAppendShort(string, &str_add));
385 }
386 return ZydisStringAppendDecU(string, value, padding_length, prefix, suffix);
387}
388
409ZyanStatus ZydisStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
410 ZyanBool force_leading_number, ZyanBool uppercase, const ZyanStringView* prefix,
411 const ZyanStringView* suffix);
412
435ZYAN_INLINE ZyanStatus ZydisStringAppendHexS(ZyanString* string, ZyanI64 value,
436 ZyanU8 padding_length, ZyanBool force_leading_number, ZyanBool uppercase, ZyanBool force_sign,
437 const ZyanStringView* prefix, const ZyanStringView* suffix)
438{
439 static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+");
440 static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-");
441
442 if (value < 0)
443 {
444 ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub));
445 if (prefix)
446 {
447 ZYAN_CHECK(ZydisStringAppend(string, prefix));
448 }
449 return ZydisStringAppendHexU(string, ZyanAbsI64(value), padding_length,
450 force_leading_number, uppercase, (const ZyanStringView*)ZYAN_NULL, suffix);
451 }
452
453 if (force_sign)
454 {
455 ZYAN_ASSERT(value >= 0);
456 ZYAN_CHECK(ZydisStringAppendShort(string, &str_add));
457 }
458 return ZydisStringAppendHexU(string, value, padding_length, force_leading_number, uppercase,
459 prefix, suffix);
460}
461
462/* ---------------------------------------------------------------------------------------------- */
463
464/* ============================================================================================== */
465
466#ifdef __cplusplus
467}
468#endif
469
470#endif // ZYDIS_INTERNAL_STRING_H
ShortString.h
Defines the immutable and storage-efficient ZydisShortString struct, which is used to store strings i...
ZYDIS_MAKE_SHORTSTRING
#define ZYDIS_MAKE_SHORTSTRING(string)
Declares a ZydisShortString from a static C-style string.
Definition: ShortString.h:84
ZydisStringAppendHexS
ZYAN_INLINE ZyanStatus ZydisStringAppendHexS(ZyanString *string, ZyanI64 value, ZyanU8 padding_length, ZyanBool force_leading_number, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView *prefix, const ZyanStringView *suffix)
Formats the given signed ordinal value to its hexadecimal text-representation and appends it to the s...
Definition: String.h:435
ZydisLetterCase_
ZydisLetterCase_
Defines the ZydisLetterCase enum.
Definition: String.h:68
ZYDIS_LETTER_CASE_UPPER
@ ZYDIS_LETTER_CASE_UPPER
Converts the given text to uppercase letters.
Definition: String.h:80
ZYDIS_LETTER_CASE_REQUIRED_BITS
@ ZYDIS_LETTER_CASE_REQUIRED_BITS
The minimum number of bits required to represent all values of this enum.
Definition: String.h:89
ZYDIS_LETTER_CASE_MAX_VALUE
@ ZYDIS_LETTER_CASE_MAX_VALUE
Maximum value of this enum.
Definition: String.h:85
ZYDIS_LETTER_CASE_DEFAULT
@ ZYDIS_LETTER_CASE_DEFAULT
Uses the given text "as is".
Definition: String.h:72
ZYDIS_LETTER_CASE_LOWER
@ ZYDIS_LETTER_CASE_LOWER
Converts the given text to lowercase letters.
Definition: String.h:76
ZydisStringAppendDecS
ZYAN_INLINE ZyanStatus ZydisStringAppendDecS(ZyanString *string, ZyanI64 value, ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView *prefix, const ZyanStringView *suffix)
Formats the given signed ordinal value to its decimal text-representation and appends it to the strin...
Definition: String.h:363
ZydisStringAppendCase
ZYAN_INLINE ZyanStatus ZydisStringAppendCase(ZyanString *destination, const ZyanStringView *source, ZydisLetterCase letter_case)
Appends the content of the source string to the end of the destination string, converting the charact...
Definition: String.h:162
ZydisStringAppendShortCase
ZYAN_INLINE ZyanStatus ZydisStringAppendShortCase(ZyanString *destination, const ZydisShortString *source, ZydisLetterCase letter_case)
Appends the content of the source short-string to the end of the destination string,...
Definition: String.h:262
ZydisLetterCase
enum ZydisLetterCase_ ZydisLetterCase
Defines the ZydisLetterCase enum.
ZydisStringAppendDecU
ZyanStatus ZydisStringAppendDecU(ZyanString *string, ZyanU64 value, ZyanU8 padding_length, const ZyanStringView *prefix, const ZyanStringView *suffix)
Formats the given unsigned ordinal value to its decimal text-representation and appends it to the str...
ZydisStringAppendShort
ZYAN_INLINE ZyanStatus ZydisStringAppendShort(ZyanString *destination, const ZydisShortString *source)
Appends the content of the source short-string to the end of the destination string.
Definition: String.h:231
ZydisStringAppendHexU
ZyanStatus ZydisStringAppendHexU(ZyanString *string, ZyanU64 value, ZyanU8 padding_length, ZyanBool force_leading_number, ZyanBool uppercase, const ZyanStringView *prefix, const ZyanStringView *suffix)
Formats the given unsigned ordinal value to its hexadecimal text-representation and appends it to the...
ZYDIS_STRING_NULLTERMINATE
#define ZYDIS_STRING_NULLTERMINATE(string)
Writes a terminating '\0' character at the end of the string data.
Definition: String.h:111
ZydisStringAppend
ZYAN_INLINE ZyanStatus ZydisStringAppend(ZyanString *destination, const ZyanStringView *source)
Appends the content of the source string to the end of the destination string.
Definition: String.h:132
ZYDIS_STRING_ASSERT_NULLTERMINATION
#define ZYDIS_STRING_ASSERT_NULLTERMINATION(string)
Checks for a terminating '\0' character at the end of the string data.
Definition: String.h:105
ZydisShortString_
Defines the ZydisShortString struct.
Definition: ShortString.h:60
ZydisShortString_::size
ZyanU8 size
The length (number of characters) of the string (without 0-termination).
Definition: ShortString.h:68
ZydisShortString_::data
const char * data
The buffer that contains the actual (null-terminated) string.
Definition: ShortString.h:64