fix: fix libcmo build issue

This commit is contained in:
yyc12345 2024-08-23 11:28:49 +08:00
parent 1028aad155
commit 0447381896
13 changed files with 191 additions and 135 deletions

View File

@ -60,48 +60,48 @@ namespace LibCmo::CK2 {
/** /**
* @brief Create a black image with full alpha in specified slot. * @brief Create a black image with full alpha in specified slot.
* @param Width[in] Image width * @param[in] Width Image width
* @param Height[in] Image height * @param[in] Height Image height
* @param Slot[in] The slot placing image. * @param[in] Slot The slot placing image.
* @return True if creating success. * @return True if creating success.
*/ */
bool CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot); bool CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot);
/** /**
* @brief Load image into specified slot. * @brief Load image into specified slot.
* @param filename[in] The file name of loading image. * @param[in] filename The file name of loading image.
* @param slot[in] The slot placing loaded image. * @param[in] slot The slot placing loaded image.
* @return True if load successfully. * @return True if load successfully.
*/ */
bool LoadImage(CKSTRING filename, CKDWORD slot); bool LoadImage(CKSTRING filename, CKDWORD slot);
/** /**
* @brief Save image for specified slot. * @brief Save image for specified slot.
* @param filename[in] The file name of saving image. * @param[in] filename The file name of saving image.
* @param slot[in] The slot will be saved. * @param[in] slot The slot will be saved.
* @param isForceThisFmt[in] True to use this class specified format to save image. Otherwise use the format evaluated by the image file name. * @param[in] isForceThisFmt True to use this class specified format to save image. Otherwise use the format evaluated by the image file name.
* @return True if success. * @return True if success.
*/ */
bool SaveImage(CKSTRING filename, CKDWORD slot, bool isForceThisFmt = false); bool SaveImage(CKSTRING filename, CKDWORD slot, bool isForceThisFmt = false);
/** /**
* @brief Get specified slot image descriptor. * @brief Get specified slot image descriptor.
* @param slot[in] The slot to get. * @param[in] slot The slot to get.
* @return The descriptor. nullptr if failed. * @return The descriptor. nullptr if failed.
*/ */
VxMath::VxImageDescEx* GetImageDesc(CKDWORD slot); VxMath::VxImageDescEx* GetImageDesc(CKDWORD slot);
/** /**
* @brief Release specified slot image. * @brief Release specified slot image.
* @param slot[in] The slot to free. * @param[in] slot The slot to free.
*/ */
void ReleaseImage(CKDWORD slot); void ReleaseImage(CKDWORD slot);
/** /**
* @brief Set associated file name for specified slot. * @brief Set associated file name for specified slot.
* @param slot[in] The slot to set. * @param[in] slot The slot to set.
* @param filename[in] The associated file name. * @param[in] filename The associated file name.
*/ */
bool SetSlotFileName(CKDWORD slot, CKSTRING filename); bool SetSlotFileName(CKDWORD slot, CKSTRING filename);
/** /**
* @brief Get associated file name for specified slot. * @brief Get associated file name for specified slot.
* @param slot[in] The slot to get. * @param[in] slot The slot to get.
* @return The file name. nullptr if failed. * @return The file name. nullptr if failed.
*/ */
CKSTRING GetSlotFileName(CKDWORD slot) const; CKSTRING GetSlotFileName(CKDWORD slot) const;
@ -132,7 +132,7 @@ namespace LibCmo::CK2 {
void SetSaveOptions(CK_TEXTURE_SAVEOPTIONS opts); void SetSaveOptions(CK_TEXTURE_SAVEOPTIONS opts);
/** /**
@brief Enables or disables the color key transparency. @brief Enables or disables the color key transparency.
@param Transparency[in] TRUE activates transparency, FALSE disables it. @param[in] Transparency TRUE activates transparency, FALSE disables it.
@remark @remark
+ 0x00000000 (black) is the default transparent color. + 0x00000000 (black) is the default transparent color.
+ Setting on the transparency and a transparent color automatically + Setting on the transparency and a transparent color automatically
@ -149,7 +149,7 @@ namespace LibCmo::CK2 {
bool IsTransparent() const; bool IsTransparent() const;
/** /**
@brief Sets the transparent color. @brief Sets the transparent color.
@param Color[in] A 32 bit ARGB transparent color. @param[in] Color A 32 bit ARGB transparent color.
@remark @remark
+ 0x00000000 (black) is the default transparent color. + 0x00000000 (black) is the default transparent color.
+ Setting on the transparency and a transparent color automatically + Setting on the transparency and a transparent color automatically
@ -168,7 +168,7 @@ namespace LibCmo::CK2 {
CKDWORD GetTransparentColor() const; CKDWORD GetTransparentColor() const;
/** /**
@brief Sets pick threshold value. @brief Sets pick threshold value.
@param pt[in] Pick threshold value to be set. @param[in] pt Pick threshold value to be set.
@remark @remark
+ The pick threshold is used when picking object with + The pick threshold is used when picking object with
transparent textures. transparent textures.

View File

@ -26,7 +26,7 @@ namespace LibCmo::CK2 {
m_OutputCallback(nullptr) { m_OutputCallback(nullptr) {
// setup save format // setup save format
m_GlobalImagesSaveFormat.m_Ext.SetExt("bmp"); m_GlobalImagesSaveFormat.m_Ext.SetExt(u8"bmp");
// setup managers // setup managers
m_ObjectManager = new MgrImpls::CKObjectManager(this); m_ObjectManager = new MgrImpls::CKObjectManager(this);
@ -42,6 +42,8 @@ namespace LibCmo::CK2 {
for (auto& mgrptr : m_ManagerList) { for (auto& mgrptr : m_ManagerList) {
delete mgrptr; delete mgrptr;
} }
// free encoding
this->ClearEncoding();
} }
#pragma endregion #pragma endregion
@ -252,23 +254,18 @@ namespace LibCmo::CK2 {
void CKContext::OutputToConsole(CKSTRING str) { void CKContext::OutputToConsole(CKSTRING str) {
if (m_OutputCallback == nullptr) return; if (m_OutputCallback == nullptr) return;
if (str == nullptr) return;
m_OutputCallback(str); m_OutputCallback(str);
} }
void CKContext::OutputToConsoleEx(CKSTRING fmt, ...) { void CKContext::OutputToConsoleEx(CKSTRING fmt, ...) {
if (m_OutputCallback == nullptr) return; if (m_OutputCallback == nullptr) return;
if (fmt == nullptr) return;
va_list argptr; va_list argptr;
va_start(argptr, fmt); va_start(argptr, fmt);
XContainer::XString result; XContainer::XString result;
int count = std::vsnprintf(nullptr, 0, fmt, argptr); YYCC::StringHelper::VPrintf(fmt, argptr);
result.resize(count);
// count + 1 for NUL terminator. but we don't need allocate space for it (resize with count). let it write into the reserved tail of std::string.
int write_result = std::vsnprintf(result.data(), count + 1, fmt, argptr);
if (write_result < 0 || write_result > count) return;
va_end(argptr); va_end(argptr);
// use c_str(), not XContainer::NSXString::ToCKSTRING because we want make sure this paramter is not nullptr. // use c_str(), not XContainer::NSXString::ToCKSTRING because we want make sure this paramter is not nullptr.
@ -284,48 +281,67 @@ namespace LibCmo::CK2 {
#pragma region Encoding utilities #pragma region Encoding utilities
void CKContext::GetUtf8String(const XContainer::XString& native_name, XContainer::XString& u8_name) { void CKContext::GetUTF8String(const std::string& native_name, XContainer::XString& u8_name) {
bool success = false; bool conv_success = false, has_valid_token = false;
for (const auto& token : this->m_NameEncoding) { for (const auto& token : this->m_NameEncoding) {
success = LibCmo::EncodingHelper::GetUtf8VirtoolsName(native_name, u8_name, token); if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
if (success) break; has_valid_token = true;
conv_success = EncodingHelper::ToUTF8(native_name, u8_name, token);
if (conv_success) break;
} }
// fallback if failed.
// fallback if (!conv_success) {
if (!success) { if (!has_valid_token) {
u8_name = native_name; throw RuntimeException("Try to get UTF8 string from ordinary string in CKContext but giving empty encoding candidate.");
this->OutputToConsole("Error when converting to UTF8 string."); } else {
u8_name.clear();
this->OutputToConsole(u8"Error when converting to UTF8 string from ordinary string. The string will leave to blank.");
}
} }
} }
void CKContext::GetNativeString(const XContainer::XString& u8_name, XContainer::XString& native_name) { void CKContext::GetOrdinaryString(const XContainer::XString& u8_name, std::string& native_name) {
bool success = false; bool conv_success = false, has_valid_token = false;
for (const auto& token : this->m_NameEncoding) { for (const auto& token : this->m_NameEncoding) {
success = LibCmo::EncodingHelper::GetNativeVirtoolsName(u8_name, native_name, token); if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
if (success) break; has_valid_token = true;
conv_success = EncodingHelper::ToOrdinary(u8_name, native_name, token);
if (conv_success) break;
} }
// fallback if failed.
// fallback if (!conv_success) {
if (!success) { if (!has_valid_token) {
native_name = u8_name; throw RuntimeException("Try to get ordinary string from UTF8 string in CKContext but giving empty encoding candidate.");
this->OutputToConsole("Error when converting to native string."); } else {
native_name.clear();
this->OutputToConsole(u8"Error when converting to ordinary string from UTF8 string. The string will leave to blank.");
}
} }
} }
void CKContext::SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_series) { void CKContext::SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_seq) {
// free all current series // free all current series
for (const auto& encoding : this->m_NameEncoding) { this->ClearEncoding();
LibCmo::EncodingHelper::DestroyEncodingToken(encoding); // add new encoding
for (const auto& encoding_str : encoding_seq) {
this->m_NameEncoding.emplace_back(LibCmo::EncodingHelper::CreateEncodingToken(encoding_str));
}
}
void CKContext::ClearEncoding() {
for (const auto& token : this->m_NameEncoding) {
if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
LibCmo::EncodingHelper::DestroyEncodingToken(token);
} }
this->m_NameEncoding.clear(); this->m_NameEncoding.clear();
// add new encoding
for (const auto& encoding_str : encoding_series) {
this->m_NameEncoding.push_back(LibCmo::EncodingHelper::CreateEncodingToken(encoding_str));
}
} }
bool CKContext::IsValidEncoding() {
for (const auto& token : this->m_NameEncoding) {
if (token != EncodingHelper::INVALID_ENCODING_TOKEN) return true;
}
return false;
}
#pragma endregion #pragma endregion

View File

@ -100,18 +100,73 @@ namespace LibCmo::CK2 {
// ========== Encoding utilities ========== // ========== Encoding utilities ==========
public: public:
void GetUtf8String(const XContainer::XString& native_name, XContainer::XString& u8_name); /**
void GetNativeString(const XContainer::XString& u8_name, XContainer::XString& native_name); * @brief Convert given ordinary string to UTF8 string.
* @param[in] native_name The input ordinary string.
* @param[out] u8_name The output UTF8 string.
* @exception RuntimeException Raised when perform this operation with a blank encoding sequence.
* @remarks
* The encoding of ordinary is specified by encoding sequence.
* If we fail to do convertion, the result will leave to blank and output a message to CKContext.
* However, if you use this function with blank encoding sequence, it will raise exception.
*/
void GetUTF8String(const std::string& native_name, XContainer::XString& u8_name);
/**
* @brief Convert given UTF8 string to ordinary string.
* @param[in] u8_name The input UTF8 string.
* @param[out] native_name The output ordinary string.
* @exception RuntimeException Raised when perform this operation with a blank encoding sequence.
* @remarks
* The encoding of ordinary is specified by encoding sequence.
* If we fail to do convertion, the result will leave to blank and output a message to CKContext.
* However, if you use this function with blank encoding sequence, it will raise exception.
*/
void GetOrdinaryString(const XContainer::XString& u8_name, std::string& native_name);
/**
* @brief Set the encoding sequence.
* @param[in] encoding_series The encoding name in this sequence.
* @remarks
* \li The order in encoding sequence is important. The encoding name with lower index will be used for convertion first.
* \li Encoding sequence will be used for performing GetUTF8String() and GetOrdinaryString().
* We will try using it to do convertion from top to bottom (if one failed we will continue trying to use next one to do convertion).
*/
void SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_series); void SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_series);
/**
* @brief Clear specified encoding sequence.
*/
void ClearEncoding();
/**
* @brief Check whether current encoding sequence at least has one valid encoding for convertion.
* @return True if it is, otherwise false.
*/
bool IsValidEncoding();
protected: protected:
XContainer::XArray<EncodingHelper::ENCODING_TOKEN> m_NameEncoding; XContainer::XArray<EncodingHelper::EncodingToken> m_NameEncoding;
// ========== Print utilities ========== // ========== Print utilities ==========
public: public:
using OutputCallback = std::function<void(CKSTRING)>; /**
* @brief The callback prototype.
* @details It accept a CKSTRING representing the string need to be printed.
* The passed CKSTRING is guaranteen that it can not be nullptr.
*/
using OutputCallback = void(*)(CKSTRING);
/**
* @brief Output plain message.
* @param[in] str Plain message. nullptr is allowed but not suggested.
*/
void OutputToConsole(CKSTRING str); void OutputToConsole(CKSTRING str);
/**
* @brief Output message with given format.
* @param[in] fmt The format string. nullptr is allowed but not suggested.
* @param[in] ... The arguments of format string.
*/
void OutputToConsoleEx(CKSTRING fmt, ...); void OutputToConsoleEx(CKSTRING fmt, ...);
/**
* @brief Set the callback for message printing.
* @param[in] cb The function pointer to callback. nullptr to remove callback.
*/
void SetOutputCallback(OutputCallback cb); void SetOutputCallback(OutputCallback cb);
protected: protected:

