From 1028aad15568369babc6daa5e2993081e6efb1db Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Thu, 22 Aug 2024 10:57:53 +0800 Subject: [PATCH] doc: add documentation - add documentation for CKDefines, CKGlobals and VxMemoryMappedFile. - fix build issue in VxMemoryMappedFile. - add file size limitation in VxMemoryMappedFile. File whose size exceed the maximum value can not be opened. --- LibCmo/CK2/CKDefines.hpp | 59 +++++++++++---------- LibCmo/CK2/CKGlobals.cpp | 8 +++ LibCmo/CK2/CKGlobals.hpp | 8 +++ LibCmo/VxMath/VxMath.hpp | 38 +++++++++++++- LibCmo/VxMath/VxMemoryMappedFile.cpp | 78 ++++++++++++++++++---------- LibCmo/VxMath/VxMemoryMappedFile.hpp | 58 ++++++++++++++------- 6 files changed, 174 insertions(+), 75 deletions(-) diff --git a/LibCmo/CK2/CKDefines.hpp b/LibCmo/CK2/CKDefines.hpp index af04246..fe667dc 100644 --- a/LibCmo/CK2/CKDefines.hpp +++ b/LibCmo/CK2/CKDefines.hpp @@ -5,9 +5,9 @@ namespace LibCmo::CK2 { -#pragma region Preregistred Managers +#pragma region Preregistred Manager GUIDs - // Virtools Managers GUID second data is 0 + // Virtools Managers GUID second DWORD must be 0 constexpr const CKDWORD OBJECT_MANAGER_GUID1 = 0x7cbb3b91; constexpr const CKDWORD ATTRIBUTE_MANAGER_GUID1 = 0x3d242466; @@ -26,26 +26,26 @@ namespace LibCmo::CK2 { constexpr const CKDWORD PATH_MANAGER_GUID1 = 0x15fd54b9; constexpr const CKDWORD VARIABLE_MANAGER_GUID1 = 0x98cc3cc9; - constexpr const CKGUID OBJECT_MANAGER_GUID{ OBJECT_MANAGER_GUID1 ,0 }; - constexpr const CKGUID ATTRIBUTE_MANAGER_GUID{ ATTRIBUTE_MANAGER_GUID1, 0 }; - constexpr const CKGUID MESSAGE_MANAGER_GUID{ MESSAGE_MANAGER_GUID1 ,0 }; - constexpr const CKGUID TIME_MANAGER_GUID{ TIME_MANAGER_GUID1 ,0 }; - constexpr const CKGUID SOUND_MANAGER_GUID{ SOUND_MANAGER_GUID1 ,0 }; - constexpr const CKGUID MIDI_MANAGER_GUID{ MIDI_MANAGER_GUID1 ,0 }; - constexpr const CKGUID INPUT_MANAGER_GUID{ INPUT_MANAGER_GUID1 ,0 }; - constexpr const CKGUID BEHAVIOR_MANAGER_GUID{ BEHAVIOR_MANAGER_GUID1 ,0 }; - constexpr const CKGUID FLOOR_MANAGER_GUID{ FLOOR_MANAGER_GUID1 ,0 }; - constexpr const CKGUID COLLISION_MANAGER_GUID{ COLLISION_MANAGER_GUID1 ,0 }; - constexpr const CKGUID GRID_MANAGER_GUID{ GRID_MANAGER_GUID1 ,0 }; - constexpr const CKGUID INTERFACE_MANAGER_GUID{ INTERFACE_MANAGER_GUID1 ,0 }; - constexpr const CKGUID RENDER_MANAGER_GUID{ RENDER_MANAGER_GUID1 ,0 }; - constexpr const CKGUID PARAMETER_MANAGER_GUID{ PARAMETER_MANAGER_GUID1 ,0 }; - constexpr const CKGUID PATH_MANAGER_GUID{ PATH_MANAGER_GUID1 ,0 }; - constexpr const CKGUID VARIABLE_MANAGER_GUID{ VARIABLE_MANAGER_GUID1 ,0 }; + constexpr const CKGUID OBJECT_MANAGER_GUID { OBJECT_MANAGER_GUID1, 0 }; + constexpr const CKGUID ATTRIBUTE_MANAGER_GUID { ATTRIBUTE_MANAGER_GUID1, 0 }; + constexpr const CKGUID MESSAGE_MANAGER_GUID { MESSAGE_MANAGER_GUID1, 0 }; + constexpr const CKGUID TIME_MANAGER_GUID { TIME_MANAGER_GUID1, 0 }; + constexpr const CKGUID SOUND_MANAGER_GUID { SOUND_MANAGER_GUID1, 0 }; + constexpr const CKGUID MIDI_MANAGER_GUID { MIDI_MANAGER_GUID1, 0 }; + constexpr const CKGUID INPUT_MANAGER_GUID { INPUT_MANAGER_GUID1, 0 }; + constexpr const CKGUID BEHAVIOR_MANAGER_GUID { BEHAVIOR_MANAGER_GUID1, 0 }; + constexpr const CKGUID FLOOR_MANAGER_GUID { FLOOR_MANAGER_GUID1, 0 }; + constexpr const CKGUID COLLISION_MANAGER_GUID { COLLISION_MANAGER_GUID1, 0 }; + constexpr const CKGUID GRID_MANAGER_GUID { GRID_MANAGER_GUID1, 0 }; + constexpr const CKGUID INTERFACE_MANAGER_GUID { INTERFACE_MANAGER_GUID1, 0 }; + constexpr const CKGUID RENDER_MANAGER_GUID { RENDER_MANAGER_GUID1, 0 }; + constexpr const CKGUID PARAMETER_MANAGER_GUID { PARAMETER_MANAGER_GUID1, 0 }; + constexpr const CKGUID PATH_MANAGER_GUID { PATH_MANAGER_GUID1, 0 }; + constexpr const CKGUID VARIABLE_MANAGER_GUID { VARIABLE_MANAGER_GUID1, 0 }; #pragma endregion -#pragma region Misc Constant +#pragma region Misc Constant Variables /** * @brief The identifier of Virtools file. @@ -65,8 +65,7 @@ namespace LibCmo::CK2 { #pragma endregion #pragma region Common Used Struct - - // a stupid forward decl to remove something + /** * @brief Storage class for filename extensions */ @@ -97,10 +96,10 @@ namespace LibCmo::CK2 { void SetExt(CKSTRING s) { if (s == nullptr) { - m_Data[0] = '\0'; + m_Data[0] = u8'\0'; } else { - if (s[0] == '.') ++s; // skip dot - size_t len = std::strlen(s); + if (s[0] == u8'.') ++s; // skip dot + CKDWORD len = CKStrLen(s); if (len > (c_DataLen - 1)) len = c_DataLen - 1; std::memcpy(m_Data, s, len); } @@ -122,13 +121,13 @@ namespace LibCmo::CK2 { static constexpr size_t c_DataLen = 4u; CKCHAR m_Data[c_DataLen]; }; - + /** - * The struct describe the bitmap handler's infomation, - * including its GUID and supported file extension. - * This struct also will store some parameters related to bitmap handler, - * such as jpeg compress level and etc. But currently there are no - * such parameters. + * @brief Bitmap readers image description + * @details + * The struct describe the bitmap handler's infomation, including its GUID and supported file extension. + * This struct also will store some parameters related to bitmap handler, such as jpeg compress level and etc. + * But currently there are no such parameters. */ class CKBitmapProperties { public: diff --git a/LibCmo/CK2/CKGlobals.cpp b/LibCmo/CK2/CKGlobals.cpp index 08c2255..19af15c 100644 --- a/LibCmo/CK2/CKGlobals.cpp +++ b/LibCmo/CK2/CKGlobals.cpp @@ -122,6 +122,14 @@ namespace LibCmo::CK2 { return strl[0] == u8'\0'; } + CKDWORD CKStrLen(CKSTRING strl) { + if (strl == nullptr) return 0u; + size_t len = std::strlen(YYCC::EncodingHelper::ToOrdinary(strl)); + if (len > static_cast(std::numeric_limits::max())) + throw RuntimeException("Exceed maximum value when cast size_t to CKDWORD."); + return static_cast(len); + } + #pragma endregion #pragma region CKClass Registration diff --git a/LibCmo/CK2/CKGlobals.hpp b/LibCmo/CK2/CKGlobals.hpp index ced5da9..b0aa492 100644 --- a/LibCmo/CK2/CKGlobals.hpp +++ b/LibCmo/CK2/CKGlobals.hpp @@ -82,6 +82,14 @@ namespace LibCmo::CK2 { * @remarks nullptr string is seen as empty string. */ bool CKStrEmpty(CKSTRING strl); + /** + * @brief Get the length of given string. + * @param[in] strl String for getting length. nullptr is allowed but not suggested. + * @return String length in UTF8 code unit. + * @remarks nullptr string will return 0 instead. + * @exception RuntimeException Raised if the length of string exceed the maximum value of CKDWORD. + */ + CKDWORD CKStrLen(CKSTRING strl); // ========== Class registration utilities ========== diff --git a/LibCmo/VxMath/VxMath.hpp b/LibCmo/VxMath/VxMath.hpp index beb838e..5a3de26 100644 --- a/LibCmo/VxMath/VxMath.hpp +++ b/LibCmo/VxMath/VxMath.hpp @@ -97,15 +97,51 @@ namespace LibCmo::VxMath { // ========== Patch Section ========== - + + /** + * @brief The patch namespace for VxVector-like classes + * @details This namespace provides VxVector-like classes member functions which presented in original Virtools SDK. + * These functions are put in public namespace in original Virtools SDK. + * We just organise them into an unique namespace. + */ namespace NSVxVector { + /** + * @brief Dot product 2 2d vectors. + * @param[in] lhs The left side vector of dot product symbol. + * @param[in] rhs The right side vector of dot product symbol. + * @return The float pointing result of dot product. + */ CKFLOAT DotProduct(const VxVector2& lhs, const VxVector2& rhs); + /** + * @brief Dot product 2 3d vectors. + * @param[in] lhs The left side vector of dot product symbol. + * @param[in] rhs The right side vector of dot product symbol. + * @return The float pointing result of dot product. + */ CKFLOAT DotProduct(const VxVector3& lhs, const VxVector3& rhs); + /** + * @brief Dot product 2 4d vectors. + * @param[in] lhs The left side vector of dot product symbol. + * @param[in] rhs The right side vector of dot product symbol. + * @return The float pointing result of dot product. + */ CKFLOAT DotProduct(const VxVector4& lhs, const VxVector4& rhs); + /** + * @brief Cross product 2 3d vectors. + * @param[in] lhs The left side vector of cross product symbol. + * @param[in] rhs The right side vector of cross product symbol. + * @return The 3d vector result of cross product. + */ VxVector3 CrossProduct(const VxVector3& lhs, const VxVector3& rhs); + /** + * @brief Set all factor in vector to its absolute value. + * @param[in,out] lhs The vector for processing. + * @remarks This function is rarely used. + * Please note this function is not calculate the absolute value of vector. + */ void Abs(VxVector3& lhs); } diff --git a/LibCmo/VxMath/VxMemoryMappedFile.cpp b/LibCmo/VxMath/VxMemoryMappedFile.cpp index 45db7e2..8049efa 100644 --- a/LibCmo/VxMath/VxMemoryMappedFile.cpp +++ b/LibCmo/VxMath/VxMemoryMappedFile.cpp @@ -4,29 +4,34 @@ namespace LibCmo::VxMath { VxMemoryMappedFile::VxMemoryMappedFile(CKSTRING u8_filepath) : - // init members + // Initialize members #if YYCC_OS == YYCC_OS_WINDOWS + // Initialize Windows specific. m_hFile(NULL), m_hFileMapping(NULL), m_hFileMapView(NULL), - m_dwFileSizeLow(0), m_dwFileSizeHigh(0), + m_dwFileSize(), #else + // Initialize Linux specific. m_hFile(-1), m_offFileSize(0), m_pFileAddr((void*)-1), #endif + // Initialize common members. m_szFilePath(), m_bIsValid(false), m_pMemoryMappedFileBase(nullptr), m_cbFile(0u) { - // save file path -#if YYCC_OS == YYCC_OS_WINDOWS - EncodingHelper::U8PathToStdPath(m_szFilePath, u8_filepath); -#else - this->m_szFilePath = u8_filepath; -#endif + // Setup file path first + if (u8_filepath == nullptr) return; + m_szFilePath = u8_filepath; - // real mapping work + // Do real mapping work according to different platform. #if YYCC_OS == YYCC_OS_WINDOWS - // open file - this->m_hFile = CreateFileW( - this->m_szFilePath.wstring().c_str(), + // Parse file name to wchar_t + std::wstring w_filename; + if (!YYCC::EncodingHelper::UTF8ToWchar(m_szFilePath, w_filename)) + return; + + // Open file + this->m_hFile = ::CreateFileW( + w_filename.c_str(), GENERIC_READ, 0, // do not share NULL, // no security @@ -38,14 +43,18 @@ namespace LibCmo::VxMath { return; } - // get size - m_dwFileSizeLow = ::GetFileSize(this->m_hFile, &this->m_dwFileSizeHigh); - if (m_dwFileSizeLow == INVALID_FILE_SIZE) { + // Get size and check its range. + if (!(::GetFileSizeEx(this->m_hFile, &m_dwFileSize))) { CloseHandle(this->m_hFile); return; } + if (m_dwFileSize.HighPart != 0) { + CloseHandle(this->m_hFile); + return; + } + m_cbFile = m_dwFileSize.LowPart; - // open mapping + // Open mapping this->m_hFileMapping = CreateFileMappingW( this->m_hFile, NULL, // default security @@ -58,7 +67,7 @@ namespace LibCmo::VxMath { return; } - // open map view + // Open map view this->m_hFileMapView = MapViewOfFile( this->m_hFileMapping, FILE_MAP_READ, @@ -69,16 +78,14 @@ namespace LibCmo::VxMath { CloseHandle(m_hFileMapping); CloseHandle(m_hFile); } - - // write member data + // Set base address m_pMemoryMappedFileBase = m_hFileMapView; - m_cbFile = static_cast(static_cast(m_dwFileSizeLow) | (static_cast(m_dwFileSizeHigh) << 32)); - + #else // create file // we do not need provide mode_t, because is served for new created file. // we are opening a existed file. - this->m_hFile = open(m_szFilePath.string().c_str(), O_RDONLY); + this->m_hFile = open(YYCC::EncodingHelper::ToOrdinary(m_szFilePath.c_str()), O_RDONLY); if (m_hFile == -1) { return; } @@ -91,8 +98,13 @@ namespace LibCmo::VxMath { close(m_hFile); return; } - // setup size + // Setup size and check its range this->m_offFileSize = sb.st_size; + if (this->m_offFileSize > static_cast(std::numeric_limits::max())) { + close(m_hFile); + return; + } + m_cbFile = static_cast(this->m_offFileSize); // map file this->m_pFileAddr = mmap( @@ -107,10 +119,9 @@ namespace LibCmo::VxMath { close(m_hFile); return; } - - // write member data + // set base address m_pMemoryMappedFileBase = m_pFileAddr; - m_cbFile = static_cast(this->m_offFileSize); + #endif // set valid @@ -135,5 +146,20 @@ namespace LibCmo::VxMath { } } + const void* VxMemoryMappedFile::GetBase() const { + if (!this->IsValid()) + throw RuntimeException("Try to get file base address on an invalid VxMemoryMappedFile"); + return this->m_pMemoryMappedFileBase; + } + + CKDWORD VxMemoryMappedFile::GetFileSize() const { + if (!this->IsValid()) + throw RuntimeException("Try to get file size on an invalid VxMemoryMappedFile"); + return this->m_cbFile; + } + + bool VxMemoryMappedFile::IsValid() const { + return this->m_bIsValid; + } } diff --git a/LibCmo/VxMath/VxMemoryMappedFile.hpp b/LibCmo/VxMath/VxMemoryMappedFile.hpp index 3647503..fceab8c 100644 --- a/LibCmo/VxMath/VxMemoryMappedFile.hpp +++ b/LibCmo/VxMath/VxMemoryMappedFile.hpp @@ -2,12 +2,9 @@ #include "../VTInternal.hpp" #if YYCC_OS == YYCC_OS_WINDOWS +#include #include -// disable annoy macro at the same time -#undef GetObject -#undef GetClassName -#undef LoadImage -#undef GetTempPath +#include #else #include #include @@ -17,16 +14,19 @@ #endif #include -#include namespace LibCmo::VxMath { + /** + * @brief Utility class for memory mapped file reading. + * @details The VxMemoryMappedFile can be used have a mapping of a file into a memory buffer for reading purposes. + * @remarks Due to Virtools limitation, we disallow opening any file whose size exceed the maximum value of CKDWORD. + */ class VxMemoryMappedFile { private: - #if YYCC_OS == YYCC_OS_WINDOWS HANDLE m_hFile; - DWORD m_dwFileSizeLow, m_dwFileSizeHigh; + LARGE_INTEGER m_dwFileSize; HANDLE m_hFileMapping; LPVOID m_hFileMapView; #else @@ -35,19 +35,41 @@ namespace LibCmo::VxMath { void* m_pFileAddr; #endif - std::filesystem::path m_szFilePath; + std::u8string m_szFilePath; void* m_pMemoryMappedFileBase; - size_t m_cbFile; + CKDWORD m_cbFile; bool m_bIsValid; - public: - VxMemoryMappedFile(CKSTRING u8_filepath); - VxMemoryMappedFile(const VxMemoryMappedFile&) = delete; - VxMemoryMappedFile& operator=(const VxMemoryMappedFile&) = delete; - ~VxMemoryMappedFile(void); - void* GetBase(void) { return this->m_pMemoryMappedFileBase; } - CKDWORD GetFileSize(void) { return static_cast(this->m_cbFile); } - bool IsValid(void) { return this->m_bIsValid; } + public: + /** + * @brief Create a new VxMemoryMappedFile + * @param[in] u8_filepath The path to file to be opened. nullptr is allowed but not suggested. + * Because it must create an invalid VxMemoryMappedFile. + */ + VxMemoryMappedFile(CKSTRING u8_filepath); + ~VxMemoryMappedFile(); + YYCC_DEL_CLS_COPY_MOVE(VxMemoryMappedFile); + + /** + * @brief Returns a pointer to the mapped memory buffer. + * @return The pointer to the mapped memory buffer for reading. + * @remarks + * The returned pointer should not be deleted nor should it be used for writing purpose. + * If you did, it will cause undefined behavior. + * @exception RuntimeException Raised when calling this on an invalid file mapping. + */ + const void* GetBase() const; + /** + * @brief Returns the file size in bytes. + * @return The file size in bytes. + * @exception RuntimeException Raised when calling this on an invalid file mapping. + */ + CKDWORD GetFileSize() const; + /** + * @brief Check whether this file mapping is valid to use. + * @return True if it is, otherwise false. + */ + bool IsValid() const; }; }