mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #588 from archshift/somebranch
Sweeping cleanup of Common
This commit is contained in:
		
						commit
						5f9939070e
					
				
					 19 changed files with 47 additions and 1422 deletions
				
			
		|  | @ -4,8 +4,6 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOU | ||||||
| set(SRCS | set(SRCS | ||||||
|             break_points.cpp |             break_points.cpp | ||||||
|             emu_window.cpp |             emu_window.cpp | ||||||
|             extended_trace.cpp |  | ||||||
|             file_search.cpp |  | ||||||
|             file_util.cpp |             file_util.cpp | ||||||
|             hash.cpp |             hash.cpp | ||||||
|             key_map.cpp |             key_map.cpp | ||||||
|  | @ -16,13 +14,11 @@ set(SRCS | ||||||
|             mem_arena.cpp |             mem_arena.cpp | ||||||
|             memory_util.cpp |             memory_util.cpp | ||||||
|             misc.cpp |             misc.cpp | ||||||
|             msg_handler.cpp |  | ||||||
|             scm_rev.cpp |             scm_rev.cpp | ||||||
|             string_util.cpp |             string_util.cpp | ||||||
|             symbols.cpp |             symbols.cpp | ||||||
|             thread.cpp |             thread.cpp | ||||||
|             timer.cpp |             timer.cpp | ||||||
|             utf8.cpp |  | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| set(HEADERS | set(HEADERS | ||||||
|  | @ -38,9 +34,7 @@ set(HEADERS | ||||||
|             cpu_detect.h |             cpu_detect.h | ||||||
|             debug_interface.h |             debug_interface.h | ||||||
|             emu_window.h |             emu_window.h | ||||||
|             extended_trace.h |  | ||||||
|             fifo_queue.h |             fifo_queue.h | ||||||
|             file_search.h |  | ||||||
|             file_util.h |             file_util.h | ||||||
|             hash.h |             hash.h | ||||||
|             key_map.h |             key_map.h | ||||||
|  | @ -53,7 +47,6 @@ set(HEADERS | ||||||
|             math_util.h |             math_util.h | ||||||
|             mem_arena.h |             mem_arena.h | ||||||
|             memory_util.h |             memory_util.h | ||||||
|             msg_handler.h |  | ||||||
|             platform.h |             platform.h | ||||||
|             scm_rev.h |             scm_rev.h | ||||||
|             scope_exit.h |             scope_exit.h | ||||||
|  | @ -64,7 +57,6 @@ set(HEADERS | ||||||
|             thread_queue_list.h |             thread_queue_list.h | ||||||
|             thunk.h |             thunk.h | ||||||
|             timer.h |             timer.h | ||||||
|             utf8.h |  | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| create_directory_groups(${SRCS} ${HEADERS}) | create_directory_groups(${SRCS} ${HEADERS}) | ||||||
|  |  | ||||||
|  | @ -637,7 +637,7 @@ public: | ||||||
|         Do(cookie); |         Do(cookie); | ||||||
|         if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) |         if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) | ||||||
|         { |         { | ||||||
|             PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); |             LOG_ERROR(Common, "After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); | ||||||
|             SetError(ERROR_FAILURE); |             SetError(ERROR_FAILURE); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -28,7 +28,6 @@ private: | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/msg_handler.h" |  | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
| #include "common/common_paths.h" | #include "common/common_paths.h" | ||||||
| #include "common/platform.h" | #include "common/platform.h" | ||||||
|  | @ -36,13 +35,11 @@ private: | ||||||
| #ifdef __APPLE__ | #ifdef __APPLE__ | ||||||
| // The Darwin ABI requires that stack frames be aligned to 16-byte boundaries.
 | // The Darwin ABI requires that stack frames be aligned to 16-byte boundaries.
 | ||||||
| // This is only needed on i386 gcc - x86_64 already aligns to 16 bytes.
 | // This is only needed on i386 gcc - x86_64 already aligns to 16 bytes.
 | ||||||
| #if defined __i386__ && defined __GNUC__ |     #if defined __i386__ && defined __GNUC__ | ||||||
| #undef STACKALIGN |         #undef STACKALIGN | ||||||
| #define STACKALIGN __attribute__((__force_align_arg_pointer__)) |         #define STACKALIGN __attribute__((__force_align_arg_pointer__)) | ||||||
| #endif |     #endif | ||||||
| 
 |  | ||||||
| #elif defined _WIN32 | #elif defined _WIN32 | ||||||
| 
 |  | ||||||
| // Check MSC ver
 | // Check MSC ver
 | ||||||
|     #if defined _MSC_VER && _MSC_VER <= 1000 |     #if defined _MSC_VER && _MSC_VER <= 1000 | ||||||
|         #error needs at least version 1000 of MSC |         #error needs at least version 1000 of MSC | ||||||
|  | @ -52,9 +49,6 @@ private: | ||||||
|     #define NOMINMAX |     #define NOMINMAX | ||||||
|     #endif |     #endif | ||||||
| 
 | 
 | ||||||
| // Memory leak checks
 |  | ||||||
|     #define CHECK_HEAP_INTEGRITY() |  | ||||||
| 
 |  | ||||||
| // Alignment
 | // Alignment
 | ||||||
|     #define MEMORY_ALIGNED16(x) __declspec(align(16)) x |     #define MEMORY_ALIGNED16(x) __declspec(align(16)) x | ||||||
|     #define MEMORY_ALIGNED32(x) __declspec(align(32)) x |     #define MEMORY_ALIGNED32(x) __declspec(align(32)) x | ||||||
|  | @ -62,57 +56,34 @@ private: | ||||||
|     #define MEMORY_ALIGNED128(x) __declspec(align(128)) x |     #define MEMORY_ALIGNED128(x) __declspec(align(128)) x | ||||||
|     #define MEMORY_ALIGNED16_DECL(x) __declspec(align(16)) x |     #define MEMORY_ALIGNED16_DECL(x) __declspec(align(16)) x | ||||||
|     #define MEMORY_ALIGNED64_DECL(x) __declspec(align(64)) x |     #define MEMORY_ALIGNED64_DECL(x) __declspec(align(64)) x | ||||||
| 
 |  | ||||||
| // Since they are always around on windows
 |  | ||||||
|     #define HAVE_WX 1 |  | ||||||
|     #define HAVE_OPENAL 1 |  | ||||||
| 
 |  | ||||||
|     #define HAVE_PORTAUDIO 1 |  | ||||||
| 
 |  | ||||||
| // Debug definitions
 |  | ||||||
|     #if defined(_DEBUG) |  | ||||||
|         #include <crtdbg.h> |  | ||||||
|         #undef CHECK_HEAP_INTEGRITY |  | ||||||
|         #define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");} |  | ||||||
|         // If you want to see how much a pain in the ass singletons are, for example:
 |  | ||||||
|         // {614} normal block at 0x030C5310, 188 bytes long.
 |  | ||||||
|         // Data: <Master Log      > 4D 61 73 74 65 72 20 4C 6F 67 00 00 00 00 00 00
 |  | ||||||
|         struct CrtDebugBreak { CrtDebugBreak(int spot) { _CrtSetBreakAlloc(spot); } }; |  | ||||||
|         //CrtDebugBreak breakAt(614);
 |  | ||||||
|     #endif // end DEBUG/FAST
 |  | ||||||
| 
 |  | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| // Windows compatibility
 | // Windows compatibility
 | ||||||
| #ifndef _WIN32 | #ifndef _WIN32 | ||||||
| #ifdef _LP64 |     #ifdef _LP64 | ||||||
| #define _M_X64 1 |         #define _M_X64 1 | ||||||
| #else |     #else | ||||||
| #define _M_IX86 1 |         #define _M_IX86 1 | ||||||
| #endif |     #endif | ||||||
| #define __forceinline inline __attribute__((always_inline)) |     #define __forceinline inline __attribute__((always_inline)) | ||||||
| #define MEMORY_ALIGNED16(x) __attribute__((aligned(16))) x |     #define MEMORY_ALIGNED16(x) __attribute__((aligned(16))) x | ||||||
| #define MEMORY_ALIGNED32(x) __attribute__((aligned(32))) x |     #define MEMORY_ALIGNED32(x) __attribute__((aligned(32))) x | ||||||
| #define MEMORY_ALIGNED64(x) __attribute__((aligned(64))) x |     #define MEMORY_ALIGNED64(x) __attribute__((aligned(64))) x | ||||||
| #define MEMORY_ALIGNED128(x) __attribute__((aligned(128))) x |     #define MEMORY_ALIGNED128(x) __attribute__((aligned(128))) x | ||||||
| #define MEMORY_ALIGNED16_DECL(x) __attribute__((aligned(16))) x |     #define MEMORY_ALIGNED16_DECL(x) __attribute__((aligned(16))) x | ||||||
| #define MEMORY_ALIGNED64_DECL(x) __attribute__((aligned(64))) x |     #define MEMORY_ALIGNED64_DECL(x) __attribute__((aligned(64))) x | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| #define __strdup _strdup |     #define __strdup _strdup | ||||||
| #define __getcwd _getcwd |     #define __getcwd _getcwd | ||||||
| #define __chdir _chdir |     #define __chdir _chdir | ||||||
| #else | #else | ||||||
| #define __strdup strdup |     #define __strdup strdup | ||||||
| #define __getcwd getcwd |     #define __getcwd getcwd | ||||||
| #define __chdir chdir |     #define __chdir chdir | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| // Dummy macro for marking translatable strings that can not be immediately translated.
 |  | ||||||
| // wxWidgets does not have a true dummy macro for this.
 |  | ||||||
| #define _trans(a) a |  | ||||||
| 
 |  | ||||||
| #if defined _M_GENERIC | #if defined _M_GENERIC | ||||||
| #  define _M_SSE 0x0 | #  define _M_SSE 0x0 | ||||||
| #elif defined __GNUC__ | #elif defined __GNUC__ | ||||||
|  |  | ||||||
|  | @ -24,11 +24,6 @@ template<> struct CompileTimeAssert<true> {}; | ||||||
| #define b32(x)  (b16(x) | (b16(x) >>16) ) | #define b32(x)  (b16(x) | (b16(x) >>16) ) | ||||||
| #define ROUND_UP_POW2(x)    (b32(x - 1) + 1) | #define ROUND_UP_POW2(x)    (b32(x - 1) + 1) | ||||||
| 
 | 
 | ||||||
| #define MIN(a, b)   ((a)<(b)?(a):(b)) |  | ||||||
| #define MAX(a, b)   ((a)>(b)?(a):(b)) |  | ||||||
| 
 |  | ||||||
| #define CLAMP(x, min, max)  (((x) > max) ? max : (((x) < min) ? min : (x))) |  | ||||||
| 
 |  | ||||||
| #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) | ||||||
| 
 | 
 | ||||||
| /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
 | /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
 | ||||||
|  | @ -38,9 +33,8 @@ template<> struct CompileTimeAssert<true> {}; | ||||||
| // helper macro to properly align structure members.
 | // helper macro to properly align structure members.
 | ||||||
| // Calling INSERT_PADDING_BYTES will add a new member variable with a name like "pad121",
 | // Calling INSERT_PADDING_BYTES will add a new member variable with a name like "pad121",
 | ||||||
| // depending on the current source line to make sure variable names are unique.
 | // depending on the current source line to make sure variable names are unique.
 | ||||||
| #define INSERT_PADDING_BYTES_HELPER1(x, y) x ## y | #define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)] | ||||||
| #define INSERT_PADDING_BYTES_HELPER2(x, y) INSERT_PADDING_BYTES_HELPER1(x, y) | #define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)] | ||||||
| #define INSERT_PADDING_BYTES(num_words) u8 INSERT_PADDING_BYTES_HELPER2(pad, __LINE__)[(num_words)] |  | ||||||
| 
 | 
 | ||||||
| #ifndef _MSC_VER | #ifndef _MSC_VER | ||||||
| 
 | 
 | ||||||
|  | @ -148,15 +142,6 @@ inline u64 _rotr64(u64 x, unsigned int shift){ | ||||||
|     #define Crash() {DebugBreak();} |     #define Crash() {DebugBreak();} | ||||||
| #endif // _MSC_VER ndef
 | #endif // _MSC_VER ndef
 | ||||||
| 
 | 
 | ||||||
| // Dolphin's min and max functions
 |  | ||||||
| #undef min |  | ||||||
| #undef max |  | ||||||
| 
 |  | ||||||
| template<class T> |  | ||||||
| inline T min(const T& a, const T& b) {return a > b ? b : a;} |  | ||||||
| template<class T> |  | ||||||
| inline T max(const T& a, const T& b) {return a > b ? a : b;} |  | ||||||
| 
 |  | ||||||
| // Generic function to get last error message.
 | // Generic function to get last error message.
 | ||||||
| // Call directly after the command or use the error num.
 | // Call directly after the command or use the error num.
 | ||||||
| // This function might change the error code.
 | // This function might change the error code.
 | ||||||
|  | @ -233,13 +218,4 @@ inline void swap<8>(u8* data) | ||||||
|     *reinterpret_cast<u64*>(data) = swap64(data); |     *reinterpret_cast<u64*>(data) = swap64(data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename T> |  | ||||||
| inline T FromBigEndian(T data) |  | ||||||
| { |  | ||||||
|     //static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
 |  | ||||||
| 
 |  | ||||||
|     swap<sizeof(data)>(reinterpret_cast<u8*>(&data)); |  | ||||||
|     return data; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| }  // Namespace Common
 | }  // Namespace Common
 | ||||||
|  |  | ||||||
|  | @ -1,428 +0,0 @@ | ||||||
| // --------------------------------------------------------------------------------------
 |  | ||||||
| //
 |  | ||||||
| // Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
 |  | ||||||
| // For companies(Austin,TX): If you would like to get my resume, send an email.
 |  | ||||||
| //
 |  | ||||||
| // The source is free, but if you want to use it, mention my name and e-mail address
 |  | ||||||
| //
 |  | ||||||
| // History:
 |  | ||||||
| //    1.0      Initial version                  Zoltan Csizmadia
 |  | ||||||
| //    1.1      WhineCube version                Masken
 |  | ||||||
| //    1.2      Dolphin version                  Masken
 |  | ||||||
| //
 |  | ||||||
| // --------------------------------------------------------------------------------------
 |  | ||||||
| 
 |  | ||||||
| #if defined(WIN32) |  | ||||||
| #include <cstdio> |  | ||||||
| #include <windows.h> |  | ||||||
| #include "common/extended_trace.h" |  | ||||||
| #include "common/string_util.h" |  | ||||||
| using namespace std; |  | ||||||
| 
 |  | ||||||
| #include <tchar.h> |  | ||||||
| #include <ImageHlp.h> |  | ||||||
| 
 |  | ||||||
| #define BUFFERSIZE   0x200 |  | ||||||
| #pragma warning(disable:4996) |  | ||||||
| 
 |  | ||||||
| // Unicode safe char* -> TCHAR* conversion
 |  | ||||||
| void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut ) |  | ||||||
| { |  | ||||||
| #if defined(UNICODE)||defined(_UNICODE) |  | ||||||
|     ULONG index = 0; |  | ||||||
|     PCSTR lpAct = lpszIn; |  | ||||||
| 
 |  | ||||||
|     for( ; ; lpAct++ ) |  | ||||||
|     { |  | ||||||
|         lpszOut[index++] = (TCHAR)(*lpAct); |  | ||||||
|         if ( *lpAct == 0 ) |  | ||||||
|             break; |  | ||||||
|     } |  | ||||||
| #else |  | ||||||
|     // This is trivial :)
 |  | ||||||
|     strcpy( lpszOut, lpszIn ); |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Let's figure out the path for the symbol files
 |  | ||||||
| // Search path= ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;" + lpszIniPath
 |  | ||||||
| // Note: There is no size check for lpszSymbolPath!
 |  | ||||||
| static void InitSymbolPath( PSTR lpszSymbolPath, PCSTR lpszIniPath ) |  | ||||||
| { |  | ||||||
|     CHAR lpszPath[BUFFERSIZE]; |  | ||||||
| 
 |  | ||||||
|     // Creating the default path
 |  | ||||||
|     // ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;"
 |  | ||||||
|     strcpy( lpszSymbolPath, "." ); |  | ||||||
| 
 |  | ||||||
|     // environment variable _NT_SYMBOL_PATH
 |  | ||||||
|     if ( GetEnvironmentVariableA( "_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE ) ) |  | ||||||
|     { |  | ||||||
|         strcat( lpszSymbolPath, ";" ); |  | ||||||
|         strcat( lpszSymbolPath, lpszPath ); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // environment variable _NT_ALTERNATE_SYMBOL_PATH
 |  | ||||||
|     if ( GetEnvironmentVariableA( "_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE ) ) |  | ||||||
|     { |  | ||||||
|         strcat( lpszSymbolPath, ";" ); |  | ||||||
|         strcat( lpszSymbolPath, lpszPath ); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // environment variable SYSTEMROOT
 |  | ||||||
|     if ( GetEnvironmentVariableA( "SYSTEMROOT", lpszPath, BUFFERSIZE ) ) |  | ||||||
|     { |  | ||||||
|         strcat( lpszSymbolPath, ";" ); |  | ||||||
|         strcat( lpszSymbolPath, lpszPath ); |  | ||||||
|         strcat( lpszSymbolPath, ";" ); |  | ||||||
| 
 |  | ||||||
|         // SYSTEMROOT\System32
 |  | ||||||
|         strcat( lpszSymbolPath, lpszPath ); |  | ||||||
|         strcat( lpszSymbolPath, "\\System32" ); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Add user defined path
 |  | ||||||
|     if ( lpszIniPath != nullptr ) |  | ||||||
|         if ( lpszIniPath[0] != '\0' ) |  | ||||||
|         { |  | ||||||
|             strcat( lpszSymbolPath, ";" ); |  | ||||||
|             strcat( lpszSymbolPath, lpszIniPath ); |  | ||||||
|         } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Uninitialize the loaded symbol files
 |  | ||||||
| BOOL UninitSymInfo() { |  | ||||||
|     return SymCleanup( GetCurrentProcess() ); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Initializes the symbol files
 |  | ||||||
| BOOL InitSymInfo( PCSTR lpszInitialSymbolPath ) |  | ||||||
| { |  | ||||||
|     CHAR     lpszSymbolPath[BUFFERSIZE]; |  | ||||||
|     DWORD    symOptions = SymGetOptions(); |  | ||||||
| 
 |  | ||||||
|     symOptions |= SYMOPT_LOAD_LINES; |  | ||||||
|     symOptions &= ~SYMOPT_UNDNAME; |  | ||||||
|     SymSetOptions( symOptions ); |  | ||||||
|     InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath ); |  | ||||||
| 
 |  | ||||||
|     return SymInitialize( GetCurrentProcess(), lpszSymbolPath, TRUE); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Get the module name from a given address
 |  | ||||||
| static BOOL GetModuleNameFromAddress( UINT address, LPTSTR lpszModule ) |  | ||||||
| { |  | ||||||
|     BOOL              ret = FALSE; |  | ||||||
|     IMAGEHLP_MODULE   moduleInfo; |  | ||||||
| 
 |  | ||||||
|     ::ZeroMemory( &moduleInfo, sizeof(moduleInfo) ); |  | ||||||
|     moduleInfo.SizeOfStruct = sizeof(moduleInfo); |  | ||||||
| 
 |  | ||||||
|     if ( SymGetModuleInfo( GetCurrentProcess(), (DWORD)address, &moduleInfo ) ) |  | ||||||
|     { |  | ||||||
|         // Got it!
 |  | ||||||
|         PCSTR2LPTSTR( moduleInfo.ModuleName, lpszModule ); |  | ||||||
|         ret = TRUE; |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|         // Not found :(
 |  | ||||||
|         _tcscpy( lpszModule, _T("?") ); |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Get function prototype and parameter info from ip address and stack address
 |  | ||||||
| static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol ) |  | ||||||
| { |  | ||||||
|     BOOL              ret = FALSE; |  | ||||||
|     DWORD             dwSymSize = 10000; |  | ||||||
|     TCHAR             lpszUnDSymbol[BUFFERSIZE]=_T("?"); |  | ||||||
|     CHAR              lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?"; |  | ||||||
|     LPTSTR            lpszParamSep = nullptr; |  | ||||||
|     LPTSTR            lpszParsed = lpszUnDSymbol; |  | ||||||
|     PIMAGEHLP_SYMBOL  pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize ); |  | ||||||
| 
 |  | ||||||
|     ::ZeroMemory( pSym, dwSymSize ); |  | ||||||
|     pSym->SizeOfStruct = dwSymSize; |  | ||||||
|     pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL); |  | ||||||
| 
 |  | ||||||
|     // Set the default to unknown
 |  | ||||||
|     _tcscpy( lpszSymbol, _T("?") ); |  | ||||||
| 
 |  | ||||||
|     // Get symbol info for IP
 |  | ||||||
| #ifndef _M_X64 |  | ||||||
|     DWORD             dwDisp = 0; |  | ||||||
|     if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) ) |  | ||||||
| #else |  | ||||||
|     //makes it compile but hell im not sure if this works...
 |  | ||||||
|     DWORD64           dwDisp = 0; |  | ||||||
|     if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) ) |  | ||||||
| #endif |  | ||||||
|     { |  | ||||||
|         // Make the symbol readable for humans
 |  | ||||||
|         UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE, |  | ||||||
|             UNDNAME_COMPLETE | |  | ||||||
|             UNDNAME_NO_THISTYPE | |  | ||||||
|             UNDNAME_NO_SPECIAL_SYMS | |  | ||||||
|             UNDNAME_NO_MEMBER_TYPE | |  | ||||||
|             UNDNAME_NO_MS_KEYWORDS | |  | ||||||
|             UNDNAME_NO_ACCESS_SPECIFIERS ); |  | ||||||
| 
 |  | ||||||
|         // Symbol information is ANSI string
 |  | ||||||
|         PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol ); |  | ||||||
| 
 |  | ||||||
|         // I am just smarter than the symbol file :)
 |  | ||||||
|         if (_tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0) |  | ||||||
|             _tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)")); |  | ||||||
|         else if (_tcscmp(lpszUnDSymbol, _T("_main")) == 0) |  | ||||||
|             _tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)")); |  | ||||||
|         else if (_tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0) |  | ||||||
|             _tcscpy(lpszUnDSymbol, _T("mainCRTStartup()")); |  | ||||||
|         else if (_tcscmp(lpszUnDSymbol, _T("_wmain")) == 0) |  | ||||||
|             _tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)")); |  | ||||||
|         else if (_tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0) |  | ||||||
|             _tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()")); |  | ||||||
| 
 |  | ||||||
|         lpszSymbol[0] = _T('\0'); |  | ||||||
| 
 |  | ||||||
|         // Let's go through the stack, and modify the function prototype, and insert the actual
 |  | ||||||
|         // parameter values from the stack
 |  | ||||||
|         if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == nullptr && _tcsstr( lpszUnDSymbol, _T("()") ) == nullptr) |  | ||||||
|         { |  | ||||||
|             ULONG index = 0; |  | ||||||
|             for( ; ; index++ ) |  | ||||||
|             { |  | ||||||
|                 lpszParamSep = _tcschr( lpszParsed, _T(',') ); |  | ||||||
|                 if ( lpszParamSep == nullptr ) |  | ||||||
|                     break; |  | ||||||
| 
 |  | ||||||
|                 *lpszParamSep = _T('\0'); |  | ||||||
| 
 |  | ||||||
|                 _tcscat( lpszSymbol, lpszParsed ); |  | ||||||
|                 _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) ); |  | ||||||
| 
 |  | ||||||
|                 lpszParsed = lpszParamSep + 1; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             lpszParamSep = _tcschr( lpszParsed, _T(')') ); |  | ||||||
|             if ( lpszParamSep != nullptr ) |  | ||||||
|             { |  | ||||||
|                 *lpszParamSep = _T('\0'); |  | ||||||
| 
 |  | ||||||
|                 _tcscat( lpszSymbol, lpszParsed ); |  | ||||||
|                 _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) ); |  | ||||||
| 
 |  | ||||||
|                 lpszParsed = lpszParamSep + 1; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         _tcscat( lpszSymbol, lpszParsed ); |  | ||||||
| 
 |  | ||||||
|         ret = TRUE; |  | ||||||
|     } |  | ||||||
|     GlobalFree( pSym ); |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Get source file name and line number from IP address
 |  | ||||||
| // The output format is: "sourcefile(linenumber)" or
 |  | ||||||
| //                       "modulename!address" or
 |  | ||||||
| //                       "address"
 |  | ||||||
| static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo ) |  | ||||||
| { |  | ||||||
|     BOOL           ret = FALSE; |  | ||||||
|     IMAGEHLP_LINE  lineInfo; |  | ||||||
|     DWORD          dwDisp; |  | ||||||
|     TCHAR          lpszFileName[BUFFERSIZE] = _T(""); |  | ||||||
|     TCHAR          lpModuleInfo[BUFFERSIZE] = _T(""); |  | ||||||
| 
 |  | ||||||
|     _tcscpy( lpszSourceInfo, _T("?(?)") ); |  | ||||||
| 
 |  | ||||||
|     ::ZeroMemory( &lineInfo, sizeof( lineInfo ) ); |  | ||||||
|     lineInfo.SizeOfStruct = sizeof( lineInfo ); |  | ||||||
| 
 |  | ||||||
|     if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) ) |  | ||||||
|     { |  | ||||||
|         // Got it. Let's use "sourcefile(linenumber)" format
 |  | ||||||
|         PCSTR2LPTSTR( lineInfo.FileName, lpszFileName ); |  | ||||||
|         TCHAR fname[_MAX_FNAME]; |  | ||||||
|         TCHAR ext[_MAX_EXT]; |  | ||||||
|         _tsplitpath(lpszFileName, nullptr, nullptr, fname, ext); |  | ||||||
|         _stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber ); |  | ||||||
|         ret = TRUE; |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // There is no source file information. :(
 |  | ||||||
|         // Let's use the "modulename!address" format
 |  | ||||||
|         GetModuleNameFromAddress( address, lpModuleInfo ); |  | ||||||
| 
 |  | ||||||
|         if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0')) |  | ||||||
|             // There is no modulename information. :((
 |  | ||||||
|             // Let's use the "address" format
 |  | ||||||
|             _stprintf( lpszSourceInfo, _T("0x%08X"), address ); |  | ||||||
|         else |  | ||||||
|             _stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address ); |  | ||||||
| 
 |  | ||||||
|         ret = FALSE; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack) |  | ||||||
| { |  | ||||||
|     TCHAR symInfo[BUFFERSIZE] = _T("?"); |  | ||||||
|     TCHAR srcInfo[BUFFERSIZE] = _T("?"); |  | ||||||
| 
 |  | ||||||
|     GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo); |  | ||||||
|     GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo); |  | ||||||
|     etfprint(file, "     " + Common::TStrToUTF8(srcInfo) + " : " + Common::TStrToUTF8(symInfo) + "\n"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file ) |  | ||||||
| { |  | ||||||
|     STACKFRAME     callStack; |  | ||||||
|     BOOL           bResult; |  | ||||||
|     CONTEXT        context; |  | ||||||
|     HANDLE         hProcess = GetCurrentProcess(); |  | ||||||
| 
 |  | ||||||
|     // If it's not this thread, let's suspend it, and resume it at the end
 |  | ||||||
|     if ( hThread != GetCurrentThread() ) |  | ||||||
|         if ( SuspendThread( hThread ) == -1 ) |  | ||||||
|         { |  | ||||||
|             // whaaat ?!
 |  | ||||||
|             etfprint(file, "Call stack info failed\n"); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         ::ZeroMemory( &context, sizeof(context) ); |  | ||||||
|         context.ContextFlags = CONTEXT_FULL; |  | ||||||
| 
 |  | ||||||
|         if ( !GetThreadContext( hThread, &context ) ) |  | ||||||
|         { |  | ||||||
|             etfprint(file, "Call stack info failed\n"); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         ::ZeroMemory( &callStack, sizeof(callStack) ); |  | ||||||
| #ifndef _M_X64 |  | ||||||
|         callStack.AddrPC.Offset    = context.Eip; |  | ||||||
|         callStack.AddrStack.Offset = context.Esp; |  | ||||||
|         callStack.AddrFrame.Offset = context.Ebp; |  | ||||||
| #else |  | ||||||
|         callStack.AddrPC.Offset    = context.Rip; |  | ||||||
|         callStack.AddrStack.Offset = context.Rsp; |  | ||||||
|         callStack.AddrFrame.Offset = context.Rbp; |  | ||||||
| #endif |  | ||||||
|         callStack.AddrPC.Mode      = AddrModeFlat; |  | ||||||
|         callStack.AddrStack.Mode   = AddrModeFlat; |  | ||||||
|         callStack.AddrFrame.Mode   = AddrModeFlat; |  | ||||||
| 
 |  | ||||||
|         etfprint(file, "Call stack info: \n"); |  | ||||||
|         etfprint(file, lpszMessage); |  | ||||||
| 
 |  | ||||||
|         PrintFunctionAndSourceInfo(file, callStack); |  | ||||||
| 
 |  | ||||||
|         for( ULONG index = 0; ; index++ ) |  | ||||||
|         { |  | ||||||
|             bResult = StackWalk( |  | ||||||
|                 IMAGE_FILE_MACHINE_I386, |  | ||||||
|                 hProcess, |  | ||||||
|                 hThread, |  | ||||||
|                 &callStack, |  | ||||||
|                 nullptr, |  | ||||||
|                 nullptr, |  | ||||||
|                 SymFunctionTableAccess, |  | ||||||
|                 SymGetModuleBase, |  | ||||||
|                 nullptr); |  | ||||||
| 
 |  | ||||||
|             if ( index == 0 ) |  | ||||||
|                 continue; |  | ||||||
| 
 |  | ||||||
|             if( !bResult || callStack.AddrFrame.Offset == 0 ) |  | ||||||
|                 break; |  | ||||||
| 
 |  | ||||||
|             PrintFunctionAndSourceInfo(file, callStack); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if ( hThread != GetCurrentThread() ) |  | ||||||
|             ResumeThread( hThread ); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) |  | ||||||
| { |  | ||||||
|     STACKFRAME     callStack; |  | ||||||
|     BOOL           bResult; |  | ||||||
|     TCHAR          symInfo[BUFFERSIZE] = _T("?"); |  | ||||||
|     TCHAR          srcInfo[BUFFERSIZE] = _T("?"); |  | ||||||
|     HANDLE         hProcess = GetCurrentProcess(); |  | ||||||
| 
 |  | ||||||
|     // If it's not this thread, let's suspend it, and resume it at the end
 |  | ||||||
|     if ( hThread != GetCurrentThread() ) |  | ||||||
|         if ( SuspendThread( hThread ) == -1 ) |  | ||||||
|         { |  | ||||||
|             // whaaat ?!
 |  | ||||||
|             etfprint(file, "Call stack info failed\n"); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         ::ZeroMemory( &callStack, sizeof(callStack) ); |  | ||||||
|         callStack.AddrPC.Offset    = eip; |  | ||||||
|         callStack.AddrStack.Offset = esp; |  | ||||||
|         callStack.AddrFrame.Offset = ebp; |  | ||||||
|         callStack.AddrPC.Mode      = AddrModeFlat; |  | ||||||
|         callStack.AddrStack.Mode   = AddrModeFlat; |  | ||||||
|         callStack.AddrFrame.Mode   = AddrModeFlat; |  | ||||||
| 
 |  | ||||||
|         etfprint(file, "Call stack info: \n"); |  | ||||||
|         etfprint(file, lpszMessage); |  | ||||||
| 
 |  | ||||||
|         PrintFunctionAndSourceInfo(file, callStack); |  | ||||||
| 
 |  | ||||||
|         for( ULONG index = 0; ; index++ ) |  | ||||||
|         { |  | ||||||
|             bResult = StackWalk( |  | ||||||
|                 IMAGE_FILE_MACHINE_I386, |  | ||||||
|                 hProcess, |  | ||||||
|                 hThread, |  | ||||||
|                 &callStack, |  | ||||||
|                 nullptr, |  | ||||||
|                 nullptr, |  | ||||||
|                 SymFunctionTableAccess, |  | ||||||
|                 SymGetModuleBase, |  | ||||||
|                 nullptr); |  | ||||||
| 
 |  | ||||||
|             if ( index == 0 ) |  | ||||||
|                 continue; |  | ||||||
| 
 |  | ||||||
|             if( !bResult || callStack.AddrFrame.Offset == 0 ) |  | ||||||
|                 break; |  | ||||||
| 
 |  | ||||||
|             PrintFunctionAndSourceInfo(file, callStack); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if ( hThread != GetCurrentThread() ) |  | ||||||
|             ResumeThread( hThread ); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| char g_uefbuf[2048]; |  | ||||||
| 
 |  | ||||||
| void etfprintf(FILE *file, const char *format, ...) |  | ||||||
| { |  | ||||||
|     va_list ap; |  | ||||||
|     va_start(ap, format); |  | ||||||
|     int len = vsprintf(g_uefbuf, format, ap); |  | ||||||
|     fwrite(g_uefbuf, 1, len, file); |  | ||||||
|     va_end(ap); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void etfprint(FILE *file, const std::string &text) |  | ||||||
| { |  | ||||||
|     size_t len = text.length(); |  | ||||||
|     fwrite(text.data(), 1, len, file); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif //WIN32
 |  | ||||||
|  | @ -1,50 +0,0 @@ | ||||||
| // -----------------------------------------------------------------------------------------
 |  | ||||||
| //
 |  | ||||||
| // Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
 |  | ||||||
| // For companies(Austin,TX): If you would like to get my resume, send an email.
 |  | ||||||
| //
 |  | ||||||
| // The source is free, but if you want to use it, mention my name and e-mail address
 |  | ||||||
| //
 |  | ||||||
| // History:
 |  | ||||||
| //    1.0      Initial version                  Zoltan Csizmadia
 |  | ||||||
| //    1.1      WhineCube version                Masken
 |  | ||||||
| //    1.2      Dolphin version                  Masken
 |  | ||||||
| //
 |  | ||||||
| // ----------------------------------------------------------------------------------------
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #if defined(WIN32) |  | ||||||
| 
 |  | ||||||
| #include <windows.h> |  | ||||||
| #include <tchar.h> |  | ||||||
| 
 |  | ||||||
| #include <string> |  | ||||||
| 
 |  | ||||||
| #pragma comment( lib, "imagehlp.lib" ) |  | ||||||
| 
 |  | ||||||
| #define EXTENDEDTRACEINITIALIZE( IniSymbolPath )    InitSymInfo( IniSymbolPath ) |  | ||||||
| #define EXTENDEDTRACEUNINITIALIZE()                    UninitSymInfo() |  | ||||||
| #define STACKTRACE(file)                            StackTrace( GetCurrentThread(), "", file) |  | ||||||
| #define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp) |  | ||||||
| // class File;
 |  | ||||||
| 
 |  | ||||||
| BOOL InitSymInfo( PCSTR ); |  | ||||||
| BOOL UninitSymInfo(); |  | ||||||
| void StackTrace(HANDLE, char const* msg, FILE *file); |  | ||||||
| void StackTrace(HANDLE, char const* msg, FILE *file, DWORD eip, DWORD esp, DWORD ebp); |  | ||||||
| 
 |  | ||||||
| // functions by Masken
 |  | ||||||
| void etfprintf(FILE *file, const char *format, ...); |  | ||||||
| void etfprint(FILE *file, const std::string &text); |  | ||||||
| #define UEFBUFSIZE 2048 |  | ||||||
| extern char g_uefbuf[UEFBUFSIZE]; |  | ||||||
| 
 |  | ||||||
| #else    // not WIN32
 |  | ||||||
| 
 |  | ||||||
| #define EXTENDEDTRACEINITIALIZE( IniSymbolPath )    ((void)0) |  | ||||||
| #define EXTENDEDTRACEUNINITIALIZE()                    ((void)0) |  | ||||||
| #define STACKTRACE(file)                            ((void)0) |  | ||||||
| #define STACKTRACE2(file, eip, esp, ebp)            ((void)0) |  | ||||||
| 
 |  | ||||||
| #endif    // WIN32
 |  | ||||||
|  | @ -1,103 +0,0 @@ | ||||||
| // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include "common/common.h" |  | ||||||
| 
 |  | ||||||
| #ifndef _WIN32 |  | ||||||
| #include <dirent.h> |  | ||||||
| #else |  | ||||||
| #include <windows.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #include <algorithm> |  | ||||||
| 
 |  | ||||||
| #include "common/file_search.h" |  | ||||||
| #include "common/string_util.h" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| CFileSearch::CFileSearch(const CFileSearch::XStringVector& _rSearchStrings, const CFileSearch::XStringVector& _rDirectories) |  | ||||||
| { |  | ||||||
|     // Reverse the loop order for speed?
 |  | ||||||
|     for (size_t j = 0; j < _rSearchStrings.size(); j++) |  | ||||||
|     { |  | ||||||
|         for (size_t i = 0; i < _rDirectories.size(); i++) |  | ||||||
|         { |  | ||||||
|             FindFiles(_rSearchStrings[j], _rDirectories[i]); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath) |  | ||||||
| { |  | ||||||
|     std::string GCMSearchPath; |  | ||||||
|     Common::BuildCompleteFilename(GCMSearchPath, _strPath, _searchString); |  | ||||||
| #ifdef _WIN32 |  | ||||||
|     WIN32_FIND_DATA findData; |  | ||||||
|     HANDLE FindFirst = FindFirstFile(Common::UTF8ToTStr(GCMSearchPath).c_str(), &findData); |  | ||||||
| 
 |  | ||||||
|     if (FindFirst != INVALID_HANDLE_VALUE) |  | ||||||
|     { |  | ||||||
|         bool bkeepLooping = true; |  | ||||||
| 
 |  | ||||||
|         while (bkeepLooping) |  | ||||||
|         { |  | ||||||
|             if (findData.cFileName[0] != '.') |  | ||||||
|             { |  | ||||||
|                 std::string strFilename; |  | ||||||
|                 Common::BuildCompleteFilename(strFilename, _strPath, Common::TStrToUTF8(findData.cFileName)); |  | ||||||
|                 m_FileNames.push_back(strFilename); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     FindClose(FindFirst); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #else |  | ||||||
|     // TODO: super lame/broken
 |  | ||||||
| 
 |  | ||||||
|     auto end_match(_searchString); |  | ||||||
| 
 |  | ||||||
|     // assuming we have a "*.blah"-like pattern
 |  | ||||||
|     if (!end_match.empty() && end_match[0] == '*') |  | ||||||
|         end_match.erase(0, 1); |  | ||||||
| 
 |  | ||||||
|     // ugly
 |  | ||||||
|     if (end_match == ".*") |  | ||||||
|         end_match.clear(); |  | ||||||
| 
 |  | ||||||
|     DIR* dir = opendir(_strPath.c_str()); |  | ||||||
| 
 |  | ||||||
|     if (!dir) |  | ||||||
|         return; |  | ||||||
| 
 |  | ||||||
|     while (auto const dp = readdir(dir)) |  | ||||||
|     { |  | ||||||
|         std::string found(dp->d_name); |  | ||||||
| 
 |  | ||||||
|         if ((found != ".") && (found != "..") |  | ||||||
|             && (found.size() >= end_match.size()) |  | ||||||
|             && std::equal(end_match.rbegin(), end_match.rend(), found.rbegin())) |  | ||||||
|         { |  | ||||||
|             std::string full_name; |  | ||||||
|             if (_strPath.c_str()[_strPath.size()-1] == DIR_SEP_CHR) |  | ||||||
|                 full_name = _strPath + found; |  | ||||||
|             else |  | ||||||
|                 full_name = _strPath + DIR_SEP + found; |  | ||||||
| 
 |  | ||||||
|             m_FileNames.push_back(full_name); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     closedir(dir); |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const CFileSearch::XStringVector& CFileSearch::GetFileNames() const |  | ||||||
| { |  | ||||||
|     return m_FileNames; |  | ||||||
| } |  | ||||||
|  | @ -1,23 +0,0 @@ | ||||||
| // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <string> |  | ||||||
| #include <vector> |  | ||||||
| 
 |  | ||||||
| class CFileSearch |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|     typedef std::vector<std::string>XStringVector; |  | ||||||
| 
 |  | ||||||
|     CFileSearch(const XStringVector& _rSearchStrings, const XStringVector& _rDirectories); |  | ||||||
|     const XStringVector& GetFileNames() const; |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
| 
 |  | ||||||
|     void FindFiles(const std::string& _searchString, const std::string& _strPath); |  | ||||||
| 
 |  | ||||||
|     XStringVector m_FileNames; |  | ||||||
| }; |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <algorithm> | ||||||
| 
 | 
 | ||||||
| #include "common/hash.h" | #include "common/hash.h" | ||||||
| #if _M_SSE >= 0x402 | #if _M_SSE >= 0x402 | ||||||
|  | @ -155,7 +156,7 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) | ||||||
|     const u8 * data = (const u8*)src; |     const u8 * data = (const u8*)src; | ||||||
|     const int nblocks = len / 16; |     const int nblocks = len / 16; | ||||||
|     u32 Step = (len / 8); |     u32 Step = (len / 8); | ||||||
|     if(samples == 0) samples = max(Step, 1u); |     if(samples == 0) samples = std::max(Step, 1u); | ||||||
|     Step = Step / samples; |     Step = Step / samples; | ||||||
|     if(Step < 1) Step = 1; |     if(Step < 1) Step = 1; | ||||||
| 
 | 
 | ||||||
|  | @ -233,7 +234,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) | ||||||
|     u32 Step = (len / 8); |     u32 Step = (len / 8); | ||||||
|     const u64 *data = (const u64 *)src; |     const u64 *data = (const u64 *)src; | ||||||
|     const u64 *end = data + Step; |     const u64 *end = data + Step; | ||||||
|     if(samples == 0) samples = max(Step, 1u); |     if(samples == 0) samples = std::max(Step, 1u); | ||||||
|     Step = Step / samples; |     Step = Step / samples; | ||||||
|     if(Step < 1) Step = 1; |     if(Step < 1) Step = 1; | ||||||
|     while(data < end) |     while(data < end) | ||||||
|  | @ -265,7 +266,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) | ||||||
|     u32 Step = (len / 8); |     u32 Step = (len / 8); | ||||||
|     const u64 *data = (const u64 *)src; |     const u64 *data = (const u64 *)src; | ||||||
|     const u64 *end = data + Step; |     const u64 *end = data + Step; | ||||||
|     if(samples == 0) samples = max(Step, 1u); |     if(samples == 0) samples = std::max(Step, 1u); | ||||||
|     Step = Step / samples; |     Step = Step / samples; | ||||||
|     if(Step < 1) Step = 1; |     if(Step < 1) Step = 1; | ||||||
|     while(data < end) |     while(data < end) | ||||||
|  | @ -308,7 +309,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) | ||||||
|     u32 Step = (len/4); |     u32 Step = (len/4); | ||||||
|     const u32 *data = (const u32 *)src; |     const u32 *data = (const u32 *)src; | ||||||
|     const u32 *end = data + Step; |     const u32 *end = data + Step; | ||||||
|     if(samples == 0) samples = max(Step, 1u); |     if(samples == 0) samples = std::max(Step, 1u); | ||||||
|     Step  = Step / samples; |     Step  = Step / samples; | ||||||
|     if(Step < 1) Step = 1; |     if(Step < 1) Step = 1; | ||||||
|     while(data < end) |     while(data < end) | ||||||
|  | @ -380,7 +381,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) | ||||||
|     u32 out[2]; |     u32 out[2]; | ||||||
|     const int nblocks = len / 8; |     const int nblocks = len / 8; | ||||||
|     u32 Step = (len / 4); |     u32 Step = (len / 4); | ||||||
|     if(samples == 0) samples = max(Step, 1u); |     if(samples == 0) samples = std::max(Step, 1u); | ||||||
|     Step = Step / samples; |     Step = Step / samples; | ||||||
|     if(Step < 1) Step = 1; |     if(Step < 1) Step = 1; | ||||||
| 
 | 
 | ||||||
|  | @ -456,7 +457,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) | ||||||
|     u32 Step = (len / 8); |     u32 Step = (len / 8); | ||||||
|     const u64 *data = (const u64 *)src; |     const u64 *data = (const u64 *)src; | ||||||
|     const u64 *end = data + Step; |     const u64 *end = data + Step; | ||||||
|     if(samples == 0) samples = max(Step, 1u); |     if(samples == 0) samples = std::max(Step, 1u); | ||||||
|     Step = Step / samples; |     Step = Step / samples; | ||||||
|     if(Step < 1) Step = 1; |     if(Step < 1) Step = 1; | ||||||
|     while(data < end) |     while(data < end) | ||||||
|  |  | ||||||
|  | @ -218,7 +218,7 @@ u8* MemArena::Find4GBBase() | ||||||
|     void* base = mmap(0, 0x10000000, PROT_READ | PROT_WRITE, |     void* base = mmap(0, 0x10000000, PROT_READ | PROT_WRITE, | ||||||
|         MAP_ANON | MAP_SHARED, -1, 0); |         MAP_ANON | MAP_SHARED, -1, 0); | ||||||
|     if (base == MAP_FAILED) { |     if (base == MAP_FAILED) { | ||||||
|         PanicAlert("Failed to map 256 MB of memory space: %s", strerror(errno)); |         LOG_ERROR(Common_Memory, "Failed to map 256 MB of memory space: %s", strerror(errno)); | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|     munmap(base, 0x10000000); |     munmap(base, 0x10000000); | ||||||
|  | @ -338,7 +338,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena | ||||||
|     // address space.
 |     // address space.
 | ||||||
|     if (!Memory_TryBase(base, views, num_views, flags, arena)) |     if (!Memory_TryBase(base, views, num_views, flags, arena)) | ||||||
|     { |     { | ||||||
|         PanicAlert("MemoryMap_Setup: Failed finding a memory base."); |         LOG_ERROR(Common_Memory, "MemoryMap_Setup: Failed finding a memory base."); | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| #elif defined(_WIN32) | #elif defined(_WIN32) | ||||||
|  | @ -363,12 +363,11 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena | ||||||
|     if (!Memory_TryBase(base, views, num_views, flags, arena)) |     if (!Memory_TryBase(base, views, num_views, flags, arena)) | ||||||
|     { |     { | ||||||
|         LOG_ERROR(Common_Memory, "MemoryMap_Setup: Failed finding a memory base."); |         LOG_ERROR(Common_Memory, "MemoryMap_Setup: Failed finding a memory base."); | ||||||
|         PanicAlert("MemoryMap_Setup: Failed finding a memory base."); |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|     if (base_attempts) |     if (base_attempts) | ||||||
|         PanicAlert("No possible memory base pointer found!"); |         LOG_ERROR(Common_Memory, "No possible memory base pointer found!"); | ||||||
|     return base; |     return base; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -56,7 +56,7 @@ void* AllocateExecutableMemory(size_t size, bool low) | ||||||
|     { |     { | ||||||
|         ptr = nullptr; |         ptr = nullptr; | ||||||
| #endif | #endif | ||||||
|         PanicAlert("Failed to allocate executable memory"); |         LOG_ERROR(Common_Memory, "Failed to allocate executable memory"); | ||||||
|     } |     } | ||||||
| #if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT) | #if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT) | ||||||
|     else |     else | ||||||
|  | @ -72,7 +72,7 @@ void* AllocateExecutableMemory(size_t size, bool low) | ||||||
| 
 | 
 | ||||||
| #if defined(_M_X64) | #if defined(_M_X64) | ||||||
|     if ((u64)ptr >= 0x80000000 && low == true) |     if ((u64)ptr >= 0x80000000 && low == true) | ||||||
|         PanicAlert("Executable memory ended up above 2GB!"); |         LOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!"); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     return ptr; |     return ptr; | ||||||
|  | @ -94,7 +94,7 @@ void* AllocateMemoryPages(size_t size) | ||||||
|     //    (unsigned long)size);
 |     //    (unsigned long)size);
 | ||||||
| 
 | 
 | ||||||
|     if (ptr == nullptr) |     if (ptr == nullptr) | ||||||
|         PanicAlert("Failed to allocate raw memory"); |         LOG_ERROR(Common_Memory, "Failed to allocate raw memory"); | ||||||
| 
 | 
 | ||||||
|     return ptr; |     return ptr; | ||||||
| } | } | ||||||
|  | @ -117,7 +117,7 @@ void* AllocateAlignedMemory(size_t size,size_t alignment) | ||||||
|     //    (unsigned long)size);
 |     //    (unsigned long)size);
 | ||||||
| 
 | 
 | ||||||
|     if (ptr == nullptr) |     if (ptr == nullptr) | ||||||
|         PanicAlert("Failed to allocate aligned memory"); |         LOG_ERROR(Common_Memory, "Failed to allocate aligned memory"); | ||||||
| 
 | 
 | ||||||
|     return ptr; |     return ptr; | ||||||
| } | } | ||||||
|  | @ -129,7 +129,7 @@ void FreeMemoryPages(void* ptr, size_t size) | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| 
 | 
 | ||||||
|         if (!VirtualFree(ptr, 0, MEM_RELEASE)) |         if (!VirtualFree(ptr, 0, MEM_RELEASE)) | ||||||
|             PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg()); |             LOG_ERROR(Common_Memory, "FreeMemoryPages failed!\n%s", GetLastErrorMsg()); | ||||||
|         ptr = nullptr; // Is this our responsibility?
 |         ptr = nullptr; // Is this our responsibility?
 | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
|  | @ -155,7 +155,7 @@ void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|     DWORD oldValue; |     DWORD oldValue; | ||||||
|     if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue)) |     if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue)) | ||||||
|         PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg()); |         LOG_ERROR(Common_Memory, "WriteProtectMemory failed!\n%s", GetLastErrorMsg()); | ||||||
| #else | #else | ||||||
|     mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ); |     mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ); | ||||||
| #endif | #endif | ||||||
|  | @ -166,7 +166,7 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|     DWORD oldValue; |     DWORD oldValue; | ||||||
|     if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue)) |     if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue)) | ||||||
|         PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg()); |         LOG_ERROR(Common_Memory, "UnWriteProtectMemory failed!\n%s", GetLastErrorMsg()); | ||||||
| #else | #else | ||||||
|     mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ); |     mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -1,107 +0,0 @@ | ||||||
| // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #include <cstdio> |  | ||||||
| 
 |  | ||||||
