namespace Utility
{
void CopyStringToClipboard(const String &S)
{
OpenClipboard(NULL);
EmptyClipboard();
HGLOBAL GlobalHandle;
UINT BytesToCopy = S.Length() + 1;
GlobalHandle = GlobalAlloc(GMEM_MOVEABLE, BytesToCopy);
if(GlobalHandle != NULL)
{
BYTE *StringPointer = (BYTE*)GlobalLock(GlobalHandle);
memcpy(StringPointer, S.CString(), BytesToCopy);
GlobalUnlock(GlobalHandle);
SetClipboardData(CF_TEXT, GlobalHandle);
}
CloseClipboard();
}
String LoadStringFromClipboard()
{
String Result;
OpenClipboard(NULL);
HGLOBAL GlobalHandle = GetClipboardData(CF_TEXT);
if(GlobalHandle != NULL)
{
const char *StringPointer = (const char *)GlobalLock(GlobalHandle);
if(StringPointer != NULL)
{
Result = StringPointer;
GlobalUnlock(GlobalHandle);
}
}
CloseClipboard();
return Result;
}
void GetClipboardLines(Vector<String> &Output)
{
Output.FreeMemory();
OpenClipboard(NULL);
HGLOBAL GlobalHandle = GetClipboardData(CF_TEXT);
if(GlobalHandle != NULL)
{
const char *StringPointer = (const char *)GlobalLock(GlobalHandle);
if(StringPointer != NULL)
{
String Result = StringPointer;
Result = Result.FindAndReplace(String('\r'), String());
Result.Partition('\n', Output);
GlobalUnlock(GlobalHandle);
}
}
CloseClipboard();
}
bool FileExists(const String &Filename)
{
ifstream File(Filename.CString());
return (!File.fail());
}
String GetNextLine(ifstream &File)
{
string CurLine;
getline(File, CurLine);
return String(CurLine.c_str());
}
void GetFileLines(ifstream &File, Vector<String> &Output, UINT minLineLength)
{
Output.FreeMemory();
string CurLine;
while(!File.fail())
{
getline(File, CurLine);
if(!File.fail() && CurLine.length() >= minLineLength)
{
Output.PushEnd();
Output.Last() = CurLine.c_str();
}
}
}
void GetUnicodeFileLines(wifstream &File, Vector<UnicodeString> &Output)
{
SignalError("wifstream seems to die on ASCII EOF character");
Output.FreeMemory();
wstring CurLine;
while(!File.eof())
{
getline<UnicodeCharacter>(File, CurLine);
if(!File.eof())
{
Output.PushEnd(UnicodeString(CurLine.c_str()));
}
}
}
void GetFileLines(const String &Filename, Vector<String> &Output, UINT minLineLength)
{
ifstream File(Filename.CString());
PersistentAssert(!File.fail(), String("Failed to open ") + Filename);
GetFileLines(File, Output, minLineLength);
}
void GetUnicodeFileLines(const String &Filename, Vector<UnicodeString> &Output, UINT LineLimit)
{
Vector<BYTE> Data;
Utility::GetFileData(Filename, Data);
const UINT Length = Data.Length() / 2;
const unsigned short *CArray = (unsigned short *)Data.CArray();
UINT StringCount = 0;
if(LineLimit == 0)
{
for(UINT Index = 0; Index < Length; Index++)
{
unsigned short CurCharacter = CArray[Index];
if(CurCharacter == 0x000D || CurCharacter == 0x000A)
{
if(Index < Length - 1 && (CArray[Index + 1] == 0x000D || CArray[Index + 1] == 0x000A))
{
Index++;
}
StringCount++;
}
}
Output.Allocate(StringCount);
}
else
{
Output.Allocate(LineLimit);
}
UINT StringIndex = 0;
UnicodeString *CurString = &(Output[0]);
bool Done = false;
for(UINT Index = 0; Index < Length && !Done; Index++)
{
unsigned short CurCharacter = CArray[Index];
if(CurCharacter == 0x000D || CurCharacter == 0x000A)
{
if(Index < Length - 1 && (CArray[Index + 1] == 0x000D || CArray[Index + 1] == 0x000A))
{
Index++;
}
if(StringIndex == LineLimit - 1)
{
Done = true;
}
else
{
StringIndex++;
if(StringIndex != Output.Length())
{
CurString = &(Output[StringIndex]);
}
}
}
else if(CurCharacter != 0xFEFF)
{
CurString->PushEnd(CurCharacter);
}
}
if(LineLimit != 0)
{
Output.ReSize(StringIndex + 1);
}
}
FILE* CheckedFOpen(const char *Filename, const char *Mode)
{
FILE *File = fopen(Filename, Mode);
PersistentAssert(File != NULL && !ferror(File), String("Failed to open file: ") + String(Filename));
return File;
}
UINT GetFileSize(const String &Filename)
{
BOOL Success;
WIN32_FILE_ATTRIBUTE_DATA Info;
Success = GetFileAttributesEx(Filename.CString(), GetFileExInfoStandard, (void*)&Info);
PersistentAssert(Success && Info.nFileSizeHigh == 0, String("GetFileAttributesEx failed on ") + Filename);
return Info.nFileSizeLow;
}
void GetFileData(const String &Filename, Vector<BYTE> &Output)
{
FILE *InputFile = Utility::CheckedFOpen(Filename.CString(), "rb");
UINT FileSize = Utility::GetFileSize(Filename);
Output.Allocate(FileSize);
Utility::CheckedFRead(Output.CArray(), sizeof(BYTE), FileSize, InputFile);
fclose(InputFile);
}
void CopyFile(const String &SourceFile, const String &DestFile)
{
Vector<BYTE> Data;
GetFileData(SourceFile, Data);
FILE *File = Utility::CheckedFOpen(DestFile.CString(), "wb");
Utility::CheckedFWrite(Data.CArray(), sizeof(BYTE), Data.Length(), File);
fclose(File);
}
void MessageBox(const char *String)
{
::MessageBox(NULL, String, "Data Report", MB_OK);
}
void MessageBox(const String &S)
{
::MessageBox(NULL, S.CString(), "Data Report", MB_OK);
}
__forceinline void HashMix(UINT &a, UINT &b, UINT &c)
{
a -= b; a -= c; a ^= (c>>13);
b -= c; b -= a; b ^= (a<<8);
c -= a; c -= b; c ^= (b>>13);
a -= b; a -= c; a ^= (c>>12);
b -= c; b -= a; b ^= (a<<16);
c -= a; c -= b; c ^= (b>>5);
a -= b; a -= c; a ^= (c>>3);
b -= c; b -= a; b ^= (a<<10);
c -= a; c -= b; c ^= (b>>15);
}
UINT Hash32(const BYTE *k, UINT Length)
{
UINT a, b, c, LocalLength;
LocalLength = Length;
a = b = 0x9e3779b9;
c = 0x9b9773e9;
while (LocalLength >= 12)
{
a += (k[0] + ((UINT)k[1]<<8) + ((UINT)k[2]<<16) + ((UINT)k[3]<<24));
b += (k[4] + ((UINT)k[5]<<8) + ((UINT)k[6]<<16) + ((UINT)k[7]<<24));
c += (k[8] + ((UINT)k[9]<<8) + ((UINT)k[10]<<16)+ ((UINT)k[11]<<24));
HashMix(a, b, c);
k += 12;
LocalLength -= 12;
}
c += Length;
switch(LocalLength)
{
case 11: c += ((UINT)k[10]<<24);
case 10: c += ((UINT)k[9]<<16);
case 9 : c += ((UINT)k[8]<<8);
case 8 : b += ((UINT)k[7]<<24);
case 7 : b += ((UINT)k[6]<<16);
case 6 : b += ((UINT)k[5]<<8);
case 5 : b += k[4];
case 4 : a += ((UINT)k[3]<<24);
case 3 : a += ((UINT)k[2]<<16);
case 2 : a += ((UINT)k[1]<<8);
case 1 : a += k[0];
}
HashMix(a, b, c);
return c;
}
UINT64 Hash64(const BYTE *k, UINT Length)
{
UINT a, b, c, LocalLength;
LocalLength = Length;
a = b = 0x9e3779b9;
c = 0x9b9773e9;
while (LocalLength >= 12)
{
a += (k[0] + ((UINT)k[1]<<8) + ((UINT)k[2]<<16) + ((UINT)k[3]<<24));
b += (k[4] + ((UINT)k[5]<<8) + ((UINT)k[6]<<16) + ((UINT)k[7]<<24));
c += (k[8] + ((UINT)k[9]<<8) + ((UINT)k[10]<<16)+ ((UINT)k[11]<<24));
HashMix(a, b, c);
k += 12;
LocalLength -= 12;
}
c += Length;
switch(LocalLength)
{
case 11: c += ((UINT)k[10]<<24);
case 10: c += ((UINT)k[9]<<16);
case 9 : c += ((UINT)k[8]<<8);
case 8 : b += ((UINT)k[7]<<24);
case 7 : b += ((UINT)k[6]<<16);
case 6 : b += ((UINT)k[5]<<8);
case 5 : b += k[4];
case 4 : a += ((UINT)k[3]<<24);
case 3 : a += ((UINT)k[2]<<16);
case 2 : a += ((UINT)k[1]<<8);
case 1 : a += k[0];
}
HashMix(a, b, c);
return UINT64(c) + UINT64(UINT64(a) << 32);
}
int RunCommand(const String &ExecutablePath, const String &CommandLine, bool Block)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
String FullCommandLine = ExecutablePath.CString() + String(" ") + CommandLine.CString();
if( !CreateProcess( NULL, FullCommandLine.CString(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) )
{
SignalError("CreateProcess failed");
return -1;
}
if(Block)
{
WaitForSingleObject( pi.hProcess, INFINITE );
}
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
return 0;
}
}
#if defined(_DEBUG)
void DebugOnlyAssert(bool Statement, const char *Description)
{
if(!Statement)
{
SignalError(Description);
}
}
void DebugOnlyAssert(bool Statement, const String &Description)
{
if(!Statement)
{
SignalError(Description.CString());
}
}
#endif
#if defined(_DEBUG) || defined(ALWAYS_ASSERT)
void SignalError(const char *Description)
{
MessageBox(NULL, Description, "Fatal Problem Encountered", MB_OK);
#ifdef _DEBUG
__asm int 3;
#endif
ExitProcess(1);
}
void SignalError(const String &Description)
{
MessageBox(NULL, Description.CString(), "Fatal Problem Encountered", MB_OK);
#ifdef _DEBUG
__asm int 3;
#endif
ExitProcess(1);
}
void Assert(bool Statement, const char *Description)
{
if(!Statement)
{
MessageBox(NULL, Description, "Fatal Problem Encountered", MB_OK);
#ifdef _DEBUG
__asm int 3;
#endif
ExitProcess(1);
}
}
void Assert(bool Statement, const String &Description)
{
if(!Statement)
{
MessageBox(NULL, Description.CString(), "Fatal Problem Encountered", MB_OK);
#ifdef _DEBUG
__asm int 3;
#endif
ExitProcess(1);
}
}
#endif
void PersistentSignalError(const char *Description)
{
MessageBox(NULL, Description, "Fatal Problem Encountered", MB_OK);
#ifdef _DEBUG
__asm int 3;
#endif
ExitProcess(1);
}
void PersistentSignalError(const String &Description)
{
MessageBox(NULL, Description.CString(), "Fatal Problem Encountered", MB_OK);
#ifdef _DEBUG
__asm int 3;
#endif
ExitProcess(1);
}
void PersistentAssert(bool Statement, const char *Description)
{
if(!Statement)
{
MessageBox(NULL, Description, "Fatal Problem Encountered", MB_OK);
#ifdef _DEBUG
__asm int 3;
#endif
ExitProcess(1);
}
}
void PersistentAssert(bool Statement, const String &Description)
{
if(!Statement)
{
MessageBox(NULL, Description.CString(), "Fatal Problem Encountered", MB_OK);
#ifdef _DEBUG
__asm int 3;
#endif
ExitProcess(1);
}
}