/* Stdhdr.cpp Written by Matthew Fisher Collection of very useful functions/macros/constants. See Stdhdr.h for a more thorough definition/explination of all constants/functions defined here. */ 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 &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 &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 &Output) { SignalError("wifstream seems to die on ASCII EOF character"); Output.FreeMemory(); wstring CurLine; while(!File.eof()) { getline(File, CurLine); if(!File.eof()) { Output.PushEnd(UnicodeString(CurLine.c_str())); } } } void GetFileLines(const String &Filename, Vector &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 &Output, UINT LineLimit) { Vector 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) { //Console::WriteString(String::UnsignedIntAsHex(CurCharacter) + String(" ")); 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 &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 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); } // // This hash function taken from http://www.burtleburtle.net/bob/hash/doobs.html // __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; /* Set up the internal state */ LocalLength = Length; a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ c = 0x9b9773e9; /*---------------------------------------- handle most of the key */ 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; } /*------------------------------------- handle the last 11 bytes */ c += Length; switch(LocalLength) /* all the case statements fall through */ { case 11: c += ((UINT)k[10]<<24); case 10: c += ((UINT)k[9]<<16); case 9 : c += ((UINT)k[8]<<8); /* the first byte of c is reserved for the length */ 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]; /* case 0: nothing left to add */ } HashMix(a, b, c); /*-------------------------------------------- report the result */ return c; } UINT64 Hash64(const BYTE *k, UINT Length) { UINT a, b, c, LocalLength; /* Set up the internal state */ LocalLength = Length; a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ c = 0x9b9773e9; /*---------------------------------------- handle most of the key */ 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; } /*------------------------------------- handle the last 11 bytes */ c += Length; switch(LocalLength) /* all the case statements fall through */ { case 11: c += ((UINT)k[10]<<24); case 10: c += ((UINT)k[9]<<16); case 9 : c += ((UINT)k[8]<<8); /* the first byte of c is reserved for the length */ 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]; /* case 0: nothing left to add */ } HashMix(a, b, c); /*-------------------------------------------- report the result */ return UINT64(c) + UINT64(UINT64(a) << 32); } // Create a process with the given command line, and wait until it returns 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(); // Start the child process. if( !CreateProcess( NULL, // No module name (use command line) FullCommandLine.CString(), // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure ) { SignalError("CreateProcess failed"); return -1; } if(Block) { // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); } // Close process and thread handles. 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); } }