Zydis  master
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
53 extern "C" {
54 #endif
55 
56 /* ============================================================================================== */
57 /* Enums and types */
58 /* ============================================================================================== */
59 
60 /* ---------------------------------------------------------------------------------------------- */
61 /* Letter Case */
62 /* ---------------------------------------------------------------------------------------------- */
63 
67 typedef enum ZydisLetterCase_
68 {
81 
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 
132 ZYAN_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 
162 ZYAN_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  {
180  break;
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  }
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 
231 ZYAN_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;
248 
249  return ZYAN_STATUS_SUCCESS;
250 }
251 
262 ZYAN_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  {
280  break;
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  }
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;
319 
320  return ZYAN_STATUS_SUCCESS;
321 }
322 
323 /* ---------------------------------------------------------------------------------------------- */
324 /* Formatting */
325 /* ---------------------------------------------------------------------------------------------- */
326 
343 ZyanStatus ZydisStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
344  const ZyanStringView* prefix, const ZyanStringView* suffix);
345 
363 ZYAN_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 
409 ZyanStatus ZydisStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
410  ZyanBool force_leading_number, ZyanBool uppercase, const ZyanStringView* prefix,
411  const ZyanStringView* suffix);
412 
435 ZYAN_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
Defines the immutable and storage-efficient ZydisShortString struct, which is used to store strings i...
#define ZYDIS_MAKE_SHORTSTRING(string)
Declares a ZydisShortString from a static C-style string.
Definition: ShortString.h:84
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_
Defines the ZydisLetterCase enum.
Definition: String.h:68
@ ZYDIS_LETTER_CASE_UPPER
Converts the given text to uppercase letters.
Definition: String.h:80
@ 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
Maximum value of this enum.
Definition: String.h:85
@ ZYDIS_LETTER_CASE_DEFAULT
Uses the given text "as is".
Definition: String.h:72
@ ZYDIS_LETTER_CASE_LOWER
Converts the given text to lowercase letters.
Definition: String.h:76
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
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
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
enum ZydisLetterCase_ ZydisLetterCase
Defines the ZydisLetterCase enum.
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...
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
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...
#define ZYDIS_STRING_NULLTERMINATE(string)
Writes a terminating '\0' character at the end of the string data.
Definition: String.h:111
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
#define ZYDIS_STRING_ASSERT_NULLTERMINATION(string)
Checks for a terminating '\0' character at the end of the string data.
Definition: String.h:105
Defines the ZydisShortString struct.
Definition: ShortString.h:60
ZyanU8 size
The length (number of characters) of the string (without 0-termination).
Definition: ShortString.h:68
const char * data
The buffer that contains the actual (null-terminated) string.
Definition: ShortString.h:64