From 3a840c4ceddd050371d744761b0194ffcbfe7773 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Tue, 14 Mar 2023 09:35:43 +0100 Subject: [PATCH] impr: Properly display custom encoding characters that are split between lines --- .../include/hex/helpers/encoding_file.hpp | 1 + lib/libimhex/source/helpers/encoding_file.cpp | 22 ++++++++++++-- plugins/builtin/include/ui/hex_editor.hpp | 2 ++ plugins/builtin/source/ui/hex_editor.cpp | 30 +++++++++++++++++-- 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/lib/libimhex/include/hex/helpers/encoding_file.hpp b/lib/libimhex/include/hex/helpers/encoding_file.hpp index 5e3e88a7c..a5edff4de 100644 --- a/lib/libimhex/include/hex/helpers/encoding_file.hpp +++ b/lib/libimhex/include/hex/helpers/encoding_file.hpp @@ -24,6 +24,7 @@ namespace hex { EncodingFile(Type type, const std::fs::path &path); [[nodiscard]] std::pair getEncodingFor(std::span buffer) const; + [[nodiscard]] size_t getEncodingLengthFor(std::span buffer) const; [[nodiscard]] size_t getLongestSequence() const { return this->m_longestSequence; } [[nodiscard]] bool valid() const { return this->m_valid; } diff --git a/lib/libimhex/source/helpers/encoding_file.cpp b/lib/libimhex/source/helpers/encoding_file.cpp index f585a7dfb..36b0338f0 100644 --- a/lib/libimhex/source/helpers/encoding_file.cpp +++ b/lib/libimhex/source/helpers/encoding_file.cpp @@ -26,7 +26,7 @@ namespace hex { if (size > buffer.size()) continue; - auto key = std::vector(buffer.begin(), buffer.begin() + size); + std::vector key(buffer.begin(), buffer.begin() + size); if (mapping.contains(key)) return { mapping.at(key), size }; } @@ -34,6 +34,20 @@ namespace hex { return { ".", 1 }; } + size_t EncodingFile::getEncodingLengthFor(std::span buffer) const { + for (auto riter = this->m_mapping.crbegin(); riter != this->m_mapping.crend(); ++riter) { + const auto &[size, mapping] = *riter; + + if (size > buffer.size()) continue; + + std::vector key(buffer.begin(), buffer.begin() + size); + if (mapping.contains(key)) + return size; + } + + return 1; + } + void EncodingFile::parseThingyFile(wolv::io::File &file) { for (const auto &line : splitString(file.readString(), "\n")) { @@ -60,9 +74,11 @@ namespace hex { if (!this->m_mapping.contains(fromBytes.size())) this->m_mapping.insert({ fromBytes.size(), {} }); - this->m_mapping[fromBytes.size()].insert({ fromBytes, to }); - this->m_longestSequence = std::max(this->m_longestSequence, fromBytes.size()); + auto keySize = fromBytes.size(); + this->m_mapping[keySize].insert({ std::move(fromBytes), to }); + + this->m_longestSequence = std::max(this->m_longestSequence, keySize); } } diff --git a/plugins/builtin/include/ui/hex_editor.hpp b/plugins/builtin/include/ui/hex_editor.hpp index 313610979..38d05c233 100644 --- a/plugins/builtin/include/ui/hex_editor.hpp +++ b/plugins/builtin/include/ui/hex_editor.hpp @@ -139,6 +139,7 @@ namespace hex::plugin::builtin::ui { void setCustomEncoding(EncodingFile encoding) { this->m_currCustomEncoding = std::move(encoding); + this->m_encodingLineStartAddresses.clear(); } void forceUpdateScrollPosition() { @@ -202,6 +203,7 @@ namespace hex::plugin::builtin::ui { u32 m_byteCellPadding = 0, m_characterCellPadding = 0; std::optional m_currCustomEncoding; + std::vector m_encodingLineStartAddresses; std::pair m_currValidRegion = { Region::Invalid(), false }; diff --git a/plugins/builtin/source/ui/hex_editor.cpp b/plugins/builtin/source/ui/hex_editor.cpp index 25dba1dcf..00d7d09d3 100644 --- a/plugins/builtin/source/ui/hex_editor.cpp +++ b/plugins/builtin/source/ui/hex_editor.cpp @@ -93,8 +93,10 @@ namespace hex::plugin::builtin::ui { { auto bytesPerRow = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.bytes_per_row"); - if (bytesPerRow.is_number()) + if (bytesPerRow.is_number()) { this->m_bytesPerRow = static_cast(bytesPerRow); + this->m_encodingLineStartAddresses.clear(); + } } { @@ -195,12 +197,34 @@ namespace hex::plugin::builtin::ui { ImColor color; }; - static CustomEncodingData queryCustomEncodingData(prv::Provider *provider, const EncodingFile &encodingFile, u64 address) { + static CustomEncodingData queryCustomEncodingData(prv::Provider *provider, const EncodingFile &encodingFile, std::vector &lineStartAddresses, u32 bytesPerRow, u64 address) { const auto longestSequence = encodingFile.getLongestSequence(); if (longestSequence == 0) return { ".", 1, 0xFFFF8000 }; + if (lineStartAddresses.empty() || lineStartAddresses.size() <= address / bytesPerRow) { + auto prevSize = lineStartAddresses.size(); + auto newSize = address / bytesPerRow + 1; + lineStartAddresses.reserve(newSize); + + std::vector buffer; + for (auto i = prevSize; i < newSize; i++) { + u32 offset = 0; + while (offset < bytesPerRow) { + size_t readSize = std::min(longestSequence, provider->getActualSize() - address); + buffer.resize(readSize); + provider->read(address, buffer.data(), readSize); + + offset += encodingFile.getEncodingLengthFor(buffer); + } + + lineStartAddresses.push_back(offset % bytesPerRow); + } + } + + address += lineStartAddresses[address / bytesPerRow]; + size_t size = std::min(longestSequence, provider->getActualSize() - address); std::vector buffer(size); @@ -560,7 +584,7 @@ namespace hex::plugin::builtin::ui { do { const u64 address = y * this->m_bytesPerRow + offset + this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress(); - auto result = queryCustomEncodingData(this->m_provider, *this->m_currCustomEncoding, address); + auto result = queryCustomEncodingData(this->m_provider, *this->m_currCustomEncoding, this->m_encodingLineStartAddresses, this->m_bytesPerRow, address); offset += std::max(1, result.advance); encodingData.emplace_back(address, result);