diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/common/dynamic_library.cpp | 106 | ||||
| -rw-r--r-- | src/common/dynamic_library.h | 75 | ||||
| -rw-r--r-- | src/common/file_util.cpp | 22 | ||||
| -rw-r--r-- | src/common/thread.cpp | 9 |
5 files changed, 199 insertions, 15 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index fbebed715..eeceaa655 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -106,6 +106,8 @@ add_library(common STATIC | |||
| 106 | common_funcs.h | 106 | common_funcs.h |
| 107 | common_paths.h | 107 | common_paths.h |
| 108 | common_types.h | 108 | common_types.h |
| 109 | dynamic_library.cpp | ||
| 110 | dynamic_library.h | ||
| 109 | file_util.cpp | 111 | file_util.cpp |
| 110 | file_util.h | 112 | file_util.h |
| 111 | hash.h | 113 | hash.h |
diff --git a/src/common/dynamic_library.cpp b/src/common/dynamic_library.cpp new file mode 100644 index 000000000..7ab54e9e4 --- /dev/null +++ b/src/common/dynamic_library.cpp | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | // Copyright 2019 Dolphin Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <cstring> | ||
| 6 | #include <string> | ||
| 7 | #include <utility> | ||
| 8 | |||
| 9 | #include <fmt/format.h> | ||
| 10 | |||
| 11 | #include "common/dynamic_library.h" | ||
| 12 | |||
| 13 | #ifdef _WIN32 | ||
| 14 | #include <windows.h> | ||
| 15 | #else | ||
| 16 | #include <dlfcn.h> | ||
| 17 | #endif | ||
| 18 | |||
| 19 | namespace Common { | ||
| 20 | |||
| 21 | DynamicLibrary::DynamicLibrary() = default; | ||
| 22 | |||
| 23 | DynamicLibrary::DynamicLibrary(const char* filename) { | ||
| 24 | Open(filename); | ||
| 25 | } | ||
| 26 | |||
| 27 | DynamicLibrary::DynamicLibrary(DynamicLibrary&& rhs) noexcept | ||
| 28 | : handle{std::exchange(rhs.handle, nullptr)} {} | ||
| 29 | |||
| 30 | DynamicLibrary& DynamicLibrary::operator=(DynamicLibrary&& rhs) noexcept { | ||
| 31 | Close(); | ||
| 32 | handle = std::exchange(rhs.handle, nullptr); | ||
| 33 | return *this; | ||
| 34 | } | ||
| 35 | |||
| 36 | DynamicLibrary::~DynamicLibrary() { | ||
| 37 | Close(); | ||
| 38 | } | ||
| 39 | |||
| 40 | std::string DynamicLibrary::GetUnprefixedFilename(const char* filename) { | ||
| 41 | #if defined(_WIN32) | ||
| 42 | return std::string(filename) + ".dll"; | ||
| 43 | #elif defined(__APPLE__) | ||
| 44 | return std::string(filename) + ".dylib"; | ||
| 45 | #else | ||
| 46 | return std::string(filename) + ".so"; | ||
| 47 | #endif | ||
| 48 | } | ||
| 49 | |||
| 50 | std::string DynamicLibrary::GetVersionedFilename(const char* libname, int major, int minor) { | ||
| 51 | #if defined(_WIN32) | ||
| 52 | if (major >= 0 && minor >= 0) | ||
| 53 | return fmt::format("{}-{}-{}.dll", libname, major, minor); | ||
| 54 | else if (major >= 0) | ||
| 55 | return fmt::format("{}-{}.dll", libname, major); | ||
| 56 | else | ||
| 57 | return fmt::format("{}.dll", libname); | ||
| 58 | #elif defined(__APPLE__) | ||
| 59 | const char* prefix = std::strncmp(libname, "lib", 3) ? "lib" : ""; | ||
| 60 | if (major >= 0 && minor >= 0) | ||
| 61 | return fmt::format("{}{}.{}.{}.dylib", prefix, libname, major, minor); | ||
| 62 | else if (major >= 0) | ||
| 63 | return fmt::format("{}{}.{}.dylib", prefix, libname, major); | ||
| 64 | else | ||
| 65 | return fmt::format("{}{}.dylib", prefix, libname); | ||
| 66 | #else | ||
| 67 | const char* prefix = std::strncmp(libname, "lib", 3) ? "lib" : ""; | ||
| 68 | if (major >= 0 && minor >= 0) | ||
| 69 | return fmt::format("{}{}.so.{}.{}", prefix, libname, major, minor); | ||
| 70 | else if (major >= 0) | ||
| 71 | return fmt::format("{}{}.so.{}", prefix, libname, major); | ||
| 72 | else | ||
| 73 | return fmt::format("{}{}.so", prefix, libname); | ||
| 74 | #endif | ||
| 75 | } | ||
| 76 | |||
| 77 | bool DynamicLibrary::Open(const char* filename) { | ||
| 78 | #ifdef _WIN32 | ||
| 79 | handle = reinterpret_cast<void*>(LoadLibraryA(filename)); | ||
| 80 | #else | ||
| 81 | handle = dlopen(filename, RTLD_NOW); | ||
| 82 | #endif | ||
| 83 | return handle != nullptr; | ||
| 84 | } | ||
| 85 | |||
| 86 | void DynamicLibrary::Close() { | ||
| 87 | if (!IsOpen()) | ||
| 88 | return; | ||
| 89 | |||
| 90 | #ifdef _WIN32 | ||
| 91 | FreeLibrary(reinterpret_cast<HMODULE>(handle)); | ||
| 92 | #else | ||
| 93 | dlclose(handle); | ||
| 94 | #endif | ||
| 95 | handle = nullptr; | ||
| 96 | } | ||
| 97 | |||
| 98 | void* DynamicLibrary::GetSymbolAddress(const char* name) const { | ||
| 99 | #ifdef _WIN32 | ||
| 100 | return reinterpret_cast<void*>(GetProcAddress(reinterpret_cast<HMODULE>(handle), name)); | ||
| 101 | #else | ||
| 102 | return reinterpret_cast<void*>(dlsym(handle, name)); | ||
| 103 | #endif | ||
| 104 | } | ||
| 105 | |||
| 106 | } // namespace Common | ||
diff --git a/src/common/dynamic_library.h b/src/common/dynamic_library.h new file mode 100644 index 000000000..2a06372fd --- /dev/null +++ b/src/common/dynamic_library.h | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | // Copyright 2019 Dolphin Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <string> | ||
| 8 | |||
| 9 | namespace Common { | ||
| 10 | |||
| 11 | /** | ||
| 12 | * Provides a platform-independent interface for loading a dynamic library and retrieving symbols. | ||
| 13 | * The interface maintains an internal reference count to allow one handle to be shared between | ||
| 14 | * multiple users. | ||
| 15 | */ | ||
| 16 | class DynamicLibrary final { | ||
| 17 | public: | ||
| 18 | /// Default constructor, does not load a library. | ||
| 19 | explicit DynamicLibrary(); | ||
| 20 | |||
| 21 | /// Automatically loads the specified library. Call IsOpen() to check validity before use. | ||
| 22 | explicit DynamicLibrary(const char* filename); | ||
| 23 | |||
| 24 | /// Moves the library. | ||
| 25 | DynamicLibrary(DynamicLibrary&&) noexcept; | ||
| 26 | DynamicLibrary& operator=(DynamicLibrary&&) noexcept; | ||
| 27 | |||
| 28 | /// Delete copies, we can't copy a dynamic library. | ||
| 29 | DynamicLibrary(const DynamicLibrary&) = delete; | ||
| 30 | DynamicLibrary& operator=(const DynamicLibrary&) = delete; | ||
| 31 | |||
| 32 | /// Closes the library. | ||
| 33 | ~DynamicLibrary(); | ||
| 34 | |||
| 35 | /// Returns the specified library name with the platform-specific suffix added. | ||
| 36 | static std::string GetUnprefixedFilename(const char* filename); | ||
| 37 | |||
| 38 | /// Returns the specified library name in platform-specific format. | ||
| 39 | /// Major/minor versions will not be included if set to -1. | ||
| 40 | /// If libname already contains the "lib" prefix, it will not be added again. | ||
| 41 | /// Windows: LIBNAME-MAJOR-MINOR.dll | ||
| 42 | /// Linux: libLIBNAME.so.MAJOR.MINOR | ||
| 43 | /// Mac: libLIBNAME.MAJOR.MINOR.dylib | ||
| 44 | static std::string GetVersionedFilename(const char* libname, int major = -1, int minor = -1); | ||
| 45 | |||
| 46 | /// Returns true if a module is loaded, otherwise false. | ||
| 47 | bool IsOpen() const { | ||
| 48 | return handle != nullptr; | ||
| 49 | } | ||
| 50 | |||
| 51 | /// Loads (or replaces) the handle with the specified library file name. | ||
| 52 | /// Returns true if the library was loaded and can be used. | ||
| 53 | bool Open(const char* filename); | ||
| 54 | |||
| 55 | /// Unloads the library, any function pointers from this library are no longer valid. | ||
| 56 | void Close(); | ||
| 57 | |||
| 58 | /// Returns the address of the specified symbol (function or variable) as an untyped pointer. | ||
| 59 | /// If the specified symbol does not exist in this library, nullptr is returned. | ||
| 60 | void* GetSymbolAddress(const char* name) const; | ||
| 61 | |||
| 62 | /// Obtains the address of the specified symbol, automatically casting to the correct type. | ||
| 63 | /// Returns true if the symbol was found and assigned, otherwise false. | ||
| 64 | template <typename T> | ||
| 65 | bool GetSymbol(const char* name, T* ptr) const { | ||
| 66 | *ptr = reinterpret_cast<T>(GetSymbolAddress(name)); | ||
| 67 | return *ptr != nullptr; | ||
| 68 | } | ||
| 69 | |||
| 70 | private: | ||
| 71 | /// Platform-dependent data type representing a dynamic library handle. | ||
| 72 | void* handle = nullptr; | ||
| 73 | }; | ||
| 74 | |||
| 75 | } // namespace Common | ||
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 41167f57a..35eee0096 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <array> | 5 | #include <array> |
| 6 | #include <limits> | ||
| 6 | #include <memory> | 7 | #include <memory> |
| 7 | #include <sstream> | 8 | #include <sstream> |
| 8 | #include <unordered_map> | 9 | #include <unordered_map> |
| @@ -530,11 +531,11 @@ void CopyDir(const std::string& source_path, const std::string& dest_path) { | |||
| 530 | std::optional<std::string> GetCurrentDir() { | 531 | std::optional<std::string> GetCurrentDir() { |
| 531 | // Get the current working directory (getcwd uses malloc) | 532 | // Get the current working directory (getcwd uses malloc) |
| 532 | #ifdef _WIN32 | 533 | #ifdef _WIN32 |
| 533 | wchar_t* dir; | 534 | wchar_t* dir = _wgetcwd(nullptr, 0); |
| 534 | if (!(dir = _wgetcwd(nullptr, 0))) { | 535 | if (!dir) { |
| 535 | #else | 536 | #else |
| 536 | char* dir; | 537 | char* dir = getcwd(nullptr, 0); |
| 537 | if (!(dir = getcwd(nullptr, 0))) { | 538 | if (!dir) { |
| 538 | #endif | 539 | #endif |
| 539 | LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); | 540 | LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); |
| 540 | return {}; | 541 | return {}; |
| @@ -918,19 +919,22 @@ void IOFile::Swap(IOFile& other) noexcept { | |||
| 918 | 919 | ||
| 919 | bool IOFile::Open(const std::string& filename, const char openmode[], int flags) { | 920 | bool IOFile::Open(const std::string& filename, const char openmode[], int flags) { |
| 920 | Close(); | 921 | Close(); |
| 922 | bool m_good; | ||
| 921 | #ifdef _WIN32 | 923 | #ifdef _WIN32 |
| 922 | if (flags != 0) { | 924 | if (flags != 0) { |
| 923 | m_file = _wfsopen(Common::UTF8ToUTF16W(filename).c_str(), | 925 | m_file = _wfsopen(Common::UTF8ToUTF16W(filename).c_str(), |
| 924 | Common::UTF8ToUTF16W(openmode).c_str(), flags); | 926 | Common::UTF8ToUTF16W(openmode).c_str(), flags); |
| 927 | m_good = m_file != nullptr; | ||
| 925 | } else { | 928 | } else { |
| 926 | _wfopen_s(&m_file, Common::UTF8ToUTF16W(filename).c_str(), | 929 | m_good = _wfopen_s(&m_file, Common::UTF8ToUTF16W(filename).c_str(), |
| 927 | Common::UTF8ToUTF16W(openmode).c_str()); | 930 | Common::UTF8ToUTF16W(openmode).c_str()) == 0; |
| 928 | } | 931 | } |
| 929 | #else | 932 | #else |
| 930 | m_file = fopen(filename.c_str(), openmode); | 933 | m_file = std::fopen(filename.c_str(), openmode); |
| 934 | m_good = m_file != nullptr; | ||
| 931 | #endif | 935 | #endif |
| 932 | 936 | ||
| 933 | return IsOpen(); | 937 | return m_good; |
| 934 | } | 938 | } |
| 935 | 939 | ||
| 936 | bool IOFile::Close() { | 940 | bool IOFile::Close() { |
| @@ -956,7 +960,7 @@ u64 IOFile::Tell() const { | |||
| 956 | if (IsOpen()) | 960 | if (IsOpen()) |
| 957 | return ftello(m_file); | 961 | return ftello(m_file); |
| 958 | 962 | ||
| 959 | return -1; | 963 | return std::numeric_limits<u64>::max(); |
| 960 | } | 964 | } |
| 961 | 965 | ||
| 962 | bool IOFile::Flush() { | 966 | bool IOFile::Flush() { |
diff --git a/src/common/thread.cpp b/src/common/thread.cpp index fe7a420cc..0cd2d10bf 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp | |||
| @@ -28,11 +28,8 @@ namespace Common { | |||
| 28 | #ifdef _MSC_VER | 28 | #ifdef _MSC_VER |
| 29 | 29 | ||
| 30 | // Sets the debugger-visible name of the current thread. | 30 | // Sets the debugger-visible name of the current thread. |
| 31 | // Uses undocumented (actually, it is now documented) trick. | 31 | // Uses trick documented in: |
| 32 | // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp | 32 | // https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code |
| 33 | |||
| 34 | // This is implemented much nicer in upcoming msvc++, see: | ||
| 35 | // http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx | ||
| 36 | void SetCurrentThreadName(const char* name) { | 33 | void SetCurrentThreadName(const char* name) { |
| 37 | static const DWORD MS_VC_EXCEPTION = 0x406D1388; | 34 | static const DWORD MS_VC_EXCEPTION = 0x406D1388; |
| 38 | 35 | ||
| @@ -47,7 +44,7 @@ void SetCurrentThreadName(const char* name) { | |||
| 47 | 44 | ||
| 48 | info.dwType = 0x1000; | 45 | info.dwType = 0x1000; |
| 49 | info.szName = name; | 46 | info.szName = name; |
| 50 | info.dwThreadID = -1; // dwThreadID; | 47 | info.dwThreadID = std::numeric_limits<DWORD>::max(); |
| 51 | info.dwFlags = 0; | 48 | info.dwFlags = 0; |
| 52 | 49 | ||
| 53 | __try { | 50 | __try { |