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.
This commit is contained in:
yyc12345 2024-08-22 10:57:53 +08:00
parent a7c1028926
commit 1028aad155
6 changed files with 174 additions and 75 deletions

View File

@ -5,9 +5,9 @@
namespace LibCmo::CK2 { 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 OBJECT_MANAGER_GUID1 = 0x7cbb3b91;
constexpr const CKDWORD ATTRIBUTE_MANAGER_GUID1 = 0x3d242466; constexpr const CKDWORD ATTRIBUTE_MANAGER_GUID1 = 0x3d242466;
@ -26,26 +26,26 @@ namespace LibCmo::CK2 {
constexpr const CKDWORD PATH_MANAGER_GUID1 = 0x15fd54b9; constexpr const CKDWORD PATH_MANAGER_GUID1 = 0x15fd54b9;
constexpr const CKDWORD VARIABLE_MANAGER_GUID1 = 0x98cc3cc9; constexpr const CKDWORD VARIABLE_MANAGER_GUID1 = 0x98cc3cc9;
constexpr const CKGUID OBJECT_MANAGER_GUID{ OBJECT_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 ATTRIBUTE_MANAGER_GUID { ATTRIBUTE_MANAGER_GUID1, 0 };
constexpr const CKGUID MESSAGE_MANAGER_GUID{ MESSAGE_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 TIME_MANAGER_GUID { TIME_MANAGER_GUID1, 0 };
constexpr const CKGUID SOUND_MANAGER_GUID{ SOUND_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 MIDI_MANAGER_GUID { MIDI_MANAGER_GUID1, 0 };
constexpr const CKGUID INPUT_MANAGER_GUID{ INPUT_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 BEHAVIOR_MANAGER_GUID { BEHAVIOR_MANAGER_GUID1, 0 };
constexpr const CKGUID FLOOR_MANAGER_GUID{ FLOOR_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 COLLISION_MANAGER_GUID { COLLISION_MANAGER_GUID1, 0 };
constexpr const CKGUID GRID_MANAGER_GUID{ GRID_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 INTERFACE_MANAGER_GUID { INTERFACE_MANAGER_GUID1, 0 };
constexpr const CKGUID RENDER_MANAGER_GUID{ RENDER_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 PARAMETER_MANAGER_GUID { PARAMETER_MANAGER_GUID1, 0 };
constexpr const CKGUID PATH_MANAGER_GUID{ PATH_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 VARIABLE_MANAGER_GUID { VARIABLE_MANAGER_GUID1, 0 };
#pragma endregion #pragma endregion
#pragma region Misc Constant #pragma region Misc Constant Variables
/** /**
* @brief The identifier of Virtools file. * @brief The identifier of Virtools file.
@ -65,8 +65,7 @@ namespace LibCmo::CK2 {
#pragma endregion #pragma endregion
#pragma region Common Used Struct #pragma region Common Used Struct
// a stupid forward decl to remove something
/** /**
* @brief Storage class for filename extensions * @brief Storage class for filename extensions
*/ */
@ -97,10 +96,10 @@ namespace LibCmo::CK2 {
void SetExt(CKSTRING s) { void SetExt(CKSTRING s) {
if (s == nullptr) { if (s == nullptr) {
m_Data[0] = '\0'; m_Data[0] = u8'\0';
} else { } else {
if (s[0] == '.') ++s; // skip dot if (s[0] == u8'.') ++s; // skip dot
size_t len = std::strlen(s); CKDWORD len = CKStrLen(s);
if (len > (c_DataLen - 1)) len = c_DataLen - 1; if (len > (c_DataLen - 1)) len = c_DataLen - 1;
std::memcpy(m_Data, s, len); std::memcpy(m_Data, s, len);
} }
@ -122,13 +121,13 @@ namespace LibCmo::CK2 {
static constexpr size_t c_DataLen = 4u; static constexpr size_t c_DataLen = 4u;
CKCHAR m_Data[c_DataLen]; CKCHAR m_Data[c_DataLen];
}; };
/** /**
* The struct describe the bitmap handler's infomation, * @brief Bitmap readers image description
* including its GUID and supported file extension. * @details
* This struct also will store some parameters related to bitmap handler, * The struct describe the bitmap handler's infomation, including its GUID and supported file extension.
* such as jpeg compress level and etc. But currently there are no * This struct also will store some parameters related to bitmap handler, such as jpeg compress level and etc.
* such parameters. * But currently there are no such parameters.
*/ */
class CKBitmapProperties { class CKBitmapProperties {
public: public:

View File

@ -122,6 +122,14 @@ namespace LibCmo::CK2 {
return strl[0] == u8'\0'; 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<size_t>(std::numeric_limits<CKDWORD>::max()))
throw RuntimeException("Exceed maximum value when cast size_t to CKDWORD.");
return static_cast<CKDWORD>(len);
}
#pragma endregion #pragma endregion
#pragma region CKClass Registration #pragma region CKClass Registration

View File

@ -82,6 +82,14 @@ namespace LibCmo::CK2 {
* @remarks nullptr string is seen as empty string. * @remarks nullptr string is seen as empty string.
*/ */
bool CKStrEmpty(CKSTRING strl); 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 ========== // ========== Class registration utilities ==========

View File

@ -97,15 +97,51 @@ namespace LibCmo::VxMath {
// ========== Patch Section ========== // ========== 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 { 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); 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); 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); 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); 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); void Abs(VxVector3& lhs);
} }

View File

@ -4,29 +4,34 @@
namespace LibCmo::VxMath { namespace LibCmo::VxMath {
VxMemoryMappedFile::VxMemoryMappedFile(CKSTRING u8_filepath) : VxMemoryMappedFile::VxMemoryMappedFile(CKSTRING u8_filepath) :
// init members // Initialize members
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
// Initialize Windows specific.
m_hFile(NULL), m_hFileMapping(NULL), m_hFileMapView(NULL), m_hFile(NULL), m_hFileMapping(NULL), m_hFileMapView(NULL),
m_dwFileSizeLow(0), m_dwFileSizeHigh(0), m_dwFileSize(),
#else #else
// Initialize Linux specific.
m_hFile(-1), m_offFileSize(0), m_pFileAddr((void*)-1), m_hFile(-1), m_offFileSize(0), m_pFileAddr((void*)-1),
#endif #endif
// Initialize common members.
m_szFilePath(), m_szFilePath(),
m_bIsValid(false), m_pMemoryMappedFileBase(nullptr), m_cbFile(0u) { m_bIsValid(false), m_pMemoryMappedFileBase(nullptr), m_cbFile(0u) {
// save file path // Setup file path first
#if YYCC_OS == YYCC_OS_WINDOWS if (u8_filepath == nullptr) return;
EncodingHelper::U8PathToStdPath(m_szFilePath, u8_filepath); m_szFilePath = u8_filepath;
#else
this->m_szFilePath = u8_filepath;
#endif
// real mapping work // Do real mapping work according to different platform.
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
// open file // Parse file name to wchar_t
this->m_hFile = CreateFileW( std::wstring w_filename;
this->m_szFilePath.wstring().c_str(), if (!YYCC::EncodingHelper::UTF8ToWchar(m_szFilePath, w_filename))
return;
// Open file
this->m_hFile = ::CreateFileW(
w_filename.c_str(),
GENERIC_READ, GENERIC_READ,
0, // do not share 0, // do not share
NULL, // no security NULL, // no security
@ -38,14 +43,18 @@ namespace LibCmo::VxMath {
return; return;
} }
// get size // Get size and check its range.
m_dwFileSizeLow = ::GetFileSize(this->m_hFile, &this->m_dwFileSizeHigh); if (!(::GetFileSizeEx(this->m_hFile, &m_dwFileSize))) {
if (m_dwFileSizeLow == INVALID_FILE_SIZE) {
CloseHandle(this->m_hFile); CloseHandle(this->m_hFile);
return; 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_hFileMapping = CreateFileMappingW(
this->m_hFile, this->m_hFile,
NULL, // default security NULL, // default security
@ -58,7 +67,7 @@ namespace LibCmo::VxMath {
return; return;
} }
// open map view // Open map view
this->m_hFileMapView = MapViewOfFile( this->m_hFileMapView = MapViewOfFile(
this->m_hFileMapping, this->m_hFileMapping,
FILE_MAP_READ, FILE_MAP_READ,
@ -69,16 +78,14 @@ namespace LibCmo::VxMath {
CloseHandle(m_hFileMapping); CloseHandle(m_hFileMapping);
CloseHandle(m_hFile); CloseHandle(m_hFile);
} }
// Set base address
// write member data
m_pMemoryMappedFileBase = m_hFileMapView; m_pMemoryMappedFileBase = m_hFileMapView;
m_cbFile = static_cast<size_t>(static_cast<uint64_t>(m_dwFileSizeLow) | (static_cast<uint64_t>(m_dwFileSizeHigh) << 32));
#else #else
// create file // create file
// we do not need provide mode_t, because is served for new created file. // we do not need provide mode_t, because is served for new created file.
// we are opening a existed 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) { if (m_hFile == -1) {
return; return;
} }
@ -91,8 +98,13 @@ namespace LibCmo::VxMath {
close(m_hFile); close(m_hFile);
return; return;
} }
// setup size // Setup size and check its range
this->m_offFileSize = sb.st_size; this->m_offFileSize = sb.st_size;
if (this->m_offFileSize > static_cast<off_t>(std::numeric_limits<CKDWORD>::max())) {
close(m_hFile);
return;
}
m_cbFile = static_cast<CKDWORD>(this->m_offFileSize);
// map file // map file
this->m_pFileAddr = mmap( this->m_pFileAddr = mmap(
@ -107,10 +119,9 @@ namespace LibCmo::VxMath {
close(m_hFile); close(m_hFile);
return; return;
} }
// set base address
// write member data
m_pMemoryMappedFileBase = m_pFileAddr; m_pMemoryMappedFileBase = m_pFileAddr;
m_cbFile = static_cast<size_t>(this->m_offFileSize);
#endif #endif
// set valid // 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;
}
} }

View File

@ -2,12 +2,9 @@
#include "../VTInternal.hpp" #include "../VTInternal.hpp"
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
#include <WinImportPrefix.hpp>
#include <Windows.h> #include <Windows.h>
// disable annoy macro at the same time #include <WinImportSuffix.hpp>
#undef GetObject
#undef GetClassName
#undef LoadImage
#undef GetTempPath
#else #else
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -17,16 +14,19 @@
#endif #endif
#include <string> #include <string>
#include <filesystem>
namespace LibCmo::VxMath { 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 { class VxMemoryMappedFile {
private: private:
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
HANDLE m_hFile; HANDLE m_hFile;
DWORD m_dwFileSizeLow, m_dwFileSizeHigh; LARGE_INTEGER m_dwFileSize;
HANDLE m_hFileMapping; HANDLE m_hFileMapping;
LPVOID m_hFileMapView; LPVOID m_hFileMapView;
#else #else
@ -35,19 +35,41 @@ namespace LibCmo::VxMath {
void* m_pFileAddr; void* m_pFileAddr;
#endif #endif
std::filesystem::path m_szFilePath; std::u8string m_szFilePath;
void* m_pMemoryMappedFileBase; void* m_pMemoryMappedFileBase;
size_t m_cbFile; CKDWORD m_cbFile;
bool m_bIsValid; 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; } public:
CKDWORD GetFileSize(void) { return static_cast<CKDWORD>(this->m_cbFile); } /**
bool IsValid(void) { return this->m_bIsValid; } * @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;
}; };
} }