From 88ce33c35895f8b2d40ed2928405f0851cf59003 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sat, 24 Aug 2024 21:27:23 +0800 Subject: [PATCH] fix: fix build issue in Unvirt --- Unvirt/CMakeLists.txt | 2 - Unvirt/CmdHelper.cpp | 232 +++++++++++++++++++----------------- Unvirt/CmdHelper.hpp | 234 +++++++++++++++++++++++++------------ Unvirt/StructFormatter.cpp | 140 ++++++++++------------ Unvirt/TerminalHelper.cpp | 61 ---------- Unvirt/TerminalHelper.hpp | 54 --------- 6 files changed, 344 insertions(+), 379 deletions(-) delete mode 100644 Unvirt/TerminalHelper.cpp delete mode 100644 Unvirt/TerminalHelper.hpp diff --git a/Unvirt/CMakeLists.txt b/Unvirt/CMakeLists.txt index b2f692b..95b61a3 100644 --- a/Unvirt/CMakeLists.txt +++ b/Unvirt/CMakeLists.txt @@ -6,7 +6,6 @@ PRIVATE AccessibleValue.cpp CmdHelper.cpp StructFormatter.cpp - TerminalHelper.cpp UnvirtContext.cpp Unvirt.cpp ) @@ -18,7 +17,6 @@ FILES AccessibleValue.hpp CmdHelper.hpp StructFormatter.hpp - TerminalHelper.hpp UnvirtContext.hpp ) # Setup header infomation diff --git a/Unvirt/CmdHelper.cpp b/Unvirt/CmdHelper.cpp index ccb62e9..284787e 100644 --- a/Unvirt/CmdHelper.cpp +++ b/Unvirt/CmdHelper.cpp @@ -4,24 +4,30 @@ namespace Unvirt::CmdHelper { #pragma region CmdSplitter - std::deque CmdSplitter::Convert(const std::string& u8cmd) { - // set up variables - std::deque result; - std::string buffer; - mBuffer = &buffer; - mResult = &result; - mState = mPreState = StateType::SPACE; + const std::deque& CmdSplitter::GetResult() const { + if (!m_ValidResult) + throw std::runtime_error("try to get result from an invalid CmdSplitter."); + return m_Result; + } + + bool CmdSplitter::Convert(const std::u8string& u8cmd) { + // Clear variables + m_ValidResult = false; + m_Result.clear(); + m_Buffer.clear(); + m_CurrentChar = u8'\0'; + m_State = m_PrevState = StateType::SPACE; // split - for (auto& c : u8cmd) { - mCmdChar = c; + for (char8_t c : u8cmd) { + m_CurrentChar = c; - // skip all invalid characters, \0 and etc. - // mCmdChar >= 0 to ensure all non-ASCII UTF8 char can be accepted directly. - if (mCmdChar >= 0 && (!std::isprint(mCmdChar))) + // skip all invalid characters (ascii code unit lower than space char) + // thus UTF8 code unit can directly accepted. + if (m_CurrentChar < u8' ') continue; - switch (mState) { + switch (m_State) { case StateType::SPACE: ProcSpace(); break; @@ -41,157 +47,183 @@ namespace Unvirt::CmdHelper { } // final proc - switch (mState) { + bool is_success = false; + switch (m_State) { case StateType::SPACE: + is_success = true; break; case StateType::NORMAL: // push the last one - mResult->push_back(*mBuffer); + m_Result.emplace_back(m_Buffer); + is_success = true; break; case StateType::SINGLE: case StateType::DOUBLE: case StateType::ESCAPE: // error - result.clear(); + is_success = false; break; + default: + throw std::runtime_error("unreachable code."); } - // return value - return result; + // check success + if (is_success) { + m_ValidResult = true; + return true; + } else { + m_Result.clear(); + return false; + } } - void CmdSplitter::ProcSpace(void) { - switch (mCmdChar) { - case '\'': - mState = StateType::SINGLE; + void CmdSplitter::ProcSpace() { + switch (m_CurrentChar) { + case u8'\'': + m_State = StateType::SINGLE; break; - case '"': - mState = StateType::DOUBLE; + case u8'"': + m_State = StateType::DOUBLE; break; - case '\\': - mState = StateType::ESCAPE; - mPreState = StateType::NORMAL; + case u8'\\': + m_State = StateType::ESCAPE; + m_PrevState = StateType::NORMAL; break; - case ' ': + case u8' ': break; // skip blank default: - mBuffer->push_back(mCmdChar); - mState = StateType::NORMAL; + m_Buffer.push_back(m_CurrentChar); + m_State = StateType::NORMAL; break; } } - void CmdSplitter::ProcSingle(void) { - switch (mCmdChar) { - case '\'': - mState = StateType::NORMAL; + void CmdSplitter::ProcSingle() { + switch (m_CurrentChar) { + case u8'\'': + m_State = StateType::NORMAL; break; - case '"': - mBuffer->push_back('"'); + case u8'"': + m_Buffer.push_back('"'); break; - case '\\': - mState = StateType::ESCAPE; - mPreState = StateType::SINGLE; + case u8'\\': + m_State = StateType::ESCAPE; + m_PrevState = StateType::SINGLE; break; - case ' ': - mBuffer->push_back(' '); + case u8' ': + m_Buffer.push_back(u8' '); break; default: - mBuffer->push_back(mCmdChar); + m_Buffer.push_back(m_CurrentChar); break; } } - void CmdSplitter::ProcDouble(void) { - switch (mCmdChar) { - case '\'': - mBuffer->push_back('\''); + void CmdSplitter::ProcDouble() { + switch (m_CurrentChar) { + case u8'\'': + m_Buffer.push_back(u8'\''); break; - case '"': - mState = StateType::NORMAL; + case u8'"': + m_State = StateType::NORMAL; break; - case '\\': - mState = StateType::ESCAPE; - mPreState = StateType::DOUBLE; + case u8'\\': + m_State = StateType::ESCAPE; + m_PrevState = StateType::DOUBLE; break; - case ' ': - mBuffer->push_back(' '); + case u8' ': + m_Buffer.push_back(u8' '); break; default: - mBuffer->push_back(mCmdChar); + m_Buffer.push_back(m_CurrentChar); break; } } - void CmdSplitter::ProcEscape(void) { + void CmdSplitter::ProcEscape() { // add itself - mBuffer->push_back(mCmdChar); + m_Buffer.push_back(m_CurrentChar); // restore state - mState = mPreState; + m_State = m_PrevState; } - void CmdSplitter::ProcNormal(void) { - switch (mCmdChar) { - case '\'': - mBuffer->push_back('\''); + void CmdSplitter::ProcNormal() { + switch (m_CurrentChar) { + case u8'\'': + m_Buffer.push_back(u8'\''); break; - case '"': - mBuffer->push_back('"'); + case u8'"': + m_Buffer.push_back(u8'"'); break; - case '\\': - mState = StateType::ESCAPE; - mPreState = StateType::NORMAL; + case u8'\\': + m_State = StateType::ESCAPE; + m_PrevState = StateType::NORMAL; break; - case ' ': - mResult->push_back(*mBuffer); - mBuffer->clear(); - mState = StateType::SPACE; + case u8' ': + m_Result.emplace_back(m_Buffer); + m_Buffer.clear(); + m_State = StateType::SPACE; break; default: - mBuffer->push_back(mCmdChar); + m_Buffer.push_back(m_CurrentChar); break; } } #pragma endregion +#pragma region Arguments Map + +#pragma endregion + #pragma region Help Document HelpDocument::HelpDocument() : m_Stack(), m_Results() {} HelpDocument::~HelpDocument() {} - void HelpDocument::Push(const std::string& arg_name, const std::string& arg_desc) { + HelpDocument::StackItem::StackItem() : m_Name(), m_Desc() {} + + HelpDocument::StackItem::StackItem(const std::u8string& name, const std::u8string& desc) : m_Name(name), m_Desc(desc) {} + + HelpDocument::ResultItem::ResultItem() : m_CmdDesc(), m_ArgDesc() {} + + HelpDocument::ResultItem::ResultItem(const std::u8string& cmd_desc, const std::deque& arg_desc) : + m_CmdDesc(cmd_desc), m_ArgDesc(arg_desc.begin(), arg_desc.end()) {} + + void HelpDocument::Push(const std::u8string& arg_name, const std::u8string& arg_desc) { m_Stack.emplace_back(StackItem { arg_name, arg_desc }); } void HelpDocument::Pop() { + if (m_Stack.empty()) + throw std::runtime_error("try pop back on an empty help document."); m_Stack.pop_back(); } - void HelpDocument::Terminate(std::string& command_desc) { - // create new result and copy stack - ResultItem result(command_desc); - result.m_ArgDesc.insert(result.m_ArgDesc.end(), m_Stack.begin(), m_Stack.end()); + void HelpDocument::Terminate(std::u8string& command_desc) { + // create new result + ResultItem result(command_desc, this->m_Stack); // add into result m_Results.emplace_back(std::move(result)); } void HelpDocument::Print() { - for (auto& item : m_Results) { - fputs("Syntax: ", stdout); - for (auto& cmd : item.m_ArgDesc) { - fputs(cmd.m_Name.c_str(), stdout); - fputc(' ', stdout); + for (auto& cmd : m_Results) { + // syntax + YYCC::ConsoleHelper::WriteLine(u8"Syntax: "); + for (const auto& arg : cmd.m_ArgDesc) { + YYCC::ConsoleHelper::Format(u8"%s ", arg.m_Name.c_str()); } - fputc('\n', stdout); - - if (!item.m_CmdDesc.empty()) { - fprintf(stdout, "Description: %s\n", item.m_CmdDesc.c_str()); + YYCC::ConsoleHelper::WriteLine(u8""); + // command description + if (!cmd.m_CmdDesc.empty()) { + YYCC::ConsoleHelper::FormatLine(u8"Description: %s", cmd.m_CmdDesc.c_str()); } - - for (auto& cmd : item.m_ArgDesc) { - if (!cmd.m_Desc.empty()) { - fprintf(stdout, "\t%s: %s\n", cmd.m_Name.c_str(), cmd.m_Desc.c_str()); + // argument description + YYCC::ConsoleHelper::WriteLine(u8"Arguments:"); + for (auto& arg : cmd.m_ArgDesc) { + if (!arg.m_Desc.empty()) { + YYCC::ConsoleHelper::FormatLine(u8"\t%s: %s", arg.m_Name.c_str(), arg.m_Desc.c_str()); } } - - fputc('\n', stdout); + // space between each commands + YYCC::ConsoleHelper::WriteLine(u8""); } } @@ -406,8 +438,8 @@ namespace Unvirt::CmdHelper { #pragma region Literal - Literal::Literal(const char* words) : - AbstractNode(), + Literal::Literal(const char* words) : + AbstractNode(), m_Literal(words == nullptr ? "" : words) { if (words == nullptr || m_Literal.empty()) throw std::invalid_argument("Invalid literal."); @@ -536,7 +568,7 @@ namespace Unvirt::CmdHelper { AbstractArgument::AbstractArgument(const char* argname) : AbstractNode(), - m_ArgName(argname == nullptr ? "" : argname), + m_ArgName(argname == nullptr ? "" : argname), m_Accepted(false), m_ParsedData(nullptr) { if (argname == nullptr || m_ArgName.empty()) throw std::invalid_argument("Invalid argument name."); @@ -652,16 +684,4 @@ namespace Unvirt::CmdHelper { #pragma endregion -#pragma region Argument Map - - void ArgumentsMap::Add(const std::string& k, AbstractNode* v) { - m_Data.emplace(std::make_pair(k, v)); - } - - void ArgumentsMap::Remove(const std::string& k) { - m_Data.erase(k); - } - -#pragma endregion - } diff --git a/Unvirt/CmdHelper.hpp b/Unvirt/CmdHelper.hpp index 8751dd8..741be7c 100644 --- a/Unvirt/CmdHelper.hpp +++ b/Unvirt/CmdHelper.hpp @@ -5,15 +5,19 @@ #include #include #include -#include +#include #include #include #include +#include +#include namespace Unvirt::CmdHelper { class CmdSplitter { public: + using Result_t = std::deque; + private: enum class StateType : int { SPACE, SINGLE, @@ -21,86 +25,194 @@ namespace Unvirt::CmdHelper { ESCAPE, NORMAL }; + public: CmdSplitter() : - mCmdChar(0), mBuffer(nullptr), mResult(nullptr), - mState(StateType::NORMAL), mPreState(StateType::NORMAL) {} + m_CurrentChar(u8'\0'), m_Buffer(), m_Result(), m_ValidResult(false), + m_State(StateType::NORMAL), m_PrevState(StateType::NORMAL) {} ~CmdSplitter() {} YYCC_DEL_CLS_COPY_MOVE(CmdSplitter); - std::deque Convert(const std::string& u8cmd); - protected: - char mCmdChar; - std::string* mBuffer; - std::deque* mResult; + bool Convert(const std::u8string& u8cmd); + const Result_t& GetResult() const; - StateType mState, mPreState; + private: + void ProcSpace(); + void ProcSingle(); + void ProcDouble(); + void ProcEscape(); + void ProcNormal(); - void ProcSpace(void); - void ProcSingle(void); - void ProcDouble(void); - void ProcEscape(void); - void ProcNormal(void); + char8_t m_CurrentChar; + std::u8string m_Buffer; + Result_t m_Result; + bool m_ValidResult; + StateType m_State, m_PrevState; }; +#pragma region ArgumentsMap + + namespace ArgumentsMapItem { + + class AbstractItem { + public: + AbstractItem() {} + virtual ~AbstractItem() {} + YYCC_DEF_CLS_COPY_MOVE(AbstractItem); + }; + + template, int> = 0> + class ArithmeticItem : public AbstractItem { + public: + ArithmeticItem(_Ty value) : AbstractItem(), m_Data(value) {} + virtual ~ArithmeticItem() {} + YYCC_DEF_CLS_COPY_MOVE(ArithmeticItem); + public: + _Ty Get() const { return m_Data; } + protected: + _Ty m_Data; + }; + + template, int> = 0> + class ArithmeticArrayItem : public AbstractItem { + public: + ArithmeticArrayItem(const std::vector<_Ty>& values) : AbstractItem(), m_Data(values) {} + virtual ~ArithmeticArrayItem() {} + YYCC_DEF_CLS_COPY_MOVE(ArithmeticArrayItem); + public: + const std::vector<_Ty>& Get() const { return m_Data; } + protected: + std::vector<_Ty> m_Data; + }; + + class StringItem : public AbstractItem { + public: + StringItem(const std::u8string_view& value) : AbstractItem(), m_Data(value) {} + virtual ~StringItem() {} + YYCC_DEF_CLS_COPY_MOVE(StringItem); + public: + const std::u8string& Get() const { return m_Data; } + protected: + std::u8string m_Data; + }; + + class StringArrayItem : public AbstractItem { + public: + StringArrayItem(const std::vector& value) : AbstractItem(), m_Data(value) {} + virtual ~StringArrayItem() {} + YYCC_DEF_CLS_COPY_MOVE(StringArrayItem); + public: + const std::vector& Get() const { return m_Data; } + protected: + std::vector m_Data; + }; + + } + + class ArgumentsMap { + public: + ArgumentsMap() : m_Data() {} + ~ArgumentsMap() {} + YYCC_DEF_CLS_COPY_MOVE(ArgumentsMap); + + protected: + std::map> m_Data; + + public: + template, int> = 0> + void Add(const std::u8string_view& key, _Types&&... args) { + // check argument + if (key.empty()) + throw std::invalid_argument("argument key should not be empty"); + // insert into data + auto result = m_Data.try_emplace(std::u8string(key), std::make_unique<_Ty>(std::forward<_Types>(args)...)); + if (!result.second) + throw std::runtime_error("try to add an existing key."); + } + template, int> = 0> + const _Ty& Get() const { + // check argument + if (key.empty()) + throw std::invalid_argument("argument key should not be empty"); + // find key first + auto finder = m_Data.find(std::u8string(key)); + if (finder == m_Data.end()) + throw std::runtime_error("try to get a non-existent key."); + // get stored value data + const ArgumentsMapItem::AbstractItem& value = *finder->second.get(); + return static_cast(value); + } + void Remove(const std::u8string_view& key) { + // check argument + if (key.empty()) + throw std::invalid_argument("argument key should not be empty"); + // remove and return remove result. + if (m_Data.erase(std::u8string(key)) == 0u) + throw std::runtime_error("try to delete a non-existent key."); + } + }; + +#pragma endregion + class HelpDocument { public: HelpDocument(); ~HelpDocument(); - YYCC_DEL_CLS_COPY_MOVE(HelpDocument); + YYCC_DEF_CLS_COPY_MOVE(HelpDocument); - void Push(const std::string& arg_name, const std::string& arg_desc); + public: + void Push(const std::u8string& arg_name, const std::u8string& arg_desc); void Pop(); - void Terminate(std::string& command_desc); + void Terminate(std::u8string& command_desc); void Print(); protected: struct StackItem { - StackItem() : m_Name(), m_Desc() {} - StackItem(const std::string& name, const std::string& desc) : m_Name(name), m_Desc(desc) {} + StackItem(); + StackItem(const std::u8string& name, const std::u8string& desc); YYCC_DEF_CLS_COPY_MOVE(StackItem); - std::string m_Name; - std::string m_Desc; + + std::u8string m_Name; + std::u8string m_Desc; }; std::deque m_Stack; + struct ResultItem { - ResultItem() : m_CmdDesc(), m_ArgDesc() {} - ResultItem(const std::string& desc) : m_CmdDesc(desc), m_ArgDesc() {} + ResultItem(); + ResultItem(const std::u8string& cmd_desc, const std::deque& arg_desc); YYCC_DEF_CLS_COPY_MOVE(ResultItem); - std::string m_CmdDesc; + + std::u8string m_CmdDesc; std::vector m_ArgDesc; }; std::vector m_Results; }; - enum class NodeType { - Literal, Choice, Argument - }; - class ArgumentsMap; - using ExecutionFct = std::function; class AbstractNode { + friend class CommandRoot; + public: + using ExecutionFct = void(*)(const ArgumentsMap&); + public: AbstractNode(); virtual ~AbstractNode(); - YYCC_DEL_CLS_COPY_MOVE(AbstractNode); + YYCC_DEF_CLS_COPY_MOVE(AbstractNode); AbstractNode* Then(AbstractNode*); AbstractNode* Executes(ExecutionFct, const char* = nullptr); AbstractNode* Comment(const char*); - public: - void Help(HelpDocument*); - bool Consume(std::deque&, ArgumentsMap*); - virtual NodeType GetNodeType() = 0; - virtual bool IsConflictWith(AbstractNode*) = 0; protected: - virtual std::string GetHelpSymbol() = 0; - virtual bool BeginAccept(const std::string&, ArgumentsMap*) = 0; - virtual void EndAccept(ArgumentsMap*) = 0; + void Help(HelpDocument& doc); + bool Consume(CmdSplitter::Result_t& cmds, ArgumentsMap& am); + virtual bool IsConflictWith(AbstractNode* node) = 0; + virtual bool IsArgument() = 0; + virtual std::u8string HelpSymbol() = 0; + virtual bool BeginConsume(const std::u8string& cur_cmd, ArgumentsMap& am) = 0; + virtual void EndConsume(ArgumentsMap*) = 0; - std::vector m_Literals; - std::vector m_Choices; - std::vector m_Args; + protected: + std::vector> m_Nodes; ExecutionFct m_Execution; std::string m_ExecutionDesc; std::string m_Comment; @@ -178,8 +290,8 @@ namespace Unvirt::CmdHelper { YYCC_DEL_CLS_COPY_MOVE(AbstractArgument); template - T GetData() { - return reinterpret_cast(m_ParsedData); + T GetData() { + return reinterpret_cast(m_ParsedData); } public: @@ -220,7 +332,7 @@ namespace Unvirt::CmdHelper { class StringArgument : public AbstractArgument { public: using vType = std::string; - StringArgument(const char* argname) : + StringArgument(const char* argname) : AbstractArgument(argname) {} virtual ~StringArgument() {} YYCC_DEL_CLS_COPY_MOVE(StringArgument); @@ -233,7 +345,7 @@ namespace Unvirt::CmdHelper { class EncodingArgument : public AbstractArgument { public: using vType = std::vector; - EncodingArgument(const char* argname) : + EncodingArgument(const char* argname) : AbstractArgument(argname) {} virtual ~EncodingArgument() {} YYCC_DEL_CLS_COPY_MOVE(EncodingArgument); @@ -243,36 +355,4 @@ namespace Unvirt::CmdHelper { virtual void EndParse() override; }; - class ArgumentsMap { - public: - ArgumentsMap() : m_Data() {} - ~ArgumentsMap() {} - YYCC_DEL_CLS_COPY_MOVE(ArgumentsMap); - - void Add(const std::string& k, AbstractNode* v); - void Remove(const std::string& k); - - template - _Ty* Get(const char* k) const { - if (k == nullptr) throw std::invalid_argument("Null argument name."); - std::string conv(k); - - auto finder = m_Data.find(conv); - if (finder == m_Data.end()) throw std::invalid_argument("No such argument name."); - AbstractNode* node = finder->second; - switch (node->GetNodeType()) { - case NodeType::Argument: - return reinterpret_cast<_Ty*>(dynamic_cast(node)->GetData<_Ty*>()); - case NodeType::Choice: - return reinterpret_cast<_Ty*>(dynamic_cast(node)->GetIndex()); - case NodeType::Literal: - default: - throw std::runtime_error("No such argument type."); - } - } - - protected: - std::unordered_map m_Data; - }; - } diff --git a/Unvirt/StructFormatter.cpp b/Unvirt/StructFormatter.cpp index a936555..1db3186 100644 --- a/Unvirt/StructFormatter.cpp +++ b/Unvirt/StructFormatter.cpp @@ -132,7 +132,7 @@ namespace Unvirt::StructFormatter { beobj->GetID(), AccessibleValue::GetClassIdName(beobj->GetClassID()).c_str(), PrintPointer(beobj).c_str(), - PrintCKSTRING(beobj->GetName()).c_str() + (beobj != nullptr ? PrintCKSTRING(beobj->GetName()).c_str() : u8"") ); } } @@ -166,16 +166,10 @@ namespace Unvirt::StructFormatter { // print current mesh { auto curmesh = obj->GetCurrentMesh(); - Console::Format(u8"->\t%s", - PrintPointer(curmesh).c_str() + Console::Format(u8"->\t%s\t%s", + PrintPointer(curmesh).c_str(), + (curmesh != nullptr ? PrintCKSTRING(curmesh->GetName()).c_str() : u8"") ); - if (curmesh != nullptr) { - Console::FormatLine(u8"\t%s", - PrintCKSTRING(curmesh->GetName()).c_str() - ); - } else { - Console::WriteLine(u8""); - } } // print other meshes for (LibCmo::CKDWORD i = 0; i < obj->GetPotentialMeshCount(); ++i) { @@ -183,7 +177,7 @@ namespace Unvirt::StructFormatter { Console::FormatLine(u8"#%" PRIuCKDWORD "\t%s\t%s", i, PrintPointer(thismesh).c_str(), - PrintCKSTRING(thismesh->GetName()).c_str() + (thismesh != nullptr ? PrintCKSTRING(thismesh->GetName()).c_str() : u8"") ); } @@ -239,26 +233,16 @@ namespace Unvirt::StructFormatter { // color Console::WriteLine(u8"== Color =="); - Console::Write(u8"Diffuse: "); - PrintColor(obj->GetDiffuse()); - Console::Write(u8"\n"); - Console::Write(u8"Ambient: "); - PrintColor(obj->GetAmbient()); - Console::Write(u8"\n"); - Console::Write(u8"Specular: "); - PrintColor(obj->GetSpecular()); - Console::Write(u8"\n"); - Console::Write(u8"Emissive: "); - PrintColor(obj->GetEmissive()); - Console::Write(u8"\n"); + Console::FormatLine(u8"Diffuse: %s", PrintColor(obj->GetDiffuse()).c_str()); + Console::FormatLine(u8"Ambient: %s", PrintColor(obj->GetAmbient()).c_str()); + Console::FormatLine(u8"Specular: %s", PrintColor(obj->GetSpecular()).c_str()); + Console::FormatLine(u8"Emissive: %s", PrintColor(obj->GetEmissive()).c_str()); Console::FormatLine(u8"Specular Power: %.2" PRIfCKFLOAT, obj->GetSpecularPower()); // basic data Console::WriteLine(u8"== Basic =="); - Console::Write(u8"Both Sided: "); - PrintBool(obj->GetTwoSidedEnabled()); - Console::Write(u8"\n"); + Console::FormatLine(u8"Both Sided: %s", PrintBool(obj->GetTwoSidedEnabled()).c_str()); Console::FormatLine(u8"Fill Mode: %s", AccessibleValue::GetEnumName(obj->GetFillMode(), AccessibleValue::EnumDesc::VXFILL_MODE).c_str()); Console::FormatLine(u8"Shade Mode: %s", AccessibleValue::GetEnumName(obj->GetShadeMode(), AccessibleValue::EnumDesc::VXSHADE_MODE).c_str()); @@ -268,48 +252,33 @@ namespace Unvirt::StructFormatter { Console::WriteLine(u8"Index\tAddress\tName"); for (LibCmo::CKDWORD i = 0; i < 4; ++i) { auto tex = obj->GetTexture(i); - if (tex != nullptr) { - Console::FormatLine(u8"#%" PRIuCKDWORD "\t%s\t%s", - i, - PrintPointer(tex), - PrintCKSTRING(tex->GetName()).c_str() - ); - } else { - Console::FormatLine(u8"#%" PRIuCKDWORD "\t%s", - i, - PrintPointer(tex) - ); - } + Console::FormatLine(u8"#%" PRIuCKDWORD "\t%s\t%s", + i, + PrintPointer(tex).c_str(), + (tex != nullptr ? PrintCKSTRING(tex->GetName()).c_str() : u8"") + ); } Console::FormatLine(u8"Texture Blend: %s", AccessibleValue::GetEnumName(obj->GetTextureBlendMode(), AccessibleValue::EnumDesc::VXTEXTURE_BLENDMODE).c_str()); Console::FormatLine(u8"Filter Min: %s", AccessibleValue::GetEnumName(obj->GetTextureMinMode(), AccessibleValue::EnumDesc::VXTEXTURE_FILTERMODE).c_str()); Console::FormatLine(u8"Filter Mag: %s", AccessibleValue::GetEnumName(obj->GetTextureMagMode(), AccessibleValue::EnumDesc::VXTEXTURE_FILTERMODE).c_str()); Console::FormatLine(u8"Address Mode: %s", AccessibleValue::GetEnumName(obj->GetTextureAddressMode(), AccessibleValue::EnumDesc::VXTEXTURE_ADDRESSMODE).c_str()); - Console::Write(u8"Perspective Correct: "); - PrintBool(obj->GetPerspectiveCorrectionEnabled()); - Console::Write(u8"\n"); + Console::FormatLine(u8"Perspective Correct: %s", PrintBool(obj->GetPerspectiveCorrectionEnabled()).c_str()); // alpha test Console::WriteLine(u8"== Alpha Test =="); - Console::Write(u8"Enabled: "); - PrintBool(obj->GetAlphaTestEnabled()); - Console::Write(u8"\n"); + Console::FormatLine(u8"Enabled: %s", PrintBool(obj->GetAlphaTestEnabled()).c_str()); Console::FormatLine(u8"Alpha Function: %s", AccessibleValue::GetEnumName(obj->GetAlphaFunc(), AccessibleValue::EnumDesc::VXCMPFUNC).c_str()); Console::FormatLine(u8"Alpha Ref Value: %" PRIuCKBYTE, obj->GetAlphaRef()); // alpha blend Console::WriteLine(u8"== Alpha Blend =="); - Console::Write(u8"Enabled: "); - PrintBool(obj->GetAlphaBlendEnabled()); - Console::Write(u8"\n"); + Console::FormatLine(u8"Enabled: %s", PrintBool(obj->GetAlphaBlendEnabled()).c_str()); Console::FormatLine(u8"Source Blend: %s", AccessibleValue::GetEnumName(obj->GetSourceBlend(), AccessibleValue::EnumDesc::VXBLEND_MODE).c_str()); Console::FormatLine(u8"Destination Blend: %s", AccessibleValue::GetEnumName(obj->GetDestBlend(), AccessibleValue::EnumDesc::VXBLEND_MODE).c_str()); // z buffer Console::WriteLine(u8"== Z-Buffer Write =="); - Console::Write(u8"Enabled: "); - PrintBool(obj->GetZWriteEnabled()); - Console::Write(u8"\n"); + Console::FormatLine(u8"Enabled: %s", PrintBool(obj->GetZWriteEnabled()).c_str()); Console::FormatLine(u8"Z Compare Function: %s", AccessibleValue::GetEnumName(obj->GetZFunc(), AccessibleValue::EnumDesc::VXCMPFUNC).c_str()); // effect @@ -324,7 +293,7 @@ namespace Unvirt::StructFormatter { Console::WriteLine(u8"== Flags =="); Console::WriteLine(u8"Mesh Flags:"); - Console::WriteLine(AccessibleValue::GetFlagEnumName(obj->GetMeshFlags(), AccessibleValue::EnumDesc::VXMESH_FLAGS, u8"\n").c_str()); + Console::WriteLine(AccessibleValue::GetFlagEnumName(obj->GetMeshFlags(), AccessibleValue::EnumDesc::VXMESH_FLAGS, u8"\n", u8"\t").c_str()); Console::FormatLine(u8"Lit Mode: %s", AccessibleValue::GetEnumName(obj->GetLitMode(), AccessibleValue::EnumDesc::VXMESH_LITMODE).c_str()); Console::FormatLine(u8"Wrap Mode: %s", AccessibleValue::GetEnumName(obj->GetWrapMode(), AccessibleValue::EnumDesc::VXTEXTURE_WRAPMODE).c_str()); @@ -333,26 +302,40 @@ namespace Unvirt::StructFormatter { Console::FormatLine(u8"Vertex Count: %" PRIuCKDWORD, obj->GetVertexCount()); Console::WriteLine(u8"Address\tSize\tType"); - PrintPointer(obj->GetVertexPositions()); - Console::FormatLine(u8"\t0x%" PRIxCKDWORD " bytes\tPositions", obj->GetVertexCount() * CKSizeof(LibCmo::VxMath::VxVector3)); - PrintPointer(obj->GetVertexNormals()); - Console::FormatLine(u8"\t0x%" PRIxCKDWORD " bytes\tNormals", obj->GetVertexCount() * CKSizeof(LibCmo::VxMath::VxVector3)); - PrintPointer(obj->GetVertexUVs()); - Console::FormatLine(u8"\t0x%" PRIxCKDWORD " bytes\tUVs", obj->GetVertexCount() * CKSizeof(LibCmo::VxMath::VxVector2)); - PrintPointer(obj->GetVertexColors()); - Console::FormatLine(u8"\t0x%" PRIxCKDWORD " bytes\tColors", obj->GetVertexCount() * CKSizeof(LibCmo::CKDWORD)); - PrintPointer(obj->GetVertexSpecularColors()); - Console::FormatLine(u8"\t0x%" PRIxCKDWORD " bytes\tSpecularColors", obj->GetVertexCount() * CKSizeof(LibCmo::CKDWORD)); + Console::FormatLine(u8"%s\t0x%" PRIxCKDWORD " bytes\tPositions", + PrintPointer(obj->GetVertexPositions()).c_str(), + obj->GetVertexCount() * CKSizeof(LibCmo::VxMath::VxVector3) + ); + Console::FormatLine(u8"%s\t0x%" PRIxCKDWORD " bytes\tNormals", + PrintPointer(obj->GetVertexNormals()).c_str(), + obj->GetVertexCount() * CKSizeof(LibCmo::VxMath::VxVector3) + ); + Console::FormatLine(u8"%s\t0x%" PRIxCKDWORD " bytes\tUVs", + PrintPointer(obj->GetVertexUVs()).c_str(), + obj->GetVertexCount() * CKSizeof(LibCmo::VxMath::VxVector2) + ); + Console::FormatLine(u8"%s\t0x%" PRIxCKDWORD " bytes\tColors", + PrintPointer(obj->GetVertexColors()).c_str(), + obj->GetVertexCount() * CKSizeof(LibCmo::CKDWORD) + ); + Console::FormatLine(u8"%s\t0x%" PRIxCKDWORD " bytes\tSpecularColors", + PrintPointer(obj->GetVertexSpecularColors()).c_str(), + obj->GetVertexCount() * CKSizeof(LibCmo::CKDWORD) + ); // face data Console::WriteLine(u8"== Face =="); Console::FormatLine(u8"Face Count: %" PRIuCKDWORD, obj->GetFaceCount()); Console::WriteLine(u8"Address\tSize\tType"); - PrintPointer(obj->GetFaceIndices()); - Console::FormatLine(u8"\t0x%" PRIxCKDWORD " bytes\tIndices", obj->GetFaceCount() * 3 * CKSizeof(LibCmo::CKWORD)); - PrintPointer(obj->GetFaceMaterialSlotIndexs()); - Console::FormatLine(u8"\t0x%" PRIxCKDWORD " bytes\tMaterialSlotIndexs", obj->GetFaceCount() * CKSizeof(LibCmo::CKWORD)); + Console::FormatLine(u8"%s\t0x%" PRIxCKDWORD " bytes\tIndices", + PrintPointer(obj->GetFaceIndices()).c_str(), + obj->GetFaceCount() * 3 * CKSizeof(LibCmo::CKWORD) + ); + Console::FormatLine(u8"%s\t0x%" PRIxCKDWORD " bytes\tMaterialSlotIndexs", + PrintPointer(obj->GetFaceMaterialSlotIndexs()).c_str(), + obj->GetFaceCount() * CKSizeof(LibCmo::CKWORD) + ); // mtl slot data Console::WriteLine(u8"== Material Slot =="); @@ -363,12 +346,11 @@ namespace Unvirt::StructFormatter { for (LibCmo::CKDWORD i = 0; i < slotcount; ++i) { LibCmo::CK2::ObjImpls::CKMaterial* mtl = pMtlSlots[i]; - Console::Format(u8"#%" PRIuCKDWORD "\t", i); - PrintPointer(mtl); - Console::Write(u8"\t"); - if (mtl != nullptr) - PrintCKSTRING(mtl->GetName()); - Console::Write(u8"\n"); + Console::FormatLine(u8"#%" PRIuCKDWORD "\t%s\t%s", + i, + PrintPointer(mtl).c_str(), + (mtl != nullptr ? PrintCKSTRING(mtl->GetName()).c_str() : u8"") + ); } } @@ -437,27 +419,27 @@ namespace Unvirt::StructFormatter { } static void PrintObjectListEntry(const LibCmo::CK2::CKFileObject& obj, const LibCmo::CK2::CKFileInfo& fileinfo, size_t entry_index, bool full_detail) { if (full_detail) { - Console::FormatLine(u8"0x%08" PRIxCKDWORD, obj.SaveFlags); - Console::FormatLine(u8"\t%s", AccessibleValue::GetEnumName(obj.Options, AccessibleValue::EnumDesc::CK_FO_OPTIONS).c_str()); + Console::Format(u8"0x%08" PRIxCKDWORD "\t", obj.SaveFlags); + Console::Format(u8"%s\t", AccessibleValue::GetEnumName(obj.Options, AccessibleValue::EnumDesc::CK_FO_OPTIONS).c_str()); - Console::FormatLine(u8"\t%" PRIuCKID "\t%" PRIuCKID, + Console::Format(u8"%" PRIuCKID "\t%" PRIuCKID "\t", obj.CreatedObjectId, obj.ObjectId ); - Console::FormatLine(u8"\t0x%08" PRIxCKDWORD " (Rel: 0x%08" PRIxCKDWORD ")", + Console::Format(u8"0x%08" PRIxCKDWORD " (Rel: 0x%08" PRIxCKDWORD ")\t", obj.FileIndex, obj.FileIndex - CKSizeof(LibCmo::CK2::CKRawFileInfo) - fileinfo.Hdr1UnPackSize ); - Console::FormatLine(u8"\t0x%08" PRIxCKDWORD, obj.PackSize); + Console::Format(u8"0x%08" PRIxCKDWORD "\t", obj.PackSize); } // following items are shared by full details and simple layout - Console::FormatLine(u8"\t#%" PRIuSIZET "\t%s\t%s\t%s\t%s", + Console::FormatLine(u8"#%" PRIuSIZET "\t%s\t%s\t%s\t%s", entry_index, AccessibleValue::GetClassIdName(obj.ObjectCid).c_str(), PrintColorfulBool(obj.ObjPtr != nullptr).c_str(), PrintColorfulBool(obj.Data != nullptr).c_str(), - PrintCKSTRING(LibCmo::XContainer::NSXString::ToCKSTRING(obj.Name)) + PrintCKSTRING(LibCmo::XContainer::NSXString::ToCKSTRING(obj.Name)).c_str() ); } void PrintObjectList( @@ -648,7 +630,7 @@ namespace Unvirt::StructFormatter { Console::WriteLine(YYCC_COLOR_LIGHT_YELLOW(u8"Identifiers")); Console::WriteLine(u8"Identifier\tData Pointer\tData Size"); for (const auto& ident : collection) { - Console::FormatLine(u8"0x%08" PRIxCKDWORD "\t%s\t%" PRIuCKDWORD " (%" PRIuCKDWORD " DWORD + %" PRIuCKDWORD ")\n", + Console::FormatLine(u8"0x%08" PRIxCKDWORD "\t%s\t%" PRIuCKDWORD " (%" PRIuCKDWORD " DWORD + %" PRIuCKDWORD ")", ident.m_Identifier, PrintPointer(ident.m_DataPtr).c_str(), ident.m_AreaSize, diff --git a/Unvirt/TerminalHelper.cpp b/Unvirt/TerminalHelper.cpp deleted file mode 100644 index e9a6b72..0000000 --- a/Unvirt/TerminalHelper.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "TerminalHelper.hpp" -#include -#include -#include -#include -#include - -#if YYCC_OS == YYCC_OS_WINDOWS -#include -#include -#include -#include -#endif - -namespace Unvirt { - namespace TerminalHelper { - - // all of these functions only works on Windows platform - // due to shitty Windows implementations. - - bool EnsureTerminalColor(void) { -#if YYCC_OS == YYCC_OS_WINDOWS - if (_isatty(_fileno(stdout))) { - HANDLE h_output; - DWORD dw_mode; - - h_output = (HANDLE)_get_osfhandle(_fileno(stdout)); - if (!GetConsoleMode(h_output, &dw_mode)) return false; - if (!SetConsoleMode(h_output, dw_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return false; - - return true; - } else return false; -#else - return true; -#endif - } - - bool EnsureTerminalEncoding(void) { -#if YYCC_OS == YYCC_OS_WINDOWS - if (!SetConsoleCP(CP_UTF8)) return false; - if (!SetConsoleOutputCP(CP_UTF8)) return false; - - /*_setmode(_fileno(stdout), _O_U8TEXT);*/ - _setmode(_fileno(stdin), _O_U16TEXT); -#endif - return true; - } - - void GetCmdLine(std::string& u8cmd) { - fputs(UNVIRT_TERMCOL_LIGHT_GREEN(("Unvirt> ")), stdout); -#if YYCC_OS == YYCC_OS_WINDOWS - std::wstring wcmd; - std::getline(std::wcin, wcmd); - LibCmo::EncodingHelper::WcharToChar(wcmd, u8cmd, CP_UTF8); -#else - std::getline(std::cin, u8cmd); -#endif - } - - } -} \ No newline at end of file diff --git a/Unvirt/TerminalHelper.hpp b/Unvirt/TerminalHelper.hpp deleted file mode 100644 index e1b39c7..0000000 --- a/Unvirt/TerminalHelper.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include - -namespace Unvirt::TerminalHelper { - -#define UNVIRT_REMOVE_PARENS_IMPL(...) __VA_ARGS__ -#define UNVIRT_REMOVE_PARENS(T) UNVIRT_REMOVE_PARENS_IMPL T - - -#define UNVIRT_TERMCOLHDR_BLACK "\033[30m" -#define UNVIRT_TERMCOLHDR_RED "\033[31m" -#define UNVIRT_TERMCOLHDR_GREEN "\033[32m" -#define UNVIRT_TERMCOLHDR_YELLOW "\033[33m" -#define UNVIRT_TERMCOLHDR_BLUE "\033[34m" -#define UNVIRT_TERMCOLHDR_MAGENTA "\033[35m" -#define UNVIRT_TERMCOLHDR_CYAN "\033[36m" -#define UNVIRT_TERMCOLHDR_WHITE "\033[37m" - -#define UNVIRT_TERMCOLHDR_LIGHT_BLACK "\033[90m" -#define UNVIRT_TERMCOLHDR_LIGHT_RED "\033[91m" -#define UNVIRT_TERMCOLHDR_LIGHT_GREEN "\033[92m" -#define UNVIRT_TERMCOLHDR_LIGHT_YELLOW "\033[93m" -#define UNVIRT_TERMCOLHDR_LIGHT_BLUE "\033[94m" -#define UNVIRT_TERMCOLHDR_LIGHT_MAGENTA "\033[95m" -#define UNVIRT_TERMCOLHDR_LIGHT_CYAN "\033[96m" -#define UNVIRT_TERMCOLHDR_LIGHT_WHITE "\033[97m" - -#define UNVIRT_TERMCOLTAIL "\033[0m" - - -#define UNVIRT_TERMCOL_BLACK(T) "\033[30m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_RED(T) "\033[31m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_GREEN(T) "\033[32m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_YELLOW(T) "\033[33m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_BLUE(T) "\033[34m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_MAGENTA(T) "\033[35m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_CYAN(T) "\033[36m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_WHITE(T) "\033[37m" UNVIRT_REMOVE_PARENS(T) "\033[0m" - -#define UNVIRT_TERMCOL_LIGHT_BLACK(T) "\033[90m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_LIGHT_RED(T) "\033[91m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_LIGHT_GREEN(T) "\033[92m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_LIGHT_YELLOW(T) "\033[93m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_LIGHT_BLUE(T) "\033[94m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_LIGHT_MAGENTA(T) "\033[95m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_LIGHT_CYAN(T) "\033[96m" UNVIRT_REMOVE_PARENS(T) "\033[0m" -#define UNVIRT_TERMCOL_LIGHT_WHITE(T) "\033[97m" UNVIRT_REMOVE_PARENS(T) "\033[0m" - - bool EnsureTerminalColor(void); - bool EnsureTerminalEncoding(void); - void GetCmdLine(std::string&); - -}