Blame |
Last modification |
View Log
| RSS feed
#include "Common.h"
#include "MTRand.h"
#include "Debug.h"
#include <direct.h>
#include <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <aclapi.h>
#include "PerfTimer.h"
HINSTANCE Sexy::gHInstance;
bool Sexy::gDebug = false;
static Sexy::MTRand gMTRand;
namespace Sexy
{
std::string gAppDataFolder = "";
}
int Sexy::Rand()
{
return gMTRand.Next();
}
int Sexy::Rand(int range)
{
return gMTRand.Next((unsigned long)range);
}
float Sexy::Rand(float range)
{
return gMTRand.Next(range);
}
void Sexy::SRand(ulong theSeed)
{
gMTRand.SRand(theSeed);
}
bool Sexy::CheckFor98Mill()
{
static bool needOsCheck = true;
static bool is98Mill = false;
if (needOsCheck)
{
bool invalid = false;
OSVERSIONINFOEXA osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
if( GetVersionExA((LPOSVERSIONINFOA)&osvi) == 0)
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOA);
if ( GetVersionExA((LPOSVERSIONINFOA)&osvi) == 0)
return false;
}
needOsCheck = false;
is98Mill = osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS; // let's check Win95, 98, *AND* ME.
}
return is98Mill;
}
bool Sexy::CheckForVista()
{
static bool needOsCheck = true;
static bool isVista = false;
if (needOsCheck)
{
bool invalid = false;
OSVERSIONINFOEXA osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
if( GetVersionExA((LPOSVERSIONINFOA)&osvi) == 0)
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOA);
if ( GetVersionExA((LPOSVERSIONINFOA)&osvi) == 0)
return false;
}
needOsCheck = false;
isVista = osvi.dwMajorVersion >= 6;
}
return isVista;
}
std::string Sexy::GetAppDataFolder()
{
return Sexy::gAppDataFolder;
}
void Sexy::SetAppDataFolder(const std::string& thePath)
{
if (CheckForVista())
{
std::string aPath = thePath;
if (!aPath.empty())
{
if (aPath[aPath.length()-1] != '\\' && aPath[aPath.length()-1] != '/')
aPath += '\\';
}
Sexy::gAppDataFolder = aPath;
}
}
std::string Sexy::URLEncode(const std::string& theString)
{
char* aHexChars = "0123456789ABCDEF";
std::string aString;
for (unsigned i = 0; i < theString.length(); i++)
{
switch (theString[i])
{
case ' ':
aString.insert(aString.end(), '+');
break;
case '?':
case '&':
case '%':
case '+':
case '\r':
case '\n':
case '\t':
aString.insert(aString.end(), '%');
aString.insert(aString.end(), aHexChars[(theString[i] >> 4) & 0xF]);
aString.insert(aString.end(), aHexChars[(theString[i] ) & 0xF]);
break;
default:
aString.insert(aString.end(), theString[i]);
}
}
return aString;
}
std::string Sexy::StringToUpper(const std::string& theString)
{
std::string aString;
for (unsigned i = 0; i < theString.length(); i++)
aString += toupper(theString[i]);
return aString;
}
std::wstring Sexy::StringToUpper(const std::wstring& theString)
{
std::wstring aString;
for (unsigned i = 0; i < theString.length(); i++)
aString += towupper(theString[i]);
return aString;
}
std::string Sexy::StringToLower(const std::string& theString)
{
std::string aString;
for (unsigned i = 0; i < theString.length(); i++)
aString += tolower(theString[i]);
return aString;
}
std::wstring Sexy::StringToLower(const std::wstring& theString)
{
std::wstring aString;
for (unsigned i = 0; i < theString.length(); ++i)
aString += tolower(theString[i]);
return aString;
}
std::wstring Sexy::StringToWString(const std::string &theString)
{
std::wstring aString;
aString.reserve(theString.length());
for(size_t i = 0; i < theString.length(); ++i)
aString += (unsigned char)theString[i];
return aString;
}
std::string Sexy::WStringToString(const std::wstring &theString)
{
size_t aRequiredLength = wcstombs( NULL, theString.c_str(), 0 );
if (aRequiredLength < 16384)
{
char aBuffer[16384];
wcstombs( aBuffer, theString.c_str(), 16384 );
return std::string(aBuffer);
}
else
{
DBG_ASSERTE(aRequiredLength != (size_t)-1);
if (aRequiredLength == (size_t)-1) return "";
char* aBuffer = new char[aRequiredLength+1];
wcstombs( aBuffer, theString.c_str(), aRequiredLength+1 );
std::string aStr = aBuffer;
delete[] aBuffer;
return aStr;
}
}
SexyString Sexy::StringToSexyString(const std::string& theString)
{
#ifdef _USE_WIDE_STRING
return StringToWString(theString);
#else
return SexyString(theString);
#endif
}
SexyString Sexy::WStringToSexyString(const std::wstring &theString)
{
#ifdef _USE_WIDE_STRING
return SexyString(theString);
#else
return WStringToString(theString);
#endif
}
std::string Sexy::SexyStringToString(const SexyString& theString)
{
#ifdef _USE_WIDE_STRING
return WStringToString(theString);
#else
return std::string(theString);
#endif
}
std::wstring Sexy::SexyStringToWString(const SexyString& theString)
{
#ifdef _USE_WIDE_STRING
return std::wstring(theString);
#else
return StringToWString(theString);
#endif
}
std::string Sexy::Trim(const std::string& theString)
{
int aStartPos = 0;
while ( aStartPos < (int) theString.length() && isspace(theString[aStartPos]) )
aStartPos++;
int anEndPos = theString.length() - 1;
while ( anEndPos >= 0 && isspace(theString[anEndPos]) )
anEndPos--;
return theString.substr(aStartPos, anEndPos - aStartPos + 1);
}
std::wstring Sexy::Trim(const std::wstring& theString)
{
int aStartPos = 0;
while ( aStartPos < (int) theString.length() && iswspace(theString[aStartPos]) )
aStartPos++;
int anEndPos = theString.length() - 1;
while ( anEndPos >= 0 && iswspace(theString[anEndPos]) )
anEndPos--;
return theString.substr(aStartPos, anEndPos - aStartPos + 1);
}
bool Sexy::StringToInt(const std::string theString, int* theIntVal)
{
*theIntVal = 0;
if (theString.length() == 0)
return false;
int theRadix = 10;
bool isNeg = false;
unsigned i = 0;
if (theString[i] == '-')
{
isNeg = true;
i++;
}
for (; i < theString.length(); i++)
{
char aChar = theString[i];
if ((theRadix == 10) && (aChar >= '0') && (aChar <= '9'))
*theIntVal = (*theIntVal * 10) + (aChar - '0');
else if ((theRadix == 0x10) &&
(((aChar >= '0') && (aChar <= '9')) ||
((aChar >= 'A') && (aChar <= 'F')) ||
((aChar >= 'a') && (aChar <= 'f'))))
{
if (aChar <= '9')
*theIntVal = (*theIntVal * 0x10) + (aChar - '0');
else if (aChar <= 'F')
*theIntVal = (*theIntVal * 0x10) + (aChar - 'A') + 0x0A;
else
*theIntVal = (*theIntVal * 0x10) + (aChar - 'a') + 0x0A;
}
else if (((aChar == 'x') || (aChar == 'X')) && (i == 1) && (*theIntVal == 0))
{
theRadix = 0x10;
}
else
{
*theIntVal = 0;
return false;
}
}
if (isNeg)
*theIntVal = -*theIntVal;
return true;
}
bool Sexy::StringToInt(const std::wstring theString, int* theIntVal)
{
*theIntVal = 0;
if (theString.length() == 0)
return false;
int theRadix = 10;
bool isNeg = false;
unsigned i = 0;
if (theString[i] == '-')
{
isNeg = true;
i++;
}
for (; i < theString.length(); i++)
{
wchar_t aChar = theString[i];
if ((theRadix == 10) && (aChar >= L'0') && (aChar <= L'9'))
*theIntVal = (*theIntVal * 10) + (aChar - L'0');
else if ((theRadix == 0x10) &&
(((aChar >= L'0') && (aChar <= L'9')) ||
((aChar >= L'A') && (aChar <= L'F')) ||
((aChar >= L'a') && (aChar <= L'f'))))
{
if (aChar <= L'9')
*theIntVal = (*theIntVal * 0x10) + (aChar - L'0');
else if (aChar <= L'F')
*theIntVal = (*theIntVal * 0x10) + (aChar - L'A') + 0x0A;
else
*theIntVal = (*theIntVal * 0x10) + (aChar - L'a') + 0x0A;
}
else if (((aChar == L'x') || (aChar == L'X')) && (i == 1) && (*theIntVal == 0))
{
theRadix = 0x10;
}
else
{
*theIntVal = 0;
return false;
}
}
if (isNeg)
*theIntVal = -*theIntVal;
return true;
}
bool Sexy::StringToDouble(const std::string theString, double* theDoubleVal)
{
*theDoubleVal = 0.0;
if (theString.length() == 0)
return false;
bool isNeg = false;
unsigned i = 0;
if (theString[i] == '-')
{
isNeg = true;
i++;
}
for (; i < theString.length(); i++)
{
char aChar = theString[i];
if ((aChar >= '0') && (aChar <= '9'))
*theDoubleVal = (*theDoubleVal * 10) + (aChar - '0');
else if (aChar == '.')
{
i++;
break;
}
else
{
*theDoubleVal = 0.0;
return false;
}
}
double aMult = 0.1;
for (; i < theString.length(); i++)
{
char aChar = theString[i];
if ((aChar >= '0') && (aChar <= '9'))
{
*theDoubleVal += (aChar - '0') * aMult;
aMult /= 10.0;
}
else
{
*theDoubleVal = 0.0;
return false;
}
}
if (isNeg)
*theDoubleVal = -*theDoubleVal;
return true;
}
bool Sexy::StringToDouble(const std::wstring theString, double* theDoubleVal)
{
*theDoubleVal = 0.0;
if (theString.length() == 0)
return false;
bool isNeg = false;
unsigned i = 0;
if (theString[i] == '-')
{
isNeg = true;
i++;
}
for (; i < theString.length(); i++)
{
wchar_t aChar = theString[i];
if ((aChar >= L'0') && (aChar <= L'9'))
*theDoubleVal = (*theDoubleVal * 10) + (aChar - L'0');
else if (aChar == L'.')
{
i++;
break;
}
else
{
*theDoubleVal = 0.0;
return false;
}
}
double aMult = 0.1;
for (; i < theString.length(); i++)
{
wchar_t aChar = theString[i];
if ((aChar >= L'0') && (aChar <= L'9'))
{
*theDoubleVal += (aChar - L'0') * aMult;
aMult /= 10.0;
}
else
{
*theDoubleVal = 0.0;
return false;
}
}
if (isNeg)
*theDoubleVal = -*theDoubleVal;
return true;
}
// TODO: Use <locale> for localization of number output?
SexyString Sexy::CommaSeperate(int theValue)
{
if (theValue == 0)
return _S("0");
SexyString aCurString;
int aPlace = 0;
int aCurValue = theValue;
while (aCurValue > 0)
{
if ((aPlace != 0) && (aPlace % 3 == 0))
aCurString = _S(',') + aCurString;
aCurString = (SexyChar) (_S('0') + (aCurValue % 10)) + aCurString;
aCurValue /= 10;
aPlace++;
}
return aCurString;
}
std::string Sexy::GetCurDir()
{
char aDir[256];
return _getcwd(aDir, sizeof(aDir));
}
std::string Sexy::GetFullPath(const std::string& theRelPath)
{
return GetPathFrom(theRelPath, GetCurDir());
}
std::string Sexy::GetPathFrom(const std::string& theRelPath, const std::string& theDir)
{
std::string aDriveString;
std::string aNewPath = theDir;
if ((theRelPath.length() >= 2) && (theRelPath[1] == ':'))
return theRelPath;
char aSlashChar = '/';
if ((theRelPath.find('\\') != -1) || (theDir.find('\\') != -1))
aSlashChar = '\\';
if ((aNewPath.length() >= 2) && (aNewPath[1] == ':'))
{
aDriveString = aNewPath.substr(0, 2);
aNewPath.erase(aNewPath.begin(), aNewPath.begin()+2);
}
// Append a trailing slash if necessary
if ((aNewPath.length() > 0) && (aNewPath[aNewPath.length()-1] != '\\') && (aNewPath[aNewPath.length()-1] != '/'))
aNewPath += aSlashChar;
std::string aTempRelPath = theRelPath;
for (;;)
{
if (aNewPath.length() == 0)
break;
int aFirstSlash = aTempRelPath.find('\\');
int aFirstForwardSlash = aTempRelPath.find('/');
if ((aFirstSlash == -1) || ((aFirstForwardSlash != -1) && (aFirstForwardSlash < aFirstSlash)))
aFirstSlash = aFirstForwardSlash;
if (aFirstSlash == -1)
break;
std::string aChDir = aTempRelPath.substr(0, aFirstSlash);
aTempRelPath.erase(aTempRelPath.begin(), aTempRelPath.begin() + aFirstSlash + 1);
if (aChDir.compare("..") == 0)
{
int aLastDirStart = aNewPath.length() - 1;
while ((aLastDirStart > 0) && (aNewPath[aLastDirStart-1] != '\\') && (aNewPath[aLastDirStart-1] != '/'))
aLastDirStart--;
std::string aLastDir = aNewPath.substr(aLastDirStart, aNewPath.length() - aLastDirStart - 1);
if (aLastDir.compare("..") == 0)
{
aNewPath += "..";
aNewPath += aSlashChar;
}
else
{
aNewPath.erase(aNewPath.begin() + aLastDirStart, aNewPath.end());
}
}
else if (aChDir.compare("") == 0)
{
aNewPath = aSlashChar;
break;
}
else if (aChDir.compare(".") != 0)
{
aNewPath += aChDir + aSlashChar;
break;
}
}
aNewPath = aDriveString + aNewPath + aTempRelPath;
if (aSlashChar == '/')
{
for (;;)
{
int aSlashPos = aNewPath.find('\\');
if (aSlashPos == -1)
break;
aNewPath[aSlashPos] = '/';
}
}
else
{
for (;;)
{
int aSlashPos = aNewPath.find('/');
if (aSlashPos == -1)
break;
aNewPath[aSlashPos] = '\\';
}
}
return aNewPath;
}
bool Sexy::AllowAllAccess(const std::string& theFileName)
{
HMODULE aLib = LoadLibraryA("advapi32.dll");
if (aLib == NULL)
return false;
BOOL (WINAPI *fnSetFileSecurity)(LPCTSTR lpFileName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor);
BOOL (WINAPI *fnSetSecurityDescriptorDacl)(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted);
BOOL (WINAPI *fnInitializeSecurityDescriptor)(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision);
BOOL (WINAPI *fnAllocateAndInitializeSid)(
PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
BYTE nSubAuthorityCount,
DWORD dwSubAuthority0,
DWORD dwSubAuthority1,
DWORD dwSubAuthority2,
DWORD dwSubAuthority3,
DWORD dwSubAuthority4,
DWORD dwSubAuthority5,
DWORD dwSubAuthority6,
DWORD dwSubAuthority7,
PSID* pSid
);
DWORD (WINAPI *fnSetEntriesInAcl)(ULONG cCountOfExplicitEntries, PEXPLICIT_ACCESS pListOfExplicitEntries, PACL OldAcl, PACL* NewAcl);
PVOID (WINAPI *fnFreeSid)(PSID pSid);
*(void**)&fnSetFileSecurity = (void*)GetProcAddress(aLib, "SetFileSecurityA");
*(void**)&fnSetSecurityDescriptorDacl = (void*)GetProcAddress(aLib, "SetSecurityDescriptorDacl");
*(void**)&fnInitializeSecurityDescriptor = (void*)GetProcAddress(aLib, "InitializeSecurityDescriptor");
*(void**)&fnAllocateAndInitializeSid = (void*)GetProcAddress(aLib, "AllocateAndInitializeSid");
*(void**)&fnSetEntriesInAcl = (void*)GetProcAddress(aLib, "SetEntriesInAclA");
*(void**)&fnFreeSid = (void*) GetProcAddress(aLib, "FreeSid");
if (!(fnSetFileSecurity && fnSetSecurityDescriptorDacl && fnInitializeSecurityDescriptor && fnAllocateAndInitializeSid && fnSetEntriesInAcl && fnFreeSid))
{
FreeLibrary(aLib);
return false;
}
PSID pEveryoneSID = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
bool result = false;
// Create a well-known SID for the Everyone group.
if (fnAllocateAndInitializeSid(&SIDAuthWorld, 1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&pEveryoneSID))
{
EXPLICIT_ACCESS ea;
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow Everyone read access to the key.
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID;
// Create a new ACL that contains the new ACEs.
PACL pACL = NULL;
if (fnSetEntriesInAcl(1, &ea, NULL, &pACL) == ERROR_SUCCESS)
{
// Initialize a security descriptor.
PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR) new char[SECURITY_DESCRIPTOR_MIN_LENGTH];
if (fnInitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
{
// Add the ACL to the security descriptor.
if (fnSetSecurityDescriptorDacl(pSD,
TRUE, // bDaclPresent flag
pACL,
FALSE)) // not a default DACL
{
if (fnSetFileSecurity(theFileName.c_str(), DACL_SECURITY_INFORMATION, pSD))
result = true;
}
}
}
}
FreeLibrary(aLib);
return result;
}
bool Sexy::Deltree(const std::string& thePath)
{
bool success = true;
std::string aSourceDir = thePath;
if (aSourceDir.length() < 2)
return false;
if ((aSourceDir[aSourceDir.length() - 1] != '\\') ||
(aSourceDir[aSourceDir.length() - 1] != '/'))
aSourceDir += "\\";
WIN32_FIND_DATAA aFindData;
HANDLE aFindHandle = FindFirstFileA((aSourceDir + "*.*").c_str(), &aFindData);
if (aFindHandle == INVALID_HANDLE_VALUE)
return false;
do
{
if ((aFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
if ((strcmp(aFindData.cFileName, ".") != 0) &&
(strcmp(aFindData.cFileName, "..") != 0))
{
// Follow the directory
if (!Deltree(aSourceDir + aFindData.cFileName))
success = false;
}
}
else
{
std::string aFullName = aSourceDir + aFindData.cFileName;
if (!DeleteFileA(aFullName.c_str()))
success = false;
}
}
while (FindNextFileA(aFindHandle, &aFindData));
FindClose(aFindHandle);
if (rmdir(thePath.c_str()) == 0)
success = false;
return success;
}
bool Sexy::FileExists(const std::string& theFileName)
{
WIN32_FIND_DATAA aFindData;
HANDLE aFindHandle = FindFirstFileA(theFileName.c_str(), &aFindData);
if (aFindHandle == INVALID_HANDLE_VALUE)
return false;
FindClose(aFindHandle);
return true;
}
void Sexy::MkDir(const std::string& theDir)
{
std::string aPath = theDir;
int aCurPos = 0;
for (;;)
{
int aSlashPos = aPath.find_first_of("\\/", aCurPos);
if (aSlashPos == -1)
{
_mkdir(aPath.c_str());
break;
}
aCurPos = aSlashPos+1;
std::string aCurPath = aPath.substr(0, aSlashPos);
_mkdir(aCurPath.c_str());
}
}
std::string Sexy::GetFileName(const std::string& thePath, bool noExtension)
{
int aLastSlash = max((int) thePath.rfind('\\'), (int) thePath.rfind('/'));
if (noExtension)
{
int aLastDot = (int)thePath.rfind('.');
if (aLastDot > aLastSlash)
return thePath.substr(aLastSlash + 1, aLastDot - aLastSlash - 1);
}
if (aLastSlash == -1)
return thePath;
else
return thePath.substr(aLastSlash + 1);
}
std::string Sexy::GetFileDir(const std::string& thePath, bool withSlash)
{
int aLastSlash = max((int) thePath.rfind('\\'), (int) thePath.rfind('/'));
if (aLastSlash == -1)
return "";
else
{
if (withSlash)
return thePath.substr(0, aLastSlash+1);
else
return thePath.substr(0, aLastSlash);
}
}
std::string Sexy::RemoveTrailingSlash(const std::string& theDirectory)
{
int aLen = theDirectory.length();
if ((aLen > 0) && ((theDirectory[aLen-1] == '\\') || (theDirectory[aLen-1] == '/')))
return theDirectory.substr(0, aLen - 1);
else
return theDirectory;
}
std::string Sexy::AddTrailingSlash(const std::string& theDirectory, bool backSlash)
{
if (!theDirectory.empty())
{
char aChar = theDirectory[theDirectory.length()-1];
if (aChar!='\\' && aChar!='/')
return theDirectory + (backSlash?'\\':'/');
else
return theDirectory;
}
else
return "";
}
time_t Sexy::GetFileDate(const std::string& theFileName)
{
time_t aFileDate = 0;
WIN32_FIND_DATAA aFindData;
HANDLE aFindHandle = ::FindFirstFileA(theFileName.c_str(), &aFindData);
if (aFindHandle != INVALID_HANDLE_VALUE)
{
FILETIME aFileTime = aFindData.ftLastWriteTime;
//FileTimeToUnixTime(&aFileTime, &aFileDate, FALSE);
LONGLONG ll = (__int64) aFileTime.dwHighDateTime << 32;
ll = ll + aFileTime.dwLowDateTime - 116444736000000000;
aFileDate = (time_t) (ll/10000000);
FindClose(aFindHandle);
}
return aFileDate;
}
std::string Sexy::vformat(const char* fmt, va_list argPtr)
{
// We draw the line at a 1MB string.
const int maxSize = 1000000;
// If the string is less than 161 characters,
// allocate it on the stack because this saves
// the malloc/free time.
const int bufSize = 161;
char stackBuffer[bufSize];
int attemptedSize = bufSize - 1;
int numChars = 0;
#ifdef _WIN32
numChars = _vsnprintf(stackBuffer, attemptedSize, fmt, argPtr);
#else
numChars = vsnprintf(stackBuffer, attemptedSize, fmt, argPtr);
#endif
//cout << "NumChars: " << numChars << endl;
if ((numChars >= 0) && (numChars <= attemptedSize))
{
// Needed for case of 160-character printf thing
stackBuffer[numChars] = '\0';
// Got it on the first try.
return std::string(stackBuffer);
}
// Now use the heap.
char* heapBuffer = NULL;
while (((numChars == -1) || (numChars > attemptedSize)) &&
(attemptedSize < maxSize))
{
// Try a bigger size
attemptedSize *= 2;
heapBuffer = (char*)realloc(heapBuffer, (attemptedSize + 1));
#ifdef _WIN32
numChars = _vsnprintf(heapBuffer, attemptedSize, fmt, argPtr);
#else
numChars = vsnprintf(heapBuffer, attemptedSize, fmt, argPtr);
#endif
}
heapBuffer[numChars] = 0;
std::string result = std::string(heapBuffer);
free(heapBuffer);
return result;
}
//overloaded StrFormat: should only be used by the xml strings
std::string Sexy::StrFormat(const char* fmt ...)
{
va_list argList;
va_start(argList, fmt);
std::string result = vformat(fmt, argList);
va_end(argList);
return result;
}
std::wstring Sexy::vformat(const wchar_t* fmt, va_list argPtr)
{
// We draw the line at a 1MB string.
const int maxSize = 1000000;
// If the string is less than 161 characters,
// allocate it on the stack because this saves
// the malloc/free time.
const int bufSize = 161;
wchar_t stackBuffer[bufSize];
int attemptedSize = bufSize - 1;
int numChars = 0;
#ifdef _WIN32
numChars = _vsnwprintf(stackBuffer, attemptedSize, fmt, argPtr);
#else
numChars = vsnwprintf(stackBuffer, attemptedSize, fmt, argPtr);
#endif
//cout << "NumChars: " << numChars << endl;
if ((numChars >= 0) && (numChars <= attemptedSize))
{
// Needed for case of 160-character printf thing
stackBuffer[numChars] = '\0';
// Got it on the first try.
return std::wstring(stackBuffer);
}
// Now use the heap.
wchar_t* heapBuffer = NULL;
while (((numChars == -1) || (numChars > attemptedSize)) &&
(attemptedSize < maxSize))
{
// Try a bigger size
attemptedSize *= 2;
heapBuffer = (wchar_t*)realloc(heapBuffer, (attemptedSize + 1));
#ifdef _WIN32
numChars = _vsnwprintf(heapBuffer, attemptedSize, fmt, argPtr);
#else
numChars = vsnwprintf(heapBuffer, attemptedSize, fmt, argPtr);
#endif
}
heapBuffer[numChars] = 0;
std::wstring result = std::wstring(heapBuffer);
free(heapBuffer);
return result;
}
//overloaded StrFormat: should only be used by the xml strings
std::wstring Sexy::StrFormat(const wchar_t* fmt ...)
{
va_list argList;
va_start(argList, fmt);
std::wstring result = vformat(fmt, argList);
va_end(argList);
return result;
}
std::string Sexy::Evaluate(const std::string& theString, const DefinesMap& theDefinesMap)
{
std::string anEvaluatedString = theString;
for (;;)
{
int aPercentPos = anEvaluatedString.find('%');
if (aPercentPos == std::string::npos)
break;
int aSecondPercentPos = anEvaluatedString.find('%', aPercentPos + 1);
if (aSecondPercentPos == std::string::npos)
break;
std::string aName = anEvaluatedString.substr(aPercentPos + 1, aSecondPercentPos - aPercentPos - 1);
std::string aValue;
DefinesMap::const_iterator anItr = theDefinesMap.find(aName);
if (anItr != theDefinesMap.end())
aValue = anItr->second;
else
aValue = "";
anEvaluatedString.erase(anEvaluatedString.begin() + aPercentPos, anEvaluatedString.begin() + aSecondPercentPos + 1);
anEvaluatedString.insert(anEvaluatedString.begin() + aPercentPos, aValue.begin(), aValue.begin() + aValue.length());
}
return anEvaluatedString;
}
std::string Sexy::XMLDecodeString(const std::string& theString)
{
std::string aNewString;
int aUTF8Len = 0;
int aUTF8CurVal = 0;
for (ulong i = 0; i < theString.length(); i++)
{
char c = theString[i];
if (c == '&')
{
int aSemiPos = theString.find(';', i);
if (aSemiPos != -1)
{
std::string anEntName = theString.substr(i+1, aSemiPos-i-1);
i = aSemiPos;
if (anEntName == "lt")
c = '<';
else if (anEntName == "amp")
c = '&';
else if (anEntName == "gt")
c = '>';
else if (anEntName == "quot")
c = '"';
else if (anEntName == "apos")
c = '\'';
else if (anEntName == "nbsp")
c = ' ';
else if (anEntName == "cr")
c = '\n';
}
}
aNewString += c;
}
return aNewString;
}
std::wstring Sexy::XMLDecodeString(const std::wstring& theString)
{
std::wstring aNewString;
int aUTF8Len = 0;
int aUTF8CurVal = 0;
for (ulong i = 0; i < theString.length(); i++)
{
wchar_t c = theString[i];
if (c == L'&')
{
int aSemiPos = theString.find(L';', i);
if (aSemiPos != -1)
{
std::wstring anEntName = theString.substr(i+1, aSemiPos-i-1);
i = aSemiPos;
if (anEntName == L"lt")
c = L'<';
else if (anEntName == L"amp")
c = L'&';
else if (anEntName == L"gt")
c = L'>';
else if (anEntName == L"quot")
c = L'"';
else if (anEntName == L"apos")
c = L'\'';
else if (anEntName == L"nbsp")
c = L' ';
else if (anEntName == L"cr")
c = L'\n';
}
}
aNewString += c;
}
return aNewString;
}
std::string Sexy::XMLEncodeString(const std::string& theString)
{
std::string aNewString;
bool hasSpace = false;
for (ulong i = 0; i < theString.length(); i++)
{
char c = theString[i];
if (c == ' ')
{
if (hasSpace)
{
aNewString += " ";
continue;
}
hasSpace = true;
}
else
hasSpace = false;
/*if ((uchar) c >= 0x80)
{
// Convert to UTF
aNewString += (char) (0xC0 | ((c >> 6) & 0xFF));
aNewString += (char) (0x80 | (c & 0x3F));
}
else*/
{
switch (c)
{
case '<':
aNewString += "<";
break;
case '&':
aNewString += "&";
break;
case '>':
aNewString += ">";
break;
case '"':
aNewString += """;
break;
case '\'':
aNewString += "'";
break;
case '\n':
aNewString += "&cr;";
break;
default:
aNewString += c;
break;
}
}
}
return aNewString;
}
std::wstring Sexy::XMLEncodeString(const std::wstring& theString)
{
std::wstring aNewString;
bool hasSpace = false;
for (ulong i = 0; i < theString.length(); i++)
{
wchar_t c = theString[i];
if (c == ' ')
{
if (hasSpace)
{
aNewString += L" ";
continue;
}
hasSpace = true;
}
else
hasSpace = false;
/*if ((uchar) c >= 0x80)
{
// Convert to UTF
aNewString += (char) (0xC0 | ((c >> 6) & 0xFF));
aNewString += (char) (0x80 | (c & 0x3F));
}
else*/
{
switch (c)
{
case L'<':
aNewString += L"<";
break;
case L'&':
aNewString += L"&";
break;
case L'>':
aNewString += L">";
break;
case L'"':
aNewString += L""";
break;
case L'\'':
aNewString += L"'";
break;
case L'\n':
aNewString += L"&cr;";
break;
default:
aNewString += c;
break;
}
}
}
return aNewString;
}
std::string Sexy::Upper(const std::string& _data)
{
std::string s = _data;
std::transform(s.begin(), s.end(), s.begin(), toupper);
return s;
}
std::wstring Sexy::Upper(const std::wstring& _data)
{
std::wstring s = _data;
std::transform(s.begin(), s.end(), s.begin(), towupper);
return s;
}
std::string Sexy::Lower(const std::string& _data)
{
std::string s = _data;
std::transform(s.begin(), s.end(), s.begin(), tolower);
return s;
}
std::wstring Sexy::Lower(const std::wstring& _data)
{
std::wstring s = _data;
std::transform(s.begin(), s.end(), s.begin(), towlower);
return s;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int Sexy::StrFindNoCase(const char *theStr, const char *theFind)
{
int p1,p2;
int cp = 0;
const int len1 = (int)strlen(theStr);
const int len2 = (int)strlen(theFind);
while(cp < len1)
{
p1 = cp;
p2 = 0;
while(p1<len1 && p2<len2)
{
if(tolower(theStr[p1])!=tolower(theFind[p2]))
break;
p1++; p2++;
}
if(p2==len2)
return p1-len2;
cp++;
}
return -1;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool Sexy::StrPrefixNoCase(const char *theStr, const char *thePrefix, int maxLength)
{
int i;
char c1 = 0, c2 = 0;
for (i=0; i<maxLength; i++)
{
c1 = tolower(*theStr++);
c2 = tolower(*thePrefix++);
if (c1==0 || c2==0)
break;
if (c1!=c2)
return false;
}
return c2==0 || i==maxLength;
}