Harmonic Flow Framework (libhffwk)
Cross platform C++ 2D Game Engine Framework
UString.cpp
1 /*
2  Harmonic Flow Framework
3  Copyright (C) 2011-2018 Andreas Widen <andreas@harmonicflow.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "UString.h"
22 
23 #include <assert.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <wchar.h>
28 #include <wctype.h>
29 
30 using namespace HFCore;
31 
32 #include "debug/CrtDbgNew.h"
33 
34 #define MASK_1BYTE 0x80 /* 1000 0000 */
35 #define VALUE_1BYTE 0x00 /* 0000 0000 */
36 #define MASK_2BYTE 0xE0 /* 1110 0000 */
37 #define VALUE_2BYTE 0xC0 /* 1100 0000 */
38 #define MASK_3BYTE 0xF0 /* 1111 0000 */
39 #define VALUE_3BYTE 0xE0 /* 1110 0000 */
40 #define MASK_4BYTE 0xF8 /* 1111 1000 */
41 #define VALUE_4BYTE 0xF0 /* 1111 0000 */
42 #define MASK_5BYTE 0xFC /* 1111 1100 */
43 #define VALUE_5BYTE 0xF8 /* 1111 1000 */
44 #define MASK_6BYTE 0xFE /* 1111 1110 */
45 #define VALUE_6BYTE 0xFC /* 1111 1100 */
46 
47 #define MASK_MULTIBYTE 0x3F /* 0011 1111 */
48 
50 {
51  mUnicode = NULL;
52  mLength = 0;
53  mUtf8 = NULL;
54  mIsAsciiOnly = false;
55 }
56 
58 {
59  fromUtf8(utf8);
60 }
61 
63 {
64  mUnicode = NULL;
65  mLength = 0;
66  mUtf8 = NULL;
67  (*this) = ustr;
68 }
69 
70 UString::UString(const wchar_t *str)
71 {
72  // get length:
73  mLength = (int32_hf)wcslen(str);
74 
75  // allocate new mem for unicode data:
76  mUnicode = new wchar_t[mLength + 1];
77 
78  // initialize:
79  memset(mUnicode, 0, (mLength + 1) * sizeof(wchar_t));
80 
81  // copy contents and null terminate:
82  memcpy(mUnicode, str, (mLength + 1) * sizeof(wchar_t));
83 
84  // null out the utf version
85  mUtf8 = NULL;
86 }
87 
89 {
90  HF_SAFE_DELETE_ARR(mUnicode);
91  HF_SAFE_DELETE_ARR(mUtf8);
92 }
93 
94 UString UString::format(const int8_hf *utf8format, ...)
95 {
96  // decode the utf8 string:
97  UString formatted;
98  int32_hf bufSize = formatted.fromUtf8(utf8format) + 2;
99 
100  // print the args to the format:
101  wchar_t *buf = NULL;
102  int32_hf written = -1;
103  while (true)
104  {
105  buf = new wchar_t[bufSize];
106  memset(buf, 0, bufSize * sizeof(wchar_t));
107 
108  va_list ap;
109  va_start(ap, utf8format);
110 #ifdef __MINGW32__
111  written = vsnwprintf(buf, bufSize, formatted.mUnicode, ap);
112 #else
113  written = vswprintf(buf, bufSize, formatted.mUnicode, ap);
114 #endif
115  va_end(ap);
116 
117  // if we didn't use the entire buffer:
118  if (written > 0 && written < bufSize)
119  {
120  // cool, keep the formatted string and move on:
121  HF_SAFE_DELETE_ARR(formatted.mUnicode);
122  formatted.mUnicode = buf;
123  formatted.mLength = written;
124  formatted.updateUtf8();
125  break;
126  }
127  else
128  {
129  // we need a larger buffer:
130  HF_SAFE_DELETE_ARR(buf);
131  bufSize *= 2;
132  }
133  }
134 
135  return formatted;
136 }
137 
139 {
140  assert(utf8 != NULL);
141 
142  int32_hf startIndex = 0;
143  if (utf8[0] == (int8_hf)0xef && utf8[1] == (int8_hf)0xbb && utf8[2] == (int8_hf)0xbf) // utf-8
144  {
145  startIndex = 3;
146  }
147  else
148  {
149  int8_hf c0 = utf8[0];
150  int8_hf c1 = utf8[1];
151  int8_hf c2 = utf8[2];
152  int8_hf c3 = utf8[3];
153  bool utf16le = (c0 == (int8_hf)0xff && c1 == (int8_hf)0xfe && c2 != (int8_hf)0x00);
154  bool utf16be = (c0 == (int8_hf)0xfe && c1 == (int8_hf)0xff && c2 != (int8_hf)0x00);
155  bool utf32le = (c0 == (int8_hf)0xff && c1 == (int8_hf)0xfe && c2 == (int8_hf)0x00 &&
156  c3 == (int8_hf)0x00);
157  bool utf32be = (c0 == (int8_hf)0x00 && c1 == (int8_hf)0x00 && c2 == (int8_hf)0xfe &&
158  c3 == (int8_hf)0xff);
159  if (utf16le || utf16be || utf32le || utf32be)
160  {
161  // UTF-16/32 not yet supported:
162  assert(false);
163  }
164  }
165 
166  mLength = decode(&(utf8[startIndex]), NULL);
167  mUnicode = new wchar_t[mLength + 1];
168  memset(mUnicode, 0, (mLength + 1) * sizeof(wchar_t));
169  mUtf8 = NULL;
170  int32_hf length = decode(&(utf8[startIndex]), mUnicode);
171 
172  // reencode to utf8:
173  updateUtf8();
174 
175  return length;
176 }
177 
179 {
180  return mLength;
181 }
182 
183 UString UString::substr(int32_hf offset, int32_hf charCount) const
184 {
185  UString str;
186 
187  if (charCount < 0)
188  {
189  charCount = mLength - offset;
190  }
191 
192  // allocate new mem:
193  str.mLength = charCount;
194  str.mUnicode = new wchar_t[charCount + 1];
195 
196  // initialize:
197  memset(str.mUnicode, 0, (charCount + 1) * sizeof(wchar_t));
198 
199  // copy mem contents and null terminate:
200  memcpy(str.mUnicode, &(mUnicode[offset]), charCount * sizeof(wchar_t));
201  str.mUnicode[charCount] = 0;
202 
203  // update the substring's utf encoding:
204  str.updateUtf8();
205 
206  return str;
207 }
208 
209 wchar_t UString::operator [](int32_hf index) const
210 {
211  assert(index < mLength);
212  return mUnicode[index];
213 }
214 
215 int32_hf UString::decode(const int8_hf *utf8, wchar_t *unicode)
216 {
217  int32_hf length = 0;
218  for (int32_hf i = 0; utf8[i] != 0; i++)
219  {
220  int8_hf b = utf8[i];
221  if ((b & MASK_1BYTE) == VALUE_1BYTE) // if this is a single byte code point
222  {
223  if (unicode != NULL)
224  {
225  unicode[length] = b;
226  }
227  }
228  else if ((b & MASK_2BYTE) == VALUE_2BYTE) // if this is a 2 byte code point
229  {
230  if (unicode != NULL)
231  {
232  unicode[length] = getCodePoint(utf8, i, 2, (uint8_hf)~MASK_2BYTE);
233  }
234  i += 1;
235  }
236  else if ((b & MASK_3BYTE) == VALUE_3BYTE) // if this is a 3 byte code point
237  {
238  if (unicode != NULL)
239  {
240  unicode[length] = getCodePoint(utf8, i, 3, (uint8_hf)~MASK_3BYTE);
241  }
242  i += 2;
243  }
244  else if ((b & MASK_4BYTE) == VALUE_4BYTE) // if this is a 4 byte code point
245  {
246  if (unicode != NULL)
247  {
248  unicode[length] = getCodePoint(utf8, i, 4, (uint8_hf)~MASK_4BYTE);
249  }
250  i += 3;
251  }
252  else if ((b & MASK_5BYTE) == VALUE_5BYTE) // if this is a 5 byte code point
253  {
254  if (unicode != NULL)
255  {
256  unicode[length] = getCodePoint(utf8, i, 5, (uint8_hf)~MASK_5BYTE);
257  }
258  i += 4;
259  }
260  else if ((b & MASK_6BYTE) == VALUE_6BYTE) // if this is a 6 byte code point
261  {
262  if (unicode != NULL)
263  {
264  unicode[length] = getCodePoint(utf8, i, 6, (uint8_hf)~MASK_6BYTE);
265  }
266  i += 5;
267  }
268 
269  length++;
270  }
271 
272  if (unicode != NULL)
273  {
274  // null terminate:
275  unicode[length] = 0;
276  }
277 
278  return length;
279 }
280 
281 wchar_t UString::getCodePoint(const int8_hf *utf8, int32_hf offset, int32_hf numBytes,
282  uint8_hf firstByteMask)
283 {
284  // get the bits out of the first byte:
285  wchar_t wc = utf8[offset] & firstByteMask;
286 
287  // iterate over the rest of the bytes:
288  for (int32_hf i = 1; i < numBytes; i++)
289  {
290  // shift the code point bits to make room for the new bits:
291  wc = wc << 6;
292 
293  // add the new bits:
294  wc |= utf8[offset + i] & MASK_MULTIBYTE;
295  }
296 
297  // return the code point:
298  return wc;
299 }
300 
302 {
303  wchar_t *newUnicode = NULL;
304 
305  // if this is not a null string:
306  if (ustr.mLength > 0)
307  {
308  // allocate new mem for unicode data:
309  newUnicode = new wchar_t[ustr.mLength + 1];
310 
311  // initialize:
312  memset(newUnicode, 0, (ustr.mLength + 1) * sizeof(wchar_t));
313 
314  // copy unicode mem contents:
315  memcpy(newUnicode, ustr.mUnicode, (ustr.mLength + 1)*sizeof(wchar_t));
316  }
317 
318  // deallocate old mem:
319  HF_SAFE_DELETE_ARR(mUnicode);
320 
321  // init variables:
322  mLength = ustr.mLength;
323  mUnicode = newUnicode;
324 
325  // reencode to utf8:
326  updateUtf8();
327 
328  return *this;
329 }
330 
331 bool UString::operator != (const UString &ustr) const
332 {
333  bool equal = (*this == ustr);
334  return !equal;
335 }
336 
337 bool UString::operator == (const UString &ustr) const
338 {
339  if (mLength != ustr.mLength)
340  {
341  return false;
342  }
343 
344  return memcmp(mUnicode, ustr.mUnicode, mLength * sizeof(wchar_t)) == 0;
345 }
346 
347 bool UString::operator < (const UString &ustr) const
348 {
349  for (int32_hf i = 0; i < mLength && i < ustr.mLength; i++)
350  {
351  if (mUnicode[i] != ustr.mUnicode[i])
352  {
353  return mUnicode[i] < ustr.mUnicode[i];
354  }
355  }
356 
357  if (mLength == ustr.mLength)
358  {
359  return false;
360  }
361 
362  return mLength < ustr.mLength;
363 }
364 
365 void UString::append(const UString &str)
366 {
367  if (str.mLength == 0)
368  {
369  return;
370  }
371 
372  // calculate new size:
373  int32_hf newSize = mLength + str.mLength;
374 
375  // allocate new data buffer:
376  wchar_t *newUnicode = new wchar_t[newSize + 1];
377 
378  // initialize:
379  memset(newUnicode, 0, (newSize + 1) * sizeof(wchar_t));
380 
381  // copy existing data:
382  memcpy(newUnicode, mUnicode, mLength * sizeof(wchar_t));
383 
384  // copy appended data: (+1 for null termination)
385  memcpy(&(newUnicode[mLength]), str.mUnicode, (str.mLength + 1)*sizeof(wchar_t));
386 
387  // replace the old values with the new:
388  HF_SAFE_DELETE_ARR(mUnicode);
389  mUnicode = newUnicode;
390  mLength = newSize;
391 
392  // reencode to utf8:
393  updateUtf8();
394 }
395 
396 void UString::insert(int32_hf offset, const UString &str)
397 {
398  // calculate new size:
399  int32_hf newSize = mLength + str.mLength;
400 
401  // allocate new data buffer:
402  wchar_t *newUnicode = new wchar_t[newSize + 1];
403 
404  // initialize:
405  memset(newUnicode, 0, (newSize + 1) * sizeof(wchar_t));
406 
407  // if we're not inserting at the beginning of the string:
408  if (offset > 0)
409  {
410  // copy first part of data:
411  memcpy(newUnicode, mUnicode, offset * sizeof(wchar_t));
412  }
413 
414  // copy inserted string:
415  memcpy(&(newUnicode[offset]), str.mUnicode, str.mLength * sizeof(wchar_t));
416 
417  // if we're not inserting at the end of the string:
418  if (offset < mLength)
419  {
420  // copy rest of string: (+1 for null termination)
421  memcpy(&(newUnicode[offset + str.mLength]), &(mUnicode[offset]),
422  (mLength - offset + 1)*sizeof(wchar_t));
423  }
424  else
425  {
426  // just null terminate it:
427  newUnicode[newSize] = 0;
428  }
429 
430  // replace the old values with the new:
431  HF_SAFE_DELETE_ARR(mUnicode);
432  mUnicode = newUnicode;
433  mLength = newSize;
434 
435  // reencode to utf8:
436  updateUtf8();
437 }
438 
439 void UString::insert(int32_hf offset, wchar_t ch)
440 {
441  // calculate new size:
442  int32_hf newSize = mLength + 1;
443 
444  // allocate new data buffer:
445  wchar_t *newUnicode = new wchar_t[newSize];
446 
447  // initialize:
448  memset(newUnicode, 0, newSize * sizeof(wchar_t));
449 
450  // copy first part of data:
451  memcpy(newUnicode, mUnicode, offset * sizeof(wchar_t));
452 
453  // place the inserted char:
454  newUnicode[offset] = ch;
455 
456  // copy rest of string: (+1 for null termination)
457  memcpy(&(newUnicode[offset + 1]), &(mUnicode[offset]), (mLength - offset + 1)*sizeof(wchar_t));
458 
459  // replace the old values with the new:
460  HF_SAFE_DELETE_ARR(mUnicode);
461  mUnicode = newUnicode;
462  mLength = newSize;
463 
464  // reencode to utf8:
465  updateUtf8();
466 }
467 
468 #define ESCAPE_CHAR '\\'
469 int32_hf UString::findChar(wchar_t ch, int32_hf start, bool respectEscapeChars) const
470 {
471  bool escaped = false;
472  for (int32_hf i = start; i < mLength; i++)
473  {
474  // if we're respecting escape chars AND we are not in an escape
475  // sequence AND we've found an escape character:
476  if (respectEscapeChars && !escaped && mUnicode[i] == ESCAPE_CHAR)
477  {
478  // now we're in an escape sequence:
479  escaped = true;
480  }
481  else
482  {
483  if (!escaped && mUnicode[i] == ch)
484  {
485  return i;
486  }
487  escaped = false;
488  }
489  }
490 
491  return -1;
492 }
493 
494 int32_hf UString::findChar(const UString &str, int32_hf start, bool respectEscapeChars) const
495 {
496  bool escaped = false;
497  for (int32_hf i = start; i < mLength; i++)
498  {
499  // if we're respecting escape chars AND we are not in an escape
500  // sequence AND we've found an escape character:
501  if (respectEscapeChars && !escaped && mUnicode[i] == ESCAPE_CHAR)
502  {
503  // now we're in an escape sequence:
504  escaped = true;
505  }
506  else
507  {
508  if (!escaped && str.findChar(mUnicode[i]) >= 0)
509  {
510  return i;
511  }
512  escaped = false;
513  }
514  }
515 
516  return -1;
517 }
518 
519 int32_hf UString::find(const UString &str, int32_hf start) const
520 {
521  int32_hf lastPossibleMatch = mLength - str.mLength;
522  for (int32_hf i = start; i <= lastPossibleMatch; i++)
523  {
524  if (memcmp(&(mUnicode[i]), str.mUnicode, str.mLength * sizeof(*mUnicode)) == 0)
525  {
526  return i;
527  }
528  }
529 
530  return -1;
531 }
532 
533 void UString::erase(int32_hf offset, int32_hf count)
534 {
535  // calculate new size:
536  int32_hf newLength = mLength - count;
537 
538  // allocate new data buffer:
539  wchar_t *newUnicode = new wchar_t[newLength + 1];
540 
541  // initialize:
542  memset(newUnicode, 0, (newLength + 1) * sizeof(wchar_t));
543 
544  // copy first part of data:
545  memcpy(newUnicode, mUnicode, offset * sizeof(wchar_t));
546 
547  // copy rest of string: (including terminating zero character)
548  memcpy(&(newUnicode[offset]), &(mUnicode[offset + count]),
549  (newLength - offset + 1)*sizeof(wchar_t));
550 
551  // replace the old values with the new?
552  HF_SAFE_DELETE_ARR(mUnicode);
553  mUnicode = newUnicode;
554  mLength = newLength;
555 
556  // reencode to utf8:
557  updateUtf8();
558 }
559 
561 {
562  HF_SAFE_DELETE_ARR(mUnicode);
563 
564  mLength = 0;
565 
566  HF_SAFE_DELETE_ARR(mUtf8);
567 }
568 
570 {
571  return (fp32_hf)atof(mUtf8);
572 }
573 
574 const int8_hf *UString::toUtf8() const
575 {
576  return mUtf8;
577 }
578 
579 const wchar_t *UString::wc_str() const
580 {
581  return mUnicode;
582 }
583 
584 void UString::updateUtf8()
585 {
586  HF_SAFE_DELETE_ARR(mUtf8);
587 
588  int32_hf size = encode(mUnicode, mLength, NULL, &mIsAsciiOnly);
589  if (size > 0)
590  {
591  mUtf8 = new int8_hf[size + 1];
592  memset(mUtf8, 0, (size + 1) * sizeof(int8_hf));
593  encode(mUnicode, mLength, mUtf8, NULL);
594  mUtf8[size] = 0; // null terminate
595  }
596  else
597  {
598  mUtf8 = new int8_hf[1];
599  mUtf8[0] = 0; // null terminate the string
600  }
601 }
602 
603 int32_hf UString::encode(const wchar_t *unicode, int32_hf length, int8_hf *utf8,
604  bool *isAsciiOnly) const
605 {
606  int32_hf utf8len = 0;
607  bool foundMultibyte = false;
608  for (int32_hf i = 0; i < length; i++)
609  {
610  wchar_t ch = unicode[i];
611 
612  assert(ch >= 0);
613 
614  if (ch < 0x00000080) // 1 byte
615  {
616  if (utf8 != NULL)
617  {
618  utf8[utf8len] = (int8_hf)ch;
619  }
620  utf8len += 1;
621  }
622  else if (ch < 0x00000800) // 2 bytes
623  {
624  if (utf8 != NULL)
625  {
626  getUtf8(ch, &(utf8[utf8len]), 2, VALUE_2BYTE);
627  }
628  utf8len += 2;
629  foundMultibyte = true;
630  }
631  else if (ch < 0x00010000) // 3 bytes
632  {
633  if (utf8 != NULL)
634  {
635  getUtf8(ch, &(utf8[utf8len]), 3, VALUE_3BYTE);
636  }
637  utf8len += 3;
638  foundMultibyte = true;
639  }
640  else if (ch < 0x00200000) // 4 bytes
641  {
642  if (utf8 != NULL)
643  {
644  getUtf8(ch, &(utf8[utf8len]), 4, VALUE_4BYTE);
645  }
646  utf8len += 4;
647  foundMultibyte = true;
648  }
649  else if (ch < 0x04000000) // 5 bytes
650  {
651  if (utf8 != NULL)
652  {
653  getUtf8(ch, &(utf8[utf8len]), 5, VALUE_5BYTE);
654  }
655  utf8len += 5;
656  foundMultibyte = true;
657  }
658  else // 6 bytes
659  {
660  if (utf8 != NULL)
661  {
662  getUtf8(ch, &(utf8[utf8len]), 6, VALUE_6BYTE);
663  }
664  utf8len += 6;
665  foundMultibyte = true;
666  }
667  }
668 
669  if (isAsciiOnly != NULL)
670  {
671  *isAsciiOnly = !foundMultibyte;
672  }
673 
674  return utf8len;
675 }
676 
677 void UString::getUtf8(wchar_t ch, int8_hf *utf8, int32_hf numBytes, int32_hf firstByteValue) const
678 {
679  for (int32_hf i = numBytes - 1; i > 0; i--)
680  {
681  // store the lowest bits in a utf8 byte:
682  utf8[i] = (ch & MASK_MULTIBYTE) | 0x80;
683  ch >>= 6;
684  }
685 
686  // store the remaining bits:
687  *utf8 = (firstByteValue | ch);
688 }
689 
691 {
692  int32_hf writeIndex = 0;
693  bool escaped = false;
694  wchar_t *buf = new wchar_t[mLength];
695  memset(buf, 0, mLength * sizeof(wchar_t));
696 
697  // iterate over the unicode string:
698  for (int32_hf readIndex = 0; readIndex < mLength; readIndex++)
699  {
700  // if we're not already escaped and this is an escape char:
701  if (!escaped && mUnicode[readIndex] == ESCAPE_CHAR)
702  {
703  // we're escaped:
704  escaped = true;
705  }
706  else
707  {
708  // move this char over and increment the write index:
709  buf[writeIndex] = mUnicode[readIndex];
710  writeIndex++;
711 
712  // we're no longer escaped:
713  escaped = false;
714  }
715  }
716 
717  // replace old data with new data:
718  HF_SAFE_DELETE_ARR(mUnicode);
719  mLength = writeIndex;
720  mUnicode = new wchar_t[mLength];
721  memset(mUnicode, 0, mLength * sizeof(wchar_t));
722  memcpy(mUnicode, buf, mLength * sizeof(wchar_t));
723 
724  // free the temporary buffer:
725  HF_SAFE_DELETE_ARR(buf);
726 
727  // the utf encoding is out of date, update it:
728  updateUtf8();
729 }
730 
732 {
733  return mIsAsciiOnly;
734 }
735 
737 {
738  int32_hf startPos = 0;
739  while (startPos < mLength && iswspace(mUnicode[startPos]))
740  {
741  startPos++;
742  }
743 
744  int32_hf endPos = mLength - 1;
745  while ((endPos >= 0) && (endPos < mLength) && iswspace(mUnicode[endPos]))
746  {
747  endPos--;
748  }
749 
750  return substr(startPos, endPos - startPos + 1);
751 }
int32_hf findChar(wchar_t ch, int32_hf start=0, bool respectEscapeChars=false) const
Find a char and return it&#39;s index if found or -1 if not.
Definition: UString.cpp:469
void erase(int32_hf offset, int32_hf count)
Erase count character/s at offset position.
Definition: UString.cpp:533
Interface for unicode string class UString.
Definition: UString.h:35
int int32_hf
A type definition for int.
Definition: HFDataTypes.h:349
bool operator!=(const UString &ustr) const
Overload of binary operator !=.
Definition: UString.cpp:331
UString & operator=(const UString &ustr)
Overload of binary operator =.
Definition: UString.cpp:301
const wchar_t * wc_str() const
Get the unicode widechar string.
Definition: UString.cpp:579
#define HF_SAFE_DELETE_ARR(p)
Check if not NULL, delete array and set to NULL.
Definition: HFDataTypes.h:56
bool operator<(const UString &ustr) const
Overload of operator < (less than).
Definition: UString.cpp:347
#define NULL
Convenient define for 0.
Definition: HFDataTypes.h:42
UString substr(int32_hf offset, int32_hf charCount=-1) const
Get a substring from offset to charCount.
Definition: UString.cpp:183
void collapseEscapes()
Collapse / remove ESCAPE CHAR&#39;s ("\\").
Definition: UString.cpp:690
int32_hf length() const
Get the length of the string.
Definition: UString.cpp:178
const int8_hf * toUtf8() const
Get the utf8 encoded string.
Definition: UString.cpp:574
char int8_hf
A type definition for char.
Definition: HFDataTypes.h:329
Interface for unicode string class UString.
void clear()
Clear string and free memory used internally.
Definition: UString.cpp:560
int32_hf find(const UString &str, int32_hf start=0) const
Find first index matching str or -1 if not found.
Definition: UString.cpp:519
void append(const UString &str)
Append str to internal string.
Definition: UString.cpp:365
bool isAsciiOnly()
Determine if string has Ascii only characters.
Definition: UString.cpp:731
wchar_t operator[](int32_hf index) const
Overload of subscript operator [].
Definition: UString.cpp:209
fp32_hf toFloat() const
Convert string to float.
Definition: UString.cpp:569
Definition: Actor.h:34
bool operator==(const UString &ustr) const
Overload of binary operator ==.
Definition: UString.cpp:337
UString trim()
Trim string left and right.
Definition: UString.cpp:736
void insert(int32_hf offset, const UString &str)
Insert str at offset position.
Definition: UString.cpp:396
UString()
Constructor.
Definition: UString.cpp:49
int32_hf fromUtf8(const int8_hf *utf8)
Create string from utf8 encoded string.
Definition: UString.cpp:138
unsigned char uint8_hf
A type definition for unsigned char.
Definition: HFDataTypes.h:334
virtual ~UString()
Destructor.
Definition: UString.cpp:88
static UString format(const int8_hf *utf8format,...)
Format a string.
Definition: UString.cpp:94
float fp32_hf
A type definition for float.
Definition: HFDataTypes.h:359