impr: Speed up Import Pattern popup

Closes #2264
This commit is contained in:
WerWolv
2025-05-25 21:08:52 +02:00
parent c78c8072e9
commit 38ef00548a

View File

@@ -8,6 +8,7 @@
#include <pl/pattern_language.hpp>
#include <pl/core/errors/error.hpp>
#include <pl/core/lexer.hpp>
#include <ui/hex_editor.hpp>
#include <ui/pattern_drawer.hpp>
@@ -350,26 +351,51 @@ namespace hex::plugin::builtin {
}
}
auto createRuntime = [this, provider] {
auto runtime = std::make_shared<pl::PatternLanguage>();
ContentRegistry::PatternLanguage::configureRuntime(*runtime, provider);
return runtime;
};
ui::PopupNamedFileChooser::open(
basePaths, paths, std::vector<hex::fs::ItemFilter>{ { "Pattern File", "hexpat" } }, false,
[this, provider](const std::fs::path &path, const std::fs::path &adjustedPath) mutable -> std::string {
auto it = m_patternNames.find(path);
if (it != m_patternNames.end()) {
[this, provider, runtime = createRuntime()](const std::fs::path &path, const std::fs::path &adjustedPath) mutable -> std::string {
if (auto it = m_patternNames.find(path); it != m_patternNames.end()) {
return it->second;
}
const auto fileName = wolv::util::toUTF8String(adjustedPath.filename());
m_patternNames[path] = fileName;
pl::PatternLanguage runtime;
ContentRegistry::PatternLanguage::configureRuntime(runtime, provider);
runtime.addPragma("description", [&](pl::PatternLanguage &, const std::string &value) -> bool {
m_patternNames[path] = hex::format("{} ({})", value, fileName);
return true;
});
wolv::io::File file(path, wolv::io::File::Mode::Read);
std::ignore = runtime.preprocessString(file.readString(), pl::api::Source::DefaultSource);
pl::api::Source source(file.readString());
// Only run the lexer on the source file and manually extract the #pragma description to make this
// process as fast as possible. Running the preprocessor directly takes too much time
auto result = runtime->getInternals().lexer->lex(&source);
if (result.isOk()) {
const auto tokens = result.unwrap();
for (auto it = tokens.begin(); it != tokens.end(); ++it) {
if (it->type == pl::core::Token::Type::Directive && std::get<pl::core::Token::Directive>(it->value) == pl::core::Token::Directive::Pragma) {
++it;
if (it != tokens.end() && it->type == pl::core::Token::Type::String) {
auto literal = std::get<pl::core::Token::Literal>(it->value);
auto string = std::get_if<std::string>(&literal);
if (string != nullptr && *string == "description") {
++it;
if (it != tokens.end() && it->type == pl::core::Token::Type::String) {
literal = std::get<pl::core::Token::Literal>(it->value);
string = std::get_if<std::string>(&literal);
if (string != nullptr) {
m_patternNames[path] = hex::format("{} ({})", *string, fileName);
}
}
}
}
}
}
}
return m_patternNames[path];
},