| #include "common/common.h" // Local
 |  | ||||||
| #include "common/string_util.h" |  | ||||||
| 
 |  | ||||||
| bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style); |  | ||||||
| static MsgAlertHandler msg_handler = DefaultMsgHandler; |  | ||||||
| static bool AlertEnabled = true; |  | ||||||
| 
 |  | ||||||
| std::string DefaultStringTranslator(const char* text); |  | ||||||
| static StringTranslator str_translator = DefaultStringTranslator; |  | ||||||
| 
 |  | ||||||
| // Select which of these functions that are used for message boxes. If
 |  | ||||||
| // wxWidgets is enabled we will use wxMsgAlert() that is defined in Main.cpp
 |  | ||||||
| void RegisterMsgAlertHandler(MsgAlertHandler handler) |  | ||||||
| { |  | ||||||
|     msg_handler = handler; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Select translation function.  For wxWidgets use wxStringTranslator in Main.cpp
 |  | ||||||
| void RegisterStringTranslator(StringTranslator translator) |  | ||||||
| { |  | ||||||
|     str_translator = translator; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // enable/disable the alert handler
 |  | ||||||
| void SetEnableAlert(bool enable) |  | ||||||
| { |  | ||||||
|     AlertEnabled = enable; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // This is the first stop for gui alerts where the log is updated and the
 |  | ||||||
| // correct window is shown
 |  | ||||||
| bool MsgAlert(bool yes_no, int Style, const char* format, ...) |  | ||||||
| { |  | ||||||
|     // Read message and write it to the log
 |  | ||||||
|     std::string caption; |  | ||||||
|     char buffer[2048]; |  | ||||||
| 
 |  | ||||||
|     static std::string info_caption; |  | ||||||
|     static std::string warn_caption; |  | ||||||
|     static std::string ques_caption; |  | ||||||
|     static std::string crit_caption; |  | ||||||
| 
 |  | ||||||
|     if (!info_caption.length()) |  | ||||||
|     { |  | ||||||
|         info_caption = str_translator(_trans("Information")); |  | ||||||
|         ques_caption = str_translator(_trans("Question")); |  | ||||||
|         warn_caption = str_translator(_trans("Warning")); |  | ||||||
|         crit_caption = str_translator(_trans("Critical")); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     switch(Style) |  | ||||||
|     { |  | ||||||
|         case INFORMATION: |  | ||||||
|             caption = info_caption; |  | ||||||
|             break; |  | ||||||
|         case QUESTION: |  | ||||||
|             caption = ques_caption; |  | ||||||
|             break; |  | ||||||
|         case WARNING: |  | ||||||
|             caption = warn_caption; |  | ||||||
|             break; |  | ||||||
|         case CRITICAL: |  | ||||||
|             caption = crit_caption; |  | ||||||
|             break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     va_list args; |  | ||||||
|     va_start(args, format); |  | ||||||
|     Common::CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args); |  | ||||||
|     va_end(args); |  | ||||||
| 
 |  | ||||||
|     LOG_INFO(Common, "%s: %s", caption.c_str(), buffer); |  | ||||||
| 
 |  | ||||||
|     // Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
 |  | ||||||
|     if (msg_handler && (AlertEnabled || Style == QUESTION || Style == CRITICAL)) |  | ||||||
|         return msg_handler(caption.c_str(), buffer, yes_no, Style); |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Default non library dependent panic alert
 |  | ||||||
| bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style) |  | ||||||
| { |  | ||||||
| //#ifdef _WIN32
 |  | ||||||
| //    int STYLE = MB_ICONINFORMATION;
 |  | ||||||
| //    if (Style == QUESTION) STYLE = MB_ICONQUESTION;
 |  | ||||||
| //    if (Style == WARNING) STYLE = MB_ICONWARNING;
 |  | ||||||
| //
 |  | ||||||
| //    return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
 |  | ||||||
| //#else
 |  | ||||||
|     printf("%s\n", text); |  | ||||||
|     return true; |  | ||||||
| //#endif
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Default (non) translator
 |  | ||||||
| std::string DefaultStringTranslator(const char* text) |  | ||||||
| { |  | ||||||
|     return text; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  | @ -1,56 +0,0 @@ | ||||||
| // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <string> |  | ||||||
| 
 |  | ||||||
| // Message alerts
 |  | ||||||
| enum MSG_TYPE |  | ||||||
| { |  | ||||||
|     INFORMATION, |  | ||||||
|     QUESTION, |  | ||||||
|     WARNING, |  | ||||||
|     CRITICAL |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef bool (*MsgAlertHandler)(const char* caption, const char* text, |  | ||||||
|                                 bool yes_no, int Style); |  | ||||||
| typedef std::string (*StringTranslator)(const char* text); |  | ||||||
| 
 |  | ||||||
| void RegisterMsgAlertHandler(MsgAlertHandler handler); |  | ||||||
| void RegisterStringTranslator(StringTranslator translator); |  | ||||||
| 
 |  | ||||||
| extern bool MsgAlert(bool yes_no, int Style, const char* format, ...) |  | ||||||
| #ifdef __GNUC__ |  | ||||||
|     __attribute__((format(printf, 3, 4))) |  | ||||||
| #endif |  | ||||||
|     ; |  | ||||||
| void SetEnableAlert(bool enable); |  | ||||||
| 
 |  | ||||||
| #ifdef _MSC_VER |  | ||||||
|     #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) |  | ||||||
|     #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) |  | ||||||
|     #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) |  | ||||||
|     #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) |  | ||||||
|     #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) |  | ||||||
|     // Use these macros (that do the same thing) if the message should be translated.
 |  | ||||||
|     #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) |  | ||||||
|     #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) |  | ||||||
|     #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) |  | ||||||
|     #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) |  | ||||||
|     #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) |  | ||||||
| #else |  | ||||||
|     #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) |  | ||||||
|     #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) |  | ||||||
|     #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) |  | ||||||
|     #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) |  | ||||||
|     #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) |  | ||||||
|     // Use these macros (that do the same thing) if the message should be translated.
 |  | ||||||
|     #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) |  | ||||||
|     #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) |  | ||||||
|     #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) |  | ||||||
|     #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) |  | ||||||
|     #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) |  | ||||||
| #endif |  | ||||||
|  | @ -1,459 +0,0 @@ | ||||||
| /*
 |  | ||||||
|   Basic UTF-8 manipulation routines |  | ||||||
|   by Jeff Bezanson |  | ||||||
|   placed in the public domain Fall 2005 |  | ||||||
| 
 |  | ||||||
|   This code is designed to provide the utilities you need to manipulate |  | ||||||
|   UTF-8 as an internal string encoding. These functions do not perform the |  | ||||||
|   error checking normally needed when handling UTF-8 data, so if you happen |  | ||||||
|   to be from the Unicode Consortium you will want to flay me alive. |  | ||||||
|   I do this because error checking can be performed at the boundaries (I/O), |  | ||||||
|   with these routines reserved for higher performance on data known to be |  | ||||||
|   valid. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| #ifdef _WIN32 |  | ||||||
| #include <windows.h> |  | ||||||
| #undef min |  | ||||||
| #undef max |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #include <cstdlib> |  | ||||||
| #include <cstring> |  | ||||||
| #include <algorithm> |  | ||||||
| 
 |  | ||||||
| #include "common/common_types.h" |  | ||||||
| #include "common/utf8.h" |  | ||||||
| 
 |  | ||||||
| // is start of UTF sequence
 |  | ||||||
| inline bool isutf(char c) { |  | ||||||
|     return (c & 0xC0) != 0x80; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static const u32 offsetsFromUTF8[6] = { |  | ||||||
|   0x00000000UL, 0x00003080UL, 0x000E2080UL, |  | ||||||
|   0x03C82080UL, 0xFA082080UL, 0x82082080UL |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const u8 trailingBytesForUTF8[256] = { |  | ||||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |  | ||||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |  | ||||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |  | ||||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |  | ||||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |  | ||||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |  | ||||||
|   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, |  | ||||||
|         2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /* returns length of next utf-8 sequence */ |  | ||||||
| int u8_seqlen(const char *s) |  | ||||||
| { |  | ||||||
|   return trailingBytesForUTF8[(unsigned int)(unsigned char)s[0]] + 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* conversions without error checking
 |  | ||||||
|    only works for valid UTF-8, i.e. no 5- or 6-byte sequences |  | ||||||
|    srcsz = source size in bytes, or -1 if 0-terminated |  | ||||||
|    sz = dest size in # of wide characters |  | ||||||
| 
 |  | ||||||
|    returns # characters converted |  | ||||||
|    dest will always be L'\0'-terminated, even if there isn't enough room |  | ||||||
|    for all the characters. |  | ||||||
|    if sz = srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space. |  | ||||||
| */ |  | ||||||
| int u8_toucs(u32 *dest, int sz, const char *src, int srcsz) |  | ||||||
| { |  | ||||||
|   u32 ch; |  | ||||||
|   const char *src_end = src + srcsz; |  | ||||||
|   int nb; |  | ||||||
|   int i=0; |  | ||||||
| 
 |  | ||||||
|   while (i < sz-1) { |  | ||||||
|     nb = trailingBytesForUTF8[(unsigned char)*src]; |  | ||||||
|     if (srcsz == -1) { |  | ||||||
|       if (*src == 0) |  | ||||||
|         goto done_toucs; |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       if (src + nb >= src_end) |  | ||||||
|         goto done_toucs; |  | ||||||
|     } |  | ||||||
|     ch = 0; |  | ||||||
|     switch (nb) { |  | ||||||
|       /* these fall through deliberately */ |  | ||||||
|     case 3: ch += (unsigned char)*src++; ch <<= 6; |  | ||||||
|     case 2: ch += (unsigned char)*src++; ch <<= 6; |  | ||||||
|     case 1: ch += (unsigned char)*src++; ch <<= 6; |  | ||||||
|     case 0: ch += (unsigned char)*src++; |  | ||||||
|     } |  | ||||||
|     ch -= offsetsFromUTF8[nb]; |  | ||||||
|     dest[i++] = ch; |  | ||||||
|   } |  | ||||||
|  done_toucs: |  | ||||||
|   dest[i] = 0; |  | ||||||
|   return i; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* srcsz = number of source characters, or -1 if 0-terminated
 |  | ||||||
|    sz = size of dest buffer in bytes |  | ||||||
| 
 |  | ||||||
|    returns # characters converted |  | ||||||
|    dest will only be '\0'-terminated if there is enough space. this is |  | ||||||
|    for consistency; imagine there are 2 bytes of space left, but the next |  | ||||||
|    character requires 3 bytes. in this case we could NUL-terminate, but in |  | ||||||
|    general we can't when there's insufficient space. therefore this function |  | ||||||
|    only NUL-terminates if all the characters fit, and there's space for |  | ||||||
|    the NUL as well. |  | ||||||
|    the destination string will never be bigger than the source string. |  | ||||||
| */ |  | ||||||
| int u8_toutf8(char *dest, int sz, u32 *src, int srcsz) |  | ||||||
| { |  | ||||||
|   u32 ch; |  | ||||||
|   int i = 0; |  | ||||||
|   char *dest_end = dest + sz; |  | ||||||
| 
 |  | ||||||
|   while (srcsz<0 ? src[i]!=0 : i < srcsz) { |  | ||||||
|     ch = src[i]; |  | ||||||
|     if (ch < 0x80) { |  | ||||||
|       if (dest >= dest_end) |  | ||||||
|         return i; |  | ||||||
|       *dest++ = (char)ch; |  | ||||||
|     } |  | ||||||
|     else if (ch < 0x800) { |  | ||||||
|       if (dest >= dest_end-1) |  | ||||||
|         return i; |  | ||||||
|       *dest++ = (ch>>6) | 0xC0; |  | ||||||
|       *dest++ = (ch & 0x3F) | 0x80; |  | ||||||
|     } |  | ||||||
|     else if (ch < 0x10000) { |  | ||||||
|       if (dest >= dest_end-2) |  | ||||||
|         return i; |  | ||||||
|       *dest++ = (ch>>12) | 0xE0; |  | ||||||
|       *dest++ = ((ch>>6) & 0x3F) | 0x80; |  | ||||||
|       *dest++ = (ch & 0x3F) | 0x80; |  | ||||||
|     } |  | ||||||
|     else if (ch < 0x110000) { |  | ||||||
|       if (dest >= dest_end-3) |  | ||||||
|         return i; |  | ||||||
|       *dest++ = (ch>>18) | 0xF0; |  | ||||||
|       *dest++ = ((ch>>12) & 0x3F) | 0x80; |  | ||||||
|       *dest++ = ((ch>>6) & 0x3F) | 0x80; |  | ||||||
|       *dest++ = (ch & 0x3F) | 0x80; |  | ||||||
|     } |  | ||||||
|     i++; |  | ||||||
|   } |  | ||||||
|   if (dest < dest_end) |  | ||||||
|     *dest = '\0'; |  | ||||||
|   return i; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int u8_wc_toutf8(char *dest, u32 ch) |  | ||||||
| { |  | ||||||
|   if (ch < 0x80) { |  | ||||||
|     dest[0] = (char)ch; |  | ||||||
|     return 1; |  | ||||||
|   } |  | ||||||
|   if (ch < 0x800) { |  | ||||||
|     dest[0] = (ch>>6) | 0xC0; |  | ||||||
|     dest[1] = (ch & 0x3F) | 0x80; |  | ||||||
|     return 2; |  | ||||||
|   } |  | ||||||
|   if (ch < 0x10000) { |  | ||||||
|     dest[0] = (ch>>12) | 0xE0; |  | ||||||
|     dest[1] = ((ch>>6) & 0x3F) | 0x80; |  | ||||||
|     dest[2] = (ch & 0x3F) | 0x80; |  | ||||||
|     return 3; |  | ||||||
|   } |  | ||||||
|   if (ch < 0x110000) { |  | ||||||
|     dest[0] = (ch>>18) | 0xF0; |  | ||||||
|     dest[1] = ((ch>>12) & 0x3F) | 0x80; |  | ||||||
|     dest[2] = ((ch>>6) & 0x3F) | 0x80; |  | ||||||
|     dest[3] = (ch & 0x3F) | 0x80; |  | ||||||
|     return 4; |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* charnum => byte offset */ |  | ||||||
| int u8_offset(const char *str, int charnum) |  | ||||||
| { |  | ||||||
|   int offs=0; |  | ||||||
| 
 |  | ||||||
|   while (charnum > 0 && str[offs]) { |  | ||||||
|     (void)(isutf(str[++offs]) || isutf(str[++offs]) || |  | ||||||
|          isutf(str[++offs]) || ++offs); |  | ||||||
|     charnum--; |  | ||||||
|   } |  | ||||||
|   return offs; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* byte offset => charnum */ |  | ||||||
| int u8_charnum(const char *s, int offset) |  | ||||||
| { |  | ||||||
|   int charnum = 0, offs=0; |  | ||||||
| 
 |  | ||||||
|   while (offs < offset && s[offs]) { |  | ||||||
|     (void)(isutf(s[++offs]) || isutf(s[++offs]) || |  | ||||||
|          isutf(s[++offs]) || ++offs); |  | ||||||
|     charnum++; |  | ||||||
|   } |  | ||||||
|   return charnum; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* number of characters */ |  | ||||||
| int u8_strlen(const char *s) |  | ||||||
| { |  | ||||||
|   int count = 0; |  | ||||||
|   int i = 0; |  | ||||||
| 
 |  | ||||||
|   while (u8_nextchar(s, &i) != 0) |  | ||||||
|     count++; |  | ||||||
| 
 |  | ||||||
|   return count; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* reads the next utf-8 sequence out of a string, updating an index */ |  | ||||||
| u32 u8_nextchar(const char *s, int *i) |  | ||||||
| { |  | ||||||
|   u32 ch = 0; |  | ||||||
|   int sz = 0; |  | ||||||
| 
 |  | ||||||
|   do { |  | ||||||
|     ch <<= 6; |  | ||||||
|     ch += (unsigned char)s[(*i)++]; |  | ||||||
|     sz++; |  | ||||||
|   } while (s[*i] && !isutf(s[*i])); |  | ||||||
|   ch -= offsetsFromUTF8[sz-1]; |  | ||||||
| 
 |  | ||||||
|   return ch; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void u8_inc(const char *s, int *i) |  | ||||||
| { |  | ||||||
|   (void)(isutf(s[++(*i)]) || isutf(s[++(*i)]) || |  | ||||||
|        isutf(s[++(*i)]) || ++(*i)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void u8_dec(const char *s, int *i) |  | ||||||
| { |  | ||||||
|   (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) || |  | ||||||
|        isutf(s[--(*i)]) || --(*i)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int octal_digit(char c) |  | ||||||
| { |  | ||||||
|   return (c >= '0' && c <= '7'); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int hex_digit(char c) |  | ||||||
| { |  | ||||||
|   return ((c >= '0' && c <= '9') || |  | ||||||
|       (c >= 'A' && c <= 'F') || |  | ||||||
|       (c >= 'a' && c <= 'f')); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* assumes that src points to the character after a backslash
 |  | ||||||
|    returns number of input characters processed */ |  | ||||||
| int u8_read_escape_sequence(const char *str, u32 *dest) |  | ||||||
| { |  | ||||||
|   u32 ch; |  | ||||||
|   char digs[9]="\0\0\0\0\0\0\0\0"; |  | ||||||
|   int dno=0, i=1; |  | ||||||
| 
 |  | ||||||
|   ch = (u32)str[0];  /* take literal character */ |  | ||||||
|   if (str[0] == 'n') |  | ||||||
|     ch = L'\n'; |  | ||||||
|   else if (str[0] == 't') |  | ||||||
|     ch = L'\t'; |  | ||||||
|   else if (str[0] == 'r') |  | ||||||
|     ch = L'\r'; |  | ||||||
|   else if (str[0] == 'b') |  | ||||||
|     ch = L'\b'; |  | ||||||
|   else if (str[0] == 'f') |  | ||||||
|     ch = L'\f'; |  | ||||||
|   else if (str[0] == 'v') |  | ||||||
|     ch = L'\v'; |  | ||||||
|   else if (str[0] == 'a') |  | ||||||
|     ch = L'\a'; |  | ||||||
|   else if (octal_digit(str[0])) { |  | ||||||
|     i = 0; |  | ||||||
|     do { |  | ||||||
|       digs[dno++] = str[i++]; |  | ||||||
|     } while (octal_digit(str[i]) && dno < 3); |  | ||||||
|     ch = strtol(digs, nullptr, 8); |  | ||||||
|   } |  | ||||||
|   else if (str[0] == 'x') { |  | ||||||
|     while (hex_digit(str[i]) && dno < 2) { |  | ||||||
|       digs[dno++] = str[i++]; |  | ||||||
|     } |  | ||||||
|     if (dno > 0) |  | ||||||
|       ch = strtol(digs, nullptr, 16); |  | ||||||
|   } |  | ||||||
|   else if (str[0] == 'u') { |  | ||||||
|     while (hex_digit(str[i]) && dno < 4) { |  | ||||||
|       digs[dno++] = str[i++]; |  | ||||||
|     } |  | ||||||
|     if (dno > 0) |  | ||||||
|       ch = strtol(digs, nullptr, 16); |  | ||||||
|   } |  | ||||||
|   else if (str[0] == 'U') { |  | ||||||
|     while (hex_digit(str[i]) && dno < 8) { |  | ||||||
|       digs[dno++] = str[i++]; |  | ||||||
|     } |  | ||||||
|     if (dno > 0) |  | ||||||
|       ch = strtol(digs, nullptr, 16); |  | ||||||
|   } |  | ||||||
|   *dest = ch; |  | ||||||
| 
 |  | ||||||
|   return i; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* convert a string with literal \uxxxx or \Uxxxxxxxx characters to UTF-8
 |  | ||||||
|    example: u8_unescape(mybuf, 256, "hello\\u220e") |  | ||||||
|    note the double backslash is needed if called on a C string literal */ |  | ||||||
| int u8_unescape(char *buf, int sz, char *src) |  | ||||||
| { |  | ||||||
|   int c=0, amt; |  | ||||||
|   u32 ch; |  | ||||||
|   char temp[4]; |  | ||||||
| 
 |  | ||||||
|   while (*src && c < sz) { |  | ||||||
|     if (*src == '\\') { |  | ||||||
|       src++; |  | ||||||
|       amt = u8_read_escape_sequence(src, &ch); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       ch = (u32)*src; |  | ||||||
|       amt = 1; |  | ||||||
|     } |  | ||||||
|     src += amt; |  | ||||||
|     amt = u8_wc_toutf8(temp, ch); |  | ||||||
|     if (amt > sz-c) |  | ||||||
|       break; |  | ||||||
|     memcpy(&buf[c], temp, amt); |  | ||||||
|     c += amt; |  | ||||||
|   } |  | ||||||
|   if (c < sz) |  | ||||||
|     buf[c] = '\0'; |  | ||||||
|   return c; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const char *u8_strchr(const char *s, u32 ch, int *charn) |  | ||||||
| { |  | ||||||
|   int i = 0, lasti=0; |  | ||||||
|   u32 c; |  | ||||||
| 
 |  | ||||||
|   *charn = 0; |  | ||||||
|   while (s[i]) { |  | ||||||
|     c = u8_nextchar(s, &i); |  | ||||||
|     if (c == ch) { |  | ||||||
|       return &s[lasti]; |  | ||||||
|     } |  | ||||||
|     lasti = i; |  | ||||||
|     (*charn)++; |  | ||||||
|   } |  | ||||||
|   return nullptr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const char *u8_memchr(const char *s, u32 ch, size_t sz, int *charn) |  | ||||||
| { |  | ||||||
|   u32 i = 0, lasti=0; |  | ||||||
|   u32 c; |  | ||||||
|   int csz; |  | ||||||
| 
 |  | ||||||
|   *charn = 0; |  | ||||||
|   while (i < sz) { |  | ||||||
|     c = csz = 0; |  | ||||||
|     do { |  | ||||||
|       c <<= 6; |  | ||||||
|       c += (unsigned char)s[i++]; |  | ||||||
|       csz++; |  | ||||||
|     } while (i < sz && !isutf(s[i])); |  | ||||||
|     c -= offsetsFromUTF8[csz-1]; |  | ||||||
| 
 |  | ||||||
|     if (c == ch) { |  | ||||||
|       return &s[lasti]; |  | ||||||
|     } |  | ||||||
|     lasti = i; |  | ||||||
|     (*charn)++; |  | ||||||
|   } |  | ||||||
|   return nullptr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int u8_is_locale_utf8(const char *locale) |  | ||||||
| { |  | ||||||
|   /* this code based on libutf8 */ |  | ||||||
|   const char* cp = locale; |  | ||||||
| 
 |  | ||||||
|   for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) { |  | ||||||
|     if (*cp == '.') { |  | ||||||
|       const char* encoding = ++cp; |  | ||||||
|       for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) |  | ||||||
|         ; |  | ||||||
|       if ((cp-encoding == 5 && !strncmp(encoding, "UTF-8", 5)) |  | ||||||
|         || (cp-encoding == 4 && !strncmp(encoding, "utf8", 4))) |  | ||||||
|         return 1; /* it's UTF-8 */ |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int UTF8StringNonASCIICount(const char *utf8string) { |  | ||||||
|     UTF8 utf(utf8string); |  | ||||||
|     int count = 0; |  | ||||||
|     while (!utf.end()) { |  | ||||||
|         int c = utf.next(); |  | ||||||
|         if (c > 127) |  | ||||||
|             ++count; |  | ||||||
|     } |  | ||||||
|     return count; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool UTF8StringHasNonASCII(const char *utf8string) { |  | ||||||
|     return UTF8StringNonASCIICount(utf8string) > 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #ifdef _WIN32 |  | ||||||
| 
 |  | ||||||
| std::string ConvertWStringToUTF8(const wchar_t *wstr) { |  | ||||||
|     int len = (int)wcslen(wstr); |  | ||||||
|     int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, nullptr, nullptr); |  | ||||||
|     std::string s; |  | ||||||
|     s.resize(size); |  | ||||||
|     if (size > 0) { |  | ||||||
|         WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, nullptr, nullptr); |  | ||||||
|     } |  | ||||||
|     return s; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::string ConvertWStringToUTF8(const std::wstring &wstr) { |  | ||||||
|     int len = (int)wstr.size(); |  | ||||||
|     int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, nullptr, nullptr); |  | ||||||
|     std::string s; |  | ||||||
|     s.resize(size); |  | ||||||
|     if (size > 0) { |  | ||||||
|         WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, nullptr, nullptr); |  | ||||||
|     } |  | ||||||
|     return s; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) { |  | ||||||
|     int len = (int)source.size(); |  | ||||||
|     int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0); |  | ||||||
|     MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::wstring ConvertUTF8ToWString(const std::string &source) { |  | ||||||
|     int len = (int)source.size(); |  | ||||||
|     int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0); |  | ||||||
|     std::wstring str; |  | ||||||
|     str.resize(size); |  | ||||||
|     if (size > 0) { |  | ||||||
|         MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size); |  | ||||||
|     } |  | ||||||
|     return str; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
|  | @ -1,67 +0,0 @@ | ||||||
| /*
 |  | ||||||
|   Basic UTF-8 manipulation routines |  | ||||||
|   by Jeff Bezanson |  | ||||||
|   placed in the public domain Fall 2005 |  | ||||||
| 
 |  | ||||||
|   This code is designed to provide the utilities you need to manipulate |  | ||||||
|   UTF-8 as an internal string encoding. These functions do not perform the |  | ||||||
|   error checking normally needed when handling UTF-8 data, so if you happen |  | ||||||
|   to be from the Unicode Consortium you will want to flay me alive. |  | ||||||
|   I do this because error checking can be performed at the boundaries (I/O), |  | ||||||
|   with these routines reserved for higher performance on data known to be |  | ||||||
|   valid. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| // Further modified, and C++ stuff added, by hrydgard@gmail.com.
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include "common/common_types.h" |  | ||||||
| #include <string> |  | ||||||
| 
 |  | ||||||
| u32 u8_nextchar(const char *s, int *i); |  | ||||||
| int u8_wc_toutf8(char *dest, u32 ch); |  | ||||||
| int u8_strlen(const char *s); |  | ||||||
| 
 |  | ||||||
| class UTF8 { |  | ||||||
| public: |  | ||||||
|     static const u32 INVALID = (u32)-1; |  | ||||||
|     UTF8(const char *c) : c_(c), index_(0) {} |  | ||||||
|     bool end() const { return c_[index_] == 0; } |  | ||||||
|     u32 next() { |  | ||||||
|         return u8_nextchar(c_, &index_); |  | ||||||
|     } |  | ||||||
|     u32 peek() { |  | ||||||
|         int tempIndex = index_; |  | ||||||
|         return u8_nextchar(c_, &tempIndex); |  | ||||||
|     } |  | ||||||
|     int length() const { |  | ||||||
|         return u8_strlen(c_); |  | ||||||
|     } |  | ||||||
|     int byteIndex() const { |  | ||||||
|         return index_; |  | ||||||
|     } |  | ||||||
|     static int encode(char *dest, u32 ch) { |  | ||||||
|         return u8_wc_toutf8(dest, ch); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     const char *c_; |  | ||||||
|     int index_; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int UTF8StringNonASCIICount(const char *utf8string); |  | ||||||
| 
 |  | ||||||
| bool UTF8StringHasNonASCII(const char *utf8string); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // UTF8 to Win32 UTF-16
 |  | ||||||
| // Should be used when calling Win32 api calls
 |  | ||||||
| #ifdef _WIN32 |  | ||||||
| 
 |  | ||||||
| std::string ConvertWStringToUTF8(const std::wstring &wstr); |  | ||||||
| std::string ConvertWStringToUTF8(const wchar_t *wstr); |  | ||||||
| void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source); |  | ||||||
| std::wstring ConvertUTF8ToWString(const std::string &source); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
|  | @ -147,7 +147,7 @@ void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callba | ||||||
| 
 | 
 | ||||||
| void UnregisterAllEvents() { | void UnregisterAllEvents() { | ||||||
|     if (first) |     if (first) | ||||||
|         PanicAlert("Cannot unregister events with events pending"); |         LOG_ERROR(Core_Timing, "Cannot unregister events with events pending"); | ||||||
|     event_types.clear(); |     event_types.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -535,7 +535,7 @@ std::string GetScheduledEventsSummary() { | ||||||
|     while (event) { |     while (event) { | ||||||
|         unsigned int t = event->type; |         unsigned int t = event->type; | ||||||
|         if (t >= event_types.size()) |         if (t >= event_types.size()) | ||||||
|             PanicAlert("Invalid event type"); // %i", t);
 |             LOG_ERROR(Core_Timing, "Invalid event type"); // %i", t);
 | ||||||
|         const char* name = event_types[event->type].name; |         const char* name = event_types[event->type].name; | ||||||
|         if (!name) |         if (!name) | ||||||
|             name = "[unknown]"; |             name = "[unknown]"; | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
|  | #include "common/math_util.h" | ||||||
| #include "common/thread_queue_list.h" | #include "common/thread_queue_list.h" | ||||||
| 
 | 
 | ||||||
| #include "core/arm/arm_interface.h" | #include "core/arm/arm_interface.h" | ||||||
|  | @ -339,7 +340,7 @@ static void DebugThreadQueue() { | ||||||
| ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, | ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, | ||||||
|         u32 arg, s32 processor_id, VAddr stack_top) { |         u32 arg, s32 processor_id, VAddr stack_top) { | ||||||
|     if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { |     if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { | ||||||
|         s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); |         s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | ||||||
|         LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", |         LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", | ||||||
|             name.c_str(), priority, new_priority); |             name.c_str(), priority, new_priority); | ||||||
|         // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
 |         // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
 | ||||||
|  | @ -387,7 +388,7 @@ static void ClampPriority(const Thread* thread, s32* priority) { | ||||||
|     if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { |     if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { | ||||||
|         DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); |         DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); | ||||||
| 
 | 
 | ||||||
|         s32 new_priority = CLAMP(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); |         s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | ||||||
|         LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", |         LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", | ||||||
|                     thread->name.c_str(), *priority, new_priority); |                     thread->name.c_str(), *priority, new_priority); | ||||||
|         // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
 |         // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
 | ||||||
|  |  | ||||||
|  | @ -34,13 +34,6 @@ namespace GPU { | ||||||
| // MMIO region 0x1EFxxxxx
 | // MMIO region 0x1EFxxxxx
 | ||||||
| struct Regs { | struct Regs { | ||||||
| 
 | 
 | ||||||
| // helper macro to properly align structure members.
 |  | ||||||
| // Calling INSERT_PADDING_WORDS will add a new member variable with a name like "pad121",
 |  | ||||||
| // depending on the current source line to make sure variable names are unique.
 |  | ||||||
| #define INSERT_PADDING_WORDS_HELPER1(x, y) x ## y |  | ||||||
| #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) |  | ||||||
| #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)] |  | ||||||
| 
 |  | ||||||
| // helper macro to make sure the defined structures are of the expected size.
 | // helper macro to make sure the defined structures are of the expected size.
 | ||||||
| #if defined(_MSC_VER) | #if defined(_MSC_VER) | ||||||
| // TODO: MSVC does not support using sizeof() on non-static data members even though this
 | // TODO: MSVC does not support using sizeof() on non-static data members even though this
 | ||||||
|  | @ -238,10 +231,6 @@ struct Regs { | ||||||
| 
 | 
 | ||||||
|     INSERT_PADDING_WORDS(0x9c3); |     INSERT_PADDING_WORDS(0x9c3); | ||||||
| 
 | 
 | ||||||
| #undef INSERT_PADDING_WORDS_HELPER1 |  | ||||||
| #undef INSERT_PADDING_WORDS_HELPER2 |  | ||||||
| #undef INSERT_PADDING_WORDS |  | ||||||
| 
 |  | ||||||
|     static inline size_t NumIds() { |     static inline size_t NumIds() { | ||||||
|         return sizeof(Regs) / sizeof(u32); |         return sizeof(Regs) / sizeof(u32); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -39,13 +39,6 @@ namespace Pica { | ||||||
| 
 | 
 | ||||||
| struct Regs { | struct Regs { | ||||||
| 
 | 
 | ||||||
| // helper macro to properly align structure members.
 |  | ||||||
| // Calling INSERT_PADDING_WORDS will add a new member variable with a name like "pad121",
 |  | ||||||
| // depending on the current source line to make sure variable names are unique.
 |  | ||||||
| #define INSERT_PADDING_WORDS_HELPER1(x, y) x ## y |  | ||||||
| #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) |  | ||||||
| #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)]; |  | ||||||
| 
 |  | ||||||
|     INSERT_PADDING_WORDS(0x10); |     INSERT_PADDING_WORDS(0x10); | ||||||
| 
 | 
 | ||||||
|     u32 trigger_irq; |     u32 trigger_irq; | ||||||
|  | @ -709,10 +702,6 @@ struct Regs { | ||||||
| 
 | 
 | ||||||
|     INSERT_PADDING_WORDS(0x22); |     INSERT_PADDING_WORDS(0x22); | ||||||
| 
 | 
 | ||||||
| #undef INSERT_PADDING_WORDS_HELPER1 |  | ||||||
| #undef INSERT_PADDING_WORDS_HELPER2 |  | ||||||
| #undef INSERT_PADDING_WORDS |  | ||||||
| 
 |  | ||||||
|     // Map register indices to names readable by humans
 |     // Map register indices to names readable by humans
 | ||||||
|     // Used for debugging purposes, so performance is not an issue here
 |     // Used for debugging purposes, so performance is not an issue here
 | ||||||
|     static std::string GetCommandName(int index) { |     static std::string GetCommandName(int index) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue