1
0
mirror of synced 2024-12-23 21:14:51 +01:00
ImHex/plugins/builtin/include/content/views/view_find.hpp
SparkyTD 9b594d81bd
feat: Added CSV, TSV and JSON as export options for Find results (#1673)
### Problem description
The default result export functionality of the Find tool is limited to
only exporting data in a nonstandard text format. This PR adds support
for exporting the results in CSV, TSV or JSON format. The PR also
removes the old format.

### Implementation description
I added the classes `ExportFormatter`, `ExportFormatterCsv`,
`ExportFormatterTsv` and `ExportFormatterJson`, with similar
implementations to the pattern data exporters.

~~I also moved the `ViewFind::Occurrence` class into
`hex/helpers/types.hh`, so the exporters can access it.~~

### Screenshots

![image](https://github.com/WerWolv/ImHex/assets/45818400/c7a1016b-6494-416d-a963-86484952837c)

### Additional things
Another small change I made is moving the "{} entries found" line on the
same line as the Search and Reset buttons. I think it looks cleaner this
way, but if anyone disagrees, I can revert it.

---------

Co-authored-by: WerWolv <werwolv98@gmail.com>
2024-06-18 20:57:55 +00:00

125 lines
4.3 KiB
C++

#pragma once
#include <hex.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/ui/view.hpp>
#include <hex/helpers/binary_pattern.hpp>
#include <ui/widgets.hpp>
#include <vector>
#include <wolv/container/interval_tree.hpp>
#include <hex/api/content_registry.hpp>
namespace hex::plugin::builtin {
class ViewFind : public View::Window {
public:
ViewFind();
~ViewFind() override = default;
void drawContent() override;
private:
using Occurrence = hex::ContentRegistry::DataFormatter::impl::FindOccurrence;
struct BinaryPattern {
u8 mask, value;
};
struct SearchSettings {
ui::RegionType range = ui::RegionType::EntireData;
Region region = { 0, 0 };
enum class Mode : int {
Strings,
Sequence,
Regex,
BinaryPattern,
Value
} mode = Mode::Strings;
enum class StringType : int { ASCII = 0, UTF16LE = 1, UTF16BE = 2, ASCII_UTF16LE = 3, ASCII_UTF16BE = 4 };
struct Strings {
int minLength = 5;
bool nullTermination = false;
StringType type = StringType::ASCII;
bool lowerCaseLetters = true;
bool upperCaseLetters = true;
bool numbers = true;
bool underscores = true;
bool symbols = true;
bool spaces = true;
bool lineFeeds = false;
} strings;
struct Sequence {
std::string sequence;
StringType type = StringType::ASCII;
bool ignoreCase = false;
} bytes;
struct Regex {
int minLength = 5;
bool nullTermination = false;
StringType type = StringType::ASCII;
std::string pattern;
bool fullMatch = true;
} regex;
struct BinaryPattern {
std::string input;
hex::BinaryPattern pattern;
u32 alignment = 1;
} binaryPattern;
struct Value {
std::string inputMin, inputMax;
std::endian endian = std::endian::native;
bool aligned = false;
bool range = false;
enum class Type {
U8 = 0, U16 = 1, U32 = 2, U64 = 3,
I8 = 4, I16 = 5, I32 = 6, I64 = 7,
F32 = 8, F64 = 9
} type = Type::U8;
} value;
} m_searchSettings, m_decodeSettings;
using OccurrenceTree = wolv::container::IntervalTree<Occurrence>;
PerProvider<std::vector<Occurrence>> m_foundOccurrences, m_sortedOccurrences;
PerProvider<Occurrence*> m_lastSelectedOccurrence;
PerProvider<OccurrenceTree> m_occurrenceTree;
PerProvider<std::string> m_currFilter;
TaskHolder m_searchTask, m_filterTask;
bool m_settingsValid = false;
std::string m_replaceBuffer;
private:
static std::vector<Occurrence> searchStrings(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Strings &settings);
static std::vector<Occurrence> searchSequence(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Sequence &settings);
static std::vector<Occurrence> searchRegex(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Regex &settings);
static std::vector<Occurrence> searchBinaryPattern(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::BinaryPattern &settings);
static std::vector<Occurrence> searchValue(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Value &settings);
void drawContextMenu(Occurrence &target, const std::string &value);
static std::vector<BinaryPattern> parseBinaryPatternString(std::string string);
static std::tuple<bool, std::variant<u64, i64, float, double>, size_t> parseNumericValueInput(const std::string &input, SearchSettings::Value::Type type);
void runSearch();
std::string decodeValue(prv::Provider *provider, const Occurrence &occurrence, size_t maxBytes = 0xFFFF'FFFF) const;
};
}