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 
26const char* tStd::SeparatorSubStr = "\x1a"; 
27const char* tStd::SeparatorFileStr = "\x1c"; 
28const char* tStd::SeparatorGroupStr = "\x1d"; 
29const char* tStd::SeparatorRecordStr = "\x1e"; 
30const char* tStd::SeparatorUnitStr = "\x1f"; 
31const char* tStd::SeparatorAStr = tStd::SeparatorUnitStr; 
32const char* tStd::SeparatorBStr = tStd::SeparatorRecordStr; 
33const char* tStd::SeparatorCStr = tStd::SeparatorGroupStr; 
34const char* tStd::SeparatorDStr = tStd::SeparatorFileStr; 
35const char* tStd::SeparatorEStr = tStd::SeparatorSubStr; 
36 
37 
38void* 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 
55float 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 
68double 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 
100bool 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 
118void tStd::tStrrev(char* begin, char* end) 
119{  
120 char aux; 
121 while (end > begin) 
122 aux = *end, *end-- = *begin, *begin++ = aux; 
123} 
124