orx  1.10
Portable Game Engine
orxString.h
Go to the documentation of this file.
1 /* Orx - Portable Game Engine
2  *
3  * Copyright (c) 2008-2019 Orx-Project
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  *
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  * misrepresented as being the original software.
20  *
21  * 3. This notice may not be removed or altered from any source
22  * distribution.
23  */
24 
44 #ifndef _orxSTRING_H_
45 #define _orxSTRING_H_
46 
47 
48 #include "orxInclude.h"
49 #include "memory/orxMemory.h"
50 #include "math/orxVector.h"
51 
52 #ifdef __orxMSVC__
53 
54  #pragma warning(disable : 4996)
55 
56  #define strtoll _strtoi64
57  #define strtoull _strtoui64
58 
59 #endif /* __orxMSVC__ */
60 
61 #ifdef __orxIOS__
62  #define STRTO_CAST (int)
63 #else /* __orxIOS__ */
64  #define STRTO_CAST (size_t)
65 #endif /* __orxIOS__ */
66 
67 #include <stdio.h>
68 #include <stdarg.h>
69 #include <string.h>
70 #include <stdlib.h>
71 
72 #ifndef __orxWINDOWS__
73  #include <strings.h>
74 #endif /* !__orxWINDOWS__ */
75 
76 #include "debug/orxDebug.h"
77 
78 
79 #define orxSTRING_KC_VECTOR_START '('
80 #define orxSTRING_KC_VECTOR_START_ALT '{'
81 #define orxSTRING_KC_VECTOR_SEPARATOR ','
82 #define orxSTRING_KC_VECTOR_END ')'
83 #define orxSTRING_KC_VECTOR_END_ALT '}'
84 
85 
88 #define orxSTRING_KU32_CRC_POLYNOMIAL 0xEDB88320U
93 extern orxDLLAPI orxU32 saau32CRCTable[8][256];
94 
95 
96 /* *** String inlined functions *** */
97 
98 
103 static orxINLINE const orxSTRING orxString_SkipWhiteSpaces(const orxSTRING _zString)
104 {
105  const orxSTRING zResult;
106 
107  /* Non null? */
108  if(_zString != orxNULL)
109  {
110  /* Skips all white spaces */
111  for(zResult = _zString; (*zResult == ' ') || (*zResult == '\t'); zResult++);
112 
113  /* Empty? */
114  if(*zResult == orxCHAR_NULL)
115  {
116  /* Updates result */
117  zResult = orxSTRING_EMPTY;
118  }
119  }
120  else
121  {
122  /* Updates result */
123  zResult = orxNULL;
124  }
125 
126  /* Done! */
127  return zResult;
128 }
129 
134 static orxINLINE const orxSTRING orxString_SkipPath(const orxSTRING _zString)
135 {
136  const orxSTRING zResult;
137 
138  /* Non null? */
139  if(_zString != orxNULL)
140  {
141  const orxCHAR *pc;
142 
143  /* Updates result */
144  zResult = _zString;
145 
146  /* For all characters */
147  for(pc = _zString; *pc != orxCHAR_NULL; pc++)
148  {
149  /* Is a directory separator? */
151  {
152  orxCHAR cNextChar = *(pc + 1);
153 
154  /* Non terminal and not a directory separator? */
155  if((cNextChar != orxCHAR_NULL) && (cNextChar != orxCHAR_DIRECTORY_SEPARATOR_LINUX) && (cNextChar != orxCHAR_DIRECTORY_SEPARATOR_WINDOWS))
156  {
157  /* Updates result */
158  zResult = pc + 1;
159  }
160  }
161  }
162  }
163  else
164  {
165  /* Updates result */
166  zResult = orxNULL;
167  }
168 
169  /* Done! */
170  return zResult;
171 }
172 
177 static orxINLINE orxU32 orxString_GetLength(const orxSTRING _zString)
178 {
179  /* Checks */
180  orxASSERT(_zString != orxNULL);
181 
182  /* Done! */
183  return((orxU32)strlen(_zString));
184 }
185 
190 static orxINLINE orxBOOL orxString_IsCharacterASCII(orxU32 _u32CharacterCodePoint)
191 {
192  /* Done! */
193  return((_u32CharacterCodePoint < 0x80) ? orxTRUE : orxFALSE);
194 }
195 
200 static orxINLINE orxBOOL orxString_IsCharacterAlphaNumeric(orxU32 _u32CharacterCodePoint)
201 {
202  /* Done! */
203  return (((_u32CharacterCodePoint >= 'a') && (_u32CharacterCodePoint <= 'z'))
204  || ((_u32CharacterCodePoint >= 'A') && (_u32CharacterCodePoint <= 'Z'))
205  || ((_u32CharacterCodePoint >= '0') && (_u32CharacterCodePoint <= '9'))) ? orxTRUE : orxFALSE;
206 }
207 
212 static orxINLINE orxU32 orxString_GetUTF8CharacterLength(orxU32 _u32CharacterCodePoint)
213 {
214  orxU32 u32Result;
215 
216  /* 1-byte long? */
217  if(_u32CharacterCodePoint < 0x80)
218  {
219  /* Updates result */
220  u32Result = 1;
221  }
222  else if(_u32CharacterCodePoint < 0x0800)
223  {
224  /* Updates result */
225  u32Result = 2;
226  }
227  else if(_u32CharacterCodePoint < 0x00010000)
228  {
229  /* Updates result */
230  u32Result = 3;
231  }
232  else if(_u32CharacterCodePoint < 0x00110000)
233  {
234  /* Updates result */
235  u32Result = 4;
236  }
237  else
238  {
239  /* Updates result */
240  u32Result = orxU32_UNDEFINED;
241  }
242 
243  /* Done! */
244  return u32Result;
245 }
246 
253 static orxU32 orxFASTCALL orxString_PrintUTF8Character(orxSTRING _zDstString, orxU32 _u32Size, orxU32 _u32CharacterCodePoint)
254 {
255  orxU32 u32Result;
256 
257  /* Gets character's encoded length */
258  u32Result = orxString_GetUTF8CharacterLength(_u32CharacterCodePoint);
259 
260  /* Enough room? */
261  if(u32Result <= _u32Size)
262  {
263  /* Depending on character's length */
264  switch(u32Result)
265  {
266  case 1:
267  {
268  /* Writes character */
269  *_zDstString = (orxCHAR)_u32CharacterCodePoint;
270 
271  break;
272  }
273 
274  case 2:
275  {
276  /* Writes first character */
277  *_zDstString++ = (orxCHAR)(0xC0 | ((_u32CharacterCodePoint & 0x07C0) >> 6));
278 
279  /* Writes second character */
280  *_zDstString = (orxCHAR)(0x80 | (_u32CharacterCodePoint & 0x3F));
281 
282  break;
283  }
284 
285  case 3:
286  {
287  /* Writes first character */
288  *_zDstString++ = (orxCHAR)(0xE0 | ((_u32CharacterCodePoint & 0xF000) >> 12));
289 
290  /* Writes second character */
291  *_zDstString++ = (orxCHAR)(0x80 | ((_u32CharacterCodePoint & 0x0FC0) >> 6));
292 
293  /* Writes third character */
294  *_zDstString = (orxCHAR)(0x80 | (_u32CharacterCodePoint & 0x3F));
295 
296  break;
297  }
298 
299  case 4:
300  {
301  /* Writes first character */
302  *_zDstString++ = (orxCHAR)(0xF0 | ((_u32CharacterCodePoint & 0x001C0000) >> 18));
303 
304  /* Writes second character */
305  *_zDstString++ = (orxCHAR)(0x80 | ((_u32CharacterCodePoint & 0x0003F000) >> 12));
306 
307  /* Writes third character */
308  *_zDstString++ = (orxCHAR)(0x80 | ((_u32CharacterCodePoint & 0x00000FC0) >> 6));
309 
310  /* Writes fourth character */
311  *_zDstString = (orxCHAR)(0x80 | (_u32CharacterCodePoint & 0x3F));
312 
313  break;
314  }
315 
316  default:
317  {
318  /* Logs message */
319  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Can't print invalid unicode character <0x%X> to string.", _u32CharacterCodePoint);
320 
321  /* Updates result */
322  u32Result = orxU32_UNDEFINED;
323 
324  break;
325  }
326  }
327  }
328  else
329  {
330  /* Logs message */
331  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Can't print unicode character <0x%X> to string as there isn't enough space for it.", _u32CharacterCodePoint);
332 
333  /* Updates result */
334  u32Result = orxU32_UNDEFINED;
335  }
336 
337  /* Done! */
338  return u32Result;
339 }
340 
346 static orxU32 orxFASTCALL orxString_GetFirstCharacterCodePoint(const orxSTRING _zString, const orxSTRING *_pzRemaining)
347 {
348  orxU8 *pu8Byte;
349  orxU32 u32Result;
350 
351  /* Checks */
352  orxASSERT(_zString != orxNULL);
353 
354  /* Gets the first byte */
355  pu8Byte = (orxU8 *)_zString;
356 
357  /* ASCII? */
358  if(*pu8Byte < 0x80)
359  {
360  /* Updates result */
361  u32Result = *pu8Byte;
362  }
363  /* Invalid UTF-8 byte sequence */
364  else if(*pu8Byte < 0xC0)
365  {
366  /* Logs message */
367  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: multi-byte sequence non-leading byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
368 
369  /* Updates result */
370  u32Result = orxU32_UNDEFINED;
371  }
372  /* Overlong UTF-8 2-byte sequence */
373  else if(*pu8Byte < 0xC2)
374  {
375  /* Logs message */
376  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: overlong 2-byte sequence starting with byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
377 
378  /* Updates result */
379  u32Result = orxU32_UNDEFINED;
380  }
381  /* 2-byte sequence */
382  else if(*pu8Byte < 0xE0)
383  {
384  /* Updates result with first character */
385  u32Result = *pu8Byte++ & 0x1F;
386 
387  /* Valid second character? */
388  if((*pu8Byte & 0xC0) == 0x80)
389  {
390  /* Updates result */
391  u32Result = (u32Result << 6) | (*pu8Byte & 0x3F);
392  }
393  else
394  {
395  /* Logs message */
396  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: 2-byte sequence non-trailing byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
397 
398  /* Updates result */
399  u32Result = orxU32_UNDEFINED;
400  }
401  }
402  /* 3-byte sequence */
403  else if(*pu8Byte < 0xF0)
404  {
405  /* Updates result with first character */
406  u32Result = *pu8Byte++ & 0x0F;
407 
408  /* Valid second character? */
409  if((*pu8Byte & 0xC0) == 0x80)
410  {
411  /* Updates result */
412  u32Result = (u32Result << 6) | (*pu8Byte++ & 0x3F);
413 
414  /* Valid third character? */
415  if((*pu8Byte & 0xC0) == 0x80)
416  {
417  /* Updates result */
418  u32Result = (u32Result << 6) | (*pu8Byte & 0x3F);
419  }
420  else
421  {
422  /* Logs message */
423  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: 3-byte sequence non-trailing byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
424 
425  /* Updates result */
426  u32Result = orxU32_UNDEFINED;
427  }
428  }
429  else
430  {
431  /* Logs message */
432  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: 3-byte sequence non-trailing byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
433 
434  /* Updates result */
435  u32Result = orxU32_UNDEFINED;
436  }
437  }
438  /* 4-byte sequence */
439  else if(*pu8Byte < 0xF5)
440  {
441  /* Updates result with first character */
442  u32Result = *pu8Byte++ & 0x07;
443 
444  /* Valid second character? */
445  if((*pu8Byte & 0xC0) == 0x80)
446  {
447  /* Updates result */
448  u32Result = (u32Result << 6) | (*pu8Byte++ & 0x3F);
449 
450  /* Valid third character? */
451  if((*pu8Byte & 0xC0) == 0x80)
452  {
453  /* Updates result */
454  u32Result = (u32Result << 6) | (*pu8Byte++ & 0x3F);
455 
456  /* Valid fourth character? */
457  if((*pu8Byte & 0xC0) == 0x80)
458  {
459  /* Updates result */
460  u32Result = (u32Result << 6) | (*pu8Byte & 0x3F);
461  }
462  else
463  {
464  /* Logs message */
465  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: 4-byte sequence non-trailing byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
466 
467  /* Updates result */
468  u32Result = orxU32_UNDEFINED;
469  }
470  }
471  else
472  {
473  /* Logs message */
474  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: 4-byte sequence non-trailing byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
475 
476  /* Updates result */
477  u32Result = orxU32_UNDEFINED;
478  }
479  }
480  else
481  {
482  /* Logs message */
483  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: 4-byte sequence non-trailing byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
484 
485  /* Updates result */
486  u32Result = orxU32_UNDEFINED;
487  }
488  }
489  else
490  {
491  /* Logs message */
492  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF-8 string at <0x%X>: invalid out-of-bound byte '%c' (0x%2X) at index %d.", _zString, *pu8Byte, *pu8Byte, pu8Byte - (orxU8 *)_zString);
493 
494  /* Updates result */
495  u32Result = orxU32_UNDEFINED;
496  }
497 
498  /* Asks for remaining string? */
499  if(_pzRemaining != orxNULL)
500  {
501  /* Stores it */
502  *_pzRemaining = (orxSTRING)(pu8Byte + 1);
503  }
504 
505  /* Done! */
506  return u32Result;
507 }
508 
513 static orxINLINE orxU32 orxString_GetCharacterCount(const orxSTRING _zString)
514 {
515  const orxCHAR *pc;
516  orxU32 u32Result;
517 
518  /* Checks */
519  orxASSERT(_zString != orxNULL);
520 
521  /* For all characters */
522  for(pc = _zString, u32Result = 0; *pc != orxCHAR_NULL; u32Result++)
523  {
524  /* Invalid current character ID */
526  {
527  /* Updates result */
528  u32Result = orxU32_UNDEFINED;
529 
530  /* Logs message */
531  orxDEBUG_PRINT(orxDEBUG_LEVEL_SYSTEM, "Invalid or non-UTF8 string <%s>, can't count characters.", _zString);
532 
533  break;
534  }
535  }
536 
537  /* Done! */
538  return u32Result;
539 }
540 
547 static orxINLINE orxSTRING orxString_NCopy(orxSTRING _zDstString, const orxSTRING _zSrcString, orxU32 _u32CharNumber)
548 {
549  /* Checks */
550  orxASSERT(_zDstString != orxNULL);
551  orxASSERT(_zSrcString != orxNULL);
552 
553  /* Done! */
554  return(strncpy(_zDstString, _zSrcString, (size_t)_u32CharNumber));
555 }
556 
562 static orxINLINE orxSTRING orxString_Copy(orxSTRING _zDstString, const orxSTRING _zSrcString)
563 {
564  /* Checks */
565  orxASSERT(_zDstString != orxNULL);
566  orxASSERT(_zSrcString != orxNULL);
567 
568  /* Done! */
569  return(strcpy(_zDstString, _zSrcString));
570 }
571 
576 static orxINLINE orxSTRING orxString_Duplicate(const orxSTRING _zSrcString)
577 {
578  orxU32 u32Size;
579  orxSTRING zResult;
580 
581  /* Checks */
582  orxASSERT(_zSrcString != orxNULL);
583 
584  /* Gets string size in bytes */
585  u32Size = (orxString_GetLength(_zSrcString) + 1) * sizeof(orxCHAR);
586 
587  /* Allocates it */
588  zResult = (orxSTRING)orxMemory_Allocate(u32Size, orxMEMORY_TYPE_TEXT);
589 
590  /* Valid? */
591  if(zResult != orxNULL)
592  {
593  /* Copies source to it */
594  orxMemory_Copy(zResult, _zSrcString, u32Size);
595  }
596 
597  /* Done! */
598  return zResult;
599 }
600 
604 static orxINLINE orxSTATUS orxString_Delete(orxSTRING _zString)
605 {
606  /* Checks */
607  orxASSERT(_zString != orxNULL);
608  orxASSERT(_zString != orxSTRING_EMPTY);
609 
610  /* Frees its memory */
611  orxMemory_Free(_zString);
612 
613  /* Done! */
614  return orxSTATUS_SUCCESS;
615 }
616 
623 static orxINLINE orxS32 orxString_Compare(const orxSTRING _zString1, const orxSTRING _zString2)
624 {
625  /* Checks */
626  orxASSERT(_zString1 != orxNULL);
627  orxASSERT(_zString2 != orxNULL);
628 
629  /* Done! */
630  return(strcmp(_zString1, _zString2));
631 }
632 
641 static orxINLINE orxS32 orxString_NCompare(const orxSTRING _zString1, const orxSTRING _zString2, orxU32 _u32CharNumber)
642 {
643  /* Checks */
644  orxASSERT(_zString1 != orxNULL);
645  orxASSERT(_zString2 != orxNULL);
646 
647  /* Done! */
648  return strncmp(_zString1, _zString2, (size_t)_u32CharNumber);
649 }
650 
657 static orxINLINE orxS32 orxString_ICompare(const orxSTRING _zString1, const orxSTRING _zString2)
658 {
659  /* Checks */
660  orxASSERT(_zString1 != orxNULL);
661  orxASSERT(_zString2 != orxNULL);
662 
663 #ifdef __orxWINDOWS__
664 
665  /* Done! */
666  return(stricmp(_zString1, _zString2));
667 
668 #else /* __orxWINDOWS__ */
669 
670  /* Done! */
671  return strcasecmp(_zString1, _zString2);
672 
673 #endif /* __orxWINDOWS__ */
674 }
675 
684 static orxINLINE orxS32 orxString_NICompare(const orxSTRING _zString1, const orxSTRING _zString2, orxU32 _u32CharNumber)
685 {
686  /* Checks */
687  orxASSERT(_zString1 != orxNULL);
688  orxASSERT(_zString2 != orxNULL);
689 
690 #ifdef __orxWINDOWS__
691 
692  /* Done! */
693  return strnicmp(_zString1, _zString2, (size_t)_u32CharNumber);
694 
695 #else /* __orxWINDOWS__ */
696 
697  /* Done! */
698  return strncasecmp(_zString1, _zString2, _u32CharNumber);
699 
700 #endif /* __orxWINDOWS__ */
701 }
702 
708 static orxINLINE orxU32 orxString_ExtractBase(const orxSTRING _zString, const orxSTRING *_pzRemaining)
709 {
710  orxU32 u32Result, u32Offset;
711 
712  /* Checks */
713  orxASSERT(_zString != orxNULL);
714 
715  /* Default result and offset: decimal */
716  u32Result = 10;
717  u32Offset = 0;
718 
719  /* Depending on first character */
720  switch(_zString[0])
721  {
722  case '0':
723  {
724  /* Depending on second character */
725  switch(_zString[1] | 0x20)
726  {
727  case 'x':
728  {
729  /* Updates result and offset: hexadecimal */
730  u32Result = 16;
731  u32Offset = 2;
732 
733  break;
734  }
735 
736  case 'b':
737  {
738  /* Updates result and offset: binary */
739  u32Result = 2;
740  u32Offset = 2;
741 
742  break;
743  }
744 
745  default:
746  {
747  /* Octal? */
748  if((_zString[1] >= '0')
749  && (_zString[1] <= '9'))
750  {
751  /* Updates result and offset: octal */
752  u32Result = 8;
753  u32Offset = 1;
754  }
755 
756  break;
757  }
758  }
759 
760  break;
761  }
762 
763  case '#':
764  {
765  /* Updates result and offset: hexadecimal */
766  u32Result = 16;
767  u32Offset = 1;
768 
769  break;
770  }
771 
772  default:
773  {
774  break;
775  }
776  }
777 
778  /* Asks for remaining string? */
779  if(_pzRemaining != orxNULL)
780  {
781  /* Stores it */
782  *_pzRemaining = _zString + u32Offset;
783  }
784 
785  /* Done! */
786  return u32Result;
787 }
788 
796 static orxINLINE orxSTATUS orxString_ToS32Base(const orxSTRING _zString, orxU32 _u32Base, orxS32 *_ps32OutValue, const orxSTRING *_pzRemaining)
797 {
798  orxCHAR *pcEnd;
799  orxSTATUS eResult;
800 
801  /* Checks */
802  orxASSERT(_ps32OutValue != orxNULL);
803  orxASSERT(_zString != orxNULL);
804 
805  /* Convert */
806  *_ps32OutValue = (orxS32)strtol(_zString, &pcEnd, STRTO_CAST _u32Base);
807 
808  /* Valid conversion ? */
809  if((pcEnd != _zString) && (_zString[0] != orxCHAR_NULL))
810  {
811  /* Updates result */
812  eResult = orxSTATUS_SUCCESS;
813  }
814  else
815  {
816  /* Updates result */
817  eResult = orxSTATUS_FAILURE;
818  }
819 
820  /* Asks for remaining string? */
821  if(_pzRemaining != orxNULL)
822  {
823  /* Stores it */
824  *_pzRemaining = pcEnd;
825  }
826 
827  /* Done! */
828  return eResult;
829 }
830 
837 static orxINLINE orxSTATUS orxString_ToS32(const orxSTRING _zString, orxS32 *_ps32OutValue, const orxSTRING *_pzRemaining)
838 {
839  const orxSTRING zValue;
840  orxU32 u32Base;
841  orxSTATUS eResult;
842 
843  /* Checks */
844  orxASSERT(_ps32OutValue != orxNULL);
845  orxASSERT(_zString != orxNULL);
846 
847  /* Extracts base */
848  u32Base = orxString_ExtractBase(_zString, &zValue);
849 
850  /* Gets value */
851  eResult = orxString_ToS32Base(zValue, u32Base, _ps32OutValue, _pzRemaining);
852 
853  /* Done! */
854  return eResult;
855 }
856 
864 static orxINLINE orxSTATUS orxString_ToU32Base(const orxSTRING _zString, orxU32 _u32Base, orxU32 *_pu32OutValue, const orxSTRING *_pzRemaining)
865 {
866  orxCHAR *pcEnd;
867  orxSTATUS eResult;
868 
869  /* Checks */
870  orxASSERT(_pu32OutValue != orxNULL);
871  orxASSERT(_zString != orxNULL);
872 
873  /* Convert */
874  *_pu32OutValue = (orxU32)strtoul(_zString, &pcEnd, STRTO_CAST _u32Base);
875 
876  /* Valid conversion ? */
877  if((pcEnd != _zString) && (_zString[0] != orxCHAR_NULL))
878  {
879  /* Updates result */
880  eResult = orxSTATUS_SUCCESS;
881  }
882  else
883  {
884  /* Updates result */
885  eResult = orxSTATUS_FAILURE;
886  }
887 
888  /* Asks for remaining string? */
889  if(_pzRemaining != orxNULL)
890  {
891  /* Stores it */
892  *_pzRemaining = pcEnd;
893  }
894 
895  /* Done! */
896  return eResult;
897 }
898 
905 static orxINLINE orxSTATUS orxString_ToU32(const orxSTRING _zString, orxU32 *_pu32OutValue, const orxSTRING *_pzRemaining)
906 {
907  const orxSTRING zValue;
908  orxU32 u32Base;
909  orxSTATUS eResult;
910 
911  /* Checks */
912  orxASSERT(_pu32OutValue != orxNULL);
913  orxASSERT(_zString != orxNULL);
914 
915  /* Extracts base */
916  u32Base = orxString_ExtractBase(_zString, &zValue);
917 
918  /* Gets value */
919  eResult = orxString_ToU32Base(zValue, u32Base, _pu32OutValue, _pzRemaining);
920 
921  /* Done! */
922  return eResult;
923 }
924 
932 static orxINLINE orxSTATUS orxString_ToS64Base(const orxSTRING _zString, orxU32 _u32Base, orxS64 *_ps64OutValue, const orxSTRING *_pzRemaining)
933 {
934  orxCHAR *pcEnd;
935  orxSTATUS eResult;
936 
937  /* Checks */
938  orxASSERT(_ps64OutValue != orxNULL);
939  orxASSERT(_zString != orxNULL);
940 
941  /* Convert */
942  *_ps64OutValue = (orxS64)strtoll(_zString, &pcEnd, STRTO_CAST _u32Base);
943 
944  /* Valid conversion ? */
945  if((pcEnd != _zString) && (_zString[0] != orxCHAR_NULL))
946  {
947  /* Updates result */
948  eResult = orxSTATUS_SUCCESS;
949  }
950  else
951  {
952  /* Updates result */
953  eResult = orxSTATUS_FAILURE;
954  }
955 
956  /* Asks for remaining string? */
957  if(_pzRemaining != orxNULL)
958  {
959  /* Stores it */
960  *_pzRemaining = pcEnd;
961  }
962 
963  /* Done! */
964  return eResult;
965 }
966 
973 static orxINLINE orxSTATUS orxString_ToS64(const orxSTRING _zString, orxS64 *_ps64OutValue, const orxSTRING *_pzRemaining)
974 {
975  const orxSTRING zValue;
976  orxU32 u32Base;
977  orxSTATUS eResult;
978 
979  /* Checks */
980  orxASSERT(_ps64OutValue != orxNULL);
981  orxASSERT(_zString != orxNULL);
982 
983  /* Extracts base */
984  u32Base = orxString_ExtractBase(_zString, &zValue);
985 
986  /* Gets signed value */
987  eResult = orxString_ToS64Base(zValue, u32Base, _ps64OutValue, _pzRemaining);
988 
989  /* Done! */
990  return eResult;
991 }
992 
1000 static orxINLINE orxSTATUS orxString_ToU64Base(const orxSTRING _zString, orxU32 _u32Base, orxU64 *_pu64OutValue, const orxSTRING *_pzRemaining)
1001 {
1002  orxCHAR *pcEnd;
1003  orxSTATUS eResult;
1004 
1005  /* Checks */
1006  orxASSERT(_pu64OutValue != orxNULL);
1007  orxASSERT(_zString != orxNULL);
1008 
1009  /* Convert */
1010  *_pu64OutValue = (orxU64)strtoull(_zString, &pcEnd, STRTO_CAST _u32Base);
1011 
1012  /* Valid conversion ? */
1013  if((pcEnd != _zString) && (_zString[0] != orxCHAR_NULL))
1014  {
1015  /* Updates result */
1016  eResult = orxSTATUS_SUCCESS;
1017  }
1018  else
1019  {
1020  /* Updates result */
1021  eResult = orxSTATUS_FAILURE;
1022  }
1023 
1024  /* Asks for remaining string? */
1025  if(_pzRemaining != orxNULL)
1026  {
1027  /* Stores it */
1028  *_pzRemaining = pcEnd;
1029  }
1030 
1031  /* Done! */
1032  return eResult;
1033 }
1034 
1041 static orxINLINE orxSTATUS orxString_ToU64(const orxSTRING _zString, orxU64 *_pu64OutValue, const orxSTRING *_pzRemaining)
1042 {
1043  const orxSTRING zValue;
1044  orxU32 u32Base;
1045  orxSTATUS eResult;
1046 
1047  /* Checks */
1048  orxASSERT(_pu64OutValue != orxNULL);
1049  orxASSERT(_zString != orxNULL);
1050 
1051  /* Extracts base */
1052  u32Base = orxString_ExtractBase(_zString, &zValue);
1053 
1054  /* Gets signed value */
1055  eResult = orxString_ToU64Base(zValue, u32Base, _pu64OutValue, _pzRemaining);
1056 
1057  /* Done! */
1058  return eResult;
1059 }
1060 
1067 static orxINLINE orxSTATUS orxString_ToFloat(const orxSTRING _zString, orxFLOAT *_pfOutValue, const orxSTRING *_pzRemaining)
1068 {
1069  orxCHAR *pcEnd;
1070  orxSTATUS eResult;
1071 
1072  /* Checks */
1073  orxASSERT(_pfOutValue != orxNULL);
1074  orxASSERT(_zString != orxNULL);
1075 
1076  /* Linux / Mac / iOS / Android / MSVC? */
1077 #if defined(__orxLINUX__) || defined(__orxMAC__) || defined (__orxIOS__) || defined(__orxMSVC__) || defined(__orxANDROID__)
1078 
1079  /* Converts it */
1080  *_pfOutValue = (orxFLOAT)strtod(_zString, &pcEnd);
1081 
1082 #else /* __orxLINUX__ || __orxMAC__ || __orxIOS__ || __orxMSVC__ || __orxANDROID__ */
1083 
1084  /* Converts it */
1085  *_pfOutValue = strtof(_zString, &pcEnd);
1086 
1087 #endif /* __orxLINUX__ || __orxMAC__ || __orxIOS__ || __orxMSVC__ || __orxANDROID__ */
1088 
1089  /* Valid conversion ? */
1090  if((pcEnd != _zString) && (_zString[0] != orxCHAR_NULL))
1091  {
1092  /* Updates result */
1093  eResult = orxSTATUS_SUCCESS;
1094  }
1095  else
1096  {
1097  /* Updates result */
1098  eResult = orxSTATUS_FAILURE;
1099  }
1100 
1101  /* Asks for remaining string? */
1102  if(_pzRemaining != orxNULL)
1103  {
1104  /* Stores it */
1105  *_pzRemaining = pcEnd;
1106  }
1107 
1108  /* Done! */
1109  return eResult;
1110 }
1111 
1118 static orxINLINE orxSTATUS orxString_ToVector(const orxSTRING _zString, orxVECTOR *_pvOutValue, const orxSTRING *_pzRemaining)
1119 {
1120  orxVECTOR stValue;
1121  const orxSTRING zString;
1122  orxSTATUS eResult = orxSTATUS_FAILURE;
1123 
1124  /* Checks */
1125  orxASSERT(_pvOutValue != orxNULL);
1126  orxASSERT(_zString != orxNULL);
1127 
1128  /* Skips all white spaces */
1129  zString = orxString_SkipWhiteSpaces(_zString);
1130 
1131  /* Is a vector start character? */
1132  if((*zString == orxSTRING_KC_VECTOR_START)
1133  || (*zString == orxSTRING_KC_VECTOR_START_ALT))
1134  {
1135  orxCHAR cEndMarker;
1136 
1137  /* Gets end marker */
1139 
1140  /* Skips all white spaces */
1141  zString = orxString_SkipWhiteSpaces(zString + 1);
1142 
1143  /* Gets X value */
1144  if(orxString_ToFloat(zString, &(stValue.fX), &zString) != orxSTATUS_FAILURE)
1145  {
1146  /* Skips all white spaces */
1147  zString = orxString_SkipWhiteSpaces(zString);
1148 
1149  /* Is a vector separator character? */
1150  if(*zString == orxSTRING_KC_VECTOR_SEPARATOR)
1151  {
1152  /* Skips all white spaces */
1153  zString = orxString_SkipWhiteSpaces(zString + 1);
1154 
1155  /* Gets Y value */
1156  if(orxString_ToFloat(zString, &(stValue.fY), &zString) != orxSTATUS_FAILURE)
1157  {
1158  /* Skips all white spaces */
1159  zString = orxString_SkipWhiteSpaces(zString);
1160 
1161  /* Is a vector separator character? */
1162  if(*zString == orxSTRING_KC_VECTOR_SEPARATOR)
1163  {
1164  /* Skips all white spaces */
1165  zString = orxString_SkipWhiteSpaces(zString + 1);
1166 
1167  /* Gets Z value */
1168  if(orxString_ToFloat(zString, &(stValue.fZ), &zString) != orxSTATUS_FAILURE)
1169  {
1170  /* Skips all white spaces */
1171  zString = orxString_SkipWhiteSpaces(zString);
1172 
1173  /* Has a valid end marker? */
1174  if(*zString == cEndMarker)
1175  {
1176  /* Updates result */
1177  eResult = orxSTATUS_SUCCESS;
1178  }
1179  }
1180  }
1181  /* Has a valid end marker? */
1182  else if(*zString == cEndMarker)
1183  {
1184  /* Clears Z component */
1185  stValue.fZ = orxFLOAT_0;
1186 
1187  /* Updates result */
1188  eResult = orxSTATUS_SUCCESS;
1189  }
1190  }
1191  }
1192  }
1193  }
1194 
1195  /* Valid? */
1196  if(eResult != orxSTATUS_FAILURE)
1197  {
1198  /* Updates vector */
1199  orxVector_Copy(_pvOutValue, &stValue);
1200 
1201  /* Asks for remaining string? */
1202  if(_pzRemaining != orxNULL)
1203  {
1204  /* Stores it */
1205  *_pzRemaining = zString + 1;
1206  }
1207  }
1208 
1209  /* Done! */
1210  return eResult;
1211 }
1212 
1219 static orxINLINE orxSTATUS orxString_ToBool(const orxSTRING _zString, orxBOOL *_pbOutValue, const orxSTRING *_pzRemaining)
1220 {
1221  orxS32 s32Value;
1222  orxSTATUS eResult;
1223 
1224  /* Checks */
1225  orxASSERT(_pbOutValue != orxNULL);
1226  orxASSERT(_zString != orxNULL);
1227 
1228  /* Tries numeric value */
1229  eResult = orxString_ToS32Base(_zString, 10, &s32Value, _pzRemaining);
1230 
1231  /* Valid? */
1232  if(eResult != orxSTATUS_FAILURE)
1233  {
1234  /* Updates boolean */
1235  *_pbOutValue = (s32Value != 0) ? orxTRUE : orxFALSE;
1236  }
1237  else
1238  {
1239  orxU32 u32Length;
1240 
1241  /* Gets length of false */
1242  u32Length = orxString_GetLength(orxSTRING_FALSE);
1243 
1244  /* Is false? */
1245  if(orxString_NICompare(_zString, orxSTRING_FALSE, u32Length) == 0)
1246  {
1247  /* Updates boolean */
1248  *_pbOutValue = orxFALSE;
1249 
1250  /* Has remaining? */
1251  if(_pzRemaining != orxNULL)
1252  {
1253  /* Updates it */
1254  *_pzRemaining += u32Length;
1255  }
1256 
1257  /* Updates result */
1258  eResult = orxSTATUS_SUCCESS;
1259  }
1260  else
1261  {
1262  /* Gets length of true */
1263  u32Length = orxString_GetLength(orxSTRING_TRUE);
1264 
1265  /* Is true? */
1266  if(orxString_NICompare(_zString, orxSTRING_TRUE, u32Length) == 0)
1267  {
1268  /* Updates boolean */
1269  *_pbOutValue = orxTRUE;
1270 
1271  /* Has remaining? */
1272  if(_pzRemaining != orxNULL)
1273  {
1274  /* Updates it */
1275  *_pzRemaining += u32Length;
1276  }
1277 
1278  /* Updates result */
1279  eResult = orxSTATUS_SUCCESS;
1280  }
1281  }
1282  }
1283 
1284  /* Done! */
1285  return eResult;
1286 }
1287 
1292 static orxINLINE orxSTRING orxString_LowerCase(orxSTRING _zString)
1293 {
1294  orxCHAR *pc;
1295 
1296  /* Checks */
1297  orxASSERT(_zString != orxNULL);
1298 
1299  /* Converts the whole string */
1300  for(pc = _zString; *pc != orxCHAR_NULL; pc++)
1301  {
1302  /* Needs to be converted? */
1303  if(*pc >= 'A' && *pc <= 'Z')
1304  {
1305  /* Lower case */
1306  *pc |= 0x20;
1307  }
1308  }
1309 
1310  return _zString;
1311 }
1312 
1317 static orxINLINE orxSTRING orxString_UpperCase(orxSTRING _zString)
1318 {
1319  orxCHAR *pc;
1320 
1321  /* Checks */
1322  orxASSERT(_zString != orxNULL);
1323 
1324  /* Converts the whole string */
1325  for(pc = _zString; *pc != orxCHAR_NULL; pc++)
1326  {
1327  /* Needs to be converted? */
1328  if(*pc >= 'a' && *pc <= 'z')
1329  {
1330  /* Upper case */
1331  *pc &= ~0x20;
1332  }
1333  }
1334 
1335  return _zString;
1336 }
1337 
1344 static orxINLINE orxSTRINGID orxString_NContinueCRC(const orxSTRING _zString, orxSTRINGID _stCRC, orxU32 _u32CharNumber)
1345 {
1346  orxU32 u32CRC, u32Length;
1347  const orxU8 *pu8;
1348 
1349 #ifdef __orxLITTLE_ENDIAN__
1350 
1351 #define orxCRC_GET_FIRST(VALUE) VALUE
1352 #define orxCRC_INDEX_0 0
1353 #define orxCRC_INDEX_1 1
1354 #define orxCRC_INDEX_2 2
1355 #define orxCRC_INDEX_3 3
1356 #define orxCRC_INDEX_4 4
1357 #define orxCRC_INDEX_5 5
1358 #define orxCRC_INDEX_6 6
1359 #define orxCRC_INDEX_7 7
1360 
1361 #else /* __orxLITTLE_ENDIAN__ */
1362 
1363 #define orxCRC_GET_FIRST(VALUE) (((VALUE) >> 24) | (((VALUE) >> 8) & 0x0000FF00) | (((VALUE) << 8) & 0x00FF0000) | ((VALUE) << 24))
1364 #define orxCRC_INDEX_0 3
1365 #define orxCRC_INDEX_1 2
1366 #define orxCRC_INDEX_2 1
1367 #define orxCRC_INDEX_3 0
1368 #define orxCRC_INDEX_4 7
1369 #define orxCRC_INDEX_5 6
1370 #define orxCRC_INDEX_6 5
1371 #define orxCRC_INDEX_7 4
1372 
1373 #endif /* __orxLITTLE_ENDIAN__ */
1374 
1375  /* Checks */
1376  orxASSERT(_zString != orxNULL);
1377  orxASSERT(_u32CharNumber <= orxString_GetLength(_zString));
1378 
1379  /* Inits CRC */
1380  u32CRC = ~(orxU32)_stCRC;
1381 
1382  /* For all slices */
1383  for(u32Length = _u32CharNumber, pu8 = (const orxU8 *)_zString; u32Length >= 8; u32Length -= 8, pu8 += 8)
1384  {
1385  orxU32 u32First, u32Second;
1386 
1387  /* Gets the slice's data */
1388  orxMemory_Copy(&u32First, pu8, sizeof(orxU32));
1389  orxMemory_Copy(&u32Second, pu8 + 4, sizeof(orxU32));
1390  u32First ^= orxCRC_GET_FIRST(u32CRC);
1391 
1392  /* Updates the CRC */
1393  u32CRC = saau32CRCTable[orxCRC_INDEX_7][u32First & 0xFF]
1394  ^ saau32CRCTable[orxCRC_INDEX_6][(u32First >> 8) & 0xFF]
1395  ^ saau32CRCTable[orxCRC_INDEX_5][(u32First >> 16) & 0xFF]
1396  ^ saau32CRCTable[orxCRC_INDEX_4][u32First >> 24]
1397  ^ saau32CRCTable[orxCRC_INDEX_3][u32Second & 0xFF]
1398  ^ saau32CRCTable[orxCRC_INDEX_2][(u32Second >> 8) & 0xFF]
1399  ^ saau32CRCTable[orxCRC_INDEX_1][(u32Second >> 16) & 0xFF]
1400  ^ saau32CRCTable[orxCRC_INDEX_0][u32Second >> 24];
1401  }
1402 
1403  /* For all remaining characters */
1404  for(; u32Length != 0; u32Length--, pu8++)
1405  {
1406  /* Updates the CRC */
1407  u32CRC = saau32CRCTable[0][((orxU8)(u32CRC & 0xFF)) ^ *pu8] ^ (u32CRC >> 8);
1408  }
1409 
1410 #undef orxCRC_GET_FIRST
1411 #undef orxCRC_INDEX_0
1412 #undef orxCRC_INDEX_1
1413 #undef orxCRC_INDEX_2
1414 #undef orxCRC_INDEX_3
1415 #undef orxCRC_INDEX_4
1416 #undef orxCRC_INDEX_5
1417 #undef orxCRC_INDEX_6
1418 #undef orxCRC_INDEX_7
1419 
1420  /* Done! */
1421  return (orxSTRINGID)~u32CRC;
1422 }
1423 
1429 static orxINLINE orxSTRINGID orxString_ContinueCRC(const orxSTRING _zString, orxSTRINGID _stCRC)
1430 {
1431  orxSTRINGID stCRC;
1432 
1433  /* Updates CRC */
1434  stCRC = orxString_NContinueCRC(_zString, _stCRC, orxString_GetLength(_zString));
1435 
1436  /* Done! */
1437  return stCRC;
1438 }
1439 
1445 static orxINLINE orxSTRINGID orxString_NToCRC(const orxSTRING _zString, orxU32 _u32CharNumber)
1446 {
1447  /* Checks */
1448  orxASSERT(_zString != orxNULL);
1449  orxASSERT(_u32CharNumber <= orxString_GetLength(_zString));
1450 
1451  /* Done! */
1452  return orxString_NContinueCRC(_zString, 0, _u32CharNumber);
1453 }
1454 
1459 static orxINLINE orxSTRINGID orxString_ToCRC(const orxSTRING _zString)
1460 {
1461  /* Checks */
1462  orxASSERT(_zString != orxNULL);
1463 
1464  /* Done! */
1465  return orxString_ContinueCRC(_zString, 0);
1466 }
1467 
1473 static orxINLINE const orxSTRING orxString_SearchString(const orxSTRING _zString1, const orxSTRING _zString2)
1474 {
1475  /* Checks */
1476  orxASSERT(_zString1 != orxNULL);
1477  orxASSERT(_zString2 != orxNULL);
1478 
1479  /* Returns result */
1480  return(strstr(_zString1, _zString2));
1481 }
1482 
1488 static orxINLINE const orxSTRING orxString_SearchChar(const orxSTRING _zString, orxCHAR _cChar)
1489 {
1490  /* Checks */
1491  orxASSERT(_zString != orxNULL);
1492 
1493  /* Returns result */
1494  return(strchr(_zString, _cChar));
1495 }
1496 
1503 static orxINLINE orxS32 orxString_SearchCharIndex(const orxSTRING _zString, orxCHAR _cChar, orxU32 _u32Position)
1504 {
1505  orxS32 s32Result = -1;
1506  orxS32 s32Index;
1507  const orxCHAR *pc;
1508 
1509  /* Checks */
1510  orxASSERT(_zString != orxNULL);
1511  orxASSERT(_u32Position <= orxString_GetLength(_zString));
1512 
1513  /* For all characters */
1514  for(s32Index = _u32Position, pc = _zString + s32Index; *pc != orxCHAR_NULL; pc++, s32Index++)
1515  {
1516  /* Found? */
1517  if(*pc == _cChar)
1518  {
1519  /* Updates result */
1520  s32Result = s32Index;
1521 
1522  break;
1523  }
1524  }
1525 
1526  /* Done! */
1527  return s32Result;
1528 }
1529 
1535 static orxINLINE orxS32 orxCDECL orxString_Print(orxSTRING _zDstString, const orxSTRING _zSrcString, ...)
1536 {
1537  va_list stArgs;
1538  orxS32 s32Result;
1539 
1540  /* Checks */
1541  orxASSERT(_zDstString != orxNULL);
1542  orxASSERT(_zSrcString != orxNULL);
1543 
1544  /* Gets variable arguments & prints the string */
1545  va_start(stArgs, _zSrcString);
1546  s32Result = vsprintf(_zDstString, _zSrcString, stArgs);
1547  va_end(stArgs);
1548 
1549  /* Clamps result */
1550  s32Result = orxMAX(s32Result, 0);
1551 
1552  /* Done! */
1553  return s32Result;
1554 }
1555 
1562 static orxINLINE orxS32 orxCDECL orxString_NPrint(orxSTRING _zDstString, orxU32 _u32CharNumber, const orxSTRING _zSrcString, ...)
1563 {
1564  va_list stArgs;
1565  orxS32 s32Result;
1566 
1567  /* Checks */
1568  orxASSERT(_zDstString != orxNULL);
1569  orxASSERT(_zSrcString != orxNULL);
1570 
1571  /* Gets variable arguments & prints the string */
1572  va_start(stArgs, _zSrcString);
1573  s32Result = vsnprintf(_zDstString, (size_t)_u32CharNumber, _zSrcString, stArgs);
1574  va_end(stArgs);
1575 
1576 #ifdef __orxMSVC__
1577  /* Overflow? */
1578  if(s32Result <= 0)
1579  {
1580  /* Updates result */
1581  s32Result = _u32CharNumber;
1582  }
1583 #endif /* __orxWINDOWS__ */
1584 
1585  /* Clamps result */
1586  s32Result = orxCLAMP(s32Result, 0, (orxS32)_u32CharNumber);
1587 
1588  /* Done! */
1589  return s32Result;
1590 }
1591 
1597 static orxINLINE orxS32 orxCDECL orxString_Scan(const orxSTRING _zString, const orxSTRING _zFormat, ...)
1598 {
1599  va_list stArgs;
1600  orxS32 s32Result;
1601 
1602  /* Checks */
1603  orxASSERT(_zString != orxNULL);
1604 
1605 #ifdef __orxMSVC__
1606 
1607  /* Ugly workaround the missing vsscanf in MSVC up to version 2013 */
1608  {
1609  void *p[16];
1610  orxS32 i;
1611 
1612  /* Starts variable list */
1613  va_start(stArgs, _zFormat);
1614 
1615  /* For all potential parameters */
1616  for(i = 0; i < orxARRAY_GET_ITEM_COUNT(p); i++)
1617  {
1618  /* Gets its address */
1619  p[i] = va_arg(stArgs, void *);
1620  }
1621 
1622  /* Scans the string */
1623  s32Result = sscanf(_zString, _zFormat, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
1624 
1625  /* Ends variable list */
1626  va_end(stArgs);
1627  }
1628 
1629 #else /* __orxMSVC__ */
1630 
1631  /* Gets variable arguments & scans the string */
1632  va_start(stArgs, _zFormat);
1633  s32Result = vsscanf(_zString, _zFormat, stArgs);
1634  va_end(stArgs);
1635 
1636 #endif /* __orxMSVC__ */
1637 
1638  /* Clamps result */
1639  s32Result = orxMAX(s32Result, 0);
1640 
1641  /* Done! */
1642  return s32Result;
1643 }
1644 
1649 static orxINLINE const orxSTRING orxString_GetExtension(const orxSTRING _zFileName)
1650 {
1651  orxS32 s32Index, s32NextIndex;
1652  const orxSTRING zResult;
1653 
1654  /* Checks */
1655  orxASSERT(_zFileName != orxNULL);
1656 
1657  /* Finds last '.' */
1658  for(s32Index = orxString_SearchCharIndex(_zFileName, '.', 0);
1659  (s32Index >= 0) && ((s32NextIndex = orxString_SearchCharIndex(_zFileName, '.', s32Index + 1)) > 0);
1660  s32Index = s32NextIndex);
1661 
1662  /* Updates result */
1663  zResult = (s32Index >= 0) ? _zFileName + s32Index + 1 : orxSTRING_EMPTY;
1664 
1665  /* Done! */
1666  return zResult;
1667 }
1668 
1669 /* *** String module functions *** */
1670 
1673 extern orxDLLAPI void orxFASTCALL orxString_Setup();
1674 
1678 extern orxDLLAPI orxSTATUS orxFASTCALL orxString_Init();
1679 
1682 extern orxDLLAPI void orxFASTCALL orxString_Exit();
1683 
1684 
1689 extern orxDLLAPI orxSTRINGID orxFASTCALL orxString_GetID(const orxSTRING _zString);
1690 
1695 extern orxDLLAPI const orxSTRING orxFASTCALL orxString_GetFromID(orxSTRINGID _u32ID);
1696 
1701 extern orxDLLAPI const orxSTRING orxFASTCALL orxString_Store(const orxSTRING _zString);
1702 
1703 
1704 #ifdef __orxMSVC__
1705 
1706  #pragma warning(default : 4996)
1707 
1708 #endif /* __orxMSVC__ */
1709 
1710 #endif /* _orxSTRING_H_ */
1711 
#define orxARRAY_GET_ITEM_COUNT(ARRAY)
Definition: orxDecl.h:399
static orxINLINE const orxSTRING orxString_GetExtension(const orxSTRING _zFileName)
Definition: orxString.h:1649
static orxINLINE orxSTATUS orxString_ToS64(const orxSTRING _zString, orxS64 *_ps64OutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:973
orxDLLAPI orxSTRINGID orxFASTCALL orxString_GetID(const orxSTRING _zString)
#define orxCRC_INDEX_3
orxDLLAPI void orxFASTCALL orxString_Setup()
orxDLLAPI const orxSTRING orxFASTCALL orxString_Store(const orxSTRING _zString)
#define orxCRC_INDEX_6
static orxINLINE orxSTRINGID orxString_NContinueCRC(const orxSTRING _zString, orxSTRINGID _stCRC, orxU32 _u32CharNumber)
Definition: orxString.h:1344
static orxINLINE orxBOOL orxString_IsCharacterAlphaNumeric(orxU32 _u32CharacterCodePoint)
Definition: orxString.h:200
static orxINLINE orxSTATUS orxString_ToU32Base(const orxSTRING _zString, orxU32 _u32Base, orxU32 *_pu32OutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:864
static orxINLINE orxS32 orxString_NICompare(const orxSTRING _zString1, const orxSTRING _zString2, orxU32 _u32CharNumber)
Definition: orxString.h:684
static orxINLINE const orxSTRING orxString_SkipWhiteSpaces(const orxSTRING _zString)
Definition: orxString.h:103
static orxINLINE orxSTRING orxString_Duplicate(const orxSTRING _zSrcString)
Definition: orxString.h:576
#define orxSTRING_KC_VECTOR_END
Definition: orxString.h:82
static orxINLINE orxSTRING orxString_LowerCase(orxSTRING _zString)
Definition: orxString.h:1292
#define orxCRC_INDEX_7
#define orxTRUE
Definition: orxType.h:188
orxDLLAPI orxU32 saau32CRCTable[8][256]
orxDLLAPI orxSTATUS orxFASTCALL orxString_Init()
static orxINLINE orxS32 orxString_NCompare(const orxSTRING _zString1, const orxSTRING _zString2, orxU32 _u32CharNumber)
Definition: orxString.h:641
static orxINLINE orxSTRINGID orxString_NToCRC(const orxSTRING _zString, orxU32 _u32CharNumber)
Definition: orxString.h:1445
static const orxU32 orxU32_UNDEFINED
Definition: orxType.h:204
#define orxSTRING_KC_VECTOR_END_ALT
Definition: orxString.h:83
static orxINLINE orxSTATUS orxString_ToU64(const orxSTRING _zString, orxU64 *_pu64OutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:1041
static orxINLINE orxSTATUS orxString_ToU32(const orxSTRING _zString, orxU32 *_pu32OutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:905
orxFLOAT fY
Definition: orxVector.h:77
static orxINLINE orxU32 orxString_ExtractBase(const orxSTRING _zString, const orxSTRING *_pzRemaining)
Definition: orxString.h:708
static orxINLINE orxS32 orxString_SearchCharIndex(const orxSTRING _zString, orxCHAR _cChar, orxU32 _u32Position)
Definition: orxString.h:1503
#define orxCLAMP(V, MIN, MAX)
Definition: orxMath.h:89
orxDLLAPI const orxSTRING orxFASTCALL orxString_GetFromID(orxSTRINGID _u32ID)
#define orxFALSE
Definition: orxType.h:187
static orxINLINE orxS32 orxCDECL orxString_Scan(const orxSTRING _zString, const orxSTRING _zFormat,...)
Definition: orxString.h:1597
#define orxCHAR_DIRECTORY_SEPARATOR_WINDOWS
Definition: orxType.h:231
orxFLOAT fX
Definition: orxVector.h:69
orxDLLAPI void *orxFASTCALL orxMemory_Allocate(orxU32 _u32Size, orxMEMORY_TYPE _eMemType)
static orxINLINE orxSTATUS orxString_ToS32Base(const orxSTRING _zString, orxU32 _u32Base, orxS32 *_ps32OutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:796
static orxINLINE const orxSTRING orxString_SkipPath(const orxSTRING _zString)
Definition: orxString.h:134
orxDLLAPI const orxSTRING orxSTRING_EMPTY
#define orxCRC_INDEX_0
static orxINLINE orxSTATUS orxString_ToVector(const orxSTRING _zString, orxVECTOR *_pvOutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:1118
orxDLLAPI const orxSTRING orxSTRING_TRUE
#define orxCRC_INDEX_1
static orxU32 orxFASTCALL orxString_GetFirstCharacterCodePoint(const orxSTRING _zString, const orxSTRING *_pzRemaining)
Definition: orxString.h:346
static orxINLINE orxSTRING orxString_UpperCase(orxSTRING _zString)
Definition: orxString.h:1317
#define orxMAX(A, B)
Definition: orxMath.h:81
static orxINLINE orxSTRING orxString_Copy(orxSTRING _zDstString, const orxSTRING _zSrcString)
Definition: orxString.h:562
static orxINLINE orxU32 orxString_GetLength(const orxSTRING _zString)
Definition: orxString.h:177
#define orxSTRING_KC_VECTOR_START
Definition: orxString.h:79
static orxINLINE orxSTATUS orxString_ToBool(const orxSTRING _zString, orxBOOL *_pbOutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:1219
static orxINLINE orxS32 orxCDECL orxString_Print(orxSTRING _zDstString, const orxSTRING _zSrcString,...)
Definition: orxString.h:1535
static orxINLINE orxSTATUS orxString_ToU64Base(const orxSTRING _zString, orxU32 _u32Base, orxU64 *_pu64OutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:1000
static orxINLINE orxSTATUS orxString_Delete(orxSTRING _zString)
Definition: orxString.h:604
static orxINLINE orxU32 orxString_GetUTF8CharacterLength(orxU32 _u32CharacterCodePoint)
Definition: orxString.h:212
static orxINLINE orxS32 orxString_Compare(const orxSTRING _zString1, const orxSTRING _zString2)
Definition: orxString.h:623
static orxU32 orxFASTCALL orxString_PrintUTF8Character(orxSTRING _zDstString, orxU32 _u32Size, orxU32 _u32CharacterCodePoint)
Definition: orxString.h:253
static orxINLINE orxSTRINGID orxString_ContinueCRC(const orxSTRING _zString, orxSTRINGID _stCRC)
Definition: orxString.h:1429
static orxINLINE const orxSTRING orxString_SearchString(const orxSTRING _zString1, const orxSTRING _zString2)
Definition: orxString.h:1473
orxSTATUS
Definition: orxType.h:246
static orxINLINE orxS32 orxString_ICompare(const orxSTRING _zString1, const orxSTRING _zString2)
Definition: orxString.h:657
static orxINLINE orxS32 orxCDECL orxString_NPrint(orxSTRING _zDstString, orxU32 _u32CharNumber, const orxSTRING _zSrcString,...)
Definition: orxString.h:1562
static orxINLINE orxSTATUS orxString_ToS64Base(const orxSTRING _zString, orxU32 _u32Base, orxS64 *_ps64OutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:932
orxFLOAT fZ
Definition: orxVector.h:85
static orxINLINE orxSTRINGID orxString_ToCRC(const orxSTRING _zString)
Definition: orxString.h:1459
#define orxDLLAPI
Definition: orxDecl.h:381
#define STRTO_CAST
Definition: orxString.h:64
#define orxCRC_INDEX_5
static orxINLINE orxBOOL orxString_IsCharacterASCII(orxU32 _u32CharacterCodePoint)
Definition: orxString.h:190
static orxINLINE const orxSTRING orxString_SearchChar(const orxSTRING _zString, orxCHAR _cChar)
Definition: orxString.h:1488
orxDLLAPI void orxFASTCALL orxString_Exit()
static orxINLINE orxSTATUS orxString_ToFloat(const orxSTRING _zString, orxFLOAT *_pfOutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:1067
static const orxFLOAT orxFLOAT_0
Definition: orxType.h:192
orxDLLAPI void orxFASTCALL orxMemory_Free(void *_pMem)
#define orxSTRING_KC_VECTOR_SEPARATOR
Definition: orxString.h:81
#define orxCHAR_NULL
Definition: orxType.h:217
static orxINLINE orxSTATUS orxString_ToS32(const orxSTRING _zString, orxS32 *_ps32OutValue, const orxSTRING *_pzRemaining)
Definition: orxString.h:837
#define orxDEBUG_PRINT(LEVEL, STRING,...)
Definition: orxDebug.h:327
static orxINLINE orxU32 orxString_GetCharacterCount(const orxSTRING _zString)
Definition: orxString.h:513
static orxINLINE void * orxMemory_Copy(void *_pDest, const void *_pSrc, orxU32 _u32Size)
Definition: orxMemory.h:148
static orxINLINE orxSTRING orxString_NCopy(orxSTRING _zDstString, const orxSTRING _zSrcString, orxU32 _u32CharNumber)
Definition: orxString.h:547
orxDLLAPI const orxSTRING orxSTRING_FALSE
#define orxSTRING_KC_VECTOR_START_ALT
Definition: orxString.h:80
#define orxASSERT(TEST,...)
Definition: orxDebug.h:353
static orxINLINE orxVECTOR * orxVector_Copy(orxVECTOR *_pvDst, const orxVECTOR *_pvSrc)
Definition: orxVector.h:135
#define orxCHAR_DIRECTORY_SEPARATOR_LINUX
Definition: orxType.h:232
#define orxCRC_INDEX_2
#define orxCRC_INDEX_4
#define orxCRC_GET_FIRST(VALUE)

Generated for orx by doxygen 1.8.11