1 | // tStandard.cpp  |
2 | //  |
3 | // Tacent functions and types that are standard across all platforms. Includes global functions like itoa which are not  |
4 | // available on some platforms, but are common enough that they should be.  |
5 | //  |
6 | // Copyright (c) 2004-2006, 2015 Tristan Grimmer.  |
7 | // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby  |
8 | // granted, provided that the above copyright notice and this permission notice appear in all copies.  |
9 | //  |
10 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL  |
11 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,  |
12 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN  |
13 | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR  |
14 | // PERFORMANCE OF THIS SOFTWARE.  |
15 |   |
16 | #include <stdlib.h>  |
17 | #ifdef PLATFORM_WINDOWS  |
18 | #include <Windows.h>  |
19 | #endif  |
20 | #include "Foundation/tStandard.h"  |
21 | #include "Foundation/tString.h"  |
22 | #pragma warning (disable: 4146)  |
23 | #pragma warning (disable: 4018)  |
24 |   |
25 |   |
26 | const char* tStd::SeparatorSubStr = "\x1a" ;  |
27 | const char* tStd::SeparatorFileStr = "\x1c" ;  |
28 | const char* tStd::SeparatorGroupStr = "\x1d" ;  |
29 | const char* tStd::SeparatorRecordStr = "\x1e" ;  |
30 | const char* tStd::SeparatorUnitStr = "\x1f" ;  |
31 | const char* tStd::SeparatorAStr = tStd::SeparatorUnitStr;  |
32 | const char* tStd::SeparatorBStr = tStd::SeparatorRecordStr;  |
33 | const char* tStd::SeparatorCStr = tStd::SeparatorGroupStr;  |
34 | const char* tStd::SeparatorDStr = tStd::SeparatorFileStr;  |
35 | const char* tStd::SeparatorEStr = tStd::SeparatorSubStr;  |
36 |   |
37 |   |
38 | void* tStd::tMemmem(void* haystack, int haystackNumBytes, void* needle, int needleNumBytes)  |
39 | {  |
40 | if ((haystackNumBytes <= 0) || (needleNumBytes <= 0) || (haystackNumBytes < needleNumBytes))  |
41 | return nullptr;  |
42 |   |
43 | // Serach for the pattern from the first haystack byte (0) to numNeedleBytes from the end. For example, if we are  |
44 | // seraching for 4 bytes in 8, there will be 5 mem compares of 4 bytes each.  |
45 | for (int i = 0; i <= haystackNumBytes-needleNumBytes; i++)  |
46 | {  |
47 | if (tMemcmp((uint8*)haystack + i, needle, needleNumBytes) == 0)  |
48 | return (uint8*)haystack + i;  |
49 | }  |
50 |   |
51 | return nullptr;  |
52 | }  |
53 |   |
54 |   |
55 | float tStd::tStrtof(const char* s)  |
56 | {  |
57 | char* hash = tStrchr(s, '#');  |
58 | if (hash && (tStrlen(hash+1) == 8))  |
59 | {  |
60 | uint32 bin = tStd::tStrtoui32(hash+1, 16);  |
61 | return *((float*)(&bin));  |
62 | }  |
63 |   |
64 | return float( tStrtod(s) );  |
65 | }  |
66 |   |
67 |   |
68 | double tStd::tStrtod(const char* s)  |
69 | {  |
70 | int l = tStrlen(s);  |
71 | if (!l)  |
72 | return 0.0;  |
73 |   |
74 | char* hash = tStrchr(s, '#');  |
75 | if (hash && (tStrlen(hash+1) == 16))  |
76 | {  |
77 | uint64 bin = tStrtoui64(hash+1, 16);  |
78 | return *((double*)&bin);  |
79 | }  |
80 |   |
81 | // This error checking is essential. Sometimes NANs are written in text format to a string.  |
82 | // Like "nan(snan)". We want these to evaluate to 0.0, not -1 or something else. We allow  |
83 | // 'e' and 'E' for numbers in exponential form like 3.09E08.  |
84 | for (int i = 0; i < l; i++)  |
85 | {  |
86 | char ch = s[i];  |
87 | if  |
88 | (  |
89 | ((ch >= 'a') && (ch <= 'z') && (ch != 'e')) ||  |
90 | ((ch >= 'A') && (ch <= 'Z') && (ch != 'E'))  |
91 | )  |
92 | return 0.0;  |
93 | }  |
94 |   |
95 | // Will be 0.0 if there was a problem.  |
96 | return strtod(s, nullptr);  |
97 | }  |
98 |   |
99 |   |
100 | bool tStd::tStrtob(const char* str)  |
101 | {  |
102 | tString lower(str);  |
103 | lower.ToLower();  |
104 |   |
105 | if  |
106 | (  |
107 | (lower == "true" ) || (lower == "t" ) ||  |
108 | (lower == "yes" ) || (lower == "y" ) ||  |
109 | (lower == "on" ) || (lower == "1" ) || (lower == "+" ) ||  |
110 | (lower == "enable" ) || (lower == "enabled" ) || (tStrtoi(str) != 0)  |
111 | )  |
112 | return true;  |
113 | else  |
114 | return false;  |
115 | }  |
116 |   |
117 |   |
118 | void tStd::tStrrev(char* begin, char* end)  |
119 | {   |
120 | char aux;  |
121 | while (end > begin)  |
122 | aux = *end, *end-- = *begin, *begin++ = aux;  |
123 | }  |
124 | |