sys: Massively improve string search memory usage
This commit is contained in:
parent
ee7c6a91a7
commit
680587e050
@ -10,7 +10,6 @@ namespace hex {
|
|||||||
namespace prv { class Provider; }
|
namespace prv { class Provider; }
|
||||||
|
|
||||||
struct FoundString {
|
struct FoundString {
|
||||||
std::string string;
|
|
||||||
u64 offset;
|
u64 offset;
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
@ -27,8 +26,9 @@ namespace hex {
|
|||||||
bool m_searching = false;
|
bool m_searching = false;
|
||||||
|
|
||||||
std::vector<FoundString> m_foundStrings;
|
std::vector<FoundString> m_foundStrings;
|
||||||
|
std::vector<size_t> m_filterIndices;
|
||||||
int m_minimumLength = 5;
|
int m_minimumLength = 5;
|
||||||
std::vector<char> m_filter;
|
std::string m_filter;
|
||||||
|
|
||||||
std::string m_selectedString;
|
std::string m_selectedString;
|
||||||
std::string m_demangledName;
|
std::string m_demangledName;
|
||||||
|
@ -17,18 +17,25 @@ namespace hex {
|
|||||||
this->m_foundStrings.clear();
|
this->m_foundStrings.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
this->m_filter.resize(0xFFFF, 0x00);
|
this->m_filter.reserve(0xFFFF);
|
||||||
|
std::memset(this->m_filter.data(), 0x00, this->m_filter.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewStrings::~ViewStrings() {
|
ViewStrings::~ViewStrings() {
|
||||||
EventManager::unsubscribe<EventDataChanged>(this);
|
EventManager::unsubscribe<EventDataChanged>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string readString(const FoundString &foundString) {
|
||||||
|
std::string string(foundString.size + 1, '\0');
|
||||||
|
SharedData::currentProvider->read(foundString.offset, string.data(), foundString.size);
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
void ViewStrings::createStringContextMenu(const FoundString &foundString) {
|
void ViewStrings::createStringContextMenu(const FoundString &foundString) {
|
||||||
if (ImGui::TableGetColumnFlags(2) == ImGuiTableColumnFlags_IsHovered && ImGui::IsMouseReleased(1) && ImGui::IsItemHovered()) {
|
if (ImGui::TableGetColumnFlags(2) == ImGuiTableColumnFlags_IsHovered && ImGui::IsMouseReleased(1) && ImGui::IsItemHovered()) {
|
||||||
ImGui::OpenPopup("StringContextMenu");
|
ImGui::OpenPopup("StringContextMenu");
|
||||||
this->m_selectedString = foundString.string;
|
this->m_selectedString = readString(foundString);
|
||||||
}
|
}
|
||||||
if (ImGui::BeginPopup("StringContextMenu")) {
|
if (ImGui::BeginPopup("StringContextMenu")) {
|
||||||
if (ImGui::MenuItem("hex.view.strings.copy"_lang)) {
|
if (ImGui::MenuItem("hex.view.strings.copy"_lang)) {
|
||||||
@ -46,6 +53,7 @@ namespace hex {
|
|||||||
|
|
||||||
void ViewStrings::searchStrings() {
|
void ViewStrings::searchStrings() {
|
||||||
this->m_foundStrings.clear();
|
this->m_foundStrings.clear();
|
||||||
|
this->m_filterIndices.clear();
|
||||||
this->m_searching = true;
|
this->m_searching = true;
|
||||||
|
|
||||||
std::thread([this] {
|
std::thread([this] {
|
||||||
@ -59,19 +67,17 @@ namespace hex {
|
|||||||
provider->readRelative(offset, buffer.data(), readSize);
|
provider->readRelative(offset, buffer.data(), readSize);
|
||||||
|
|
||||||
for (u32 i = 0; i < readSize; i++) {
|
for (u32 i = 0; i < readSize; i++) {
|
||||||
if (buffer[i] >= 0x20 && buffer[i] <= 0x7E)
|
if (buffer[i] >= ' ' && buffer[i] <= '~' && offset < provider->getSize() - 1)
|
||||||
foundCharacters++;
|
foundCharacters++;
|
||||||
else {
|
else {
|
||||||
if (foundCharacters >= this->m_minimumLength) {
|
if (foundCharacters >= this->m_minimumLength) {
|
||||||
FoundString foundString;
|
FoundString foundString = {
|
||||||
|
offset + i - foundCharacters + provider->getBaseAddress(),
|
||||||
foundString.offset = offset + i - foundCharacters + provider->getBaseAddress();
|
foundCharacters
|
||||||
foundString.size = foundCharacters;
|
};
|
||||||
foundString.string.reserve(foundCharacters);
|
|
||||||
foundString.string.resize(foundCharacters);
|
|
||||||
provider->read(foundString.offset, foundString.string.data(), foundCharacters);
|
|
||||||
|
|
||||||
this->m_foundStrings.push_back(foundString);
|
this->m_foundStrings.push_back(foundString);
|
||||||
|
this->m_filterIndices.push_back(this->m_foundStrings.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
foundCharacters = 0;
|
foundCharacters = 0;
|
||||||
@ -93,7 +99,19 @@ namespace hex {
|
|||||||
if (ImGui::InputInt("hex.view.strings.min_length"_lang, &this->m_minimumLength, 1, 0))
|
if (ImGui::InputInt("hex.view.strings.min_length"_lang, &this->m_minimumLength, 1, 0))
|
||||||
this->m_foundStrings.clear();
|
this->m_foundStrings.clear();
|
||||||
|
|
||||||
ImGui::InputText("hex.view.strings.filter"_lang, this->m_filter.data(), this->m_filter.size());
|
ImGui::InputText("hex.view.strings.filter"_lang, this->m_filter.data(), this->m_filter.capacity(), ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) {
|
||||||
|
auto &view = *static_cast<ViewStrings*>(data->UserData);
|
||||||
|
view.m_filter.resize(data->BufTextLen);
|
||||||
|
|
||||||
|
view.m_filterIndices.clear();
|
||||||
|
for (u64 i = 0; i < view.m_foundStrings.size(); i++) {
|
||||||
|
if (readString(view.m_foundStrings[i]).find(data->Buf) != std::string::npos)
|
||||||
|
view.m_filterIndices.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}, this);
|
||||||
|
|
||||||
if (ImGui::Button("hex.view.strings.extract"_lang))
|
if (ImGui::Button("hex.view.strings.extract"_lang))
|
||||||
this->searchStrings();
|
this->searchStrings();
|
||||||
}, this->m_searching);
|
}, this->m_searching);
|
||||||
@ -132,9 +150,9 @@ namespace hex {
|
|||||||
return left.size < right.size;
|
return left.size < right.size;
|
||||||
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("string")) {
|
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("string")) {
|
||||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
||||||
return left.string > right.string;
|
return readString(left) > readString(right);
|
||||||
else
|
else
|
||||||
return left.string < right.string;
|
return readString(left) < readString(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -146,15 +164,12 @@ namespace hex {
|
|||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
ImGuiListClipper clipper;
|
ImGuiListClipper clipper;
|
||||||
clipper.Begin(this->m_foundStrings.size());
|
clipper.Begin(this->m_filterIndices.size());
|
||||||
|
|
||||||
while (clipper.Step()) {
|
while (clipper.Step()) {
|
||||||
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||||
auto &foundString = this->m_foundStrings[i];
|
auto &foundString = this->m_foundStrings[this->m_filterIndices[i]];
|
||||||
|
auto string = readString(foundString);
|
||||||
if (strlen(this->m_filter.data()) != 0 &&
|
|
||||||
foundString.string.find(this->m_filter.data()) == std::string::npos)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
@ -169,7 +184,8 @@ namespace hex {
|
|||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("0x%04lx", foundString.size);
|
ImGui::Text("0x%04lx", foundString.size);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("%s", foundString.string.c_str());
|
|
||||||
|
ImGui::Text("%s", string.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clipper.End();
|
clipper.End();
|
||||||
|
Loading…
Reference in New Issue
Block a user