View File

@ -67,7 +67,6 @@ namespace LibCmo::CK2 {
} }
}; };
#pragma pack(push)
#pragma pack(1) #pragma pack(1)
struct CKRawFileInfo { struct CKRawFileInfo {
CKBYTE NeMo[8]; CKBYTE NeMo[8];
@ -87,7 +86,7 @@ namespace LibCmo::CK2 {
CKDWORD ProductBuild; CKDWORD ProductBuild;
CKDWORD Hdr1UnPackSize; CKDWORD Hdr1UnPackSize;
}; };
#pragma pack(pop) #pragma pack()
class CKFileInfo { class CKFileInfo {
public: public:
@ -211,7 +210,7 @@ namespace LibCmo::CK2 {
// XContainer::XClassArray<XContainer::XIntArray> m_IndexByClassId; /**< List of index in the m_FileObjects table sorted by ClassID */ // XContainer::XClassArray<XContainer::XIntArray> m_IndexByClassId; /**< List of index in the m_FileObjects table sorted by ClassID */
/** /**
* @brief List of files that should be inserted in the CMO file. * @brief List of files that should be inserted in the CMO file.
* @remark Each item is just file name, not the full path to file. * @remarks Each item is just file name, not the full path to file.
*/ */
XContainer::XArray<XContainer::XString> m_IncludedFiles; XContainer::XArray<XContainer::XString> m_IncludedFiles;
CKFileInfo m_FileInfo; /**< Headers summary */ CKFileInfo m_FileInfo; /**< Headers summary */
@ -242,37 +241,36 @@ namespace LibCmo::CK2 {
protected: protected:
/** /**
* @brief A helper function to check whether given file can be written. * @brief A helper function to check whether given file can be written.
* @param filename[in] The name of file to be wriiten * @param[in] filename The name of file to be wriiten
* @return CKERROR::CK_OK if can write. * @return CKERROR::CK_OK if can write.
*/ */
CKERROR PrepareFile(CKSTRING filename); CKERROR PrepareFile(CKSTRING filename);
/** /**
* @brief Internal used Object Adder. * @brief Internal used Object Adder.
* * @details
* This function is used by AddSavedObject() and Copy from reader constructor. * This function is used by AddSavedObject() and Copy from reader constructor.
* This function accept a object pointer, and try adding them. * This function accept an object pointer, and try adding them.
* And set m_IncludedFiles and m_ObjectsHashTable properly. * And set m_IncludedFiles and m_ObjectsHashTable properly.
* * @param[in] obj The pointer to added object.
* @param obj The pointer to added object. * @param[in] flags The flag used when saving this object.
* @param flags The flag used when saving this object.
* @return True if success. * @return True if success.
*/ */
bool InternalObjectAdder(ObjImpls::CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL); bool InternalObjectAdder(ObjImpls::CKObject* obj, CKDWORD flags = CK_STATESAVE_ALL);
protected: protected:
bool m_Done; /**< True if this writer is already written into file. A written CKFileWriter can no be written again. */ bool m_Done; /**< True if this writer is already written into file. A written CKFileWriter can no be written again. */
/** /**
* @brief True if this writer is not allowed to add objects. * @brief True if this writer is not allowed to add objects.
* @remark * @remarks
* + This field should be false in default. * \li This field should be false in default.
* + This field usually be set when importing from reader. * \li This field usually be set when importing from reader.
*/ */
bool m_DisableAddingObject; bool m_DisableAddingObject;
/** /**
* @brief True if this writer is not allowed to add files. * @brief True if this writer is not allowed to add files.
* @remark * @remarks
* + This field should be false in default. * \li This field should be false in default.
* + This field usually be set when importing from reader. * \li This field usually be set when importing from reader.
*/ */
bool m_DisableAddingFile; bool m_DisableAddingFile;
@ -282,7 +280,7 @@ namespace LibCmo::CK2 {
XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; /**< Plugins dependencies for this file */ XContainer::XArray<CKFilePluginDependencies> m_PluginsDep; /**< Plugins dependencies for this file */
/** /**
* @brief List of files that should be inserted in the CMO file. * @brief List of files that should be inserted in the CMO file.
* @remark Each item is the full path to file. * @remarks Each item is the full path to file.
*/ */
XContainer::XArray<XContainer::XString> m_IncludedFiles; XContainer::XArray<XContainer::XString> m_IncludedFiles;
XContainer::XHashTable<CK_ID, CKDWORD> m_ObjectsHashTable; /**< A Object ID to save index hash table. */ XContainer::XHashTable<CK_ID, CKDWORD> m_ObjectsHashTable; /**< A Object ID to save index hash table. */

View File

@ -23,7 +23,7 @@ namespace LibCmo::CK2 {
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER; if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new VxMath::VxMemoryMappedFile(u8_filename)); std::unique_ptr<VxMath::VxMemoryMappedFile> mappedFile(new VxMath::VxMemoryMappedFile(u8_filename));
if (!mappedFile->IsValid()) { if (!mappedFile->IsValid()) {
this->m_Ctx->OutputToConsoleEx("Fail to create Memory File for \"%s\".", u8_filename); this->m_Ctx->OutputToConsoleEx(u8"Fail to create Memory File for \"%s\".", u8_filename);
return CKERROR::CKERR_INVALIDFILE; return CKERROR::CKERR_INVALIDFILE;
} }
@ -42,7 +42,7 @@ namespace LibCmo::CK2 {
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false)); std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
parser->SetCursor(ParserPtr->GetCursor()); parser->SetCursor(ParserPtr->GetCursor());
XContainer::XString name_conv; std::string name_conv;
// ========== read header ========== // ========== read header ==========
// check header size // check header size
@ -93,7 +93,7 @@ namespace LibCmo::CK2 {
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc); gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc);
if (gotten_crc != this->m_FileInfo.Crc) { if (gotten_crc != this->m_FileInfo.Crc) {
this->m_Ctx->OutputToConsole("Virtools file CRC error."); this->m_Ctx->OutputToConsole(u8"Virtools file CRC error.");
return CKERROR::CKERR_FILECRCERROR; return CKERROR::CKERR_FILECRCERROR;
} }
@ -129,7 +129,7 @@ namespace LibCmo::CK2 {
if (namelen != 0) { if (namelen != 0) {
name_conv.resize(namelen); name_conv.resize(namelen);
parser->Read(name_conv.data(), namelen); parser->Read(name_conv.data(), namelen);
m_Ctx->GetUtf8String(name_conv, fileobj.Name); m_Ctx->GetUTF8String(name_conv, fileobj.Name);
} else { } else {
XContainer::NSXString::FromCKSTRING(fileobj.Name, nullptr); XContainer::NSXString::FromCKSTRING(fileobj.Name, nullptr);
} }
@ -197,7 +197,7 @@ namespace LibCmo::CK2 {
std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false)); std::unique_ptr<CKBufferParser> parser(new CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
parser->SetCursor(ParserPtr->GetCursor()); parser->SetCursor(ParserPtr->GetCursor());
XContainer::XString name_conv; std::string name_conv;
// ========== compress feature process ========== // ========== compress feature process ==========
if (EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) || if (EnumsHelper::Has(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
@ -219,7 +219,7 @@ namespace LibCmo::CK2 {
0u 0u
); );
if (gotten_crc != this->m_FileInfo.Crc) { if (gotten_crc != this->m_FileInfo.Crc) {
this->m_Ctx->OutputToConsole("Virtools file CRC error."); this->m_Ctx->OutputToConsole(u8"Virtools file CRC error.");
return CKERROR::CKERR_FILECRCERROR; return CKERROR::CKERR_FILECRCERROR;
} }
@ -307,7 +307,7 @@ namespace LibCmo::CK2 {
// read filename // read filename
if (filenamelen != 0) { if (filenamelen != 0) {
parser->Read(name_conv.data(), filenamelen); parser->Read(name_conv.data(), filenamelen);
m_Ctx->GetUtf8String(name_conv, file); m_Ctx->GetUTF8String(name_conv, file);
} }
// read file body length // read file body length
@ -316,12 +316,12 @@ namespace LibCmo::CK2 {
// read file body // read file body
XContainer::XString tempfilename = m_Ctx->GetPathManager()->GetTempFilePath(file.c_str()); XContainer::XString tempfilename = m_Ctx->GetPathManager()->GetTempFilePath(file.c_str());
FILE* fp = EncodingHelper::U8FOpen(tempfilename.c_str(), "wb"); FILE* fp = YYCC::IOHelper::UTF8FOpen(tempfilename.c_str(), u8"wb");
if (fp != nullptr) { if (fp != nullptr) {
std::fwrite(parser->GetPtr(), sizeof(CKBYTE), filebodylen, fp); std::fwrite(parser->GetPtr(), sizeof(CKBYTE), filebodylen, fp);
std::fclose(fp); std::fclose(fp);
} else { } else {
m_Ctx->OutputToConsoleEx("Fail to open temp file: %s", tempfilename.c_str()); m_Ctx->OutputToConsoleEx(u8"Fail to open temp file: %s", tempfilename.c_str());
} }
// move to next // move to next

View File

@ -14,7 +14,7 @@ namespace LibCmo::CK2 {
if (this->m_Done) return CKERROR::CKERR_CANCELLED; if (this->m_Done) return CKERROR::CKERR_CANCELLED;
// encoding conv helper // encoding conv helper
XContainer::XString name_conv; std::string name_conv;
// try detect filename legality // try detect filename legality
CKERROR err = PrepareFile(u8_filename); CKERROR err = PrepareFile(u8_filename);
@ -89,7 +89,7 @@ namespace LibCmo::CK2 {
sumHdrObjSize += 4 * CKSizeof(CKDWORD); sumHdrObjSize += 4 * CKSizeof(CKDWORD);
if (XContainer::NSXString::ToCKSTRING(obj.Name) != nullptr) { if (XContainer::NSXString::ToCKSTRING(obj.Name) != nullptr) {
// += Name size // += Name size
m_Ctx->GetNativeString(obj.Name, name_conv); m_Ctx->GetOrdinaryString(obj.Name, name_conv);
sumHdrObjSize += static_cast<CKDWORD>(name_conv.size()); sumHdrObjSize += static_cast<CKDWORD>(name_conv.size());
} }
@ -176,7 +176,7 @@ namespace LibCmo::CK2 {
if (XContainer::NSXString::ToCKSTRING(obj.Name) != nullptr) { if (XContainer::NSXString::ToCKSTRING(obj.Name) != nullptr) {
// if have name, write it // if have name, write it
m_Ctx->GetNativeString(obj.Name, name_conv); m_Ctx->GetOrdinaryString(obj.Name, name_conv);
CKDWORD namelen = static_cast<CKDWORD>(name_conv.size()); CKDWORD namelen = static_cast<CKDWORD>(name_conv.size());
hdrparser->Write(&namelen); hdrparser->Write(&namelen);
hdrparser->Write(name_conv.data(), namelen); hdrparser->Write(name_conv.data(), namelen);
@ -299,7 +299,7 @@ namespace LibCmo::CK2 {
// ========== Open File & Write Essential Data ========== // ========== Open File & Write Essential Data ==========
// open file and test // open file and test
FILE* fs = EncodingHelper::U8FOpen(u8_filename, "wb"); FILE* fs = YYCC::IOHelper::UTF8FOpen(u8_filename, u8"wb");
if (fs == nullptr) return CKERROR::CKERR_CANTWRITETOFILE; if (fs == nullptr) return CKERROR::CKERR_CANTWRITETOFILE;
// write small header + header + data // write small header + header + data
std::fwrite(&rawHeader, sizeof(CKRawFileInfo), 1, fs); std::fwrite(&rawHeader, sizeof(CKRawFileInfo), 1, fs);
@ -316,7 +316,7 @@ namespace LibCmo::CK2 {
m_Ctx->GetPathManager()->GetFileName(filename); m_Ctx->GetPathManager()->GetFileName(filename);
// write filename // write filename
m_Ctx->GetNativeString(filename, name_conv); m_Ctx->GetOrdinaryString(filename, name_conv);
CKDWORD filenamelen = static_cast<CKDWORD>(name_conv.size()); CKDWORD filenamelen = static_cast<CKDWORD>(name_conv.size());
std::fwrite(&filenamelen, sizeof(CKDWORD), 1, fs); std::fwrite(&filenamelen, sizeof(CKDWORD), 1, fs);
std::fwrite(name_conv.data(), sizeof(CKBYTE), filenamelen, fs); std::fwrite(name_conv.data(), sizeof(CKBYTE), filenamelen, fs);
@ -336,7 +336,7 @@ namespace LibCmo::CK2 {
std::fwrite(&filebodylen, sizeof(CKDWORD), 1, fs); std::fwrite(&filebodylen, sizeof(CKDWORD), 1, fs);
// report error // report error
m_Ctx->OutputToConsoleEx("Fail to open temp file: %" PRI_CKSTRING, fentry.c_str()); m_Ctx->OutputToConsoleEx(u8"Fail to open temp file: %" PRI_CKSTRING, fentry.c_str());
} }
// release mapped file // release mapped file
@ -356,7 +356,7 @@ namespace LibCmo::CK2 {
// try open file to check whether we can write it. // try open file to check whether we can write it.
CKERROR err; CKERROR err;
FILE* tryfile = EncodingHelper::U8FOpen(filename, "ab"); FILE* tryfile = YYCC::IOHelper::UTF8FOpen(filename, u8"ab");
if (tryfile == nullptr) { if (tryfile == nullptr) {
err = CKERROR::CKERR_CANTWRITETOFILE; err = CKERROR::CKERR_CANTWRITETOFILE;
} else { } else {

View File

@ -111,10 +111,10 @@ namespace LibCmo::CK2 {
} }
} }
bool CKStrEqual(CKSTRING str1, CKSTRING str2) { bool CKStrEqual(CKSTRING str1, CKSTRING str2) {
InternalStrEqual<true>(str1, str2); return InternalStrEqual<true>(str1, str2);
} }
bool CKStrEqualI(CKSTRING str1, CKSTRING str2) { bool CKStrEqualI(CKSTRING str1, CKSTRING str2) {
InternalStrEqual<false>(str1, str2); return InternalStrEqual<false>(str1, str2);
} }
bool CKStrEmpty(CKSTRING strl) { bool CKStrEmpty(CKSTRING strl) {

View File

@ -71,7 +71,7 @@ namespace LibCmo::CK2 {
return true; return true;
} else { } else {
// failed, report to context // failed, report to context
m_BindContext->OutputToConsoleEx("CKStateChunk::LockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos); m_BindContext->OutputToConsoleEx(u8"CKStateChunk::LockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
return false; return false;
} }
} }
@ -88,7 +88,7 @@ namespace LibCmo::CK2 {
return true; return true;
} else { } else {
// failed, report to context // failed, report to context
m_BindContext->OutputToConsoleEx("CKStateChunk::UnLockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos); m_BindContext->OutputToConsoleEx(u8"CKStateChunk::UnLockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
return false; return false;
} }
} }
@ -140,7 +140,7 @@ namespace LibCmo::CK2 {
// MARK: the written string has NULL terminal. // MARK: the written string has NULL terminal.
// strByteSize also include NULL terminal, // strByteSize also include NULL terminal,
// so we need minus 1 when resizing (not ReadByteData, because we still need read NULL terminal to skip it.) // so we need minus 1 when resizing (not ReadByteData, because we still need read NULL terminal to skip it.)
XContainer::XString cache; std::string cache;
cache.resize(strByteSize - 1); cache.resize(strByteSize - 1);
if (!this->ReadByteData(cache.data(), strByteSize)) { if (!this->ReadByteData(cache.data(), strByteSize)) {
strl->clear(); strl->clear();
@ -148,7 +148,7 @@ namespace LibCmo::CK2 {
} }
// convert encoding // convert encoding
m_BindContext->GetUtf8String(cache, *strl); m_BindContext->GetUTF8String(cache, *strl);
return true; return true;
} }

View File

@ -86,7 +86,7 @@ namespace LibCmo::CK2 {
*ppData = this->m_pData + this->m_Parser.m_CurrentPos; *ppData = this->m_pData + this->m_Parser.m_CurrentPos;
return true; return true;
} else { } else {
m_BindContext->OutputToConsoleEx("CKStateChunk::LockWriteBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos); m_BindContext->OutputToConsoleEx(u8"CKStateChunk::LockWriteBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
return false; return false;
} }
} }
@ -100,7 +100,7 @@ namespace LibCmo::CK2 {
this->m_Parser.m_CurrentPos += size_in_dword; this->m_Parser.m_CurrentPos += size_in_dword;
return true; return true;
} else { } else {
m_BindContext->OutputToConsoleEx("CKStateChunk::UnLockWriteBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos); m_BindContext->OutputToConsoleEx(u8"CKStateChunk::UnLockWriteBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
return false; return false;
} }
} }
@ -137,8 +137,8 @@ namespace LibCmo::CK2 {
if (strl == nullptr) return false; if (strl == nullptr) return false;
// convert encoding // convert encoding
XContainer::XString cache; std::string cache;
m_BindContext->GetNativeString(*strl, cache); m_BindContext->GetOrdinaryString(*strl, cache);
if (cache.empty()) { if (cache.empty()) {
// write zero string // write zero string

View File

@ -135,7 +135,7 @@ namespace LibCmo::CK2::DataHandlers {
static bool StbReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) { static bool StbReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) {
if (u8filename == nullptr || read_image == nullptr) return false; if (u8filename == nullptr || read_image == nullptr) return false;
FILE* fs = EncodingHelper::U8FOpen(u8filename, "rb"); FILE* fs = YYCC::IOHelper::UTF8FOpen(u8filename, u8"rb");
if (fs == nullptr) return false; if (fs == nullptr) return false;
// read data // read data
@ -210,7 +210,7 @@ namespace LibCmo::CK2::DataHandlers {
static bool StbSaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, bool save_alpha, SaveOperation oper) { static bool StbSaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, bool save_alpha, SaveOperation oper) {
if (u8filename == nullptr || write_image == nullptr) return false; if (u8filename == nullptr || write_image == nullptr) return false;
if (!write_image->IsValid()) return false; if (!write_image->IsValid()) return false;
FILE* fs = EncodingHelper::U8FOpen(u8filename, "wb"); FILE* fs = YYCC::IOHelper::UTF8FOpen(u8filename, u8"wb");
if (fs == nullptr) return false; if (fs == nullptr) return false;
// allocate buffer and convert data from ARGB to RGBA or RGB // allocate buffer and convert data from ARGB to RGBA or RGB
@ -285,7 +285,7 @@ namespace LibCmo::CK2::DataHandlers {
#pragma region CKBitmapBMPHandler #pragma region CKBitmapBMPHandler
static const CKBitmapProperties g_BMPProperties(CKGUID(0xBCA97223u, 0x48578BCAu), "Bmp"); static const CKBitmapProperties g_BMPProperties(CKGUID(0xBCA97223u, 0x48578BCAu), u8"Bmp");
CKBitmapBMPHandler::CKBitmapBMPHandler() : CKBitmapBMPHandler::CKBitmapBMPHandler() :
CKBitmapHandler() {} CKBitmapHandler() {}
@ -330,7 +330,7 @@ namespace LibCmo::CK2::DataHandlers {
#pragma region CKBitmapTGAHandler #pragma region CKBitmapTGAHandler
static const CKBitmapProperties g_TGAProperties(CKGUID(0x585C7216u, 0x33302657u), "Tga"); static const CKBitmapProperties g_TGAProperties(CKGUID(0x585C7216u, 0x33302657u), u8"Tga");
CKBitmapTGAHandler::CKBitmapTGAHandler() : CKBitmapTGAHandler::CKBitmapTGAHandler() :
CKBitmapHandler() {} CKBitmapHandler() {}
@ -372,7 +372,7 @@ namespace LibCmo::CK2::DataHandlers {
#pragma region CKBitmapJPGHandler #pragma region CKBitmapJPGHandler
// MARK: this GUID is gotten from Virtools 3.5 Plugins. // MARK: this GUID is gotten from Virtools 3.5 Plugins.
static const CKBitmapProperties g_JPGProperties(CKGUID(0x4AE51AC4u, 0x04587D76u), "jpg"); static const CKBitmapProperties g_JPGProperties(CKGUID(0x4AE51AC4u, 0x04587D76u), u8"jpg");
// MARK: this quality is gotten from default value of virtools. // MARK: this quality is gotten from default value of virtools.
constexpr int g_JPGDefaultQuality = 75; constexpr int g_JPGDefaultQuality = 75;
@ -416,7 +416,7 @@ namespace LibCmo::CK2::DataHandlers {
#pragma region CKBitmapPNGHandler #pragma region CKBitmapPNGHandler
// MARK: this GUID is gotten from Virtools 3.5 Plugins. // MARK: this GUID is gotten from Virtools 3.5 Plugins.
static const CKBitmapProperties g_PNGProperties(CKGUID(0x02D45C7Bu, 0x4AAC16ECu), "png"); static const CKBitmapProperties g_PNGProperties(CKGUID(0x02D45C7Bu, 0x4AAC16ECu), u8"png");
// MARK: this is compress level gotten from default value of virtools. // MARK: this is compress level gotten from default value of virtools.
constexpr int g_PNGDefaultCompressLevel = 3; constexpr int g_PNGDefaultCompressLevel = 3;

View File

@ -5,7 +5,7 @@
namespace LibCmo::CK2::MgrImpls { namespace LibCmo::CK2::MgrImpls {
CKObjectManager::CKObjectManager(CKContext* ctx) : CKObjectManager::CKObjectManager(CKContext* ctx) :
CKBaseManager(ctx, OBJECT_MANAGER_GUID, "Object Manager"), CKBaseManager(ctx, OBJECT_MANAGER_GUID, u8"Object Manager"),
m_ObjectsList(), m_ReturnedObjectOffsets(), m_ObjectCount(0), m_ObjectsList(), m_ReturnedObjectOffsets(), m_ObjectCount(0),
m_GroupGlobalIndex(), m_SceneGlobalIndex(), m_GroupGlobalIndex(), m_SceneGlobalIndex(),
m_ObjectsListByClass(CKGetClassCount()) {} m_ObjectsListByClass(CKGetClassCount()) {}

View File

@ -2,20 +2,16 @@
namespace LibCmo::CK2::MgrImpls { namespace LibCmo::CK2::MgrImpls {
#if YYCC_OS == YYCC_OS_WINDOWS static constexpr char8_t g_UniqueFolder[] = u8"LibCmo";
static wchar_t g_UniqueFolder[] = L"LibCmo";
#else
static char g_UniqueFolder[] = "LibCmo";
#endif
CKPathManager::CKPathManager(CKContext* ctx) : CKPathManager::CKPathManager(CKContext* ctx) :
CKBaseManager(ctx, PATH_MANAGER_GUID, "Path Manager"), CKBaseManager(ctx, PATH_MANAGER_GUID, u8"Path Manager"),
m_TempFolder(), m_ExtraPathes() { m_TempFolder(), m_ExtraPathes() {
// preset for temp folder // preset for temp folder
// todo: add current CKContext pointer as the part of temp path. // todo: add current CKContext pointer as the part of temp path.
// thus multiple CKContext can work. // thus multiple CKContext can work.
m_TempFolder = std::filesystem::temp_directory_path(); m_TempFolder = std::filesystem::temp_directory_path();
m_TempFolder /= g_UniqueFolder; m_TempFolder /= std::filesystem::path(g_UniqueFolder);
std::filesystem::create_directories(m_TempFolder); std::filesystem::create_directories(m_TempFolder);
} }
@ -24,8 +20,7 @@ namespace LibCmo::CK2::MgrImpls {
bool CKPathManager::SetTempFolder(CKSTRING u8_temp) { bool CKPathManager::SetTempFolder(CKSTRING u8_temp) {
if (u8_temp == nullptr) return false; if (u8_temp == nullptr) return false;
std::filesystem::path cache; std::filesystem::path cache(u8_temp);
EncodingHelper::U8PathToStdPath(cache, u8_temp);
if (std::filesystem::is_directory(cache)) { if (std::filesystem::is_directory(cache)) {
m_TempFolder = cache; m_TempFolder = cache;
return true; return true;
@ -35,28 +30,22 @@ namespace LibCmo::CK2::MgrImpls {
} }
XContainer::XString CKPathManager::GetTempFolder() { XContainer::XString CKPathManager::GetTempFolder() {
XContainer::XString result; return this->m_TempFolder.u8string();
EncodingHelper::StdPathToU8Path(result, this->m_TempFolder);
return result;
} }
XContainer::XString CKPathManager::GetTempFilePath(CKSTRING u8_filename) { XContainer::XString CKPathManager::GetTempFilePath(CKSTRING u8_filename) {
if (u8_filename == nullptr) return XContainer::XString(); if (u8_filename == nullptr) return XContainer::XString();
std::filesystem::path stdfilename; std::filesystem::path stdfilename(u8_filename);
EncodingHelper::U8PathToStdPath(stdfilename, u8_filename);
auto realfile = this->m_TempFolder / stdfilename; auto realfile = this->m_TempFolder / stdfilename;
XContainer::XString result; return realfile.u8string();
EncodingHelper::StdPathToU8Path(result, realfile);
return result;
} }
bool CKPathManager::AddPath(CKSTRING u8path) { bool CKPathManager::AddPath(CKSTRING u8path) {
if (u8path == nullptr) return false; if (u8path == nullptr) return false;
std::filesystem::path newpath; std::filesystem::path newpath(u8path);
EncodingHelper::U8PathToStdPath(newpath, u8path);
if (std::filesystem::is_directory(newpath)) { if (std::filesystem::is_directory(newpath)) {
m_ExtraPathes.emplace_back(std::move(newpath)); m_ExtraPathes.emplace_back(std::move(newpath));
return true; return true;
@ -70,8 +59,7 @@ namespace LibCmo::CK2::MgrImpls {
} }
bool CKPathManager::ResolveFileName(XContainer::XString& u8_filename) { bool CKPathManager::ResolveFileName(XContainer::XString& u8_filename) {
std::filesystem::path filepath; std::filesystem::path filepath(u8_filename);
EncodingHelper::U8PathToStdPath(filepath, u8_filename.c_str());
// if it is absolute path, return it directly // if it is absolute path, return it directly
if (filepath.is_absolute()) { if (filepath.is_absolute()) {
@ -81,7 +69,7 @@ namespace LibCmo::CK2::MgrImpls {
// test in temp folder // test in temp folder
auto tempfile = m_TempFolder / filepath; auto tempfile = m_TempFolder / filepath;
if (std::filesystem::is_regular_file(tempfile)) { if (std::filesystem::is_regular_file(tempfile)) {
EncodingHelper::StdPathToU8Path(u8_filename, tempfile); u8_filename = tempfile.u8string();
return true; return true;
} }
@ -90,7 +78,7 @@ namespace LibCmo::CK2::MgrImpls {
auto combinedpath = extrapath / filepath; auto combinedpath = extrapath / filepath;
if (std::filesystem::is_regular_file(combinedpath)) { if (std::filesystem::is_regular_file(combinedpath)) {
// this is correct // this is correct
EncodingHelper::StdPathToU8Path(u8_filename, combinedpath); u8_filename = combinedpath.u8string();
return true; return true;
} }
} }
@ -100,19 +88,17 @@ namespace LibCmo::CK2::MgrImpls {
} }
void CKPathManager::GetFileName(XContainer::XString& u8path) { void CKPathManager::GetFileName(XContainer::XString& u8path) {
std::filesystem::path filepath; std::filesystem::path filepath(u8path);
EncodingHelper::U8PathToStdPath(filepath, u8path.c_str());
auto result = filepath.filename(); auto result = filepath.filename();
EncodingHelper::StdPathToU8Path(u8path, result); u8path = result.u8string();
} }
void CKPathManager::GetExtension(XContainer::XString& u8path) { void CKPathManager::GetExtension(XContainer::XString& u8path) {
std::filesystem::path filepath; std::filesystem::path filepath(u8path);
EncodingHelper::U8PathToStdPath(filepath, u8path.c_str());
auto result = filepath.extension(); auto result = filepath.extension();
EncodingHelper::StdPathToU8Path(u8path, result); u8path = result.u8string();
} }
} }

View File

@ -18,6 +18,7 @@ namespace LibCmo::XContainer {
* \li This class now is implemented by \c std::u8string. * \li This class now is implemented by \c std::u8string.
*/ */
using XString = std::u8string; using XString = std::u8string;
using XOrdinaryString = std::string;
/** /**
* @brief The representation of a set of bit flags (memory optimized to reduce occupied size). * @brief The representation of a set of bit flags (memory optimized to reduce occupied size).