add some features in Unvirt
- add style [simple | full] command to allow simple display. current object list display take too much space. - add search [obj | mgr] [plain | re] <text> command to allow user search object or manager list by substring or regex. - add ls search <page> to browse the search result. - set IronPad minidump dump type from full memory to normal. - fix Unvirt ls command page count display error.
This commit is contained in:
parent
e4a67a50a5
commit
c7af11702f
|
@ -204,7 +204,7 @@ namespace IronPad {
|
||||||
exception_info.ClientPointers = TRUE;
|
exception_info.ClientPointers = TRUE;
|
||||||
MiniDumpWriteDump(
|
MiniDumpWriteDump(
|
||||||
GetCurrentProcess(), GetCurrentProcessId(), hFile,
|
GetCurrentProcess(), GetCurrentProcessId(), hFile,
|
||||||
MiniDumpWithFullMemory,
|
MiniDumpNormal,
|
||||||
&exception_info,
|
&exception_info,
|
||||||
NULL, NULL
|
NULL, NULL
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,8 +7,6 @@ namespace Unvirt::StructFormatter {
|
||||||
|
|
||||||
#pragma region Assist Functions
|
#pragma region Assist Functions
|
||||||
|
|
||||||
#define PRIuSIZET "zu"
|
|
||||||
|
|
||||||
static void PrintCKSTRING(LibCmo::CKSTRING name) {
|
static void PrintCKSTRING(LibCmo::CKSTRING name) {
|
||||||
if (name == nullptr) {
|
if (name == nullptr) {
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_MAGENTA(("<anonymous>")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_MAGENTA(("<anonymous>")), stdout);
|
||||||
|
@ -39,6 +37,9 @@ namespace Unvirt::StructFormatter {
|
||||||
static void PrintBool(bool v) {
|
static void PrintBool(bool v) {
|
||||||
fputs(v ? "true" : "false", stdout);
|
fputs(v ? "true" : "false", stdout);
|
||||||
}
|
}
|
||||||
|
static void PrintColorfulBool(bool v) {
|
||||||
|
fputs(v ? UNVIRT_TERMCOL_LIGHT_GREEN(("Yes")) : UNVIRT_TERMCOL_LIGHT_RED(("No")), stdout);
|
||||||
|
}
|
||||||
static void PrintColor(const LibCmo::VxMath::VxColor& col) {
|
static void PrintColor(const LibCmo::VxMath::VxColor& col) {
|
||||||
LibCmo::CKDWORD argb = col.ToARGB();
|
LibCmo::CKDWORD argb = col.ToARGB();
|
||||||
LibCmo::CKDWORD a = (argb & 0xFF000000) >> 24,
|
LibCmo::CKDWORD a = (argb & 0xFF000000) >> 24,
|
||||||
|
@ -61,9 +62,16 @@ namespace Unvirt::StructFormatter {
|
||||||
const std::vector<_Ty>& data, size_t page, size_t pageitems,
|
const std::vector<_Ty>& data, size_t page, size_t pageitems,
|
||||||
std::function<void()> printHdrFct, std::function<void(size_t, const _Ty&)> printEntryFct) {
|
std::function<void()> printHdrFct, std::function<void(size_t, const _Ty&)> printEntryFct) {
|
||||||
|
|
||||||
|
// check page overflow
|
||||||
|
if (page * pageitems >= data.size()) {
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Page out of range.\n")), stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calc page data
|
||||||
size_t fulllen = data.size(),
|
size_t fulllen = data.size(),
|
||||||
startpos = page * pageitems,
|
startpos = page * pageitems,
|
||||||
fullpage = fulllen / pageitems;
|
fullpage = (fulllen + (pageitems - 1)) / pageitems; // to solve `fulllen / pageitems` empty page issue. like CKStateChunk::GetCeilDwordSize function (+3 /4 to get DWORD size).
|
||||||
|
|
||||||
// print header
|
// print header
|
||||||
printHdrFct();
|
printHdrFct();
|
||||||
|
@ -73,7 +81,7 @@ namespace Unvirt::StructFormatter {
|
||||||
printEntryFct(counter, data[counter]);
|
printEntryFct(counter, data[counter]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "Page %" PRIuSIZET " of %" PRIuSIZET "\n", page + 1, fullpage + 1);
|
fprintf(stdout, "Page %" PRIuSIZET " of %" PRIuSIZET "\n", page + 1, fullpage);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
@ -403,17 +411,17 @@ namespace Unvirt::StructFormatter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintObjectList(
|
#pragma region Object List Printer
|
||||||
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileObject>& ls,
|
|
||||||
const LibCmo::CK2::CKFileInfo& fileinfo,
|
|
||||||
size_t page, size_t pageitems) {
|
|
||||||
|
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileObject\n")), stdout);
|
static void PrintObjectListHeader(bool full_detail) {
|
||||||
GeneralPrintList<LibCmo::CK2::CKFileObject>(ls, page, pageitems,
|
if (full_detail) {
|
||||||
[]() -> void {
|
|
||||||
fputs("SaveFlags\tOptions\tCK ID\tFile CK ID\tFile Index\tPack Size\tIndex\tType\tCKObject\tCKStateChunk\tName\n", stdout);
|
fputs("SaveFlags\tOptions\tCK ID\tFile CK ID\tFile Index\tPack Size\tIndex\tType\tCKObject\tCKStateChunk\tName\n", stdout);
|
||||||
},
|
} else {
|
||||||
[&fileinfo](size_t index, const LibCmo::CK2::CKFileObject& obj) -> void {
|
fputs("Index\tType\tObject\tChunk\tName\n", stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void PrintObjectListEntry(const LibCmo::CK2::CKFileObject& obj, const LibCmo::CK2::CKFileInfo& fileinfo, size_t entry_index, bool full_detail) {
|
||||||
|
if (full_detail) {
|
||||||
fprintf(stdout, "0x%08" PRIxCKDWORD "\t", obj.SaveFlags);
|
fprintf(stdout, "0x%08" PRIxCKDWORD "\t", obj.SaveFlags);
|
||||||
fputs(AccessibleValue::GetEnumName(obj.Options, AccessibleValue::EnumDesc::CK_FO_OPTIONS).c_str(), stdout);
|
fputs(AccessibleValue::GetEnumName(obj.Options, AccessibleValue::EnumDesc::CK_FO_OPTIONS).c_str(), stdout);
|
||||||
fputc('\t', stdout);
|
fputc('\t', stdout);
|
||||||
|
@ -426,7 +434,7 @@ namespace Unvirt::StructFormatter {
|
||||||
obj.FileIndex - CKSizeof(LibCmo::CK2::CKRawFileInfo) - fileinfo.Hdr1UnPackSize);
|
obj.FileIndex - CKSizeof(LibCmo::CK2::CKRawFileInfo) - fileinfo.Hdr1UnPackSize);
|
||||||
fprintf(stdout, "0x%08" PRIxCKDWORD "\t", obj.PackSize);
|
fprintf(stdout, "0x%08" PRIxCKDWORD "\t", obj.PackSize);
|
||||||
|
|
||||||
fprintf(stdout, "#%" PRIuSIZET "\t", index);
|
fprintf(stdout, "#%" PRIuSIZET "\t", entry_index);
|
||||||
fputs(AccessibleValue::GetClassIdName(obj.ObjectCid).c_str(), stdout);
|
fputs(AccessibleValue::GetClassIdName(obj.ObjectCid).c_str(), stdout);
|
||||||
fputc('\t', stdout);
|
fputc('\t', stdout);
|
||||||
PrintPointer(obj.ObjPtr);
|
PrintPointer(obj.ObjPtr);
|
||||||
|
@ -435,32 +443,110 @@ namespace Unvirt::StructFormatter {
|
||||||
fputc('\t', stdout);
|
fputc('\t', stdout);
|
||||||
PrintCKSTRING(LibCmo::XContainer::NSXString::ToCKSTRING(obj.Name));
|
PrintCKSTRING(LibCmo::XContainer::NSXString::ToCKSTRING(obj.Name));
|
||||||
fputc('\n', stdout);
|
fputc('\n', stdout);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "#%" PRIuSIZET "\t", entry_index);
|
||||||
|
fputs(AccessibleValue::GetClassIdName(obj.ObjectCid).c_str(), stdout);
|
||||||
|
fputc('\t', stdout);
|
||||||
|
PrintColorfulBool(obj.ObjPtr != nullptr);
|
||||||
|
fputc('\t', stdout);
|
||||||
|
PrintColorfulBool(obj.Data != nullptr);
|
||||||
|
fputc('\t', stdout);
|
||||||
|
PrintCKSTRING(LibCmo::XContainer::NSXString::ToCKSTRING(obj.Name));
|
||||||
|
fputc('\n', stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void PrintObjectList(
|
||||||
|
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileObject>& ls,
|
||||||
|
const LibCmo::CK2::CKFileInfo& fileinfo,
|
||||||
|
size_t page, size_t pageitems,
|
||||||
|
bool full_detail) {
|
||||||
|
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileObject\n")), stdout);
|
||||||
|
GeneralPrintList<LibCmo::CK2::CKFileObject>(ls, page, pageitems,
|
||||||
|
[full_detail]() -> void {
|
||||||
|
PrintObjectListHeader(full_detail);
|
||||||
|
},
|
||||||
|
[&fileinfo, full_detail](size_t index, const LibCmo::CK2::CKFileObject& obj) -> void {
|
||||||
|
PrintObjectListEntry(obj, fileinfo, index, full_detail);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
void PrintSearchedObjectList(
|
||||||
|
const LibCmo::XContainer::XArray<size_t>& idxls,
|
||||||
|
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileObject>& ls,
|
||||||
|
const LibCmo::CK2::CKFileInfo& fileinfo,
|
||||||
|
size_t page, size_t pageitems,
|
||||||
|
bool full_detail) {
|
||||||
|
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileObject Searching Result\n")), stdout);
|
||||||
|
GeneralPrintList<size_t>(idxls, page, pageitems,
|
||||||
|
[full_detail]() -> void {
|
||||||
|
PrintObjectListHeader(full_detail);
|
||||||
|
},
|
||||||
|
[&ls, &fileinfo, full_detail](size_t, const size_t& index_to_obj) -> void {
|
||||||
|
// resolve index to real item.
|
||||||
|
// and pass the entry index, not the page index.
|
||||||
|
PrintObjectListEntry(ls[index_to_obj], fileinfo, index_to_obj, full_detail);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintManagerList(
|
#pragma endregion
|
||||||
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileManagerData>& ls,
|
|
||||||
size_t page, size_t pageitems) {
|
|
||||||
|
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileManager\n")), stdout);
|
#pragma region Manager List Printer
|
||||||
GeneralPrintList<LibCmo::CK2::CKFileManagerData>(ls, page, pageitems,
|
|
||||||
[]() -> void {
|
static void PrintManagerListHeader(bool full_detail) {
|
||||||
// print header
|
// manager list now do not affected by list style because it is enough short
|
||||||
fputs("Index\tCKGUID\tCKStateChunk\n", stdout);
|
fputs("Index\tCKGUID\tCKStateChunk\n", stdout);
|
||||||
},
|
}
|
||||||
[](size_t index, const LibCmo::CK2::CKFileManagerData& mgr) -> void {
|
static void PrintManagerListEntry(const LibCmo::CK2::CKFileManagerData& mgr, size_t entry_index, bool full_detail) {
|
||||||
// print body
|
// not affected by list style.
|
||||||
fprintf(stdout, "#%" PRIuSIZET "\t", index);
|
fprintf(stdout, "#%" PRIuSIZET "\t", entry_index);
|
||||||
PrintCKGUID(mgr.Manager);
|
PrintCKGUID(mgr.Manager);
|
||||||
fputc('\t', stdout);
|
fputc('\t', stdout);
|
||||||
PrintPointer(mgr.Data);
|
PrintPointer(mgr.Data);
|
||||||
fputc('\n', stdout);
|
fputc('\n', stdout);
|
||||||
}
|
}
|
||||||
|
void PrintManagerList(
|
||||||
|
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileManagerData>& ls,
|
||||||
|
size_t page, size_t pageitems,
|
||||||
|
bool full_detail) {
|
||||||
|
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileManager\n")), stdout);
|
||||||
|
GeneralPrintList<LibCmo::CK2::CKFileManagerData>(ls, page, pageitems,
|
||||||
|
[full_detail]() -> void {
|
||||||
|
// print header
|
||||||
|
PrintManagerListHeader(full_detail);
|
||||||
|
},
|
||||||
|
[full_detail](size_t index, const LibCmo::CK2::CKFileManagerData& mgr) -> void {
|
||||||
|
// print body
|
||||||
|
PrintManagerListEntry(mgr, index, full_detail);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
void PrintSearchedManagerList(
|
||||||
|
const LibCmo::XContainer::XArray<size_t>& idxls,
|
||||||
|
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileManagerData>& ls,
|
||||||
|
size_t page, size_t pageitems,
|
||||||
|
bool full_detail) {
|
||||||
|
|
||||||
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKFileManager Searching Result\n")), stdout);
|
||||||
|
GeneralPrintList<size_t>(idxls, page, pageitems,
|
||||||
|
[full_detail]() -> void {
|
||||||
|
PrintManagerListHeader(full_detail);
|
||||||
|
},
|
||||||
|
[&ls, full_detail](size_t, const size_t& index_to_mgr) -> void {
|
||||||
|
// resolve index to real one
|
||||||
|
PrintManagerListEntry(ls[index_to_mgr], index_to_mgr, full_detail);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject* obj) {
|
void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject* obj) {
|
||||||
if (obj == nullptr) {
|
if (obj == nullptr) {
|
||||||
|
@ -506,6 +592,7 @@ namespace Unvirt::StructFormatter {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager* mgr) {
|
void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager* mgr) {
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKBaseManager\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKBaseManager\n")), stdout);
|
||||||
if (mgr == nullptr) {
|
if (mgr == nullptr) {
|
||||||
|
@ -515,6 +602,7 @@ namespace Unvirt::StructFormatter {
|
||||||
|
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_RED(("Not Implemented.\n")), stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk* chunk) {
|
void PrintCKStateChunk(const LibCmo::CK2::CKStateChunk* chunk) {
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKStateChunk\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("CKStateChunk\n")), stdout);
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
|
|
|
@ -5,15 +5,31 @@
|
||||||
|
|
||||||
namespace Unvirt::StructFormatter {
|
namespace Unvirt::StructFormatter {
|
||||||
|
|
||||||
|
#define PRIuSIZET "zu"
|
||||||
|
|
||||||
void PrintCKFileInfo(const LibCmo::CK2::CKFileInfo& fileinfo);
|
void PrintCKFileInfo(const LibCmo::CK2::CKFileInfo& fileinfo);
|
||||||
|
|
||||||
void PrintObjectList(
|
void PrintObjectList(
|
||||||
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileObject>& ls,
|
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileObject>& ls,
|
||||||
const LibCmo::CK2::CKFileInfo& fileinfo,
|
const LibCmo::CK2::CKFileInfo& fileinfo,
|
||||||
size_t page, size_t pageitems);
|
size_t page, size_t pageitems,
|
||||||
|
bool full_detail);
|
||||||
|
void PrintSearchedObjectList(
|
||||||
|
const LibCmo::XContainer::XArray<size_t>& idxls,
|
||||||
|
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileObject>& ls,
|
||||||
|
const LibCmo::CK2::CKFileInfo& fileinfo,
|
||||||
|
size_t page, size_t pageitems,
|
||||||
|
bool full_detail);
|
||||||
|
|
||||||
void PrintManagerList(
|
void PrintManagerList(
|
||||||
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileManagerData>& ls,
|
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileManagerData>& ls,
|
||||||
size_t page, size_t pageitems);
|
size_t page, size_t pageitems,
|
||||||
|
bool full_detail);
|
||||||
|
void PrintSearchedManagerList(
|
||||||
|
const LibCmo::XContainer::XArray<size_t>& idxls,
|
||||||
|
const LibCmo::XContainer::XArray<LibCmo::CK2::CKFileManagerData>& ls,
|
||||||
|
size_t page, size_t pageitems,
|
||||||
|
bool full_detail);
|
||||||
|
|
||||||
void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject*);
|
void PrintCKObject(const LibCmo::CK2::ObjImpls::CKObject*);
|
||||||
void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager*);
|
void PrintCKBaseManager(const LibCmo::CK2::MgrImpls::CKBaseManager*);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "UnvirtContext.hpp"
|
#include "UnvirtContext.hpp"
|
||||||
#include <CK2/MgrImpls/CKPathManager.hpp>
|
#include <CK2/MgrImpls/CKPathManager.hpp>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
namespace Unvirt::Context {
|
namespace Unvirt::Context {
|
||||||
|
|
||||||
|
@ -8,7 +9,8 @@ namespace Unvirt::Context {
|
||||||
|
|
||||||
UnvirtContext::UnvirtContext() :
|
UnvirtContext::UnvirtContext() :
|
||||||
m_Root(), m_Splitter(), m_Help(nullptr),
|
m_Root(), m_Splitter(), m_Help(nullptr),
|
||||||
m_PageLen(10u), m_OrderExit(false),
|
m_PageLen(10u), m_ListStyleIsFull(true), m_OrderExit(false),
|
||||||
|
m_SearchPart(SearchPart::None), m_SearchIdxResult(),
|
||||||
m_Ctx(nullptr), m_FileReader(nullptr), m_IsShallowRead(true) {
|
m_Ctx(nullptr), m_FileReader(nullptr), m_IsShallowRead(true) {
|
||||||
|
|
||||||
// create command root
|
// create command root
|
||||||
|
@ -49,7 +51,7 @@ namespace Unvirt::Context {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
->Then((new CmdHelper::Literal("ls"))
|
->Then((new CmdHelper::Literal("ls"))
|
||||||
->Then((new CmdHelper::Choice("part", { "obj", "mgr"}))
|
->Then((new CmdHelper::Choice("part", { "obj", "mgr", "search"}))
|
||||||
->Comment("Which list you want to list.")
|
->Comment("Which list you want to list.")
|
||||||
->Then((new CmdHelper::IntArgument("page", [](int32_t v) -> bool { return v > 0; }))
|
->Then((new CmdHelper::IntArgument("page", [](int32_t v) -> bool { return v > 0; }))
|
||||||
->Comment("The page index. Start with 1.")
|
->Comment("The page index. Start with 1.")
|
||||||
|
@ -84,6 +86,21 @@ namespace Unvirt::Context {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
->Then((new CmdHelper::Literal("search"))
|
||||||
|
->Then((new CmdHelper::Choice("part", { "obj", "mgr"}))
|
||||||
|
->Comment("Which list you want to search.")
|
||||||
|
->Then((new CmdHelper::Choice("mode", { "plain", "re"}))
|
||||||
|
->Comment("The search mode. `plain` will search by substring and `re` will do regex search.")
|
||||||
|
->Then((new CmdHelper::StringArgument("text"))
|
||||||
|
->Comment("The text or regex to search.")
|
||||||
|
->Executes(
|
||||||
|
std::bind(&UnvirtContext::ProcSearch, this, std::placeholders::_1),
|
||||||
|
"Search object or manager by text or regex. Please note that the regex have limited UTF8 support and may cause undefined behavior."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
->Then((new CmdHelper::Literal("items"))
|
->Then((new CmdHelper::Literal("items"))
|
||||||
->Then((new CmdHelper::IntArgument("count", [](int32_t v) -> bool { return v > 0; }))
|
->Then((new CmdHelper::IntArgument("count", [](int32_t v) -> bool { return v > 0; }))
|
||||||
->Comment("The count of items you want to show in one page.")
|
->Comment("The count of items you want to show in one page.")
|
||||||
|
@ -93,6 +110,15 @@ namespace Unvirt::Context {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
->Then((new CmdHelper::Literal("style"))
|
||||||
|
->Then((new CmdHelper::Choice("level", { "full", "simple"}))
|
||||||
|
->Comment("The amount of showen content.")
|
||||||
|
->Executes(
|
||||||
|
std::bind(&UnvirtContext::ProcStyle, this, std::placeholders::_1),
|
||||||
|
"Change the detail level of showen data in `ls` command."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
->Then((new CmdHelper::Literal("encoding"))
|
->Then((new CmdHelper::Literal("encoding"))
|
||||||
->Then((new CmdHelper::EncodingArgument("enc"))
|
->Then((new CmdHelper::EncodingArgument("enc"))
|
||||||
->Comment("CKContext used encoding splitted by ','. Support mutiple encoding.")
|
->Comment("CKContext used encoding splitted by ','. Support mutiple encoding.")
|
||||||
|
@ -173,6 +199,9 @@ namespace Unvirt::Context {
|
||||||
|
|
||||||
void UnvirtContext::ClearDocument() {
|
void UnvirtContext::ClearDocument() {
|
||||||
if (m_FileReader == nullptr) return;
|
if (m_FileReader == nullptr) return;
|
||||||
|
// clear search result
|
||||||
|
m_SearchPart = SearchPart::None;
|
||||||
|
m_SearchIdxResult.clear();
|
||||||
// delete reader
|
// delete reader
|
||||||
delete m_FileReader;
|
delete m_FileReader;
|
||||||
m_FileReader = nullptr;
|
m_FileReader = nullptr;
|
||||||
|
@ -187,6 +216,14 @@ namespace Unvirt::Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnvirtContext::PrintCommonInfo(const char* u8_fmt, ...) {
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, u8_fmt);
|
||||||
|
std::vfprintf(stdout, u8_fmt, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
std::fputc('\n', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
void UnvirtContext::PrintCommonError(const char* u8_fmt, ...) {
|
void UnvirtContext::PrintCommonError(const char* u8_fmt, ...) {
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
va_start(argptr, u8_fmt);
|
va_start(argptr, u8_fmt);
|
||||||
|
@ -321,7 +358,7 @@ namespace Unvirt::Context {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get page
|
// get 0 based page (-1)
|
||||||
size_t page = *amap->Get<CmdHelper::IntArgument::vType>("page") - 1;
|
size_t page = *amap->Get<CmdHelper::IntArgument::vType>("page") - 1;
|
||||||
|
|
||||||
// show list
|
// show list
|
||||||
|
@ -329,21 +366,55 @@ namespace Unvirt::Context {
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
// obj list
|
// obj list
|
||||||
if (page * m_PageLen >= m_FileReader->GetFileObjects().size()) {
|
Unvirt::StructFormatter::PrintObjectList(
|
||||||
PrintCommonError("Page out of range.");
|
m_FileReader->GetFileObjects(),
|
||||||
return;
|
m_FileReader->GetFileInfo(),
|
||||||
}
|
page, this->m_PageLen,
|
||||||
Unvirt::StructFormatter::PrintObjectList(m_FileReader->GetFileObjects(), m_FileReader->GetFileInfo(), page, this->m_PageLen);
|
m_ListStyleIsFull
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
// mgr list
|
// mgr list
|
||||||
if (page * m_PageLen >= m_FileReader->GetManagersData().size()) {
|
Unvirt::StructFormatter::PrintManagerList(
|
||||||
PrintCommonError("Page out of range.");
|
m_FileReader->GetManagersData(),
|
||||||
return;
|
page, this->m_PageLen,
|
||||||
|
m_ListStyleIsFull
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// search list
|
||||||
|
switch (m_SearchPart) {
|
||||||
|
case SearchPart::None:
|
||||||
|
{
|
||||||
|
PrintCommonError("No search result to list.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SearchPart::Object:
|
||||||
|
{
|
||||||
|
Unvirt::StructFormatter::PrintSearchedObjectList(
|
||||||
|
m_SearchIdxResult,
|
||||||
|
m_FileReader->GetFileObjects(),
|
||||||
|
m_FileReader->GetFileInfo(),
|
||||||
|
page, this->m_PageLen,
|
||||||
|
m_ListStyleIsFull
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SearchPart::Manager:
|
||||||
|
{
|
||||||
|
Unvirt::StructFormatter::PrintSearchedManagerList(
|
||||||
|
m_SearchIdxResult,
|
||||||
|
m_FileReader->GetManagersData(),
|
||||||
|
page, this->m_PageLen,
|
||||||
|
m_ListStyleIsFull
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Unvirt::StructFormatter::PrintManagerList(m_FileReader->GetManagersData(), page, this->m_PageLen);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,7 +447,8 @@ namespace Unvirt::Context {
|
||||||
PrintCommonError("Index out of range.");
|
PrintCommonError("Index out of range.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PrintCommonError("WIP function.");
|
// todo: finish manager display
|
||||||
|
PrintCommonError("Not supported now.");
|
||||||
//Unvirt::StructFormatter::PrintCKBaseManager(m_FileReader->GetManagersData()[index].Data);
|
//Unvirt::StructFormatter::PrintCKBaseManager(m_FileReader->GetManagersData()[index].Data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -416,11 +488,110 @@ namespace Unvirt::Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnvirtContext::ProcSearch(const CmdHelper::ArgumentsMap* amap) {
|
||||||
|
// check pre-requirement
|
||||||
|
if (!HasOpenedFile()) {
|
||||||
|
PrintCommonError("No loaded file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get search text
|
||||||
|
std::string search_text(*amap->Get<CmdHelper::StringArgument::vType>("text"));
|
||||||
|
|
||||||
|
// analyse search mode
|
||||||
|
std::function<bool(const LibCmo::XContainer::XString&)> search_fct = [](const LibCmo::XContainer::XString&) -> bool { return false; };
|
||||||
|
switch (*amap->Get<CmdHelper::Choice::vType>("mode")) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// plain mode
|
||||||
|
search_fct = [&search_text](const LibCmo::XContainer::XString& cmp) -> bool {
|
||||||
|
return cmp.find(search_text) != std::string::npos;
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// regex mode
|
||||||
|
|
||||||
|
// try construct regex
|
||||||
|
std::regex re;
|
||||||
|
try {
|
||||||
|
re = std::regex(search_text, std::regex_constants::ECMAScript);
|
||||||
|
} catch (const std::regex_error& e) {
|
||||||
|
PrintCommonError("Invalid regular expressions: %s", e.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use copy ctor capture to input regex
|
||||||
|
// because re will be freed when exiting this switch.
|
||||||
|
search_fct = [re](const LibCmo::XContainer::XString& cmp) -> bool {
|
||||||
|
return std::regex_search(cmp, re);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start search
|
||||||
|
switch (*amap->Get<CmdHelper::Choice::vType>("part")) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// object
|
||||||
|
m_SearchPart = SearchPart::Object;
|
||||||
|
m_SearchIdxResult.clear();
|
||||||
|
|
||||||
|
size_t counter = 0;
|
||||||
|
for (const auto& obj : m_FileReader->GetFileObjects()) {
|
||||||
|
if (search_fct(obj.Name)) {
|
||||||
|
m_SearchIdxResult.emplace_back(counter);
|
||||||
|
}
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// manager
|
||||||
|
m_SearchPart = SearchPart::Manager;
|
||||||
|
m_SearchIdxResult.clear();
|
||||||
|
PrintCommonError("Not supported now.");
|
||||||
|
// todo: remove this return when fixing manager searching.
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// report search result
|
||||||
|
if (m_SearchIdxResult.empty()) {
|
||||||
|
PrintCommonInfo("Search done, but no result.");
|
||||||
|
} else {
|
||||||
|
PrintCommonInfo("Search done with %" PRIuSIZET " results. Use `ls search` to check them.", m_SearchIdxResult.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcItems(const CmdHelper::ArgumentsMap* amap) {
|
void UnvirtContext::ProcItems(const CmdHelper::ArgumentsMap* amap) {
|
||||||
// assign
|
// assign
|
||||||
m_PageLen = *amap->Get<CmdHelper::IntArgument::vType>("count");
|
m_PageLen = *amap->Get<CmdHelper::IntArgument::vType>("count");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnvirtContext::ProcStyle(const CmdHelper::ArgumentsMap* amap) {
|
||||||
|
// set list style level
|
||||||
|
switch (*amap->Get<CmdHelper::Choice::vType>("level")) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// full level
|
||||||
|
m_ListStyleIsFull = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// simple level
|
||||||
|
m_ListStyleIsFull = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UnvirtContext::ProcEncoding(const CmdHelper::ArgumentsMap* amap) {
|
void UnvirtContext::ProcEncoding(const CmdHelper::ArgumentsMap* amap) {
|
||||||
const auto& encodings = *amap->Get<CmdHelper::EncodingArgument::vType>("enc");
|
const auto& encodings = *amap->Get<CmdHelper::EncodingArgument::vType>("enc");
|
||||||
m_Ctx->SetEncoding(encodings);
|
m_Ctx->SetEncoding(encodings);
|
||||||
|
|
|
@ -22,9 +22,10 @@ namespace Unvirt::Context {
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum class ViewPart {
|
enum class SearchPart {
|
||||||
Objects, Managers
|
None, Object, Manager
|
||||||
};
|
};
|
||||||
|
void PrintCommonInfo(const char* u8_fmt, ...);
|
||||||
void PrintCommonError(const char* u8_fmt, ...);
|
void PrintCommonError(const char* u8_fmt, ...);
|
||||||
|
|
||||||
void ProcLoad(const CmdHelper::ArgumentsMap* amap);
|
void ProcLoad(const CmdHelper::ArgumentsMap* amap);
|
||||||
|
@ -34,7 +35,9 @@ namespace Unvirt::Context {
|
||||||
void ProcLs(const CmdHelper::ArgumentsMap* amap);
|
void ProcLs(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcData(const CmdHelper::ArgumentsMap* amap);
|
void ProcData(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcChunk(const CmdHelper::ArgumentsMap* amap);
|
void ProcChunk(const CmdHelper::ArgumentsMap* amap);
|
||||||
|
void ProcSearch(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcItems(const CmdHelper::ArgumentsMap* amap);
|
void ProcItems(const CmdHelper::ArgumentsMap* amap);
|
||||||
|
void ProcStyle(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcEncoding(const CmdHelper::ArgumentsMap* amap);
|
void ProcEncoding(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcTemp(const CmdHelper::ArgumentsMap* amap);
|
void ProcTemp(const CmdHelper::ArgumentsMap* amap);
|
||||||
void ProcRsc(const CmdHelper::ArgumentsMap* amap, bool isClear);
|
void ProcRsc(const CmdHelper::ArgumentsMap* amap, bool isClear);
|
||||||
|
@ -52,6 +55,10 @@ namespace Unvirt::Context {
|
||||||
CmdHelper::CmdSplitter m_Splitter;
|
CmdHelper::CmdSplitter m_Splitter;
|
||||||
|
|
||||||
size_t m_PageLen;
|
size_t m_PageLen;
|
||||||
|
bool m_ListStyleIsFull;
|
||||||
|
SearchPart m_SearchPart;
|
||||||
|
LibCmo::XContainer::XArray<size_t> m_SearchIdxResult;
|
||||||
|
|
||||||
bool m_OrderExit;
|
bool m_OrderExit;
|
||||||
LibCmo::CK2::CKContext* m_Ctx;
|
LibCmo::CK2::CKContext* m_Ctx;
|
||||||
LibCmo::CK2::CKFileReader* m_FileReader;
|
LibCmo::CK2::CKFileReader* m_FileReader;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user