build: Replace old interval tree in favour of custom libwolv one

This commit is contained in:
WerWolv
2023-05-11 09:27:23 +02:00
parent 1d2b8ac1f3
commit 50c3cf8272
18 changed files with 57 additions and 366 deletions

View File

@@ -29,11 +29,7 @@ namespace hex::plugin::builtin {
void readRaw(u64 offset, void *buffer, size_t size) override;
void writeRaw(u64 offset, const void *buffer, size_t size) override;
/**
* @brief closes the file streams used to read the file.
* Need to be called on file write, see https://github.com/WerWolv/ImHex/issues/988
*/
void invalidateFiles();
[[nodiscard]] size_t getActualSize() const override;
void save() override;
@@ -60,20 +56,16 @@ namespace hex::plugin::builtin {
[[nodiscard]] std::pair<Region, bool> getRegionValidity(u64 address) const override;
private:
wolv::io::File& getFile();
protected:
std::fs::path m_path;
wolv::io::File m_file;
size_t m_fileSize = 0;
wolv::io::File m_sizeFile;
std::map<std::thread::id, wolv::io::File> m_files;
std::atomic<u32> m_mapCounter = 0;
std::optional<struct stat> m_fileStats;
bool m_readable = false, m_writable = false;
std::mutex m_fileAccessMutex, m_writeMutex;
};
}

View File

