| 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 | |