fix: fix issues
- restore some CKGlobals behavior because it will cause runtime exception. - move some classes from CmdHelper to UnvirtContext to make CmdHelper more common to use. - output warning string when fail to get utf8 or ordinary string.
This commit is contained in:
parent
3735a202f3
commit
65861143bf
|
@ -281,7 +281,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
#pragma region Encoding utilities
|
#pragma region Encoding utilities
|
||||||
|
|
||||||
void CKContext::GetUTF8String(const std::string& native_name, XContainer::XString& u8_name) {
|
bool CKContext::GetUTF8String(const std::string& native_name, XContainer::XString& u8_name) {
|
||||||
bool conv_success = false, has_valid_token = false;
|
bool conv_success = false, has_valid_token = false;
|
||||||
for (const auto& token : this->m_NameEncoding) {
|
for (const auto& token : this->m_NameEncoding) {
|
||||||
if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
|
if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
|
||||||
|
@ -298,9 +298,11 @@ namespace LibCmo::CK2 {
|
||||||
this->OutputToConsole(u8"Error when converting to UTF8 string from ordinary string. The string will leave to blank.");
|
this->OutputToConsole(u8"Error when converting to UTF8 string from ordinary string. The string will leave to blank.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// return value
|
||||||
|
return conv_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKContext::GetOrdinaryString(const XContainer::XString& u8_name, std::string& native_name) {
|
bool CKContext::GetOrdinaryString(const XContainer::XString& u8_name, std::string& native_name) {
|
||||||
bool conv_success = false, has_valid_token = false;
|
bool conv_success = false, has_valid_token = false;
|
||||||
for (const auto& token : this->m_NameEncoding) {
|
for (const auto& token : this->m_NameEncoding) {
|
||||||
if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
|
if (token == EncodingHelper::INVALID_ENCODING_TOKEN) continue;
|
||||||
|
@ -317,6 +319,8 @@ namespace LibCmo::CK2 {
|
||||||
this->OutputToConsole(u8"Error when converting to ordinary string from UTF8 string. The string will leave to blank.");
|
this->OutputToConsole(u8"Error when converting to ordinary string from UTF8 string. The string will leave to blank.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// return value
|
||||||
|
return conv_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKContext::SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_seq) {
|
void CKContext::SetEncoding(const XContainer::XArray<XContainer::XString>& encoding_seq) {
|
||||||
|
|
|
@ -104,6 +104,7 @@ namespace LibCmo::CK2 {
|
||||||
* @brief Convert given ordinary string to UTF8 string.
|
* @brief Convert given ordinary string to UTF8 string.
|
||||||
* @param[in] native_name The input ordinary string.
|
* @param[in] native_name The input ordinary string.
|
||||||
* @param[out] u8_name The output UTF8 string.
|
* @param[out] u8_name The output UTF8 string.
|
||||||
|
* @return True if convertion is success, otherwise false.
|
||||||
* @exception RuntimeException Raised when perform this operation with a blank encoding sequence.
|
* @exception RuntimeException Raised when perform this operation with a blank encoding sequence.
|
||||||
* @remarks
|
* @remarks
|
||||||
* The encoding of ordinary is specified by encoding sequence.
|
* The encoding of ordinary is specified by encoding sequence.
|
||||||
|
@ -111,11 +112,12 @@ namespace LibCmo::CK2 {
|
||||||
* However, if you use this function with blank encoding sequence, it will raise exception.
|
* However, if you use this function with blank encoding sequence, it will raise exception.
|
||||||
* So becore using this function, please make sure that you have checked by calling IsValidEncoding().
|
* So becore using this function, please make sure that you have checked by calling IsValidEncoding().
|
||||||
*/
|
*/
|
||||||
void GetUTF8String(const std::string& native_name, XContainer::XString& u8_name);
|
bool GetUTF8String(const std::string& native_name, XContainer::XString& u8_name);
|
||||||
/**
|
/**
|
||||||
* @brief Convert given UTF8 string to ordinary string.
|
* @brief Convert given UTF8 string to ordinary string.
|
||||||
* @param[in] u8_name The input UTF8 string.
|
* @param[in] u8_name The input UTF8 string.
|
||||||
* @param[out] native_name The output ordinary string.
|
* @param[out] native_name The output ordinary string.
|
||||||
|
* @return True if convertion is success, otherwise false.
|
||||||
* @exception RuntimeException Raised when perform this operation with a blank encoding sequence.
|
* @exception RuntimeException Raised when perform this operation with a blank encoding sequence.
|
||||||
* @remarks
|
* @remarks
|
||||||
* The encoding of ordinary is specified by encoding sequence.
|
* The encoding of ordinary is specified by encoding sequence.
|
||||||
|
@ -123,7 +125,7 @@ namespace LibCmo::CK2 {
|
||||||
* However, if you use this function with blank encoding sequence, it will raise exception.
|
* However, if you use this function with blank encoding sequence, it will raise exception.
|
||||||
* So becore using this function, please make sure that you have checked by calling IsValidEncoding().
|
* So becore using this function, please make sure that you have checked by calling IsValidEncoding().
|
||||||
*/
|
*/
|
||||||
void GetOrdinaryString(const XContainer::XString& u8_name, std::string& native_name);
|
bool GetOrdinaryString(const XContainer::XString& u8_name, std::string& native_name);
|
||||||
/**
|
/**
|
||||||
* @brief Set the encoding sequence.
|
* @brief Set the encoding sequence.
|
||||||
* @param[in] encoding_series The encoding name in this sequence.
|
* @param[in] encoding_series The encoding name in this sequence.
|
||||||
|
|
|
@ -133,7 +133,8 @@ 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);
|
if (!m_Ctx->GetUTF8String(name_conv, fileobj.Name))
|
||||||
|
m_Ctx->OutputToConsole(u8"Fail to get UTF8 name for CKObject when reading file header. Some objects name will leave to blank.");
|
||||||
} else {
|
} else {
|
||||||
XContainer::NSXString::FromCKSTRING(fileobj.Name, nullptr);
|
XContainer::NSXString::FromCKSTRING(fileobj.Name, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -311,7 +312,8 @@ 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);
|
if (!m_Ctx->GetUTF8String(name_conv, file))
|
||||||
|
m_Ctx->OutputToConsole(u8"Fail to get UTF8 name for included file when reading file body. Some included files may be stripped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// read file body length
|
// read file body length
|
||||||
|
|
|
@ -91,7 +91,8 @@ 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->GetOrdinaryString(obj.Name, name_conv);
|
if (!m_Ctx->GetOrdinaryString(obj.Name, name_conv))
|
||||||
|
m_Ctx->OutputToConsole(u8"Fail to get ordinary string for CKObject name when computing the size of saved file. It may cause application crash or saved file has blank object name.");
|
||||||
sumHdrObjSize += static_cast<CKDWORD>(name_conv.size());
|
sumHdrObjSize += static_cast<CKDWORD>(name_conv.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +179,8 @@ 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->GetOrdinaryString(obj.Name, name_conv);
|
if (!m_Ctx->GetOrdinaryString(obj.Name, name_conv))
|
||||||
|
m_Ctx->OutputToConsole(u8"Fail to get ordinary string for CKObject name when saving file. Some objects may be saved with blank name.");
|
||||||
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);
|
||||||
|
@ -318,7 +320,8 @@ namespace LibCmo::CK2 {
|
||||||
m_Ctx->GetPathManager()->GetFileName(filename);
|
m_Ctx->GetPathManager()->GetFileName(filename);
|
||||||
|
|
||||||
// write filename
|
// write filename
|
||||||
m_Ctx->GetOrdinaryString(filename, name_conv);
|
if (!m_Ctx->GetOrdinaryString(filename, name_conv))
|
||||||
|
m_Ctx->OutputToConsole(u8"Fail to get ordinary string for included file when saving file. Some included files may not be saved correctly.");
|
||||||
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);
|
||||||
|
|
|
@ -145,8 +145,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo) {
|
void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo) {
|
||||||
size_t idxListener, idxListenTo;
|
size_t idxListener, idxListenTo;
|
||||||
if (!GetClassIdIndex(listener, idxListener) || !GetClassIdIndex(listenTo, idxListenTo))
|
if (!GetClassIdIndex(listener, idxListener) || !GetClassIdIndex(listenTo, idxListenTo)) return;
|
||||||
throw LogicException("Invalid CK_CLASSID in argument.");
|
|
||||||
|
|
||||||
XContainer::NSXBitArray::Set(g_CKClassInfo[idxListener].ToBeNotify, static_cast<CKDWORD>(idxListenTo));
|
XContainer::NSXBitArray::Set(g_CKClassInfo[idxListener].ToBeNotify, static_cast<CKDWORD>(idxListenTo));
|
||||||
}
|
}
|
||||||
|
@ -191,25 +190,25 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid) {
|
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid) {
|
||||||
size_t intcid;
|
size_t intcid;
|
||||||
if (!GetClassIdIndex(cid, intcid))
|
if (!GetClassIdIndex(cid, intcid)) return nullptr;
|
||||||
throw LogicException("Invalid CK_CLASSID.");
|
|
||||||
return &g_CKClassInfo[intcid];
|
return &g_CKClassInfo[intcid];
|
||||||
}
|
}
|
||||||
|
|
||||||
CKSTRING CKClassIDToString(CK_CLASSID cid) {
|
CKSTRING CKClassIDToString(CK_CLASSID cid) {
|
||||||
const CKClassDesc* desc = CKGetClassDesc(cid);
|
const CKClassDesc* desc = CKGetClassDesc(cid);
|
||||||
|
if (desc == nullptr) return u8"Undefined Type";
|
||||||
return desc->NameFct();
|
return desc->NameFct();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
|
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent) {
|
||||||
size_t intchild, intparent;
|
size_t intchild, intparent;
|
||||||
if (!GetClassIdIndex(child, intchild) || !GetClassIdIndex(parent, intparent))
|
if (!GetClassIdIndex(child, intchild) || !GetClassIdIndex(parent, intparent)) return false;
|
||||||
throw LogicException("Invalid CK_CLASSID.");
|
|
||||||
return g_CKClassInfo[intchild].Parents[intparent];
|
return g_CKClassInfo[intchild].Parents[intparent];
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
|
CK_CLASSID CKGetParentClassID(CK_CLASSID child) {
|
||||||
const CKClassDesc* desc = CKGetClassDesc(child);
|
const CKClassDesc* desc = CKGetClassDesc(child);
|
||||||
|
if (desc == nullptr) return CK_CLASSID::CKCID_OBJECT;
|
||||||
return desc->Parent;
|
return desc->Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +227,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid) {
|
bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid) {
|
||||||
const CKClassDesc* desc = CKGetClassDesc(listener);
|
const CKClassDesc* desc = CKGetClassDesc(listener);
|
||||||
|
if (desc == nullptr) return false;
|
||||||
return XContainer::NSXBitArray::IsSet(desc->CommonToBeNotify, static_cast<CKDWORD>(deletedObjCid));
|
return XContainer::NSXBitArray::IsSet(desc->CommonToBeNotify, static_cast<CKDWORD>(deletedObjCid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +238,8 @@ namespace LibCmo::CK2 {
|
||||||
if (!XContainer::NSXBitArray::IsSet(delObjCids, static_cast<CKDWORD>(i))) continue;
|
if (!XContainer::NSXBitArray::IsSet(delObjCids, static_cast<CKDWORD>(i))) continue;
|
||||||
|
|
||||||
const CKClassDesc* desc = CKGetClassDesc(static_cast<CK_CLASSID>(i));
|
const CKClassDesc* desc = CKGetClassDesc(static_cast<CK_CLASSID>(i));
|
||||||
|
if (desc == nullptr) continue;
|
||||||
|
|
||||||
XContainer::NSXBitArray::Or(result, desc->ToNotify);
|
XContainer::NSXBitArray::Or(result, desc->ToNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ namespace LibCmo::CK2 {
|
||||||
* @brief Order that first class id will be notified when deleting object whose class id is second argument
|
* @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] listener The id of class will be notified.
|
||||||
* @param[in] listenTo The id of class which first argument interested in.
|
* @param[in] listenTo The id of class which first argument interested in.
|
||||||
* @exception LogicException Raised if given CK_CLASSID is invalid.
|
* @remarks If one of given class ids is invalid, this function simply return and do nothing.
|
||||||
*/
|
*/
|
||||||
void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo);
|
void CKClassNeedNotificationFrom(CK_CLASSID listener, CK_CLASSID listenTo);
|
||||||
/**
|
/**
|
||||||
|
@ -188,15 +188,15 @@ namespace LibCmo::CK2 {
|
||||||
* @brief Get the class description struct by given class id.
|
* @brief Get the class description struct by given class id.
|
||||||
* @param[in] cid Class id for fetching.
|
* @param[in] cid Class id for fetching.
|
||||||
* @return The pointer to corresponding class description.
|
* @return The pointer to corresponding class description.
|
||||||
* We guaranteen that this pointer must not be nullptr.
|
* If given class id is invalid, this function will return nullptr.
|
||||||
* @exception LogicException Raised if given CK_CLASSID is invalid.
|
* According to this, caller can utilize this function to validate class id.
|
||||||
*/
|
*/
|
||||||
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
|
const CKClassDesc* CKGetClassDesc(CK_CLASSID cid);
|
||||||
/**
|
/**
|
||||||
* @brief Get the name representation of given class id.
|
* @brief Get the name representation of given class id.
|
||||||
* @param[in] cid Class id for fetching.
|
* @param[in] cid Class id for fetching.
|
||||||
* @return The name of given class id.
|
* @return The name of given class id.
|
||||||
* @exception LogicException Raised if given CK_CLASSID is invalid.
|
* If given class id is invalid, it return a predefined name.
|
||||||
*/
|
*/
|
||||||
CKSTRING CKClassIDToString(CK_CLASSID cid);
|
CKSTRING CKClassIDToString(CK_CLASSID cid);
|
||||||
|
|
||||||
|
@ -205,14 +205,14 @@ namespace LibCmo::CK2 {
|
||||||
* @param[in] child The id of first class assumed as 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.
|
* @param[in] parent The id of second class assumed as parent class.
|
||||||
* @return True if relation is satisfied, otherwise false.
|
* @return True if relation is satisfied, otherwise false.
|
||||||
* @exception LogicException Raised if given CK_CLASSID is invalid.
|
* If one of given class ids is invalid, this function always return false.
|
||||||
*/
|
*/
|
||||||
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent);
|
bool CKIsChildClassOf(CK_CLASSID child, CK_CLASSID parent);
|
||||||
/**
|
/**
|
||||||
* @brief Get the parent class id of given class id.
|
* @brief Get the parent class id of given class id.
|
||||||
* @param[in] child The id to class which need to find parent class.
|
* @param[in] child The id to class which need to find parent class.
|
||||||
* @return The parent class id.
|
* @return The parent class id.
|
||||||
* @exception LogicException Raised if given CK_CLASSID is invalid.
|
* If given class id is invalid, this function always return the class id of CKObject.
|
||||||
*/
|
*/
|
||||||
CK_CLASSID CKGetParentClassID(CK_CLASSID child);
|
CK_CLASSID CKGetParentClassID(CK_CLASSID child);
|
||||||
/**
|
/**
|
||||||
|
@ -220,7 +220,6 @@ namespace LibCmo::CK2 {
|
||||||
* @param[in] cid1 The id of first class finding common parent.
|
* @param[in] cid1 The id of first class finding common parent.
|
||||||
* @param[in] cid2 The id of second class finding common parent.
|
* @param[in] cid2 The id of second class finding common parent.
|
||||||
* @return The cloest common parent class id.
|
* @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);
|
CK_CLASSID CKGetCommonParent(CK_CLASSID cid1, CK_CLASSID cid2);
|
||||||
|
|
||||||
|
@ -229,14 +228,13 @@ namespace LibCmo::CK2 {
|
||||||
* @param[in] listener The class id of checking whether need to be notified.
|
* @param[in] listener The class id of checking whether need to be notified.
|
||||||
* @param[in] deletedObjCid The class id of deleting object.
|
* @param[in] deletedObjCid The class id of deleting object.
|
||||||
* @return True if it need to be notified, otherwise false.
|
* @return True if it need to be notified, otherwise false.
|
||||||
* @exception LogicException Raised if given CK_CLASSID is invalid.
|
* If the class id of checking is invalid, this function always return false.
|
||||||
*/
|
*/
|
||||||
bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid); /**
|
bool CKIsNeedNotify(CK_CLASSID listener, CK_CLASSID deletedObjCid); /**
|
||||||
/**
|
/**
|
||||||
* @brief Get all class ids need to be notified when objects whose class id included in \c delObjCids are deleting.
|
* @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.
|
* @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.
|
* @return The queried bit array representing class ids need to be notified.
|
||||||
* @exception LogicException Raised if given CK_CLASSID is invalid.
|
|
||||||
* @see CKIsNeedNotify()
|
* @see CKIsNeedNotify()
|
||||||
*/
|
*/
|
||||||
XContainer::XBitArray CKGetAllNotifyClassID(const XContainer::XBitArray& delObjCids);
|
XContainer::XBitArray CKGetAllNotifyClassID(const XContainer::XBitArray& delObjCids);
|
||||||
|
|
|
@ -148,7 +148,13 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert encoding
|
// convert encoding
|
||||||
m_BindContext->GetUTF8String(cache, *strl);
|
if (!m_BindContext->GetUTF8String(cache, *strl)) {
|
||||||
|
m_BindContext->OutputToConsole(u8"Fail to get UTF8 string when reading CKStateChunk. Some objects may be loaded incorrectly.");
|
||||||
|
strl->clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// okey
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,8 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
// convert encoding
|
// convert encoding
|
||||||
std::string cache;
|
std::string cache;
|
||||||
m_BindContext->GetOrdinaryString(*strl, cache);
|
if (!m_BindContext->GetOrdinaryString(*strl, cache))
|
||||||
|
m_BindContext->OutputToConsole(u8"Fail to get ordinary string when saving CKStateChunk. Some objects may be saved incorrectly.");
|
||||||
|
|
||||||
if (cache.empty()) {
|
if (cache.empty()) {
|
||||||
// write zero string
|
// write zero string
|
||||||
|
|
|
@ -20,6 +20,8 @@ namespace LibCmo::CK2::MgrImpls {
|
||||||
|
|
||||||
// get description first
|
// get description first
|
||||||
const CKClassDesc* desc = CKGetClassDesc(cls);
|
const CKClassDesc* desc = CKGetClassDesc(cls);
|
||||||
|
// if no description, return directly to reject creating object.
|
||||||
|
if (desc == nullptr) return nullptr;
|
||||||
|
|
||||||
// allocate a CK_ID first
|
// allocate a CK_ID first
|
||||||
CKDWORD decided_off;
|
CKDWORD decided_off;
|
||||||
|
@ -60,7 +62,9 @@ namespace LibCmo::CK2::MgrImpls {
|
||||||
void CKObjectManager::InternalDestroy(ObjImpls::CKObject* obj) {
|
void CKObjectManager::InternalDestroy(ObjImpls::CKObject* obj) {
|
||||||
// find desc by classid
|
// find desc by classid
|
||||||
const CKClassDesc* desc = CKGetClassDesc(obj->GetClassID());
|
const CKClassDesc* desc = CKGetClassDesc(obj->GetClassID());
|
||||||
|
// a create CKObject instance definitely can find corresponding desc.
|
||||||
|
// if not, throw exception.
|
||||||
|
if (desc == nullptr) throw LogicException("Invalid CK_CLASSID");
|
||||||
// free it
|
// free it
|
||||||
desc->ReleaseFct(m_Context, obj);
|
desc->ReleaseFct(m_Context, obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,8 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
props.m_ReaderGuid.d1 = realprops.m_ReaderGuid.d1;
|
props.m_ReaderGuid.d1 = realprops.m_ReaderGuid.d1;
|
||||||
props.m_ReaderGuid.d2 = realprops.m_ReaderGuid.d2;
|
props.m_ReaderGuid.d2 = realprops.m_ReaderGuid.d2;
|
||||||
std::string ext;
|
std::string ext;
|
||||||
m_Context->GetOrdinaryString(realprops.m_Ext.GetExt(), ext);
|
if (!m_Context->GetOrdinaryString(realprops.m_Ext.GetExt(), ext))
|
||||||
|
m_Context->OutputToConsole(u8"Fail to get ordinary string for the extension of bitmap properties when saving CKTexture. Some textures may be saved with blank extension.");
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
props.m_Ext.m_Data,
|
props.m_Ext.m_Data,
|
||||||
ext.c_str(),
|
ext.c_str(),
|
||||||
|
@ -314,7 +315,8 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
|
|
||||||
// get utf8 extension
|
// get utf8 extension
|
||||||
XContainer::XString ext;
|
XContainer::XString ext;
|
||||||
m_Context->GetUTF8String(props->m_Ext.m_Data, ext);
|
if (!m_Context->GetUTF8String(props->m_Ext.m_Data, ext))
|
||||||
|
m_Context->OutputToConsole(u8"Fail to get UTF8 extension when loading CKTexture. Some textures may have blank extension in bitmap properties.");
|
||||||
|
|
||||||
// get my bitmap prop
|
// get my bitmap prop
|
||||||
CKBitmapProperties myprops(
|
CKBitmapProperties myprops(
|
||||||
|
|
|
@ -522,6 +522,11 @@ if (!this->IsRootNode()) { \
|
||||||
|
|
||||||
#pragma region String Argument
|
#pragma region String Argument
|
||||||
|
|
||||||
|
StringArgument::StringArgument(const std::u8string_view& argname, Constraint_t constraint) :
|
||||||
|
AbstractArgument(argname), m_Constraint(constraint) {}
|
||||||
|
|
||||||
|
StringArgument::~StringArgument() {}
|
||||||
|
|
||||||
bool StringArgument::BeginConsume(const std::u8string& cur_cmd, ArgumentsMap& am) {
|
bool StringArgument::BeginConsume(const std::u8string& cur_cmd, ArgumentsMap& am) {
|
||||||
// check constraint
|
// check constraint
|
||||||
if (m_Constraint.IsValid() && !m_Constraint.m_CheckFct(cur_cmd))
|
if (m_Constraint.IsValid() && !m_Constraint.m_CheckFct(cur_cmd))
|
||||||
|
@ -531,23 +536,6 @@ if (!this->IsRootNode()) { \
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#pragma region Encoding List Argument
|
|
||||||
|
|
||||||
bool EncodingListArgument::BeginConsume(const std::u8string& cur_cmd, ArgumentsMap& am) {
|
|
||||||
// split given argument
|
|
||||||
std::vector<std::u8string> encs = YYCC::StringHelper::Split(cur_cmd, u8",");
|
|
||||||
// check each parts is a valid encoding name
|
|
||||||
for (const auto& item : encs) {
|
|
||||||
if (!LibCmo::EncodingHelper::IsValidEncodingName(item))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// okey, add into map
|
|
||||||
am.Add<ArgValue_t>(m_ArgumentName, encs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -498,9 +498,8 @@ namespace Unvirt::CmdHelper {
|
||||||
using ArgValue_t = AMItems::StringItem;
|
using ArgValue_t = AMItems::StringItem;
|
||||||
using Constraint_t = YYCC::Constraints::Constraint<std::u8string>;
|
using Constraint_t = YYCC::Constraints::Constraint<std::u8string>;
|
||||||
public:
|
public:
|
||||||
StringArgument(const std::u8string_view& argname, Constraint_t constraint = Constraint_t {}) :
|
StringArgument(const std::u8string_view& argname, Constraint_t constraint = Constraint_t {});
|
||||||
AbstractArgument(argname), m_Constraint(constraint) {}
|
virtual ~StringArgument();
|
||||||
virtual ~StringArgument() {}
|
|
||||||
YYCC_DEF_CLS_COPY_MOVE(StringArgument);
|
YYCC_DEF_CLS_COPY_MOVE(StringArgument);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -508,19 +507,6 @@ namespace Unvirt::CmdHelper {
|
||||||
Constraint_t m_Constraint;
|
Constraint_t m_Constraint;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EncodingListArgument : public AbstractArgument {
|
|
||||||
public:
|
|
||||||
using ArgValue_t = AMItems::StringArrayItem;
|
|
||||||
public:
|
|
||||||
EncodingListArgument(const std::u8string_view& argname) :
|
|
||||||
AbstractArgument(argname) {}
|
|
||||||
virtual ~EncodingListArgument() {}
|
|
||||||
YYCC_DEF_CLS_COPY_MOVE(EncodingListArgument);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool BeginConsume(const std::u8string& cur_cmd, ArgumentsMap& am) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommandParser {
|
class CommandParser {
|
||||||
|
|
|
@ -204,7 +204,7 @@ namespace Unvirt::StructFormatter {
|
||||||
for (LibCmo::CKDWORD i = 0; i < slot_count; ++i) {
|
for (LibCmo::CKDWORD i = 0; i < slot_count; ++i) {
|
||||||
auto desc = bd.GetImageDesc(i);
|
auto desc = bd.GetImageDesc(i);
|
||||||
|
|
||||||
Console::FormatLine(u8"#%" PRIuCKDWORD "\t%" PRIuCKDWORD "\t%" PRIuCKDWORD "\t0x%" PRIxCKDWORD " bytes\t",
|
Console::FormatLine(u8"#%" PRIuCKDWORD "\t%" PRIuCKDWORD "\t%" PRIuCKDWORD "\t%s\t0x%" PRIxCKDWORD " bytes\t%s",
|
||||||
i,
|
i,
|
||||||
desc->GetWidth(),
|
desc->GetWidth(),
|
||||||
desc->GetHeight(),
|
desc->GetHeight(),
|
||||||
|
|
|
@ -7,7 +7,31 @@
|
||||||
|
|
||||||
namespace Unvirt::Context {
|
namespace Unvirt::Context {
|
||||||
|
|
||||||
#pragma region Constraint Help Function
|
#pragma region Specialized for CmdHelper
|
||||||
|
|
||||||
|
class EncodingListArgument : public CmdHelper::Nodes::AbstractArgument {
|
||||||
|
public:
|
||||||
|
using ArgValue_t = CmdHelper::AMItems::StringArrayItem;
|
||||||
|
public:
|
||||||
|
EncodingListArgument(const std::u8string_view& argname) :
|
||||||
|
AbstractArgument(argname) {}
|
||||||
|
virtual ~EncodingListArgument() {}
|
||||||
|
YYCC_DEF_CLS_COPY_MOVE(EncodingListArgument);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool BeginConsume(const std::u8string& cur_cmd, CmdHelper::ArgumentsMap& am) override {
|
||||||
|
// split given argument
|
||||||
|
std::vector<std::u8string> encs = YYCC::StringHelper::Split(cur_cmd, u8",");
|
||||||
|
// check each parts is a valid encoding name
|
||||||
|
for (const auto& item : encs) {
|
||||||
|
if (!LibCmo::EncodingHelper::IsValidEncodingName(item))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// okey, add into map
|
||||||
|
am.Add<ArgValue_t>(m_ArgumentName, encs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static YYCC::Constraints::Constraint<size_t> GetOneBasedIndexConstraint() {
|
static YYCC::Constraints::Constraint<size_t> GetOneBasedIndexConstraint() {
|
||||||
return YYCC::Constraints::Constraint<size_t> {
|
return YYCC::Constraints::Constraint<size_t> {
|
||||||
|
@ -19,7 +43,6 @@ namespace Unvirt::Context {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
#pragma region UnvirtContext Misc
|
#pragma region UnvirtContext Misc
|
||||||
|
|
||||||
UnvirtContext::UnvirtContext() :
|
UnvirtContext::UnvirtContext() :
|
||||||
|
@ -136,7 +159,7 @@ namespace Unvirt::Context {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.Then<CmdHelper::Nodes::Literal>(CmdHelper::Nodes::Literal(u8"encoding")
|
.Then<CmdHelper::Nodes::Literal>(CmdHelper::Nodes::Literal(u8"encoding")
|
||||||
.Then<CmdHelper::Nodes::EncodingListArgument>(CmdHelper::Nodes::EncodingListArgument(u8"enc")
|
.Then<EncodingListArgument>(EncodingListArgument(u8"enc")
|
||||||
.Comment(u8"CKContext used encoding splitted by ','. Support mutiple encoding.")
|
.Comment(u8"CKContext used encoding splitted by ','. Support mutiple encoding.")
|
||||||
.Executes(
|
.Executes(
|
||||||
std::bind(&UnvirtContext::ProcEncoding, this, std::placeholders::_1),
|
std::bind(&UnvirtContext::ProcEncoding, this, std::placeholders::_1),
|
||||||
|
@ -644,7 +667,7 @@ namespace Unvirt::Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcEncoding(const CmdHelper::ArgumentsMap& amap) {
|
void UnvirtContext::ProcEncoding(const CmdHelper::ArgumentsMap& amap) {
|
||||||
const auto& encodings = amap.Get<CmdHelper::Nodes::EncodingListArgument::ArgValue_t>(u8"enc").Get();
|
const auto& encodings = amap.Get<EncodingListArgument::ArgValue_t>(u8"enc").Get();
|
||||||
m_Ctx->SetEncoding(encodings);
|
m_Ctx->SetEncoding(encodings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user