diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/assert.h | 2 | ||||
| -rw-r--r-- | src/common/common_funcs.h | 4 | ||||
| -rw-r--r-- | src/common/file_util.cpp | 93 | ||||
| -rw-r--r-- | src/common/file_util.h | 63 | ||||
| -rw-r--r-- | src/common/memory_util.cpp | 8 | ||||
| -rw-r--r-- | src/common/swap.h | 2 |
6 files changed, 65 insertions, 107 deletions
diff --git a/src/common/assert.h b/src/common/assert.h index 655446f34..0d4eddc19 100644 --- a/src/common/assert.h +++ b/src/common/assert.h | |||
| @@ -52,5 +52,5 @@ __declspec(noinline, noreturn) | |||
| 52 | #define DEBUG_ASSERT_MSG(_a_, _desc_, ...) | 52 | #define DEBUG_ASSERT_MSG(_a_, _desc_, ...) |
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | #define UNIMPLEMENTED() DEBUG_ASSERT_MSG(false, "Unimplemented code!") | 55 | #define UNIMPLEMENTED() LOG_CRITICAL(Debug, "Unimplemented code!") |
| 56 | #define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__) | 56 | #define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__) |
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 7cf7b7997..995938d0b 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #if !defined(ARCHITECTURE_x86_64) && !defined(_M_ARM) | 7 | #if !defined(ARCHITECTURE_x86_64) && !defined(ARCHITECTURE_ARM) |
| 8 | #include <cstdlib> // for exit | 8 | #include <cstdlib> // for exit |
| 9 | #endif | 9 | #endif |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -30,7 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #ifdef ARCHITECTURE_x86_64 | 31 | #ifdef ARCHITECTURE_x86_64 |
| 32 | #define Crash() __asm__ __volatile__("int $3") | 32 | #define Crash() __asm__ __volatile__("int $3") |
| 33 | #elif defined(_M_ARM) | 33 | #elif defined(ARCHITECTURE_ARM) |
| 34 | #define Crash() __asm__ __volatile__("trap") | 34 | #define Crash() __asm__ __volatile__("trap") |
| 35 | #else | 35 | #else |
| 36 | #define Crash() exit(1) | 36 | #define Crash() exit(1) |
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 493a81e01..7213abe18 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <sstream> | ||
| 6 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 7 | #include "common/common_funcs.h" | 6 | #include "common/common_funcs.h" |
| 8 | #include "common/common_paths.h" | 7 | #include "common/common_paths.h" |
| @@ -387,7 +386,7 @@ u64 GetSize(FILE* f) { | |||
| 387 | bool CreateEmptyFile(const std::string& filename) { | 386 | bool CreateEmptyFile(const std::string& filename) { |
| 388 | LOG_TRACE(Common_Filesystem, "{}", filename); | 387 | LOG_TRACE(Common_Filesystem, "{}", filename); |
| 389 | 388 | ||
| 390 | if (!FileUtil::IOFile(filename, "wb").IsOpen()) { | 389 | if (!FileUtil::IOFile(filename, "wb")) { |
| 391 | LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); | 390 | LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); |
| 392 | return false; | 391 | return false; |
| 393 | } | 392 | } |
| @@ -751,7 +750,7 @@ size_t WriteStringToFile(bool text_file, const std::string& str, const char* fil | |||
| 751 | size_t ReadFileToString(bool text_file, const char* filename, std::string& str) { | 750 | size_t ReadFileToString(bool text_file, const char* filename, std::string& str) { |
| 752 | IOFile file(filename, text_file ? "r" : "rb"); | 751 | IOFile file(filename, text_file ? "r" : "rb"); |
| 753 | 752 | ||
| 754 | if (!file.IsOpen()) | 753 | if (!file) |
| 755 | return false; | 754 | return false; |
| 756 | 755 | ||
| 757 | str.resize(static_cast<u32>(file.GetSize())); | 756 | str.resize(static_cast<u32>(file.GetSize())); |
| @@ -800,57 +799,6 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam | |||
| 800 | } | 799 | } |
| 801 | } | 800 | } |
| 802 | 801 | ||
| 803 | std::vector<std::string> SplitPathComponents(const std::string& filename) { | ||
| 804 | auto copy(filename); | ||
| 805 | std::replace(copy.begin(), copy.end(), '\\', '/'); | ||
| 806 | std::vector<std::string> out; | ||
| 807 | |||
| 808 | std::stringstream stream(filename); | ||
| 809 | std::string item; | ||
| 810 | while (std::getline(stream, item, '/')) | ||
| 811 | out.push_back(std::move(item)); | ||
| 812 | |||
| 813 | return out; | ||
| 814 | } | ||
| 815 | |||
| 816 | std::string GetParentPath(const std::string& path) { | ||
| 817 | auto out = path; | ||
| 818 | const auto name_bck_index = out.find_last_of('\\'); | ||
| 819 | const auto name_fwd_index = out.find_last_of('/'); | ||
| 820 | size_t name_index; | ||
| 821 | if (name_bck_index == std::string::npos || name_fwd_index == std::string::npos) | ||
| 822 | name_index = std::min<size_t>(name_bck_index, name_fwd_index); | ||
| 823 | else | ||
| 824 | name_index = std::max<size_t>(name_bck_index, name_fwd_index); | ||
| 825 | |||
| 826 | return out.erase(name_index); | ||
| 827 | } | ||
| 828 | |||
| 829 | std::string GetFilename(std::string path) { | ||
| 830 | std::replace(path.begin(), path.end(), '\\', '/'); | ||
| 831 | auto name_index = path.find_last_of('/'); | ||
| 832 | if (name_index == std::string::npos) | ||
| 833 | return ""; | ||
| 834 | return path.substr(name_index + 1); | ||
| 835 | } | ||
| 836 | |||
| 837 | std::string GetExtensionFromFilename(const std::string& name) { | ||
| 838 | size_t index = name.find_last_of('.'); | ||
| 839 | if (index == std::string::npos) | ||
| 840 | return ""; | ||
| 841 | |||
| 842 | return name.substr(index + 1); | ||
| 843 | } | ||
| 844 | |||
| 845 | std::string RemoveTrailingSlash(const std::string& path) { | ||
| 846 | if (path.empty()) | ||
| 847 | return path; | ||
| 848 | if (path.back() == '\\' || path.back() == '/') | ||
| 849 | return path.substr(0, path.size() - 1); | ||
| 850 | |||
| 851 | return path; | ||
| 852 | } | ||
| 853 | |||
| 854 | IOFile::IOFile() {} | 802 | IOFile::IOFile() {} |
| 855 | 803 | ||
| 856 | IOFile::IOFile(const std::string& filename, const char openmode[], int flags) { | 804 | IOFile::IOFile(const std::string& filename, const char openmode[], int flags) { |
| @@ -872,6 +820,7 @@ IOFile& IOFile::operator=(IOFile&& other) noexcept { | |||
| 872 | 820 | ||
| 873 | void IOFile::Swap(IOFile& other) noexcept { | 821 | void IOFile::Swap(IOFile& other) noexcept { |
| 874 | std::swap(m_file, other.m_file); | 822 | std::swap(m_file, other.m_file); |
| 823 | std::swap(m_good, other.m_good); | ||
| 875 | } | 824 | } |
| 876 | 825 | ||
| 877 | bool IOFile::Open(const std::string& filename, const char openmode[], int flags) { | 826 | bool IOFile::Open(const std::string& filename, const char openmode[], int flags) { |
| @@ -888,15 +837,16 @@ bool IOFile::Open(const std::string& filename, const char openmode[], int flags) | |||
| 888 | m_file = fopen(filename.c_str(), openmode); | 837 | m_file = fopen(filename.c_str(), openmode); |
| 889 | #endif | 838 | #endif |
| 890 | 839 | ||
| 891 | return IsOpen(); | 840 | m_good = IsOpen(); |
| 841 | return m_good; | ||
| 892 | } | 842 | } |
| 893 | 843 | ||
| 894 | bool IOFile::Close() { | 844 | bool IOFile::Close() { |
| 895 | if (!IsOpen() || 0 != std::fclose(m_file)) | 845 | if (!IsOpen() || 0 != std::fclose(m_file)) |
| 896 | return false; | 846 | m_good = false; |
| 897 | 847 | ||
| 898 | m_file = nullptr; | 848 | m_file = nullptr; |
| 899 | return true; | 849 | return m_good; |
| 900 | } | 850 | } |
| 901 | 851 | ||
| 902 | u64 IOFile::GetSize() const { | 852 | u64 IOFile::GetSize() const { |
| @@ -906,8 +856,11 @@ u64 IOFile::GetSize() const { | |||
| 906 | return 0; | 856 | return 0; |
| 907 | } | 857 | } |
| 908 | 858 | ||
| 909 | bool IOFile::Seek(s64 off, int origin) const { | 859 | bool IOFile::Seek(s64 off, int origin) { |
| 910 | return IsOpen() && 0 == fseeko(m_file, off, origin); | 860 | if (!IsOpen() || 0 != fseeko(m_file, off, origin)) |
| 861 | m_good = false; | ||
| 862 | |||
| 863 | return m_good; | ||
| 911 | } | 864 | } |
| 912 | 865 | ||
| 913 | u64 IOFile::Tell() const { | 866 | u64 IOFile::Tell() const { |
| @@ -918,20 +871,26 @@ u64 IOFile::Tell() const { | |||
| 918 | } | 871 | } |
| 919 | 872 | ||
| 920 | bool IOFile::Flush() { | 873 | bool IOFile::Flush() { |
| 921 | return IsOpen() && 0 == std::fflush(m_file); | 874 | if (!IsOpen() || 0 != std::fflush(m_file)) |
| 875 | m_good = false; | ||
| 876 | |||
| 877 | return m_good; | ||
| 922 | } | 878 | } |
| 923 | 879 | ||
| 924 | bool IOFile::Resize(u64 size) { | 880 | bool IOFile::Resize(u64 size) { |
| 925 | return IsOpen() && 0 == | 881 | if (!IsOpen() || 0 != |
| 926 | #ifdef _WIN32 | 882 | #ifdef _WIN32 |
| 927 | // ector: _chsize sucks, not 64-bit safe | 883 | // ector: _chsize sucks, not 64-bit safe |
| 928 | // F|RES: changed to _chsize_s. i think it is 64-bit safe | 884 | // F|RES: changed to _chsize_s. i think it is 64-bit safe |
| 929 | _chsize_s(_fileno(m_file), size) | 885 | _chsize_s(_fileno(m_file), size) |
| 930 | #else | 886 | #else |
| 931 | // TODO: handle 64bit and growing | 887 | // TODO: handle 64bit and growing |
| 932 | ftruncate(fileno(m_file), size) | 888 | ftruncate(fileno(m_file), size) |
| 933 | #endif | 889 | #endif |
| 934 | ; | 890 | ) |
| 891 | m_good = false; | ||
| 892 | |||
| 893 | return m_good; | ||
| 935 | } | 894 | } |
| 936 | 895 | ||
| 937 | } // namespace FileUtil | 896 | } // namespace FileUtil |
diff --git a/src/common/file_util.h b/src/common/file_util.h index 9bb3c4109..5bc7fbf7c 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -150,31 +150,6 @@ size_t ReadFileToString(bool text_file, const char* filename, std::string& str); | |||
| 150 | void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, | 150 | void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, |
| 151 | std::array<char, 4>& extension); | 151 | std::array<char, 4>& extension); |
| 152 | 152 | ||
| 153 | // Splits the path on '/' or '\' and put the components into a vector | ||
| 154 | // i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" } | ||
| 155 | std::vector<std::string> SplitPathComponents(const std::string& filename); | ||
| 156 | |||
| 157 | // Gets all of the text prior to the last '/' or '\' in the path. | ||
| 158 | std::string GetParentPath(const std::string& path); | ||
| 159 | |||
| 160 | // Gets the filename of the path | ||
| 161 | std::string GetFilename(std::string path); | ||
| 162 | |||
| 163 | // Gets the extension of the filename | ||
| 164 | std::string GetExtensionFromFilename(const std::string& name); | ||
| 165 | |||
| 166 | // Removes the final '/' or '\' if one exists | ||
| 167 | std::string RemoveTrailingSlash(const std::string& path); | ||
| 168 | |||
| 169 | // Creates a new vector containing indices [first, last) from the original. | ||
| 170 | template <typename T> | ||
| 171 | std::vector<T> SliceVector(const std::vector<T>& vector, size_t first, size_t last) { | ||
| 172 | if (first >= last) | ||
| 173 | return {}; | ||
| 174 | last = std::min<size_t>(last, vector.size()); | ||
| 175 | return std::vector<T>(vector.begin() + first, vector.begin() + first + last); | ||
| 176 | } | ||
| 177 | |||
| 178 | // simple wrapper for cstdlib file functions to | 153 | // simple wrapper for cstdlib file functions to |
| 179 | // hopefully will make error checking easier | 154 | // hopefully will make error checking easier |
| 180 | // and make forgetting an fclose() harder | 155 | // and make forgetting an fclose() harder |
| @@ -197,27 +172,41 @@ public: | |||
| 197 | bool Close(); | 172 | bool Close(); |
| 198 | 173 | ||
| 199 | template <typename T> | 174 | template <typename T> |
| 200 | size_t ReadArray(T* data, size_t length) const { | 175 | size_t ReadArray(T* data, size_t length) { |
| 201 | static_assert(std::is_trivially_copyable<T>(), | 176 | static_assert(std::is_trivially_copyable<T>(), |
| 202 | "Given array does not consist of trivially copyable objects"); | 177 | "Given array does not consist of trivially copyable objects"); |
| 203 | 178 | ||
| 204 | if (!IsOpen()) | 179 | if (!IsOpen()) { |
| 180 | m_good = false; | ||
| 205 | return -1; | 181 | return -1; |
| 182 | } | ||
| 206 | 183 | ||
| 207 | return std::fread(data, sizeof(T), length, m_file); | 184 | size_t items_read = std::fread(data, sizeof(T), length, m_file); |
| 185 | if (items_read != length) | ||
| 186 | m_good = false; | ||
| 187 | |||
| 188 | return items_read; | ||
| 208 | } | 189 | } |
| 209 | 190 | ||
| 210 | template <typename T> | 191 | template <typename T> |
| 211 | size_t WriteArray(const T* data, size_t length) { | 192 | size_t WriteArray(const T* data, size_t length) { |
| 212 | static_assert(std::is_trivially_copyable<T>(), | 193 | static_assert(std::is_trivially_copyable<T>(), |
| 213 | "Given array does not consist of trivially copyable objects"); | 194 | "Given array does not consist of trivially copyable objects"); |
| 214 | if (!IsOpen()) | 195 | |
| 196 | if (!IsOpen()) { | ||
| 197 | m_good = false; | ||
| 215 | return -1; | 198 | return -1; |
| 216 | return std::fwrite(data, sizeof(T), length, m_file); | 199 | } |
| 200 | |||
| 201 | size_t items_written = std::fwrite(data, sizeof(T), length, m_file); | ||
| 202 | if (items_written != length) | ||
| 203 | m_good = false; | ||
| 204 | |||
| 205 | return items_written; | ||
| 217 | } | 206 | } |
| 218 | 207 | ||
| 219 | template <typename T> | 208 | template <typename T> |
| 220 | size_t ReadBytes(T* data, size_t length) const { | 209 | size_t ReadBytes(T* data, size_t length) { |
| 221 | static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable"); | 210 | static_assert(std::is_trivially_copyable<T>(), "T must be trivially copyable"); |
| 222 | return ReadArray(reinterpret_cast<char*>(data), length); | 211 | return ReadArray(reinterpret_cast<char*>(data), length); |
| 223 | } | 212 | } |
| @@ -242,7 +231,15 @@ public: | |||
| 242 | return nullptr != m_file; | 231 | return nullptr != m_file; |
| 243 | } | 232 | } |
| 244 | 233 | ||
| 245 | bool Seek(s64 off, int origin) const; | 234 | // m_good is set to false when a read, write or other function fails |
| 235 | bool IsGood() const { | ||
| 236 | return m_good; | ||
| 237 | } | ||
| 238 | explicit operator bool() const { | ||
| 239 | return IsGood(); | ||
| 240 | } | ||
| 241 | |||
| 242 | bool Seek(s64 off, int origin); | ||
| 246 | u64 Tell() const; | 243 | u64 Tell() const; |
| 247 | u64 GetSize() const; | 244 | u64 GetSize() const; |
| 248 | bool Resize(u64 size); | 245 | bool Resize(u64 size); |
| @@ -250,11 +247,13 @@ public: | |||
| 250 | 247 | ||
| 251 | // clear error state | 248 | // clear error state |
| 252 | void Clear() { | 249 | void Clear() { |
| 250 | m_good = true; | ||
| 253 | std::clearerr(m_file); | 251 | std::clearerr(m_file); |
| 254 | } | 252 | } |
| 255 | 253 | ||
| 256 | private: | 254 | private: |
| 257 | std::FILE* m_file = nullptr; | 255 | std::FILE* m_file = nullptr; |
| 256 | bool m_good = true; | ||
| 258 | }; | 257 | }; |
| 259 | 258 | ||
| 260 | } // namespace FileUtil | 259 | } // namespace FileUtil |
diff --git a/src/common/memory_util.cpp b/src/common/memory_util.cpp index 5d89209ed..09462ccee 100644 --- a/src/common/memory_util.cpp +++ b/src/common/memory_util.cpp | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include <sys/mman.h> | 16 | #include <sys/mman.h> |
| 17 | #endif | 17 | #endif |
| 18 | 18 | ||
| 19 | #if !defined(_WIN32) && defined(ARCHITECTURE_X64) && !defined(MAP_32BIT) | 19 | #if !defined(_WIN32) && defined(ARCHITECTURE_x86_64) && !defined(MAP_32BIT) |
| 20 | #include <unistd.h> | 20 | #include <unistd.h> |
| 21 | #define PAGE_MASK (getpagesize() - 1) | 21 | #define PAGE_MASK (getpagesize() - 1) |
| 22 | #define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) | 22 | #define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) |
| @@ -30,7 +30,7 @@ void* AllocateExecutableMemory(size_t size, bool low) { | |||
| 30 | void* ptr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); | 30 | void* ptr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); |
| 31 | #else | 31 | #else |
| 32 | static char* map_hint = nullptr; | 32 | static char* map_hint = nullptr; |
| 33 | #if defined(ARCHITECTURE_X64) && !defined(MAP_32BIT) | 33 | #if defined(ARCHITECTURE_x86_64) && !defined(MAP_32BIT) |
| 34 | // This OS has no flag to enforce allocation below the 4 GB boundary, | 34 | // This OS has no flag to enforce allocation below the 4 GB boundary, |
| 35 | // but if we hint that we want a low address it is very likely we will | 35 | // but if we hint that we want a low address it is very likely we will |
| 36 | // get one. | 36 | // get one. |
| @@ -42,7 +42,7 @@ void* AllocateExecutableMemory(size_t size, bool low) { | |||
| 42 | #endif | 42 | #endif |
| 43 | void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, | 43 | void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, |
| 44 | MAP_ANON | MAP_PRIVATE | 44 | MAP_ANON | MAP_PRIVATE |
| 45 | #if defined(ARCHITECTURE_X64) && defined(MAP_32BIT) | 45 | #if defined(ARCHITECTURE_x86_64) && defined(MAP_32BIT) |
| 46 | | (low ? MAP_32BIT : 0) | 46 | | (low ? MAP_32BIT : 0) |
| 47 | #endif | 47 | #endif |
| 48 | , | 48 | , |
| @@ -57,7 +57,7 @@ void* AllocateExecutableMemory(size_t size, bool low) { | |||
| 57 | #endif | 57 | #endif |
| 58 | LOG_ERROR(Common_Memory, "Failed to allocate executable memory"); | 58 | LOG_ERROR(Common_Memory, "Failed to allocate executable memory"); |
| 59 | } | 59 | } |
| 60 | #if !defined(_WIN32) && defined(ARCHITECTURE_X64) && !defined(MAP_32BIT) | 60 | #if !defined(_WIN32) && defined(ARCHITECTURE_x86_64) && !defined(MAP_32BIT) |
| 61 | else { | 61 | else { |
| 62 | if (low) { | 62 | if (low) { |
| 63 | map_hint += size; | 63 | map_hint += size; |
diff --git a/src/common/swap.h b/src/common/swap.h index 4a4012d1a..f025f7450 100644 --- a/src/common/swap.h +++ b/src/common/swap.h | |||
| @@ -69,7 +69,7 @@ inline u32 swap32(u32 _data) { | |||
| 69 | inline u64 swap64(u64 _data) { | 69 | inline u64 swap64(u64 _data) { |
| 70 | return _byteswap_uint64(_data); | 70 | return _byteswap_uint64(_data); |
| 71 | } | 71 | } |
| 72 | #elif _M_ARM | 72 | #elif ARCHITECTURE_ARM |
| 73 | inline u16 swap16(u16 _data) { | 73 | inline u16 swap16(u16 _data) { |
| 74 | u32 data = _data; | 74 | u32 data = _data; |
| 75 | __asm__("rev16 %0, %1\n" : "=l"(data) : "l"(data)); | 75 | __asm__("rev16 %0, %1\n" : "=l"(data) : "l"(data)); |