├── moreCompleteExample ├── resources │ └── file.txt ├── include │ └── myHeader.h ├── thirdParty │ ├── profilerLib │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── src │ │ │ └── main.cpp │ │ └── profilerLib │ │ │ └── profilerLib.h │ └── safeSave │ │ ├── CMakeLists.txt │ │ ├── include │ │ └── safeSave.h │ │ └── src │ │ └── safeSave.cpp ├── .gitignore ├── src │ ├── myCpp.cpp │ └── main.cpp └── Cmakelists.txt ├── linkingALibrary ├── thirdParty │ └── profilerLib │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── src │ │ └── main.cpp │ │ └── profilerLib │ │ └── profilerLib.h ├── .gitignore ├── include │ └── test.h ├── src │ └── main.cpp └── Cmakelists.txt └── cmakeHelloWorld ├── .gitignore ├── main.cpp ├── main2.cpp └── CMakelists.txt /moreCompleteExample/resources/file.txt: -------------------------------------------------------------------------------- 1 | hello from the file. -------------------------------------------------------------------------------- /moreCompleteExample/include/myHeader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void print(); -------------------------------------------------------------------------------- /linkingALibrary/thirdParty/profilerLib/.gitignore: -------------------------------------------------------------------------------- 1 | /out 2 | /.vs 3 | CMakeSettings.json -------------------------------------------------------------------------------- /cmakeHelloWorld/.gitignore: -------------------------------------------------------------------------------- 1 | /out 2 | bin/ 3 | build/ 4 | /.vs 5 | .idea/ 6 | CMakeSettings.json -------------------------------------------------------------------------------- /linkingALibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /out 2 | bin/ 3 | build/ 4 | /.vs 5 | .idea/ 6 | CMakeSettings.json -------------------------------------------------------------------------------- /moreCompleteExample/thirdParty/profilerLib/.gitignore: -------------------------------------------------------------------------------- 1 | /out 2 | /.vs 3 | CMakeSettings.json -------------------------------------------------------------------------------- /moreCompleteExample/.gitignore: -------------------------------------------------------------------------------- 1 | /out 2 | bin/ 3 | build/ 4 | /.vs 5 | .idea/ 6 | CMakeSettings.json -------------------------------------------------------------------------------- /linkingALibrary/include/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void print() 5 | { 6 | std::cout << "hello."; 7 | } -------------------------------------------------------------------------------- /moreCompleteExample/src/myCpp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void print() 5 | { 6 | std::cout << "hello again.\n"; 7 | } -------------------------------------------------------------------------------- /cmakeHelloWorld/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | 6 | std::cout << "Cmake hello world\n"; 7 | std::cin.get(); 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /cmakeHelloWorld/main2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | 6 | std::cout << "Cmake hello world from the second main\n"; 7 | std::cin.get(); 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /cmakeHelloWorld/CMakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION "3.19.2") 2 | 3 | project("CmakeHelloWorld") 4 | add_executable(${CMAKE_PROJECT_NAME} "main.cpp") 5 | 6 | 7 | 8 | project("Second_Project") 9 | add_executable(Second_Project main2.cpp) 10 | 11 | -------------------------------------------------------------------------------- /linkingALibrary/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main() 7 | { 8 | 9 | PL::AverageProfiler profiler; 10 | 11 | 12 | print(); 13 | 14 | 15 | std::cin.get(); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /moreCompleteExample/thirdParty/safeSave/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(safeSave) 3 | 4 | 5 | add_library(safeSave) 6 | target_include_directories(safeSave PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/") 7 | target_sources(safeSave PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/safeSave.cpp") 8 | -------------------------------------------------------------------------------- /linkingALibrary/Cmakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | add_subdirectory("thirdParty/profilerLib") 4 | 5 | 6 | project(main1) 7 | set(CMAKE_CXX_STANDARD 17) 8 | add_executable(main1 "src/main.cpp") 9 | target_include_directories(main1 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/") 10 | target_link_libraries(main1 PRIVATE profilerLib) 11 | -------------------------------------------------------------------------------- /moreCompleteExample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | 8 | print(); 9 | 10 | 11 | std::ifstream file(RESOURCES_PATH "file.txt"); 12 | 13 | //read the file 14 | std::string str((std::istreambuf_iterator(file)), 15 | std::istreambuf_iterator()); 16 | std::cout << str; 17 | 18 | 19 | std::cin.get(); 20 | return 0; 21 | } -------------------------------------------------------------------------------- /linkingALibrary/thirdParty/profilerLib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(profilerLib) 3 | 4 | 5 | add_library(profilerLib INTERFACE) 6 | target_include_directories(profilerLib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") 7 | 8 | 9 | add_executable(profilerLib_test) 10 | target_sources(profilerLib_test PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp" ) 11 | target_link_libraries(profilerLib_test PUBLIC profilerLib) 12 | 13 | -------------------------------------------------------------------------------- /moreCompleteExample/thirdParty/profilerLib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(profilerLib) 3 | 4 | 5 | add_library(profilerLib INTERFACE) #use interface for header only libraries 6 | target_include_directories(profilerLib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") 7 | 8 | 9 | #Define MY_SOURCES to be a list of all the source files for my game 10 | file(GLOB_RECURSE PROFILER_LIB_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") 11 | add_executable(profilerLib_test) 12 | target_sources(profilerLib_test PRIVATE ${PROFILER_LIB_SOURCES} ) 13 | target_link_libraries(profilerLib_test PUBLIC profilerLib) 14 | 15 | -------------------------------------------------------------------------------- /linkingALibrary/thirdParty/profilerLib/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "profilerLib/profilerLib.h" 5 | 6 | 7 | int main() 8 | { 9 | //how to use the profiler 10 | PL::Profiler profiler; 11 | 12 | profiler.start(); 13 | 14 | Sleep(1000); 15 | 16 | auto r = profiler.end(); 17 | 18 | std::cout << r.timeSeconds << " " << r.cpuClocks << "\n"; 19 | 20 | 21 | //the average profiler can run multiple tests and average then. 22 | PL::AverageProfiler aProfiler; 23 | 24 | for(int i=0;i<5;i++) 25 | { 26 | aProfiler.start(); 27 | Sleep(1000); 28 | aProfiler.end(); 29 | } 30 | 31 | 32 | //you can also use aProfiler.getAverageNoResetData and not reset the data 33 | r = aProfiler.getAverageAndResetData(); 34 | std::cout << r.timeSeconds << " " << r.cpuClocks << "\n"; 35 | 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /moreCompleteExample/thirdParty/profilerLib/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "profilerLib/profilerLib.h" 5 | 6 | 7 | int main() 8 | { 9 | //how to use the profiler 10 | PL::Profiler profiler; 11 | 12 | profiler.start(); 13 | 14 | Sleep(1000); 15 | 16 | auto r = profiler.end(); 17 | 18 | std::cout << r.timeSeconds << " " << r.cpuClocks << "\n"; 19 | 20 | 21 | //the average profiler can run multiple tests and average then. 22 | PL::AverageProfiler aProfiler; 23 | 24 | for(int i=0;i<5;i++) 25 | { 26 | aProfiler.start(); 27 | Sleep(1000); 28 | aProfiler.end(); 29 | } 30 | 31 | 32 | //you can also use aProfiler.getAverageNoResetData and not reset the data 33 | r = aProfiler.getAverageAndResetData(); 34 | std::cout << r.timeSeconds << " " << r.cpuClocks << "\n"; 35 | 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /moreCompleteExample/Cmakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") 4 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Release>") 5 | 6 | add_subdirectory("thirdParty/profilerLib") 7 | add_subdirectory("thirdParty/safeSave") 8 | 9 | 10 | project(main1) 11 | set(CMAKE_CXX_STANDARD 17) 12 | 13 | # we define MY_SOURCES to be a list of all the source files for my project 14 | file(GLOB_RECURSE MY_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") 15 | 16 | add_executable(main1 "${MY_SOURCES}") 17 | 18 | 19 | target_compile_definitions("${CMAKE_PROJECT_NAME}" PUBLIC RESOURCES_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/") # This is useful to get an ASSETS_PATH in your IDE during development but you should comment this if you compile a release version and uncomment the next line 20 | #target_compile_definitions("${CMAKE_PROJECT_NAME}" PUBLIC RESOURCES_PATH="./resources/") # Uncomment this line to setup the ASSETS_PATH macro to the final assets directory when you share the project 21 | 22 | 23 | target_include_directories(main1 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/") 24 | target_link_libraries(main1 PRIVATE profilerLib safeSave) 25 | -------------------------------------------------------------------------------- /moreCompleteExample/thirdParty/safeSave/include/safeSave.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////// 2 | //do not remove this notice 3 | //(c) Luta Vlad 4 | // 5 | // safeSave 1.0.0 6 | // 7 | /////////////////////////////////////////// 8 | 9 | #pragma once 10 | #include 11 | #include 12 | 13 | #ifdef _MSC_VER 14 | #pragma warning( disable : 26812 ) 15 | #endif 16 | 17 | namespace sfs 18 | { 19 | enum Errors : int 20 | { 21 | noError, 22 | couldNotOpenFinle, 23 | fileSizeDitNotMatch, 24 | checkSumFailed, 25 | couldNotMakeBackup, 26 | readBackup, 27 | }; 28 | 29 | const char* getErrorString(Errors e); 30 | 31 | //can return error: couldNotOpenFinle 32 | Errors readEntireFile(std::vector& data, const char* name); 33 | 34 | //can return error: couldNotOpenFinle 35 | Errors readEntireFile(void* data, size_t size, const char* name, bool shouldMatchSize, int *bytesRead = nullptr); 36 | 37 | //can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed 38 | Errors readEntireFileWithCheckSum(void* data, size_t size, const char* name); 39 | 40 | //can return error: couldNotOpenFinle 41 | Errors writeEntireFileWithCheckSum(const void* data, size_t size, const char* name); 42 | 43 | //can return error: couldNotOpenFinle 44 | Errors writeEntireFile(const std::vector& data, const char* name); 45 | 46 | //can return error: couldNotOpenFinle 47 | Errors writeEntireFile(const void*data, size_t size, const char* name); 48 | 49 | //can return error: couldNotOpenFinle, 50 | // couldNotMakeBackup (if reportnotMakingBackupAsAnError is true, but will still save the first file) 51 | Errors safeSave(const void* data, size_t size, const char* nameWithoutExtension, bool reportnotMakingBackupAsAnError); 52 | 53 | //can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed, 54 | // readBackup (if reportLoadingBackupAsAnError but data will still be loaded with the backup) 55 | Errors safeLoad(void* data, size_t size, const char* nameWithoutExtension, bool reportLoadingBackupAsAnError); 56 | 57 | //same as safeLoad but only loads the backup file. 58 | //can return error: couldNotOpenFinle, fileSizeDitNotMatch, checkSumFailed 59 | Errors safeLoadBackup(void* data, size_t size, const char* nameWithoutExtension); 60 | 61 | #if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__ 62 | 63 | struct FileMapping 64 | { 65 | void* pointer = {}; 66 | size_t size = 0; 67 | struct 68 | { 69 | void* fileHandle = 0; 70 | void* fileMapping = 0; 71 | }internal = {}; 72 | }; 73 | 74 | #elif defined __linux__ 75 | 76 | struct FileMapping 77 | { 78 | void* pointer = {}; 79 | size_t size = 0; 80 | struct 81 | { 82 | int fd = 0; 83 | }internal = {}; 84 | }; 85 | 86 | #endif 87 | 88 | //can return error: couldNotOpenFinle 89 | Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting); 90 | 91 | void closeFileMapping(FileMapping& fileMapping); 92 | 93 | }; -------------------------------------------------------------------------------- /linkingALibrary/thirdParty/profilerLib/profilerLib/profilerLib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | /////////////////////////////////////////// 6 | //https://github.com/meemknight/profilerLib 7 | //do not remove this notice 8 | //(c) Luta Vlad 9 | /////////////////////////////////////////// 10 | 11 | 12 | //set this to true to remove the implementation 13 | //usefull to quickly remove debug and profile cod and to port to 14 | //other platforms 15 | #define PROFILER_LIB_REMOVE_IMPLEMENTATION 0 16 | 17 | 18 | namespace PL 19 | { 20 | 21 | struct ProfileRezults 22 | { 23 | float timeSeconds; 24 | unsigned int cpuClocks; 25 | }; 26 | 27 | #if !PROFILER_LIB_REMOVE_IMPLEMENTATION 28 | 29 | struct PerfFreqvency 30 | { 31 | PerfFreqvency() 32 | { 33 | QueryPerformanceFrequency(&perfFreq); 34 | } 35 | 36 | LARGE_INTEGER perfFreq; 37 | }; 38 | const static PerfFreqvency freq; 39 | 40 | 41 | struct Profiler 42 | { 43 | 44 | LARGE_INTEGER startTime = {}; 45 | __int64 cycleCount = {}; 46 | 47 | void start() 48 | { 49 | QueryPerformanceCounter(&startTime); 50 | cycleCount = __rdtsc(); 51 | } 52 | 53 | ProfileRezults end() 54 | { 55 | __int64 endCycleCount = __rdtsc(); 56 | LARGE_INTEGER endTime; 57 | QueryPerformanceCounter(&endTime); 58 | 59 | cycleCount = endCycleCount - cycleCount; 60 | startTime.QuadPart = endTime.QuadPart - startTime.QuadPart; 61 | 62 | 63 | ProfileRezults r = {}; 64 | 65 | r.timeSeconds = (float)startTime.QuadPart / (float)freq.perfFreq.QuadPart; 66 | r.cpuClocks = cycleCount; 67 | 68 | return r; 69 | } 70 | 71 | }; 72 | 73 | const int AverageProfilerMaxTests = 200; 74 | 75 | struct AverageProfiler 76 | { 77 | ProfileRezults rezults[AverageProfilerMaxTests]; 78 | int index = 0; 79 | 80 | Profiler profiler; 81 | 82 | void start() 83 | { 84 | profiler.start(); 85 | } 86 | 87 | ProfileRezults end() 88 | { 89 | auto r = profiler.end(); 90 | 91 | if(index < AverageProfilerMaxTests) 92 | { 93 | rezults[index] = r; 94 | index++; 95 | } 96 | 97 | return r; 98 | } 99 | 100 | ProfileRezults getAverageNoResetData() 101 | { 102 | if (index == 0) 103 | { 104 | return { 0,0 }; 105 | } 106 | 107 | long double time = 0; 108 | unsigned long cpuTime = 0; 109 | 110 | for(int i=0;i 3 | #include 4 | 5 | /////////////////////////////////////////// 6 | //https://github.com/meemknight/profilerLib 7 | //do not remove this notice 8 | //(c) Luta Vlad 9 | /////////////////////////////////////////// 10 | 11 | 12 | //set this to true to remove the implementation 13 | //usefull to quickly remove debug and profile cod and to port to 14 | //other platforms 15 | #define PROFILER_LIB_REMOVE_IMPLEMENTATION 0 16 | 17 | 18 | namespace PL 19 | { 20 | 21 | struct ProfileRezults 22 | { 23 | float timeSeconds; 24 | unsigned int cpuClocks; 25 | }; 26 | 27 | #if !PROFILER_LIB_REMOVE_IMPLEMENTATION 28 | 29 | struct PerfFreqvency 30 | { 31 | PerfFreqvency() 32 | { 33 | QueryPerformanceFrequency(&perfFreq); 34 | } 35 | 36 | LARGE_INTEGER perfFreq; 37 | }; 38 | const static PerfFreqvency freq; 39 | 40 | 41 | struct Profiler 42 | { 43 | 44 | LARGE_INTEGER startTime = {}; 45 | __int64 cycleCount = {}; 46 | 47 | void start() 48 | { 49 | QueryPerformanceCounter(&startTime); 50 | cycleCount = __rdtsc(); 51 | } 52 | 53 | ProfileRezults end() 54 | { 55 | __int64 endCycleCount = __rdtsc(); 56 | LARGE_INTEGER endTime; 57 | QueryPerformanceCounter(&endTime); 58 | 59 | cycleCount = endCycleCount - cycleCount; 60 | startTime.QuadPart = endTime.QuadPart - startTime.QuadPart; 61 | 62 | 63 | ProfileRezults r = {}; 64 | 65 | r.timeSeconds = (float)startTime.QuadPart / (float)freq.perfFreq.QuadPart; 66 | r.cpuClocks = cycleCount; 67 | 68 | return r; 69 | } 70 | 71 | }; 72 | 73 | const int AverageProfilerMaxTests = 200; 74 | 75 | struct AverageProfiler 76 | { 77 | ProfileRezults rezults[AverageProfilerMaxTests]; 78 | int index = 0; 79 | 80 | Profiler profiler; 81 | 82 | void start() 83 | { 84 | profiler.start(); 85 | } 86 | 87 | ProfileRezults end() 88 | { 89 | auto r = profiler.end(); 90 | 91 | if(index < AverageProfilerMaxTests) 92 | { 93 | rezults[index] = r; 94 | index++; 95 | } 96 | 97 | return r; 98 | } 99 | 100 | ProfileRezults getAverageNoResetData() 101 | { 102 | if (index == 0) 103 | { 104 | return { 0,0 }; 105 | } 106 | 107 | long double time = 0; 108 | unsigned long cpuTime = 0; 109 | 110 | for(int i=0;i 10 | 11 | #if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__ 12 | #define NOMINMAX 13 | #define WIN32_LEAN_AND_MEAN 14 | #include 15 | 16 | #elif defined __linux__ 17 | #include 18 | #include 19 | #include 20 | 21 | #endif 22 | 23 | 24 | namespace sfs 25 | { 26 | 27 | constexpr const char* errorsString[] = 28 | { 29 | "noError", 30 | "couldNotOpenFinle", 31 | "fileSizeDitNotMatch", 32 | "checkSumFailed", 33 | "couldNotMakeBackup", 34 | "readBackup", 35 | }; 36 | 37 | const char* getErrorString(Errors e) 38 | { 39 | if (e >= 0 && e < sizeof(errorsString) / sizeof(errorsString[0])) 40 | { 41 | return errorsString[e]; 42 | } 43 | else 44 | { 45 | return "unknown error"; 46 | } 47 | } 48 | 49 | Errors readEntireFile(std::vector& data, const char* name) 50 | { 51 | data.clear(); 52 | std::ifstream f(name, std::ios::binary); 53 | 54 | if(f.is_open()) 55 | { 56 | f.seekg(0, std::ios_base::end); 57 | size_t size = f.tellg(); 58 | f.seekg(0, std::ios_base::beg); 59 | 60 | data.resize(size); 61 | 62 | f.read(&data[0], size); 63 | 64 | return noError; 65 | }else 66 | { 67 | return couldNotOpenFinle; 68 | } 69 | } 70 | 71 | Errors readEntireFile(void* data, size_t size, const char* name, bool shouldMatchSize, int* bytesRead) 72 | { 73 | if (bytesRead) 74 | { 75 | *bytesRead = 0; 76 | } 77 | 78 | std::ifstream f(name, std::ios::binary); 79 | if (f.is_open()) 80 | { 81 | f.seekg(0, std::ios_base::end); 82 | size_t readSize = f.tellg(); 83 | f.seekg(0, std::ios_base::beg); 84 | 85 | if (shouldMatchSize) 86 | { 87 | if (readSize != size) 88 | { 89 | return fileSizeDitNotMatch; 90 | } 91 | else 92 | { 93 | f.read((char*)data, readSize); 94 | if (bytesRead) 95 | { 96 | *bytesRead = readSize; 97 | } 98 | 99 | return noError; 100 | } 101 | } 102 | else 103 | { 104 | f.read((char*)data, std::min(size, readSize)); 105 | 106 | if (bytesRead) 107 | { 108 | *bytesRead = std::min(size, readSize); 109 | } 110 | 111 | return noError; 112 | } 113 | } 114 | else 115 | { 116 | return couldNotOpenFinle; 117 | } 118 | } 119 | 120 | using HashType = unsigned long long; 121 | 122 | //https://stackoverflow.com/questions/34595/what-is-a-good-hash-function 123 | unsigned long long fnv_hash_1a_64(const void* key, int len) 124 | { 125 | const unsigned char* p = (const unsigned char*)key; 126 | unsigned long long h = 0xcbf29ce484222325ULL; 127 | for (int i = 0; i < len; i+=4) 128 | { 129 | h = (h ^ p[i + 0]) * 0x100000001b3ULL; 130 | h = (h ^ p[i + 1]) * 0x100000001b3ULL; 131 | h = (h ^ p[i + 2]) * 0x100000001b3ULL; 132 | h = (h ^ p[i + 3]) * 0x100000001b3ULL; 133 | } 134 | 135 | for (int i = len - (len%4); i < len; i++) 136 | { 137 | h = (h ^ p[i]) * 0x100000001b3ULL; 138 | } 139 | 140 | return h; 141 | } 142 | 143 | Errors readEntireFileWithCheckSum(void* data, size_t size, const char* name) 144 | { 145 | std::ifstream f(name, std::ios::binary); 146 | if (f.is_open()) 147 | { 148 | f.seekg(0, std::ios_base::end); 149 | size_t readSize = f.tellg(); 150 | f.seekg(0, std::ios_base::beg); 151 | 152 | size_t sizeWithCheckSum = size + sizeof(HashType); 153 | 154 | if (readSize != sizeWithCheckSum) 155 | { 156 | return fileSizeDitNotMatch; 157 | } 158 | else 159 | { 160 | f.read((char*)data, size); 161 | HashType checkSum = 0; 162 | f.read((char*)&checkSum, sizeof(HashType)); 163 | 164 | auto testCheck = fnv_hash_1a_64(data, size); 165 | 166 | if (testCheck != checkSum) 167 | { 168 | return checkSumFailed; 169 | } 170 | else 171 | { 172 | return noError; 173 | } 174 | } 175 | 176 | } 177 | else 178 | { 179 | return couldNotOpenFinle; 180 | } 181 | } 182 | 183 | Errors writeEntireFileWithCheckSum(const void* data, size_t size, const char* name) 184 | { 185 | std::ofstream f(name, std::ios::binary); 186 | 187 | if (f.is_open()) 188 | { 189 | f.write((char*)data, size); 190 | auto testCheck = fnv_hash_1a_64(data, size); 191 | 192 | f.write((char*)&testCheck, sizeof(testCheck)); 193 | 194 | return noError; 195 | } 196 | else 197 | { 198 | return couldNotOpenFinle; 199 | } 200 | } 201 | 202 | Errors writeEntireFile(const std::vector& data, const char* name) 203 | { 204 | return writeEntireFile(data.data(), data.size(), name); 205 | } 206 | 207 | Errors writeEntireFile(const void* data, size_t size, const char* name) 208 | { 209 | std::ofstream f(name, std::ios::binary); 210 | 211 | if (f.is_open()) 212 | { 213 | f.write((char*)data, size); 214 | return noError; 215 | } 216 | else 217 | { 218 | return couldNotOpenFinle; 219 | } 220 | } 221 | 222 | Errors safeSave(const void* data, size_t size, const char* nameWithoutExtension, bool reportnotMakingBackupAsAnError) 223 | { 224 | std::string file1 = nameWithoutExtension; file1 += "1.bin"; 225 | std::string file2 = nameWithoutExtension; file2 += "2.bin"; 226 | 227 | auto err = writeEntireFileWithCheckSum((char*)data, size, file1.c_str()); 228 | 229 | if (err == couldNotOpenFinle) 230 | { 231 | return couldNotOpenFinle; 232 | } 233 | else 234 | { 235 | auto err2 = writeEntireFileWithCheckSum((char*)data, size, file2.c_str()); 236 | 237 | if (err2 == couldNotOpenFinle) 238 | { 239 | if (reportnotMakingBackupAsAnError) 240 | { 241 | return couldNotMakeBackup; 242 | } 243 | else 244 | { 245 | return noError; 246 | } 247 | } 248 | else 249 | { 250 | return noError; 251 | } 252 | } 253 | } 254 | 255 | Errors safeLoad(void* data, size_t size, const char* nameWithoutExtension, bool reportLoadingBackupAsAnError) 256 | { 257 | std::string file1 = nameWithoutExtension; file1 += "1.bin"; 258 | std::string file2 = nameWithoutExtension; file2 += "2.bin"; 259 | 260 | auto err = readEntireFileWithCheckSum((char*)data, size, file1.c_str()); 261 | 262 | if (err == noError) 263 | { 264 | return noError; 265 | } 266 | else 267 | { 268 | //load backup 269 | auto err2 = readEntireFileWithCheckSum((char*)data, size, file2.c_str()); 270 | 271 | if (err2 == noError) 272 | { 273 | if (reportLoadingBackupAsAnError) 274 | { 275 | return readBackup; 276 | } 277 | else 278 | { 279 | return noError; 280 | } 281 | } 282 | else 283 | { 284 | return err2; 285 | } 286 | } 287 | } 288 | 289 | Errors safeLoadBackup(void* data, size_t size, const char* nameWithoutExtension) 290 | { 291 | std::string file2 = nameWithoutExtension; file2 += "2.bin"; 292 | 293 | //load backup 294 | auto err2 = readEntireFileWithCheckSum((char*)data, size, file2.c_str()); 295 | return err2; 296 | } 297 | 298 | #if defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__ 299 | 300 | Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting) 301 | { 302 | fileMapping = {}; 303 | 304 | DWORD createDisposition = 0; 305 | 306 | if (createIfNotExisting) 307 | { 308 | createDisposition = OPEN_ALWAYS; 309 | } 310 | else 311 | { 312 | createDisposition = OPEN_EXISTING; 313 | } 314 | 315 | fileMapping.internal.fileHandle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, 316 | NULL, createDisposition, FILE_ATTRIBUTE_NORMAL, NULL); 317 | 318 | if (fileMapping.internal.fileHandle == INVALID_HANDLE_VALUE) 319 | { 320 | auto err = GetLastError(); 321 | return Errors::couldNotOpenFinle; 322 | } 323 | 324 | fileMapping.internal.fileMapping = CreateFileMappingA(fileMapping.internal.fileHandle, NULL, PAGE_READWRITE, 0, size, NULL); 325 | 326 | if (fileMapping.internal.fileMapping == NULL) 327 | { 328 | CloseHandle(fileMapping.internal.fileHandle); 329 | return Errors::couldNotOpenFinle; 330 | } 331 | 332 | 333 | fileMapping.pointer = MapViewOfFile(fileMapping.internal.fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, size); 334 | 335 | if (fileMapping.pointer == nullptr) 336 | { 337 | CloseHandle(fileMapping.internal.fileMapping); 338 | CloseHandle(fileMapping.internal.fileHandle); 339 | return Errors::couldNotOpenFinle; 340 | } 341 | 342 | fileMapping.size = size; 343 | 344 | 345 | return Errors::noError; 346 | } 347 | 348 | void closeFileMapping(FileMapping& fileMapping) 349 | { 350 | UnmapViewOfFile(fileMapping.pointer); 351 | CloseHandle(fileMapping.internal.fileMapping); 352 | CloseHandle(fileMapping.internal.fileHandle); 353 | fileMapping = {}; 354 | } 355 | 356 | #elif defined __linux__ 357 | 358 | Errors openFileMapping(FileMapping& fileMapping, const char* name, size_t size, bool createIfNotExisting) 359 | { 360 | int createDisposition = 0; 361 | if(createIfNotExisting) 362 | { 363 | createDisposition = O_CREAT; 364 | } 365 | 366 | fileMapping.internal.fd = open(name, O_RDWR | createDisposition); 367 | 368 | if(fileMapping.internal.fd == -1) 369 | { 370 | return Errors::couldNotOpenFinle; 371 | } 372 | 373 | if(ftruncate(fileMapping.internal.fd, size) == -1) 374 | { 375 | close(fileMapping.internal.fd); 376 | return Errors::couldNotOpenFinle; 377 | } 378 | 379 | fileMapping.pointer = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, 380 | fileMapping.internal.fd, 0); 381 | 382 | if(fileMapping.pointer == MAP_FAILED) 383 | { 384 | fileMapping.pointer = 0; 385 | close(fileMapping.internal.fd); 386 | return Errors::couldNotOpenFinle; 387 | } 388 | 389 | fileMapping.size = size; 390 | 391 | 392 | return Errors::noError; 393 | } 394 | 395 | void closeFileMapping(FileMapping& fileMapping) 396 | { 397 | fsync(fileMapping.internal.fd); 398 | msync(fileMapping.pointer, fileMapping.size, MS_SYNC); 399 | munmap(fileMapping.pointer, fileMapping.size); 400 | close(fileMapping.internal.fd); 401 | 402 | fileMapping = {}; 403 | } 404 | 405 | #endif 406 | 407 | } 408 | --------------------------------------------------------------------------------