b751f98e91
* ui/ux: Initial recreation of the hex editor view * ui/ux: Added back support for editing cells * ux: Make scrolling and selecting bytes feel nice again * ui/ux: Improved byte selecting, added footer * sys: Make math evaluator more generic to support integer only calculations * patterns: Moved value formatting into pattern language * ui/ux: Added Goto and Search popups, improved selection * ui: Added better tooltips for bookmarks and patterns * sys: Use worse hex search algorithm on macOS Sadly it still doesn't support `std::boyer_moore_horsepool_searcher` * ui: Added back missing events, menu items and shortcuts * fix: Bookmark highlighting being rendered off by one * fix: Various macOS build errors * fix: size_t is not u64 on macos * fix: std::fmod and std::pow not working with integer types on macos * fix: Missing semicolons * sys: Added proper integer pow function * ui: Added back support for custom encodings * fix: Editor not jumping to selection when selection gets changed * ui: Turn Hexii setting into a data visualizer * sys: Added back remaining shortcuts * sys: Remove old hex editor files * sys: Moved more legacy things away from the hex editor view, updated localization * fix: Hex editor scrolling behaving weirdly and inconsistently * sys: Cleaned up Hex editor code * sys: Added selection color setting, localized all new settings * fix: Search feature not working correctly * ui: Replace custom ImGui::Disabled function with native ImGui ones * ui: Fix bookmark tooltip rendering issues * fix: Another size_t not being 64 bit issue on MacOS
223 lines
6.8 KiB
C++
223 lines
6.8 KiB
C++
#pragma once
|
|
|
|
#include <span>
|
|
#include <vector>
|
|
|
|
#include <hex/providers/provider.hpp>
|
|
|
|
namespace hex::prv {
|
|
|
|
class BufferedReader {
|
|
public:
|
|
explicit BufferedReader(Provider *provider, size_t bufferSize = 0xFF'FFFF) : m_provider(provider), m_maxBufferSize(bufferSize), m_buffer(bufferSize) { }
|
|
|
|
void seek(u64 address) {
|
|
this->m_baseAddress = address;
|
|
}
|
|
|
|
[[nodiscard]] std::vector<u8> read(u64 address, size_t size) {
|
|
if (size > this->m_buffer.size()) {
|
|
std::vector<u8> result;
|
|
result.resize(size);
|
|
|
|
this->m_provider->read(address, result.data(), result.size());
|
|
|
|
return result;
|
|
}
|
|
|
|
this->updateBuffer(address, size);
|
|
|
|
auto result = &this->m_buffer[address - this->m_baseAddress];
|
|
|
|
return { result, result + std::min(size, this->m_buffer.size()) };
|
|
}
|
|
|
|
[[nodiscard]] std::vector<u8> readReverse(u64 address, size_t size) {
|
|
if (size > this->m_buffer.size()) {
|
|
std::vector<u8> result;
|
|
result.resize(size);
|
|
|
|
this->m_provider->read(address, result.data(), result.size());
|
|
|
|
return result;
|
|
}
|
|
|
|
this->updateBuffer(address - std::min<u64>(address, this->m_buffer.size()), size);
|
|
|
|
auto result = &this->m_buffer[address - this->m_baseAddress];
|
|
|
|
return { result, result + std::min(size, this->m_buffer.size()) };
|
|
}
|
|
|
|
class Iterator {
|
|
public:
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = u8;
|
|
using pointer = const value_type*;
|
|
using reference = const value_type&;
|
|
|
|
Iterator(BufferedReader *reader, u64 address) : m_reader(reader), m_address(address) {}
|
|
|
|
Iterator& operator++() {
|
|
this->m_address++;
|
|
|
|
return *this;
|
|
}
|
|
|
|
Iterator operator++(int) {
|
|
auto copy = *this;
|
|
this->m_address++;
|
|
|
|
return copy;
|
|
}
|
|
|
|
Iterator& operator+=(i64 offset) {
|
|
this->m_address += offset;
|
|
|
|
return *this;
|
|
}
|
|
|
|
Iterator& operator-=(i64 offset) {
|
|
this->m_address -= offset;
|
|
|
|
return *this;
|
|
}
|
|
|
|
value_type operator*() const {
|
|
return (*this)[0];
|
|
}
|
|
|
|
[[nodiscard]] u64 getAddress() const {
|
|
return this->m_address;
|
|
}
|
|
|
|
difference_type operator-(const Iterator &other) const {
|
|
return this->m_address - other.m_address;
|
|
}
|
|
|
|
Iterator operator+(i64 offset) const {
|
|
return { this->m_reader, this->m_address + offset };
|
|
}
|
|
|
|
value_type operator[](i64 offset) const {
|
|
auto result = this->m_reader->read(this->m_address + offset, 1);
|
|
if (result.empty())
|
|
return 0x00;
|
|
|
|
return result[0];
|
|
}
|
|
|
|
friend bool operator== (const Iterator& left, const Iterator& right) { return left.m_address == right.m_address; };
|
|
friend bool operator!= (const Iterator& left, const Iterator& right) { return left.m_address != right.m_address; };
|
|
private:
|
|
BufferedReader *m_reader;
|
|
u64 m_address;
|
|
};
|
|
|
|
class ReverseIterator {
|
|
public:
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = u8;
|
|
using pointer = const value_type*;
|
|
using reference = const value_type&;
|
|
|
|
ReverseIterator(BufferedReader *reader, u64 address) : m_reader(reader), m_address(address) {}
|
|
|
|
ReverseIterator& operator++() {
|
|
this->m_address--;
|
|
|
|
return *this;
|
|
}
|
|
|
|
ReverseIterator operator++(int) {
|
|
auto copy = *this;
|
|
this->m_address--;
|
|
|
|
return copy;
|
|
}
|
|
|
|
ReverseIterator& operator+=(i64 offset) {
|
|
this->m_address -= offset;
|
|
|
|
return *this;
|
|
}
|
|
|
|
ReverseIterator& operator-=(i64 offset) {
|
|
this->m_address += offset;
|
|
|
|
return *this;
|
|
}
|
|
|
|
value_type operator*() const {
|
|
return (*this)[0];
|
|
}
|
|
|
|
[[nodiscard]] u64 getAddress() const {
|
|
return this->m_address;
|
|
}
|
|
|
|
difference_type operator-(const ReverseIterator &other) const {
|
|
return other.m_address - this->m_address;
|
|
}
|
|
|
|
ReverseIterator operator+(i64 offset) const {
|
|
return { this->m_reader, this->m_address - offset };
|
|
}
|
|
|
|
value_type operator[](i64 offset) const {
|
|
auto result = this->m_reader->readReverse(this->m_address + offset, 1);
|
|
if (result.empty())
|
|
return 0x00;
|
|
|
|
return result[0];
|
|
}
|
|
|
|
friend bool operator== (const ReverseIterator& left, const ReverseIterator& right) { return left.m_address == right.m_address; };
|
|
friend bool operator!= (const ReverseIterator& left, const ReverseIterator& right) { return left.m_address != right.m_address; };
|
|
|
|
private:
|
|
BufferedReader *m_reader;
|
|
u64 m_address;
|
|
};
|
|
|
|
Iterator begin() {
|
|
return { this, this->m_baseAddress };
|
|
}
|
|
|
|
Iterator end() {
|
|
return { this, this->m_baseAddress + this->m_provider->getActualSize() };
|
|
}
|
|
|
|
ReverseIterator rbegin() {
|
|
return { this, this->m_baseAddress };
|
|
}
|
|
|
|
ReverseIterator rend() {
|
|
return { this, std::numeric_limits<u64>::max() };
|
|
}
|
|
|
|
private:
|
|
void updateBuffer(u64 address, size_t size) {
|
|
if (!this->m_bufferValid || address < this->m_baseAddress || address + size > (this->m_baseAddress + this->m_buffer.size())) {
|
|
const auto remainingBytes = this->m_provider->getActualSize() - address;
|
|
if (remainingBytes < this->m_maxBufferSize)
|
|
this->m_buffer.resize(remainingBytes);
|
|
|
|
this->m_provider->read(address, this->m_buffer.data(), this->m_buffer.size());
|
|
this->m_baseAddress = address;
|
|
this->m_bufferValid = true;
|
|
}
|
|
}
|
|
|
|
private:
|
|
Provider *m_provider;
|
|
|
|
size_t m_maxBufferSize;
|
|
bool m_bufferValid = false;
|
|
u64 m_baseAddress = 0x00;
|
|
std::vector<u8> m_buffer;
|
|
};
|
|
|
|
} |