diff --git a/LibCmo/CK2/CKDefines.hpp b/LibCmo/CK2/CKDefines.hpp index 11ac6a7..af04246 100644 --- a/LibCmo/CK2/CKDefines.hpp +++ b/LibCmo/CK2/CKDefines.hpp @@ -50,7 +50,7 @@ namespace LibCmo::CK2 { /** * @brief The identifier of Virtools file. */ - constexpr const CKCHAR CKNEMOFI[] = "Nemo Fi"; + constexpr const CKCHAR CKNEMOFI[] = u8"Nemo Fi"; /** * @brief Current Version of CK Engine (Day/Month/Year) */ diff --git a/LibCmo/CK2/CKGlobals.cpp b/LibCmo/CK2/CKGlobals.cpp index 6fbb57b..08c2255 100644 --- a/LibCmo/CK2/CKGlobals.cpp +++ b/LibCmo/CK2/CKGlobals.cpp @@ -23,41 +23,56 @@ namespace LibCmo::CK2 { -#pragma region Compression utilities +#pragma region Compression Utilities void* CKPackData(const void* Data, CKDWORD size, CKDWORD& NewSize, CKINT compressionlevel) { - uLong boundary = compressBound(static_cast(size)); - CKBYTE* DestBuffer = new CKBYTE[boundary]; + // check argument + if (Data == nullptr && size != 0u) + throw LogicException("Data passed in CKPackData should not be nullptr."); + // get boundary and allocate buffer. + uLong boundary = compressBound(static_cast(size)); + std::unique_ptr DestBuffer(new CKBYTE[boundary]); + + // do compress uLongf _destLen = static_cast(boundary); if (compress2( - reinterpret_cast(DestBuffer), &_destLen, + reinterpret_cast(DestBuffer.get()), &_destLen, static_cast(Data), static_cast(size), static_cast(compressionlevel)) != Z_OK) { - NewSize = 0; - delete[] DestBuffer; + // failed + NewSize = 0u; return nullptr; } NewSize = static_cast(_destLen); - return DestBuffer; + return DestBuffer.release(); } void* CKUnPackData(CKDWORD DestSize, const void* SrcBuffer, CKDWORD SrcSize) { - CKBYTE* DestBuffer = new CKBYTE[DestSize]; + // check argument + if (SrcBuffer == nullptr && SrcSize != 0u) + throw LogicException("Data passed in CKUnPackData should not be nullptr."); + + // allocate buffer + std::unique_ptr DestBuffer(new CKBYTE[DestSize]); uLongf cache = DestSize; if (uncompress( - reinterpret_cast(DestBuffer), &cache, + reinterpret_cast(DestBuffer.get()), &cache, static_cast(SrcBuffer), static_cast(SrcSize)) != Z_OK) { - delete[] DestBuffer; return nullptr; } - return DestBuffer; + return DestBuffer.release(); } CKDWORD CKComputeDataCRC(const void* data, CKDWORD size, CKDWORD PreviousCRC) { + // check argument + if (data == nullptr && size != 0u) + throw LogicException("Data passed in CKComputeDataCRC should not be nullptr."); + + // compute return static_cast(adler32( static_cast(PreviousCRC), static_cast(data), @@ -69,41 +84,38 @@ namespace LibCmo::CK2 { #pragma region String Utilities - bool CKStrEqual(CKSTRING str1, CKSTRING str2) { + template + static bool InternalStrEqual(CKSTRING str1, CKSTRING str2) { if (str1 == nullptr) { if (str2 == nullptr) return true; else return false; } else { if (str2 == nullptr) return false; else { - return std::strcmp( - YYCC::EncodingHelper::ToOrdinary(str1), - YYCC::EncodingHelper::ToOrdinary(str2) - ) == 0; - } - } - } - - bool CKStrEqualI(CKSTRING str1, CKSTRING str2) { - if (str1 == nullptr) { - if (str2 == nullptr) return true; - else return false; - } else { - if (str2 == nullptr) return false; - else { - // do real cmp - size_t i = 0; - while (str1[i] != u8'\0' && str2[i] != u8'\0') { - if (std::tolower(str1[i]) != std::tolower(str2[i])) return false; + // do real compare + while (*str1 != u8'\0' && *str2 != u8'\0') { + // compare char + if constexpr (bCaseSenstive) { + if (*str1 != *str2) return false; + } else { + if (std::tolower(*str1) != std::tolower(*str2)) return false; + } + // inc step ++str1; ++str2; } - // !XOR the result, if both of them is zero, return true(1) - return !((str1[i] != u8'\0') ^ (str2[i] != u8'\0')); + // if both of them is zero, return true, otherwise false. + return *str1 == u8'\0' && *str2 == u8'\0'; } } } + bool CKStrEqual(CKSTRING str1, CKSTRING str2) { + InternalStrEqual(str1, str2); + } + bool CKStrEqualI(CKSTRING str1, CKSTRING str2) { + InternalStrEqual(str1, str2); + } bool CKStrEmpty(CKSTRING strl) { if (strl == nullptr) return true; @@ -125,7 +137,8 @@ namespace LibCmo::CK2 { void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo) { size_t idxListener, idxListenTo; - if (!GetClassIdIndex(listener, idxListener) || !GetClassIdIndex(listenTo, idxListenTo)) return; + if (!GetClassIdIndex(listener, idxListener) || !GetClassIdIndex(listenTo, idxListenTo)) + throw LogicException("Invalid CK_CLASSID in argument."); XContainer::NSXBitArray::Set(g_CKClassInfo[idxListener].ToBeNotify, static_cast(idxListenTo)); } @@ -170,25 +183,25 @@ namespace LibCmo::CK2 { const CKClassDesc* CKGetClassDesc(CK_CLASSID cid) { size_t intcid; - if (!GetClassIdIndex(cid, intcid)) return nullptr; + if (!GetClassIdIndex(cid, intcid)) + throw LogicException("Invalid CK_CLASSID."); return &g_CKClassInfo[intcid]; } CKSTRING CKClassIDToString(CK_CLASSID cid) { const CKClassDesc* desc = CKGetClassDesc(cid); - if (desc == nullptr) return u8"Undefined Type"; - else return desc->NameFct(); + return desc->NameFct(); } bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) { size_t intchild, intparent; - if (!GetClassIdIndex(child, intchild) || !GetClassIdIndex(parent, intparent)) return false; + if (!GetClassIdIndex(child, intchild) || !GetClassIdIndex(parent, intparent)) + throw LogicException("Invalid CK_CLASSID."); return g_CKClassInfo[intchild].Parents[intparent]; } CK_CLASSID CKGetParentClassID(CK_CLASSID child) { const CKClassDesc* desc = CKGetClassDesc(child); - if (desc == nullptr) return CK_CLASSID::CKCID_OBJECT; return desc->Parent; } @@ -207,7 +220,6 @@ namespace LibCmo::CK2 { bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid) { const CKClassDesc* desc = CKGetClassDesc(listener); - if (desc == nullptr) return false; return XContainer::NSXBitArray::IsSet(desc->CommonToBeNotify, static_cast(deletedObjCid)); } @@ -218,8 +230,6 @@ namespace LibCmo::CK2 { if (!XContainer::NSXBitArray::IsSet(delObjCids, static_cast(i))) continue; const CKClassDesc* desc = CKGetClassDesc(static_cast(i)); - if (desc == nullptr) continue; - XContainer::NSXBitArray::Or(result, desc->ToNotify); } @@ -236,7 +246,7 @@ namespace LibCmo::CK2 { This relation is represented in ToBeNotify, a pure relation without any inhertance hierarchy. Ok, now we assume A have children AA, B also have children BB. - Because B is a businessman, so his children BB also is a bussinessman. + Because B is a businessman, so his children BB also is a businessman. B and BB have the same goods so A can buy his stuff from both of B and BB. This is the first step executed by ComputeParentsNotifyTable(). In this step, the function expand existing business relations to all possible business relations (expand to businessman's children) @@ -429,7 +439,7 @@ CKClassRegister(cid, parentCid, \ } CKERROR CKShutdown() { - // free class indo + // free class infos g_CKClassInfo.clear(); return CKERROR::CKERR_OK; diff --git a/LibCmo/CK2/CKGlobals.hpp b/LibCmo/CK2/CKGlobals.hpp index b8ae0bc..ced5da9 100644 --- a/LibCmo/CK2/CKGlobals.hpp +++ b/LibCmo/CK2/CKGlobals.hpp @@ -3,6 +3,7 @@ #include "CKTypes.hpp" #include "../XContainer/XTypes.hpp" #include +#include namespace LibCmo::CK2 { @@ -10,87 +11,106 @@ namespace LibCmo::CK2 { /** * @brief Compress a buffer - * @param[in] Data A pointer to the buffer to coompress + * @param[in] Data A pointer to the buffer to compress. nullptr is not allowed. * @param[in] size Size of the source buffer. * @param[out] NewSize A reference that will be filled with the size of the compressed buffer. 0 if failed. - * @param[in] compressionlevel 0-9 + * @param[in] compressionlevel 0-9 Greater level smaller result size. * @return * A pointer to the compressed buffer. nullptr if failed. - * The return pointer should be freed by `delete[]` manually. - * @remark + * The return pointer should be freed by \c delete[] manually. + * @remarks * The size of allocated return value may greater than the passed value of NewSize. * NewSize only indicate the size of the part storing useful data in return value. - * @see CKUnPackData, CKComputeDataCRC + * @exception LogicException Raised if given buffer is nullptr and size is not equal to zero. + * @see CKUnPackData(), CKComputeDataCRC() */ void* CKPackData(const void* Data, CKDWORD size, CKDWORD& NewSize, CKINT compressionlevel); /** * @brief Decompress a buffer * @param[in] DestSize Expected size of the decompressed buffer. - * @param[in] SrcBuffer Compressed buffer. + * @param[in] SrcBuffer Compressed buffer. nullptr is not allowed. * @param[in] SrcSize Size of the compressed buffer. * @return * A pointer to the decompressed buffer or nullptr if there was a error. - * The return pointer should be freed by `delete[]` manually. - * @see CKPackData, CKComputeDataCRC + * The return pointer should be freed by \c delete[] manually. + * @exception LogicException Raised if given buffer is nullptr and size is not equal to zero. + * @see CKPackData(), CKComputeDataCRC() */ void* CKUnPackData(CKDWORD DestSize, const void* SrcBuffer, CKDWORD SrcSize); /** * @brief Computes a CRC for a buffer. - * @param[in] data A pointer to the buffer to create a CRC for. + * @param[in] data A pointer to the buffer to create a CRC for. nullptr is not allowed. * @param[in] size Size of the source buffer. * @param[in] PreviousCRC * The first time a CRC is computed this value should be 0, * but it can be use to compute a single CRC for a several buffers * by using the currently computed CRC for previous buffers in this value. * @return CRC of the buffer. - * @see CKPackData, CKUnPackData + * @exception LogicException Raised if given buffer is nullptr and size is not equal to zero. + * @see CKPackData(), CKUnPackData() */ CKDWORD CKComputeDataCRC(const void* data, CKDWORD size, CKDWORD PreviousCRC = 0); // ========== String Utilities ========== /** - * @brief Check whether 2 string is equal. Case senstive. - * @param str1[in] String 1 - * @param str2[in] String 2 - * @return True if 2 string is equal. - * @see CKStrIEqual + * @brief Check whether two string is equal. Case senstive. + * @param[in] str1 First string. nullptr is allowed but not suggested. + * @param[in] str2 Second string. nullptr is allowed but not suggested. + * @return True if two string is equal, otherwise false. + * @remarks + * nullptr string is not equal to any other string. + * However two nullptr string is equal. + * @see CKStrEqualI() */ bool CKStrEqual(CKSTRING str1, CKSTRING str2); /** - * @brief Check whther 2 string is equal. Case insenstive. - * @param str1 - * @param str2 - * @return True if 2 string is equal. - * @see CKStrEqual + * @brief Check whther two string is equal. Case insenstive. + * @param[in] str1 First string. nullptr is allowed but not suggested. + * @param[in] str2 Second string. nullptr is allowed but not suggested. + * @return True if two string is equal, otherwise false. + * @remarks + * nullptr string is not equal to any other string. + * However two nullptr string is equal. + * @see CKStrEqual() */ bool CKStrEqualI(CKSTRING str1, CKSTRING str2); /** * @brief Check whether string is empty - * @param strl - * @return True if string is empty. + * @param[in] strl String for checking. nullptr is allowed but not suggested. + * @return True if string is empty, otherwise false. + * @remarks nullptr string is seen as empty string. */ bool CKStrEmpty(CKSTRING strl); // ========== Class registration utilities ========== + /// @brief Function pointer which do extra stuff when registry this class. using CKClassRegisterFct = std::function; + /// @brief Function pointer which create ObjImpls::CKObject pointer by given CKContext, CK_ID and name. using CKClassCreationFct = std::function; + /// @brief Function pointer which free given ObjImpls::CKObject pointer. using CKClassReleaseFct = std::function; + /// @brief Function pointer which return the name of class. using CKClassNameFct = std::function; //using CKClassDependenciesFct = std::function; //using CKClassDependenciesCountFct = std::function; + /** + * @brief The representation of a registered class. + */ struct CKClassDesc { + // Variables used when building class hierarchy table bool IsValid; /**< True if this CKClassDesc is a valid one. Because CK_CLASSID may not be consecutive. */ - bool Done; - // Initialized upon class registration - CK_CLASSID Self; - CK_CLASSID Parent; // Class Identifier of parent class - CKClassRegisterFct RegisterFct; // Pointer to Class Specific Registration function - CKClassCreationFct CreationFct; // Pointer to Class instance creation function - CKClassReleaseFct ReleaseFct; // Pointer to Class instance release function - CKClassNameFct NameFct; // Pointer to Class name function + bool Done; /**< Temporary variable indicating this item has been processed when creating table. */ + + // Variables initialized upon class registration + CK_CLASSID Self; /**< Class identifier of self */ + CK_CLASSID Parent; /**< Class identifier of parent class */ + CKClassRegisterFct RegisterFct; /**< Function pointer which do extra stuff when registry this class. */ + CKClassCreationFct CreationFct; /**< Function pointer which create ObjImpls::CKObject pointer by given CKContext, CK_ID and name. */ + CKClassReleaseFct ReleaseFct; /**< Function pointer which free given ObjImpls::CKObject pointer. */ + CKClassNameFct NameFct; /**< Function pointer which return the name of class. */ //CKClassDependenciesFct DependsFct; // Pointer to Class dependencies function (Copy,delete,replace...) //CKClassDependenciesCountFct DependsCountFct; // Pointer to Class dependencies Count function (Copy,delete,replace...) @@ -102,13 +122,13 @@ namespace LibCmo::CK2 { //CKDWORD DefaultSaveDependencies; //CKGUID Parameter; // Associated parameter GUID - // Initialized when building class hierarchy table - CKINT DerivationLevel; // O => CKObject , etc.. - XContainer::XBitArray Parents; // Bit Mask of parents classes - XContainer::XBitArray Children; // Bit Mask of children classes - XContainer::XBitArray ToBeNotify; // User specified notify list, only for current class. If any deleted objects match class id in this XBitArray, notify the host of this XBitArray. - XContainer::XBitArray CommonToBeNotify; // Same as ToBeNotify, but merging all parents' notify list. - XContainer::XBitArray ToNotify; // The ClassID to notify when an object of this class is deleted (inverse of ToBeNotify) + // Variables initialized after building class hierarchy table + CKINT DerivationLevel; /**< How many parent level it has. 0 for CKObject, etc.. */ + XContainer::XBitArray Parents; /**< Bit Mask of parents classes */ + XContainer::XBitArray Children; /**< Bit Mask of children classes */ + XContainer::XBitArray ToBeNotify; /**< User specified notify list, only for current class. If any deleted objects match class id in this XBitArray, notify the host of this XBitArray. */ + XContainer::XBitArray CommonToBeNotify; /**< Same as ToBeNotify, but merging all parents' notify list. */ + XContainer::XBitArray ToNotify; /**< The ClassID to notify when an object of this class is deleted (inverse of ToBeNotify) */ CKClassDesc() : IsValid(false), @@ -123,39 +143,111 @@ namespace LibCmo::CK2 { // ========== CKClass Registration ========== + /** + * @brief Order that first class id will be notified when deleting object whose class id is second argument + * @param[in] listener The id of class will be notified. + * @param[in] listenTo The id of class which first argument interested in. + * @exception LogicException Raised if given CK_CLASSID is invalid. + */ void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo); + /** + * @brief Get an usable class id for registration. + * @details This function is usually used by plugin to registering classes. + * Because all embedded Virtools classes has constant class id. + * @return An usable class id for registration. + */ CK_CLASSID CKClassGetNewIdentifier(); + /** + * @brief Register a new class. + * @param[in] cid The id of this class. + * @param[in] parentCid The id of parent class. + * @param[in] regFct Pointer to class specific registration function which do extra stuff when registry this class. + * @param[in] createFct Pointer to class instance creation function + * @param[in] relFct Pointer to class instance release function + * @param[in] nameFct Pointer to class name function + */ void CKClassRegister(CK_CLASSID cid, CK_CLASSID parentCid, CKClassRegisterFct regFct, CKClassCreationFct createFct, CKClassReleaseFct relFct, CKClassNameFct nameFct); // ========== Class Hierarchy Management ========== + /** + * @brief Get total count of registered classes. + * @return The total count of registered classes. + */ CKDWORD CKGetClassCount(); + /** + * @brief Get the class description struct by given class id. + * @param[in] cid Class id for fetching. + * @return The pointer to corresponding class description. + * We guaranteen that this pointer must not be nullptr. + * @exception LogicException Raised if given CK_CLASSID is invalid. + */ const CKClassDesc* CKGetClassDesc(CK_CLASSID cid); + /** + * @brief Get the name representation of given class id. + * @param[in] cid Class id for fetching. + * @return The name of given class id. + * @exception LogicException Raised if given CK_CLASSID is invalid. + */ CKSTRING CKClassIDToString(CK_CLASSID cid); + /** + * @brief Check whether first class is second class' child class. + * @param[in] child The id of first class assumed as child class. + * @param[in] parent The id of second class assumed as parent class. + * @return True if relation is satisfied, otherwise false. + * @exception LogicException Raised if given CK_CLASSID is invalid. + */ bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent); + /** + * @brief Get the parent class id of given class id. + * @param[in] child The id to class which need to find parent class. + * @return The parent class id. + * @exception LogicException Raised if given CK_CLASSID is invalid. + */ CK_CLASSID CKGetParentClassID(CK_CLASSID child); + /** + * @brief Get the cloest common parent of given two classes. + * @param[in] cid1 The id of first class finding common parent. + * @param[in] cid2 The id of second class finding common parent. + * @return The cloest common parent class id. + * @exception LogicException Raised if given CK_CLASSID is invalid. + */ CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2); /** - * @brief Check whether 'listener' need notified by the deletion of 'deletedObjCid' - * @param listener - * @param deletedObjCid - * @return true if need notify + * @brief Check whether object whose class id is first argument, need to be notified when the objects whose class id is second argument, is deleting. + * @param[in] listener The class id of checking whether need to be notified. + * @param[in] deletedObjCid The class id of deleting object. + * @return True if it need to be notified, otherwise false. + * @exception LogicException Raised if given CK_CLASSID is invalid. */ - bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid); + bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid); /** /** - * @brief Get all object cid need to be notified when 'delObjCids' matched objects are deleting. - * @param delObjCids - * @param cidCount - * @return + * @brief Get all class ids need to be notified when objects whose class id included in \c delObjCids are deleting. + * @param[in] delObjCids The bit array representing class ids which need to be queried. + * @return The queried bit array representing class ids need to be notified. + * @exception LogicException Raised if given CK_CLASSID is invalid. + * @see CKIsNeedNotify() */ XContainer::XBitArray CKGetAllNotifyClassID(const XContainer::XBitArray& delObjCids); - // ========== Initializations functions ========== + // ========== Initializations Functions ========== + /** + * @brief Initialize CK engine. + * @details You must call this function before anything. + * @return Error code about initializing. + * @see CKShutdown() + */ CKERROR CKStartUp(); + /** + * @brief Shutdown CK engine. + * @details You must call this function after you have done all things. + * @return Error code about shutdown. + * @see CKStartUp() + */ CKERROR CKShutdown(); } diff --git a/LibCmo/CK2/MgrImpls/CKObjectManager.cpp b/LibCmo/CK2/MgrImpls/CKObjectManager.cpp index 23b34a5..0fecb05 100644 --- a/LibCmo/CK2/MgrImpls/CKObjectManager.cpp +++ b/LibCmo/CK2/MgrImpls/CKObjectManager.cpp @@ -20,7 +20,6 @@ namespace LibCmo::CK2::MgrImpls { // get description first const CKClassDesc* desc = CKGetClassDesc(cls); - if (desc == nullptr) return nullptr; // allocate a CK_ID first CKDWORD decided_off; @@ -60,12 +59,7 @@ namespace LibCmo::CK2::MgrImpls { void CKObjectManager::InternalDestroy(ObjImpls::CKObject* obj) { // find desc by classid - // if really we can not find it, we only can delete it directly. const CKClassDesc* desc = CKGetClassDesc(obj->GetClassID()); - if (desc == nullptr) { - delete obj; - return; - } // free it desc->ReleaseFct(m_Context, obj); diff --git a/LibCmo/VTUtils.hpp b/LibCmo/VTUtils.hpp index b84349f..37f53c5 100644 --- a/LibCmo/VTUtils.hpp +++ b/LibCmo/VTUtils.hpp @@ -97,7 +97,7 @@ namespace LibCmo { /** * @brief Reverse given enum flags like performing ~(e) * @tparam TEnum Enum type for processing. - * @param[in] il The list of enum flags to be inversed. + * @param[in] e The list of enum flags to be inversed. * @return The inversed enum flag. */ template, int> = 0> diff --git a/LibCmo/VxMath/VxMath.cpp b/LibCmo/VxMath/VxMath.cpp index 7a3f2e5..3bb655d 100644 --- a/LibCmo/VxMath/VxMath.cpp +++ b/LibCmo/VxMath/VxMath.cpp @@ -11,7 +11,8 @@ namespace LibCmo::VxMath { } void VxCopyStructure(CKDWORD Count, void* Dst, CKDWORD OutStride, CKDWORD SizeSrc, const void* Src, CKDWORD InStride) { - if (Dst == nullptr || Src == nullptr) return; + if ((Dst == nullptr || Src == nullptr) && Count != 0u) + throw LogicException("Source or destination buffer should not be nullptr."); CKBYTE* cdst = static_cast(Dst); const CKBYTE* csrc = static_cast(Src); @@ -27,8 +28,10 @@ namespace LibCmo::VxMath { #pragma region Graphic Utilities void VxDoBlit(const VxImageDescEx* origin, VxImageDescEx* dst) { - if (dst == nullptr || origin == nullptr) return; - if (!dst->IsValid() || !origin->IsValid()) return; + if (dst == nullptr || origin == nullptr) + throw LogicException("VxImageDescEx* should not be nullptr."); + if (!dst->IsValid() || !origin->IsValid()) + throw LogicException("VxImageDescEx* should not be invalid."); // if have same size, directly copy it if (dst->IsHWEqual(*origin)) { @@ -48,8 +51,10 @@ namespace LibCmo::VxMath { } void VxDoBlitUpsideDown(const VxImageDescEx* origin, VxImageDescEx* dst) { - if (dst == nullptr || origin == nullptr) return; - if (!dst->IsValid() || !origin->IsValid()) return; + if (dst == nullptr || origin == nullptr) + throw LogicException("VxImageDescEx* should not be nullptr."); + if (!dst->IsValid() || !origin->IsValid()) + throw LogicException("VxImageDescEx* should not be invalid."); // if size is not matched, return if (!dst->IsHWEqual(*origin)) { @@ -99,7 +104,8 @@ namespace LibCmo::VxMath { //} void VxDoAlphaBlit(VxImageDescEx* dst_desc, CKBYTE AlphaValue) { - if (dst_desc == nullptr) return; + if (dst_desc == nullptr || !dst_desc->IsValid()) + throw LogicException("VxImageDescEx* should not be nullptr or invalid."); CKDWORD* pixels = dst_desc->GetMutablePixels(); CKDWORD pixelcount = dst_desc->GetPixelCount(); @@ -111,7 +117,10 @@ namespace LibCmo::VxMath { } void VxDoAlphaBlit(VxImageDescEx* dst_desc, const CKBYTE* AlphaValues) { - if (dst_desc == nullptr) return; + if (dst_desc == nullptr || !dst_desc->IsValid() || AlphaValues == nullptr) + throw LogicException("VxImageDescEx* should not be nullptr or invalid."); + if (AlphaValues == nullptr) + throw LogicException("Alpha channel buffer should not be nullptr."); CKDWORD* pixels = dst_desc->GetMutablePixels(); CKDWORD pixelcount = dst_desc->GetPixelCount(); diff --git a/LibCmo/VxMath/VxMath.hpp b/LibCmo/VxMath/VxMath.hpp index 87de9d8..beb838e 100644 --- a/LibCmo/VxMath/VxMath.hpp +++ b/LibCmo/VxMath/VxMath.hpp @@ -7,23 +7,27 @@ namespace LibCmo::VxMath { /** * @brief Fills a memory buffer with a source buffer pattern. - * @param Count[in] Number of element to set in the destination buffer - * @param Dst[out] Destination buffer - * @param Stride[in] Amount in bytes between each element in the destination buffer - * @param SizeSrc[in] Size in bytes of an element int the Src buffer - * @param Src[in] Source buffer - * @remark This function can be used to initialized an array of structure when only some members should be modified. + * @details This function can be used to initialized an array of structure when only some members should be modified. + * @param[in] Count Number of element to set in the destination buffer + * @param[out] Dst Destination buffer + * @param[in] Stride Amount in bytes between each element in the destination buffer + * @param[in] SizeSrc Size in bytes of an element int the Src buffer + * @param[in] Src Source buffer + * @exception LogicException Raised if source or destination buffer is nullptr, and count is not zero. + * @remarks If given buffer is not sufficient to perform operations, it will cause undefined behavior. */ void VxFillStructure(CKDWORD Count, void* Dst, CKDWORD Stride, CKDWORD SizeSrc, const void* Src); /** * @brief copies an array of elements between two memory buffers. - * @param Count[in] Number of element to copy in the destination buffer - * @param Dst[out] Destination buffer - * @param OutStride[in] Amount in bytes between each element in the destination buffer - * @param SizeSrc[in] Size in bytes of an element - * @param Src[in] Source buffer. - * @param InStride[in] Amount in bytes between each element in the source buffer - * @remark This function can be used to initialized an array of structure when only some members should be modified. + * @details This function can be used to initialized an array of structure when only some members should be modified. + * @param[in] Count Number of element to copy in the destination buffer + * @param[out] Dst Destination buffer + * @param[in] OutStride Amount in bytes between each element in the destination buffer + * @param[in] SizeSrc Size in bytes of an element + * @param[in] Src Source buffer. + * @param[in] InStride Amount in bytes between each element in the source buffer + * @exception LogicException Raised if source or destination buffer is nullptr, and count is not zero. + * @remarks If given buffer is not sufficient to perform operations, it will cause undefined behavior. */ void VxCopyStructure(CKDWORD Count, void* Dst, CKDWORD OutStride, CKDWORD SizeSrc, const void* Src, CKDWORD InStride); @@ -31,55 +35,63 @@ namespace LibCmo::VxMath { /** * @brief Performs a blit between two images. This method can resize (shrink or grow) images. - * @remark The source image must be in a 32 bit ARGB8888 per pixel format. - * @param dest[out] The dest image. - * @param origin[in] The origin image. + * @param[out] dst The destination image. + * @param[in] origin The origin image. + * @remarks The source image must be in a 32 bit ARGB8888 per pixel format. + * @exception LogicException Raised if given image description is nullptr or invalid. */ void VxDoBlit(const VxImageDescEx* origin, VxImageDescEx* dst); /** * @brief Performs a blit between two images. This method can inverts the destination image. - * @remark - + The source image must be in a 32 bit ARGB8888 per pixel format. - + This function usually used in the covertion between texture coordinate - system and UV coordinate system. - * @param dest[out] The dest image. - * @param origin[in] The origin image. + * @param[out] dst The destination image. + * @param[in] origin The origin image. + * @remarks + * \li The source image must be in a 32 bit ARGB8888 per pixel format. + * \li This function usually used in the covertion between texture coordinate system and UV coordinate system. + * @exception LogicException Raised if given image description is nullptr or invalid. */ void VxDoBlitUpsideDown(const VxImageDescEx* origin, VxImageDescEx* dst); /** - * @brief Counts number of bits to representing a value in dwMask + * @brief Get the total count of set(1) bit in given value. + * @param[in] dwMask The value for counting. + * @return The total count of set(1) bit. */ CKDWORD VxGetBitCount(CKDWORD dwMask); /** - * @brief Counts number of bits to shift to acces a non zero value in dwMask. + * @brief Get the offset in bit to first set(1) bit when performing right shift. + * @param[in] dwMask The value for fetching offset. + * @return The offset in bit to first set(1) bit. + * If there is no set(1) bit in given value, return 0 instead. */ CKDWORD VxGetBitShift(CKDWORD dwMask); - ///** - // * @brief scale the integer to a new range. - // * @param val The int need to be scale - // * @param srcBitCount The bit count which source integer consumed. - // * @param dstBitCount The bit count which dest integer consumed. - // * @remark This function usually used in image color factor assign with mask. + // /** + // * @brief Scale the integer to a new range. + // * @param[in] val The int need to be scale + // * @param[in] srcBitCount The bit count which source integer consumed. + // * @param[in] dstBitCount The bit count which dest integer consumed. + // * @remarks This function usually used in image color factor assign with mask. // * @return The result integer. //*/ //CKDWORD VxScaleFactor(CKDWORD val, CKDWORD srcBitCount, CKDWORD dstBitCount); /** * @brief Sets the alpha component of an image. - * @remark The source image must be in a 32 bit ARGB8888 per pixel format. - * @param dst_desc[in] A pointer to a structure describing the destination image format. - * @param AlphaValue[in] A CKBYTE value containing the alpha value to set to the whole image - * @remark If the destination image does not have alpha information the function returns immediatly. + * @param[in] dst_desc A pointer to a structure describing the destination image format. + * @param[in] AlphaValue A CKBYTE value containing the alpha value to set to the whole image + * @remarks The source image must be in a 32 bit ARGB8888 per pixel format. + * @exception LogicException Raised if given image description is nullptr or invalid. */ void VxDoAlphaBlit(VxImageDescEx* dst_desc, CKBYTE AlphaValue); /** * @brief Sets the alpha component of an image. - * @remark The source image must be in a 32 bit ARGB8888 per pixel format. - * @param dst_desc[in] A pointer to a structure describing the destination image format. - * @param AlphaValues[in] A BYTE array containing the alpha values for each pixel. This array should be allocated to Width*Height bytes. - * @remark If the destination image does not have alpha information the function returns immediatly. + * @param[in] dst_desc A pointer to a structure describing the destination image format. + * @param[in] AlphaValues A BYTE array containing the alpha values for each pixel. This array should be allocated to Width * Height bytes. + * @remarks + * \li The source image must be in a 32 bit ARGB8888 per pixel format. + * \li If given alpha channel buffer do not have correct length, it will cause undefined behavior. + * @exception LogicException Raised if given image description or alpha channel buffer is nullptr or invalid. */ void VxDoAlphaBlit(VxImageDescEx* dst_desc, const CKBYTE* AlphaValues);