reduce some Directives exceptions down to error strings for perf

additionally, image operations that don't exist simply pass through now
This commit is contained in:
Kae 2024-04-25 09:39:23 +10:00
parent 1b86da7f36
commit a81490c35c
8 changed files with 53 additions and 60 deletions

View File

@ -14,7 +14,9 @@
"offset" : [0, 13] "offset" : [0, 13]
}, },
"specialDamageBar" : { "specialDamageBar" : {
"nameStyle" : {} "nameStyle" : {
"fontSize" : 18
}
}, },
"textStyle" : {}, "textStyle" : {},
"buttonTextStyle" : { "buttonTextStyle" : {

View File

@ -1160,7 +1160,10 @@ shared_ptr<Assets::AssetData> Assets::loadImage(AssetPath const& path) const {
Image newImage = *source->image; Image newImage = *source->image;
path.directives.forEach([&](auto const& entry, Directives const&) { path.directives.forEach([&](auto const& entry, Directives const&) {
if (auto error = entry.operation.template ptr<ErrorImageOperation>()) if (auto error = entry.operation.template ptr<ErrorImageOperation>())
std::rethrow_exception(error->exception); if (auto string = error->cause.ptr<std::string>())
throw DirectivesException::format("ImageOperation parse error: {}", *string);
else
std::rethrow_exception(error->cause.get<std::exception_ptr>());
else else
processImageOperation(entry.operation, newImage, [&](String const& ref) { return references.get(ref).get(); }); processImageOperation(entry.operation, newImage, [&](String const& ref) { return references.get(ref).get(); });
}); });

View File

@ -160,7 +160,7 @@ std::ostream& operator<<(std::ostream& os, AssetPath const& rhs) {
os << *rhs.subPath; os << *rhs.subPath;
} }
rhs.directives.forEach([&](auto const& entry, Directives const& directives) { rhs.directives.forEach([&](Directives::Entry const& entry, Directives const& directives) {
os << "?"; os << "?";
os << entry.string(*directives); os << entry.string(*directives);
}); });

View File

@ -26,8 +26,10 @@ Directives::Entry::Entry(Entry const& other) {
ImageOperation const& Directives::Entry::loadOperation(Shared const& parent) const { ImageOperation const& Directives::Entry::loadOperation(Shared const& parent) const {
if (operation.is<NullImageOperation>()) { if (operation.is<NullImageOperation>()) {
try { operation = imageOperationFromString(string(parent)); } try
catch (StarException const& e) { operation = ErrorImageOperation{ std::current_exception() }; } { operation = imageOperationFromString(string(parent)); }
catch (StarException const& e)
{ operation = ErrorImageOperation{std::exception_ptr()}; }
} }
return operation; return operation;
} }
@ -44,10 +46,9 @@ bool Directives::Shared::empty() const {
Directives::Shared::Shared() {} Directives::Shared::Shared() {}
Directives::Shared::Shared(List<Entry>&& givenEntries, String&& givenString, StringView givenPrefix) { Directives::Shared::Shared(List<Entry>&& givenEntries, String&& givenString) {
entries = std::move(givenEntries); entries = std::move(givenEntries);
string = std::move(givenString); string = std::move(givenString);
prefix = givenPrefix;
hash = string.empty() ? 0 : XXH3_64bits(string.utf8Ptr(), string.utf8Size()); hash = string.empty() ? 0 : XXH3_64bits(string.utf8Ptr(), string.utf8Size());
} }
@ -130,32 +131,25 @@ void Directives::parse(String&& directives) {
List<Entry> entries; List<Entry> entries;
StringView view(directives); StringView view(directives);
StringView prefix = "";
view.forEachSplitView("?", [&](StringView split, size_t beg, size_t end) { view.forEachSplitView("?", [&](StringView split, size_t beg, size_t end) {
if (!split.empty()) { if (!split.empty()) {
if (beg == 0) {
try {
ImageOperation operation = imageOperationFromString(split);
entries.emplace_back(std::move(operation), beg, end);
}
catch (StarException const& e) {
prefix = split;
entries.emplace_back(ImageOperation(ErrorImageOperation{std::current_exception()}), beg, end);
}
}
else {
ImageOperation operation = NullImageOperation(); ImageOperation operation = NullImageOperation();
entries.emplace_back(std::move(operation), beg, end); if (beg == 0) {
try
{ operation = imageOperationFromString(split); }
catch (StarException const& e)
{ operation = ErrorImageOperation{std::exception_ptr()}; }
} }
entries.emplace_back(std::move(operation), beg, end);
} }
}); });
if (entries.empty() && !prefix.empty()) { if (entries.empty()) {
m_shared.reset(); m_shared.reset();
return; return;
} }
m_shared = std::make_shared<Shared const>(std::move(entries), std::move(directives), prefix); m_shared = std::make_shared<Shared const>(std::move(entries), std::move(directives));
if (view.utf8().size() < 1000) { // Pre-load short enough directives if (view.utf8().size() < 1000) { // Pre-load short enough directives
for (auto& entry : m_shared->entries) for (auto& entry : m_shared->entries)
entry.loadOperation(*m_shared); entry.loadOperation(*m_shared);
@ -169,13 +163,6 @@ String Directives::string() const {
return m_shared->string; return m_shared->string;
} }
StringView Directives::prefix() const {
if (!m_shared)
return "";
else
return m_shared->prefix;
}
String const* Directives::stringPtr() const { String const* Directives::stringPtr() const {
if (!m_shared) if (!m_shared)
return nullptr; return nullptr;
@ -186,9 +173,9 @@ String const* Directives::stringPtr() const {
String Directives::buildString() const { String Directives::buildString() const {
if (m_shared) { if (m_shared) {
String built = m_shared->prefix; String built;
for (auto& entry : m_shared->entries) { for (auto& entry : m_shared->entries) {
if (entry.begin > 0)
built += "?"; built += "?";
built += entry.string(*m_shared); built += entry.string(*m_shared);
} }
@ -332,14 +319,11 @@ String DirectivesGroup::toString() const {
} }
void DirectivesGroup::addToString(String& string) const { void DirectivesGroup::addToString(String& string) const {
for (auto& directives : m_directives) { for (auto& entry : m_directives) {
if (directives) { if (entry && !entry->string.empty()) {
auto& dirString = directives->string; if (!string.empty() && string.utf8().back() != '?' && entry->string.utf8()[0] != '?')
if (!dirString.empty()) { string.append('?');
if (dirString.utf8().front() != '?') string += entry->string;
string += "?";
string += dirString;
}
} }
} }
} }
@ -376,7 +360,10 @@ void DirectivesGroup::applyExistingImage(Image& image) const {
forEach([&](auto const& entry, Directives const& directives) { forEach([&](auto const& entry, Directives const& directives) {
ImageOperation const& operation = entry.loadOperation(*directives); ImageOperation const& operation = entry.loadOperation(*directives);
if (auto error = operation.ptr<ErrorImageOperation>()) if (auto error = operation.ptr<ErrorImageOperation>())
std::rethrow_exception(error->exception); if (auto string = error->cause.ptr<std::string>())
throw DirectivesException::format("ImageOperation parse error: {}", *string);
else
std::rethrow_exception(error->cause.get<std::exception_ptr>());
else else
processImageOperation(operation, image); processImageOperation(operation, image);
}); });

View File

@ -31,13 +31,12 @@ public:
struct Shared { struct Shared {
List<Entry> entries; List<Entry> entries;
String string; String string;
StringView prefix;
size_t hash = 0; size_t hash = 0;
mutable Mutex mutex; mutable Mutex mutex;
bool empty() const; bool empty() const;
Shared(); Shared();
Shared(List<Entry>&& givenEntries, String&& givenString, StringView givenPrefix); Shared(List<Entry>&& givenEntries, String&& givenString);
}; };
Directives(); Directives();
@ -57,7 +56,6 @@ public:
void loadOperations() const; void loadOperations() const;
void parse(String&& directives); void parse(String&& directives);
String string() const; String string() const;
StringView prefix() const;
String const* stringPtr() const; String const* stringPtr() const;
String buildString() const; String buildString() const;
String& addToString(String& out) const; String& addToString(String& out) const;

View File

@ -199,13 +199,11 @@ ImageOperation imageOperationFromString(StringView string) {
hexDecode(hexPtr, 8, c, 4); hexDecode(hexPtr, 8, c, 4);
} }
else if (!which || (ptr != end && ++ptr != end)) else if (!which || (ptr != end && ++ptr != end))
throw ImageOperationException(strf("Improper size for hex string '{}' in imageOperationFromString", StringView(hexPtr, hexLen)), false); return ErrorImageOperation{strf("Improper size for hex string '{}'", StringView(hexPtr, hexLen))};
else // we're in A of A=B. In vanilla only A=B pairs are evaluated, so only throw an exception if B is also there. else // we're in A of A=B. In vanilla only A=B pairs are evaluated, so only throw an error if B is also there.
return operation; return operation;
if (which = !which)
which = !which;
if (which)
operation.colorReplaceMap[*(Vec4B*)&a] = *(Vec4B*)&b; operation.colorReplaceMap[*(Vec4B*)&a] = *(Vec4B*)&b;
hexLen = 0; hexLen = 0;
@ -341,12 +339,12 @@ ImageOperation imageOperationFromString(StringView string) {
return FlipImageOperation{FlipImageOperation::FlipXY}; return FlipImageOperation{FlipImageOperation::FlipXY};
} else { } else {
throw ImageOperationException(strf("Could not recognize ImageOperation type {}", type), false); return NullImageOperation();
} }
} catch (OutOfRangeException const& e) { } catch (OutOfRangeException const& e) {
throw ImageOperationException("Error reading ImageOperation", e); return ErrorImageOperation{std::exception_ptr()};
} catch (BadLexicalCast const& e) { } catch (BadLexicalCast const& e) {
throw ImageOperationException("Error reading ImageOperation", e); return ErrorImageOperation{std::exception_ptr()};
} }
} }

View File

@ -18,11 +18,11 @@ StringList colorDirectivesFromConfig(JsonArray const& directives);
String paletteSwapDirectivesFromConfig(Json const& swaps); String paletteSwapDirectivesFromConfig(Json const& swaps);
struct NullImageOperation { struct NullImageOperation {
bool unloaded = false;
}; };
struct ErrorImageOperation { struct ErrorImageOperation {
std::exception_ptr exception; Variant<std::string, std::exception_ptr> cause;
}; };
struct HueShiftImageOperation { struct HueShiftImageOperation {

View File

@ -64,12 +64,17 @@ const FontTextureGroup::GlyphTexture& FontTextureGroup::glyphTexture(String::Cha
for (auto& entry : directives->entries) { for (auto& entry : directives->entries) {
if (auto error = entry.operation.ptr<ErrorImageOperation>()) { if (auto error = entry.operation.ptr<ErrorImageOperation>()) {
if (error->exception) { if (auto string = error->cause.ptr<std::string>()) {
if (!string->empty()) {
Logger::error("Error parsing font directives: {}", *string);
string->clear();
}
} else if (auto& exception = error->cause.get<std::exception_ptr>()) {
try try
{ std::rethrow_exception(error->exception); } { std::rethrow_exception(error->cause.get<std::exception_ptr>()); }
catch (std::exception const& e) catch (std::exception const& e)
{ Logger::error("Exception parsing font directives: {}", e.what()); } { Logger::error("Exception parsing font directives: {}", e.what()); };
error->exception = {}; exception = {};
} }
image.forEachPixel([](unsigned x, unsigned y, Vec4B& pixel) { image.forEachPixel([](unsigned x, unsigned y, Vec4B& pixel) {
pixel = ((x + y) % 2 == 0) ? Vec4B(255, 0, 255, pixel[3]) : Vec4B(0, 0, 0, pixel[3]); pixel = ((x + y) % 2 == 0) ? Vec4B(255, 0, 255, pixel[3]) : Vec4B(0, 0, 0, pixel[3]);