diff --git a/cmake/build_helpers.cmake b/cmake/build_helpers.cmake index 4d3c679f6..25d9abe64 100644 --- a/cmake/build_helpers.cmake +++ b/cmake/build_helpers.cmake @@ -442,14 +442,12 @@ macro(addBundledLibraries) add_subdirectory(${EXTERN_LIBS_FOLDER}/microtar EXCLUDE_FROM_ALL) set_target_properties(microtar PROPERTIES POSITION_INDEPENDENT_CODE ON) - add_subdirectory(${EXTERN_LIBS_FOLDER}/intervaltree EXCLUDE_FROM_ALL) - set_target_properties(intervaltree PROPERTIES POSITION_INDEPENDENT_CODE ON) - add_subdirectory(${EXTERN_LIBS_FOLDER}/libwolv EXCLUDE_FROM_ALL) set_property(TARGET libwolv-types PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET libwolv-utils PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET libwolv-io PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET libwolv-hash PROPERTY POSITION_INDEPENDENT_CODE ON) + set_property(TARGET libwolv-containers PROPERTY POSITION_INDEPENDENT_CODE ON) set(XDGPP_INCLUDE_DIRS "${EXTERN_LIBS_FOLDER}/xdgpp") diff --git a/dist/rpm/imhex.spec b/dist/rpm/imhex.spec index 4d3c67237..24bec25e4 100644 --- a/dist/rpm/imhex.spec +++ b/dist/rpm/imhex.spec @@ -4,7 +4,7 @@ Release: 0%{?dist} Summary: A hex editor for reverse engineers and programmers License: GPL-2.0-only AND Zlib AND MIT AND Apache-2.0 -# imhex is gplv2. capstone is custom. nativefiledialog is Zlib. intervaltree is MIT +# imhex is gplv2. capstone is custom. nativefiledialog is Zlib. # see license dir for full breakdown URL: https://imhex.werwolv.net/ # We need the archive with deps bundled @@ -36,9 +36,6 @@ Provides: bundled(imgui) Provides: bundled(libromfs) Provides: bundled(microtar) Provides: bundled(libpl) -# ImHex modified upstream intervaltree so we have to package it -# https://github.com/ekg/intervaltree -Provides: bundled(intervaltree) = 0.1 Provides: bundled(xdgpp) # ftbfs on these arches. armv7hl might compile when capstone 5.x @@ -115,7 +112,6 @@ cp -a lib/external/nativefiledialog/LICENSE %{buildroot}%{ cp -a lib/external/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE cp -a lib/external/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE cp -a lib/external/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE -cp -a lib/external/pattern_language/external/intervaltree/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/pattern-language-intervaltree-LICENSE cp -a lib/external/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE diff --git a/lib/external/intervaltree/CMakeLists.txt b/lib/external/intervaltree/CMakeLists.txt deleted file mode 100644 index 34c56b077..000000000 --- a/lib/external/intervaltree/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -cmake_minimum_required(VERSION 3.16) -project(intervaltree) - -set(CMAKE_CXX_STANDARD20) - -add_library(intervaltree INTERFACE) - -target_include_directories(intervaltree INTERFACE include) -target_compile_options(intervaltree INTERFACE "-DUSE_INTERVAL_TREE_NAMESPACE") \ No newline at end of file diff --git a/lib/external/intervaltree/LICENSE b/lib/external/intervaltree/LICENSE deleted file mode 100644 index 672c2534a..000000000 --- a/lib/external/intervaltree/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -The MIT License - -Copyright (c) 2019 Dana-Farber Cancer Institute - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/lib/external/intervaltree/README.md b/lib/external/intervaltree/README.md deleted file mode 100644 index 02cc06b21..000000000 --- a/lib/external/intervaltree/README.md +++ /dev/null @@ -1,133 +0,0 @@ -## Introduction - -cgranges is a small C library for genomic interval overlap queries: given a -genomic region *r* and a set of regions *R*, finding all regions in *R* that -overlaps *r*. Although this library is based on [interval tree][itree], a well -known data structure, the core algorithm of cgranges is distinct from all -existing implementations to the best of our knowledge. Specifically, the -interval tree in cgranges is implicitly encoded as a plain sorted array -(similar to [binary heap][bheap] but packed differently). Tree -traversal is achieved by jumping between array indices. This treatment makes -cgranges very efficient and compact in memory. The core algorithm can be -implemented in ~50 lines of C++ code, much shorter than others as well. Please -see the code comments in [cpp/IITree.h](cpp/IITree.h) for details. - -## Usage - -### Test with BED coverage - -For testing purposes, this repo implements the [bedtools coverage][bedcov] tool -with cgranges. The source code is located in the [test/](test) directory. You -can compile and run the test with: -```sh -cd test && make -./bedcov-cr test1.bed test2.bed -``` -The first BED file is loaded into RAM and indexed. The depth and the breadth of -coverage of each region in the second file is computed by query against the -index of the first file. - -The [test/](test) directory also contains a few other implementations based on -[IntervalTree.h][ekg-itree] in C++, [quicksect][quicksect] in Cython and -[ncls][ncls] in Cython. The table below shows timing and peak memory on two -test BEDs available in the release page. The first BED contains GenCode -annotations with ~1.2 million lines, mixing all types of features. The second -contains ~10 million direct-RNA mappings. Time1a/Mem1a indexes the GenCode BED -into memory. Time1b adds whole chromosome intervals to the GenCode BED when -indexing. Time2/Mem2 indexes the RNA-mapping BED into memory. Numbers are -averaged over 5 runs. - -|Algo. |Lang. |Cov|Program |Time1a|Time1b|Mem1a |Time2 |Mem2 | -|:-------|:-----|:-:|:---------------|-----:|-----:|-------:|-----:|-------:| -|IAITree |C |Y |cgranges |9.0s |13.9s |19.1MB |4.6s |138.4MB | -|IAITree |C++ |Y |cpp/iitree.h |11.1s |24.5s |22.4MB |5.8s |160.4MB | -|CITree |C++ |Y |IntervalTree.h |17.4s |17.4s |27.2MB |10.5s |179.5MB | -|IAITree |C |N |cgranges |7.6s |13.0s |19.1MB |4.1s |138.4MB | -|AIList |C |N |3rd-party/AIList|7.9s |8.1s |14.4MB |6.5s |104.8MB | -|NCList |C |N |3rd-party/NCList|13.0s |13.4s |21.4MB |10.6s |183.0MB | -|AITree |C |N |3rd-party/AITree|16.8s |18.4s |73.4MB |27.3s |546.4MB | -|IAITree |Cython|N |cgranges |56.6s |63.9s |23.4MB |43.9s |143.1MB | -|binning |C++ |Y |bedtools |201.9s|280.4s|478.5MB |149.1s|3438.1MB| - -Here, IAITree = implicit augmented interval tree, used by cgranges; -CITree = centered interval tree, used by [Erik Garrison's -IntervalTree][itree]; AIList = augmented interval list, by [Feng et -al][ailist]; NCList = nested containment list, taken from [ncls][ncls] by Feng -et al; AITree = augmented interval tree, from [kerneltree][kerneltree]. -"Cov" indicates whether the program calculates breadth of coverage. -Comments: - -* AIList keeps start and end only. IAITree and CITree addtionally store a - 4-byte "ID" field per interval to reference the source of interval. This is - partly why AIList uses the least memory. - -* IAITree is more sensitive to the worse case: the presence of an interval - spanning the whole chromosome. - -* IAITree uses an efficient radix sort. CITree uses std::sort from STL, which - is ok. AIList and NCList use qsort from libc, which is slow. Faster sorting - leads to faster indexing. - -* IAITree in C++ uses identical core algorithm to the C version, but limited by - its APIs, it wastes time on memory locality and management. CITree has a - similar issue. - -* Computing coverage is better done when the returned list of intervals are - start sorted. IAITree returns sorted list. CITree doesn't. Not sure about - others. Computing coverage takes a couple of seconds. Sorting will be slower. - -* Printing intervals also takes a noticeable fraction of time. Custom printf - equivalent would be faster. - -* IAITree+Cython is a wrapper around the C version of cgranges. Cython adds - significant overhead. - -* Bedtools is designed for a variety of applications in addition to computing - coverage. It may keep other information in its internal data structure. This - micro-benchmark may be unfair to bedtools. - -* In general, the performance is affected a lot by subtle implementation - details. CITree, IAITree, NCList and AIList are all broadly comparable in - performance. AITree is not recommended when indexed intervals are immutable. - -### Use cgranges as a C library - -```c -cgranges_t *cr = cr_init(); // initialize a cgranges_t object -cr_add(cr, "chr1", 20, 30, 0); // add a genomic interval -cr_add(cr, "chr2", 10, 30, 1); -cr_add(cr, "chr1", 10, 25, 2); -cr_index(cr); // index - -int64_t i, n, *b = 0, max_b = 0; -n = cr_overlap(cr, "chr1", 15, 22, &b, &max_b); // overlap query; output array b[] can be reused -for (i = 0; i < n; ++i) // traverse overlapping intervals - printf("%d\t%d\t%d\n", cr_start(cr, b[i]), cr_end(cr, b[i]), cr_label(cr, b[i])); -free(b); // b[] is allocated by malloc() inside cr_overlap(), so needs to be freed with free() - -cr_destroy(cr); -``` - -### Use IITree as a C++ library - -```cpp -IITree tree; -tree.add(12, 34, 0); // add an interval -tree.add(0, 23, 1); -tree.add(34, 56, 2); -tree.index(); // index -std::vector a; -tree.overlap(22, 25, a); // retrieve overlaps -for (size_t i = 0; i < a.size(); ++i) - printf("%d\t%d\t%d\n", tree.start(a[i]), tree.end(a[i]), tree.data(a[i])); -``` - -[bedcov]: https://bedtools.readthedocs.io/en/latest/content/tools/coverage.html -[ekg-itree]: https://github.com/ekg/intervaltree -[quicksect]: https://github.com/brentp/quicksect -[ncls]: https://github.com/hunt-genes/ncls -[citree]: https://en.wikipedia.org/wiki/Interval_tree#Centered_interval_tree -[itree]: https://en.wikipedia.org/wiki/Interval_tree -[bheap]: https://en.wikipedia.org/wiki/Binary_heap -[ailist]: https://www.biorxiv.org/content/10.1101/593657v1 -[kerneltree]: https://github.com/biocore-ntnu/kerneltree \ No newline at end of file diff --git a/lib/external/intervaltree/include/IITree.h b/lib/external/intervaltree/include/IITree.h deleted file mode 100644 index 1c5883d9f..000000000 --- a/lib/external/intervaltree/include/IITree.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -template // "S" is a scalar type; "T" is the type of data associated with each interval -class IITree { - struct StackCell { - size_t x; // node - int w; // w: 0 if left child hasn't been processed - StackCell() {}; - StackCell(size_t x_, int w_) : x(x_), w(w_) {}; - }; - struct Interval { - S st, en, max; - T data; - Interval() = default; - Interval(const S &s, const S &e, const T &d) : st(s), en(e), max(e), data(d) { } - }; - struct IntervalLess { - bool operator()(const Interval &intervalA, const Interval &intervalB) const { return intervalA.st < intervalB.st; } - }; - std::vector a; - size_t layout_recur(Interval *b, size_t i = 0, size_t k = 0) { // see https://algorithmica.org/en/eytzinger - if (k < a.size()) { - i = layout_recur(b, i, (k<<1) + 1); - b[k] = a[i++]; - i = layout_recur(b, i, (k<<1) + 2); - } - return i; - } - void index_BFS(Interval *interval, size_t n) { // set Interval::max - int t = 0; - StackCell stack[64]; - stack[t++] = StackCell(0, 0); - while (t) { - StackCell z = stack[--t]; - size_t k = z.x, l = k<<1|1, r = l + 1; - if (z.w == 2) { // Interval::max for both children are computed - interval[k].max = interval[k].en; - if (l < n && interval[k].max < interval[l].max) interval[k].max = interval[l].max; - if (r < n && interval[k].max < interval[r].max) interval[k].max = interval[r].max; - } else { // go down into the two children - stack[t++] = StackCell(k, z.w + 1); - if (l + z.w < n) - stack[t++] = StackCell(l + z.w, 0); - } - } - } -public: - void add(const S &s, const S &e, const T &d) { a.push_back(Interval(s, e, d)); } - void index() { - std::sort(a.begin(), a.end(), IntervalLess()); - std::vector b(a.size()); - layout_recur(b.data()); - a.clear(); - std::copy(b.begin(), b.end(), std::back_inserter(a)); - index_BFS(a.data(), a.size()); - } - bool overlap(const S &st, const S &en, std::vector &out) const { - int t = 0; - std::array stack; - out.clear(); - if (a.empty()) return false; - stack[t++] = StackCell(0, 0); // push the root; this is a top down traversal - while (t) { // the following guarantees that numbers in out[] are always sorted - StackCell z = stack[--t]; - size_t l = (z.x<<1) + 1, r = l + 1; - if (l >= a.size()) { // a leaf node - if (st < a[z.x].en && a[z.x].st <= en) out.push_back(z.x); - } else if (z.w == 0) { // if left child not processed - stack[t++] = StackCell(z.x, 1); // re-add node z.x, but mark the left child having been processed - if (l < a.size() && a[l].max > st) - stack[t++] = StackCell(l, 0); - } else if (a[z.x].st <= en) { // need to push the right child - if (st < a[z.x].en) out.push_back(z.x); // test if z.x overlaps the query; if yes, append to out[] - if (r < a.size()) stack[t++] = StackCell(r, 0); - } - } - return out.size() > 0? true : false; - } - size_t size(void) const { return a.size(); } - const S &start(size_t i) const { return a[i].st; } - const S &end(size_t i) const { return a[i].en; } - const T &data(size_t i) const { return a[i].data; } -}; \ No newline at end of file diff --git a/lib/external/libwolv b/lib/external/libwolv index 2ccf828f7..30c8014d2 160000 --- a/lib/external/libwolv +++ b/lib/external/libwolv @@ -1 +1 @@ -Subproject commit 2ccf828f79a30c8524ad79bbaea44f33e2d43227 +Subproject commit 30c8014d22cebcbb791305b27ff054de4d60e211 diff --git a/lib/external/pattern_language b/lib/external/pattern_language index 4af40da17..1ace51d33 160000 --- a/lib/external/pattern_language +++ b/lib/external/pattern_language @@ -1 +1 @@ -Subproject commit 4af40da17ac91b43d4f5832dfc47dec7301d2145 +Subproject commit 1ace51d331e6e2dca64492a73c20a2a9331b6c9b diff --git a/lib/libimhex/CMakeLists.txt b/lib/libimhex/CMakeLists.txt index 349933d12..9932a189c 100644 --- a/lib/libimhex/CMakeLists.txt +++ b/lib/libimhex/CMakeLists.txt @@ -69,4 +69,4 @@ elseif (APPLE) endif () target_link_libraries(libimhex PRIVATE ${FMT_LIBRARIES}) -target_link_libraries(libimhex PUBLIC dl imgui ${NFD_LIBRARIES} magic ${CAPSTONE_LIBRARIES} LLVMDemangle microtar ${NLOHMANN_JSON_LIBRARIES} ${YARA_LIBRARIES} ${LIBCURL_LIBRARIES} ${MBEDTLS_LIBRARIES} ${LIBBACKTRACE_LIBRARIES} libpl intervaltree ${MINIAUDIO_LIBRARIES} libwolv-utils libwolv-io libwolv-hash libwolv-net) \ No newline at end of file +target_link_libraries(libimhex PUBLIC dl imgui ${NFD_LIBRARIES} magic ${CAPSTONE_LIBRARIES} LLVMDemangle microtar ${NLOHMANN_JSON_LIBRARIES} ${YARA_LIBRARIES} ${LIBCURL_LIBRARIES} ${MBEDTLS_LIBRARIES} ${LIBBACKTRACE_LIBRARIES} libpl ${MINIAUDIO_LIBRARIES} libwolv-utils libwolv-io libwolv-hash libwolv-net libwolv-containers) \ No newline at end of file diff --git a/plugins/builtin/include/content/providers/file_provider.hpp b/plugins/builtin/include/content/providers/file_provider.hpp index 75e07ae36..af85fd6e1 100644 --- a/plugins/builtin/include/content/providers/file_provider.hpp +++ b/plugins/builtin/include/content/providers/file_provider.hpp @@ -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 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 m_files; + std::atomic m_mapCounter = 0; std::optional m_fileStats; bool m_readable = false, m_writable = false; - - std::mutex m_fileAccessMutex, m_writeMutex; }; } \ No newline at end of file diff --git a/plugins/builtin/include/content/providers/intel_hex_provider.hpp b/plugins/builtin/include/content/providers/intel_hex_provider.hpp index 720e9f843..aa92b0127 100644 --- a/plugins/builtin/include/content/providers/intel_hex_provider.hpp +++ b/plugins/builtin/include/content/providers/intel_hex_provider.hpp @@ -2,7 +2,7 @@ #include -#include +#include namespace hex::plugin::builtin { @@ -44,7 +44,7 @@ namespace hex::plugin::builtin { protected: bool m_dataValid = false; size_t m_dataSize = 0x00; - IITree> m_data; + wolv::container::IntervalTree, u64, 0> m_data; std::fs::path m_sourceFilePath; }; diff --git a/plugins/builtin/include/content/views/view_diff.hpp b/plugins/builtin/include/content/views/view_diff.hpp index 65a3c9dbb..1b5db6ef6 100644 --- a/plugins/builtin/include/content/views/view_diff.hpp +++ b/plugins/builtin/include/content/views/view_diff.hpp @@ -12,8 +12,6 @@ #include "ui/hex_editor.hpp" -#include - namespace hex::plugin::builtin { class ViewDiff : public View { diff --git a/plugins/builtin/include/content/views/view_find.hpp b/plugins/builtin/include/content/views/view_find.hpp index 5cc841c36..23a316a32 100644 --- a/plugins/builtin/include/content/views/view_find.hpp +++ b/plugins/builtin/include/content/views/view_find.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace hex::plugin::builtin { @@ -94,7 +94,7 @@ namespace hex::plugin::builtin { } m_searchSettings, m_decodeSettings; - using OccurrenceTree = IITree; + using OccurrenceTree = wolv::container::IntervalTree; PerProvider> m_foundOccurrences, m_sortedOccurrences; PerProvider m_occurrenceTree; diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index e5998e3cf..f58ef39a6 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -86,9 +86,6 @@ namespace hex::plugin::builtin { this->close(); } ); - - if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape))) - this->close(); } [[nodiscard]] ImGuiWindowFlags getFlags() const override { diff --git a/plugins/builtin/source/content/providers/file_provider.cpp b/plugins/builtin/source/content/providers/file_provider.cpp index a8168d5c6..ef37e61e7 100644 --- a/plugins/builtin/source/content/providers/file_provider.cpp +++ b/plugins/builtin/source/content/providers/file_provider.cpp @@ -2,7 +2,6 @@ #include -#include #include #include @@ -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(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(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); diff --git a/plugins/builtin/source/content/providers/intel_hex_provider.cpp b/plugins/builtin/source/content/providers/intel_hex_provider.cpp index 2643e0513..dbd8f9ba6 100644 --- a/plugins/builtin/source/content/providers/intel_hex_provider.cpp +++ b/plugins/builtin/source/content/providers/intel_hex_provider.cpp @@ -161,37 +161,25 @@ namespace hex::plugin::builtin { void IntelHexProvider::setBaseAddress(u64 address) { auto oldBase = this->getBaseAddress(); - std::vector indices; - this->m_data.overlap(oldBase, oldBase + this->getActualSize(), indices); + auto regions = this->m_data.overlapping({ oldBase, oldBase + this->getActualSize() }); - IITree> 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 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(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 IntelHexProvider::getRegionValidity(u64 address) const { - std::vector 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) { diff --git a/plugins/builtin/source/content/providers/motorola_srec_provider.cpp b/plugins/builtin/source/content/providers/motorola_srec_provider.cpp index 1f3b0eae4..3b8ff5f7f 100644 --- a/plugins/builtin/source/content/providers/motorola_srec_provider.cpp +++ b/plugins/builtin/source/content/providers/motorola_srec_provider.cpp @@ -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; diff --git a/plugins/builtin/source/content/views/view_find.cpp b/plugins/builtin/source/content/views/view_find.cpp index 3b5c9a45d..8a74daabb 100644 --- a/plugins/builtin/source/content/views/view_find.cpp +++ b/plugins/builtin/source/content/views/view_find.cpp @@ -22,8 +22,7 @@ namespace hex::plugin::builtin { if (this->m_searchTask.isRunning()) return { }; - std::vector 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 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); }); }