@@ -2,7 +2,7 @@
#include <hex/providers/provider.hpp>
#include <IITree.h>
#include <wolv/container/interval_tree.hpp>
namespace hex::plugin::builtin {
@@ -44,7 +44,7 @@ namespace hex::plugin::builtin {
protected:
bool m_dataValid = false;
size_t m_dataSize = 0x00;
IITree<u64, std::vector<u8>> m_data;
wolv::container::IntervalTree<std::vector<u8>, u64, 0> m_data;
std::fs::path m_sourceFilePath;
};

View File

@@ -12,8 +12,6 @@
#include "ui/hex_editor.hpp"
#include <IITree.h>
namespace hex::plugin::builtin {
class ViewDiff : public View {

View File

@@ -9,7 +9,7 @@
#include <atomic>
#include <vector>
#include <IITree.h>
#include <wolv/container/interval_tree.hpp>
namespace hex::plugin::builtin {
@@ -94,7 +94,7 @@ namespace hex::plugin::builtin {
} m_searchSettings, m_decodeSettings;
using OccurrenceTree = IITree<u64, Occurrence>;
using OccurrenceTree = wolv::container::IntervalTree<Occurrence, u64, 0>;
PerProvider<std::vector<Occurrence>> m_foundOccurrences, m_sortedOccurrences;
PerProvider<OccurrenceTree> m_occurrenceTree;

View File

@@ -86,9 +86,6 @@ namespace hex::plugin::builtin {
this->close();
}
);
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
this->close();
}
[[nodiscard]] ImGuiWindowFlags getFlags() const override {

View File

@@ -2,7 +2,6 @@
#include <cstring>
#include <hex/api/imhex_api.hpp>
#include <hex/api/localization.hpp>
#include <hex/api/project_file_manager.hpp>
@@ -60,24 +59,28 @@ namespace hex::plugin::builtin {
if (offset > (this->getActualSize() - size) || buffer == nullptr || size == 0)
return;
auto &file = this->getFile();
file.seek(offset);
file.readBuffer(reinterpret_cast<u8*>(buffer), size);
/*auto currSize = std::fs::file_size(this->m_path);
if (this->m_fileSize != currSize) [[unlikely]] {
this->m_fileSize = currSize;
this->m_file.unmap();
this->m_file.map();
}*/
std::memcpy(buffer, this->m_file.getMapping() + offset, size);
}
void FileProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
if ((offset + size) > this->getActualSize() || buffer == nullptr || size == 0)
return;
std::scoped_lock lock(this->m_writeMutex);
wolv::io::File writeFile(this->m_path, wolv::io::File::Mode::Write);
if (!writeFile.isValid())
return;
writeFile.seek(offset);
writeFile.writeBuffer(reinterpret_cast<const u8*>(buffer), size);
auto currSize = std::fs::file_size(this->m_path);
if (this->m_fileSize != currSize) [[unlikely]] {
this->m_fileSize = currSize;
this->m_file.unmap();
this->m_file.map();
}
this->invalidateFiles();
std::memcpy(this->m_file.getMapping() + offset, buffer, size);
}
void FileProvider::save() {
@@ -125,13 +128,6 @@ namespace hex::plugin::builtin {
Provider::insert(offset, size);
}
void FileProvider::invalidateFiles() {
for(auto & [threadId, file] : this->m_files){
file.close();
}
this->m_files.clear();
}
void FileProvider::remove(u64 offset, size_t size) {
auto oldSize = this->getActualSize();
this->resize(oldSize + size);
@@ -156,7 +152,7 @@ namespace hex::plugin::builtin {
}
size_t FileProvider::getActualSize() const {
return this->m_sizeFile.getSize();
return this->m_fileSize;
}
std::string FileProvider::getName() const {
@@ -220,9 +216,10 @@ namespace hex::plugin::builtin {
}
this->m_fileStats = file.getFileInfo();
this->m_sizeFile = file.clone();
this->m_file = std::move(file);
this->m_files.emplace(std::this_thread::get_id(), std::move(file));
this->m_file.map();
this->m_fileSize = this->m_file.getSize();
return true;
}
@@ -231,18 +228,6 @@ namespace hex::plugin::builtin {
}
wolv::io::File& FileProvider::getFile() {
auto threadId = std::this_thread::get_id();
if (!this->m_files.contains(threadId)) {
std::scoped_lock lock(this->m_fileAccessMutex);
if (!this->m_files.contains(threadId))
this->m_files.emplace(threadId, this->m_sizeFile.clone());
}
return this->m_files[threadId];
}
void FileProvider::loadSettings(const nlohmann::json &settings) {
Provider::loadSettings(settings);

View File

@@ -161,37 +161,25 @@ namespace hex::plugin::builtin {
void IntelHexProvider::setBaseAddress(u64 address) {
auto oldBase = this->getBaseAddress();
std::vector<size_t> indices;
this->m_data.overlap(oldBase, oldBase + this->getActualSize(), indices);
auto regions = this->m_data.overlapping({ oldBase, oldBase + this->getActualSize() });
IITree<u64, std::vector<u8>> intervals;
for (auto &index : indices) {
intervals.add(
(this->m_data.start(index) - oldBase) + address,
(this->m_data.end(index) - oldBase) + address,
this->m_data.data(index)
);
decltype(this->m_data) newIntervals;
for (auto &[interval, data] : regions) {
newIntervals.insert({ interval.start - oldBase + address, interval.end - oldBase + address }, *data);
}
this->m_data = std::move(intervals);
this->m_data.index();
this->m_data = newIntervals;
Provider::setBaseAddress(address);
}
void IntelHexProvider::readRaw(u64 offset, void *buffer, size_t size) {
std::vector<size_t> indices;
this->m_data.overlap(offset, (offset + size) - 1, indices);
auto intervals = this->m_data.overlapping({ offset, (offset + size) - 1 });
std::memset(buffer, 0x00, size);
auto bytes = reinterpret_cast<u8*>(buffer);
for (const auto &index : indices) {
auto start = this->m_data.start(index);
auto end = this->m_data.end(index);
auto data = this->m_data.data(index);
for (u32 i = std::max(start, offset); i <= end && (i - offset) < size; i++) {
bytes[i - offset] = data[i - start];
for (const auto &[interval, data] : intervals) {
for (u32 i = std::max(interval.start, offset); i <= interval.end && (i - offset) < size; i++) {
bytes[i - offset] = (*data)[i - interval.start];
}
}
}
@@ -216,12 +204,11 @@ namespace hex::plugin::builtin {
u64 maxAddress = 0x00;
for (auto &[address, bytes] : data) {
auto endAddress = (address + bytes.size()) - 1;
this->m_data.add(address, endAddress, std::move(bytes));
this->m_data.emplace({ address, endAddress }, std::move(bytes));
if (endAddress > maxAddress)
maxAddress = endAddress;
}
this->m_data.index();
this->m_dataSize = maxAddress + 1;
this->m_dataValid = true;
@@ -265,22 +252,18 @@ namespace hex::plugin::builtin {
}
std::pair<Region, bool> IntelHexProvider::getRegionValidity(u64 address) const {
std::vector<size_t> indices;
this->m_data.overlap(address, address, indices);
if (indices.empty()) {
auto intervals = this->m_data.overlapping({ address, address });
if (intervals.empty()) {
return Provider::getRegionValidity(address);
}
auto closestIndex = indices.front();
for (const auto &index : indices) {
if (this->m_data.start(index) < this->m_data.start(closestIndex))
closestIndex = index;
decltype(this->m_data)::Interval closestInterval = { 0, 0 };
for (const auto &[interval, data] : intervals) {
if (interval.start < closestInterval.end)
closestInterval = interval;
}
return { Region { closestInterval.start, (closestInterval.end - closestInterval.start) + 1}, true };
auto start = this->m_data.start(closestIndex);
auto end = this->m_data.end(closestIndex);
return { Region { start, (end - start) + 1 }, true };
}
void IntelHexProvider::loadSettings(const nlohmann::json &settings) {

View File

@@ -182,12 +182,11 @@ namespace hex::plugin::builtin {
u64 maxAddress = 0x00;
for (auto &[address, bytes] : data) {
auto endAddress = (address + bytes.size()) - 1;
this->m_data.add(address, endAddress, std::move(bytes));
this->m_data.emplace({ address, endAddress }, std::move(bytes));
if (endAddress > maxAddress)
maxAddress = endAddress;
}
this->m_data.index();
this->m_dataSize = maxAddress + 1;
this->m_dataValid = true;

View File

@@ -22,8 +22,7 @@ namespace hex::plugin::builtin {
if (this->m_searchTask.isRunning())
return { };
std::vector<size_t> occurrences;
if (this->m_occurrenceTree->overlap(address, address, occurrences))
if (!this->m_occurrenceTree->overlapping({ address, address }).empty())
return HighlightColor();
else
return std::nullopt;
@@ -35,8 +34,8 @@ namespace hex::plugin::builtin {
if (this->m_searchTask.isRunning())
return;
std::vector<size_t> occurrences;
if (!this->m_occurrenceTree->overlap(address, address, occurrences))
auto occurrences = this->m_occurrenceTree->overlapping({ address, address });
if (occurrences.empty())
return;
ImGui::BeginTooltip();
@@ -48,10 +47,8 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn();
{
auto start = this->m_occurrenceTree->start(occurrence);
auto end = this->m_occurrenceTree->end(occurrence) - 1;
const auto &bytes = this->m_occurrenceTree->data(occurrence);
const auto value = this->decodeValue(ImHexApi::Provider::get(), bytes, 256);
auto region = occurrence.value.region;
const auto value = this->decodeValue(ImHexApi::Provider::get(), occurrence.value, 256);
ImGui::ColorButton("##color", ImColor(HighlightColor()));
ImGui::SameLine(0, 10);
@@ -65,7 +62,7 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn();
ImGui::TextFormatted("{}: ", "hex.builtin.common.region"_lang);
ImGui::TableNextColumn();
ImGui::TextFormatted("[ 0x{:08X} - 0x{:08X} ]", start, end);
ImGui::TextFormatted("[ 0x{:08X} - 0x{:08X} ]", region.getStartAddress(), region.getEndAddress());
auto demangledValue = llvm::demangle(value);
@@ -513,8 +510,7 @@ namespace hex::plugin::builtin {
this->m_sortedOccurrences.get(provider) = this->m_foundOccurrences.get(provider);
for (const auto &occurrence : this->m_foundOccurrences.get(provider))
this->m_occurrenceTree->add(occurrence.region.getStartAddress(), occurrence.region.getEndAddress() + 1, occurrence);
this->m_occurrenceTree->index();
this->m_occurrenceTree->insert({ occurrence.region.getStartAddress(), occurrence.region.getEndAddress() }, occurrence);
});
}