Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/base/StarAssets.cpp16
-rw-r--r--source/core/StarAssetPath.cpp16
-rw-r--r--source/core/StarAssetPath.hpp5
-rw-r--r--source/core/StarDirectives.cpp236
-rw-r--r--source/core/StarDirectives.hpp106
-rw-r--r--source/core/StarImageProcessing.cpp19
-rw-r--r--source/core/StarImageProcessing.hpp2
-rw-r--r--source/game/StarImageMetadataDatabase.cpp16
8 files changed, 175 insertions, 241 deletions
diff --git a/source/base/StarAssets.cpp b/source/base/StarAssets.cpp
index d0b77f5..6bd9c09 100644
--- a/source/base/StarAssets.cpp
+++ b/source/base/StarAssets.cpp
@@ -844,9 +844,14 @@ shared_ptr<Assets::AssetData> Assets::loadImage(AssetPath const& path) const {
as<ImageData>(loadAsset(AssetId{AssetType::Image, {path.basePath, path.subPath, {}}}));
if (!source)
return {};
- List<ImageOperation> operations = path.directives.transformed(imageOperationFromString);
StringMap<ImageConstPtr> references;
- for (auto const& ref : imageOperationReferences(operations)) {
+ StringList referencePaths;
+ path.directives.forEach([&](auto const& entry) {
+ addImageOperationReferences(entry.operation, referencePaths);
+ }); // TODO: This can definitely be better, was changed quickly to support the new Directives.
+
+
+ for (auto const& ref : referencePaths) {
auto components = AssetPath::split(ref);
validatePath(components, true, false);
auto refImage = as<ImageData>(loadAsset(AssetId{AssetType::Image, move(components)}));
@@ -857,8 +862,11 @@ shared_ptr<Assets::AssetData> Assets::loadImage(AssetPath const& path) const {
return unlockDuring([&]() {
auto newData = make_shared<ImageData>();
- newData->image = make_shared<Image>(processImageOperations(
- operations, *source->image, [&](String const& ref) { return references.get(ref).get(); }));
+ Image newImage = *source->image;
+ path.directives.forEach([&](auto const& entry) {
+ processImageOperation(entry.operation, newImage, [&](String const& ref) { return references.get(ref).get(); });
+ });
+ newData->image = make_shared<Image>(move(newImage));
return newData;
});
diff --git a/source/core/StarAssetPath.cpp b/source/core/StarAssetPath.cpp
index 2100ee0..eb1cd4d 100644
--- a/source/core/StarAssetPath.cpp
+++ b/source/core/StarAssetPath.cpp
@@ -151,6 +151,18 @@ AssetPath::AssetPath(String const& path) {
*this = move(AssetPath::split(path)); // split code should probably be in here, but whatever
}
+AssetPath::AssetPath(String&& basePath, Maybe<String>&& subPath, DirectivesGroup&& directives) {
+ this->basePath = move(basePath);
+ this->subPath = move(subPath);
+ this->directives = move(directives);
+}
+
+AssetPath::AssetPath(String const& basePath, Maybe<String> const& subPath, DirectivesGroup const& directives) {
+ this->basePath = basePath;
+ this->subPath = subPath;
+ this->directives = directives;
+}
+
std::ostream& operator<<(std::ostream& os, AssetPath const& rhs) {
os << rhs.basePath;
if (rhs.subPath) {
@@ -158,9 +170,9 @@ std::ostream& operator<<(std::ostream& os, AssetPath const& rhs) {
os << *rhs.subPath;
}
- rhs.directives.forEach([&](ImageOperation const& operation, String const& string) {
+ rhs.directives.forEach([&](auto const& entry) {
os << "?";
- os << string;
+ os << entry.string;
});
return os;
diff --git a/source/core/StarAssetPath.hpp b/source/core/StarAssetPath.hpp
index 9da30e7..3ca3f60 100644
--- a/source/core/StarAssetPath.hpp
+++ b/source/core/StarAssetPath.hpp
@@ -53,10 +53,11 @@ struct AssetPath {
AssetPath() = default;
AssetPath(String const& path);
-
+ AssetPath(String&& basePath, Maybe<String>&& subPath, DirectivesGroup&& directives);
+ AssetPath(const String& basePath, const Maybe<String>& subPath, const DirectivesGroup& directives);
String basePath;
Maybe<String> subPath;
- NestedDirectives directives;
+ DirectivesGroup directives;
bool operator==(AssetPath const& rhs) const;
};
diff --git a/source/core/StarDirectives.cpp b/source/core/StarDirectives.cpp
index 2394915..766b4d9 100644
--- a/source/core/StarDirectives.cpp
+++ b/source/core/StarDirectives.cpp
@@ -2,207 +2,133 @@
#include "StarImageProcessing.hpp"
#include "StarDirectives.hpp"
#include "StarXXHash.hpp"
-#include "StarHash.hpp"
namespace Star {
-NestedDirectives::NestedDirectives() : m_root(nullptr) {}
-NestedDirectives::NestedDirectives(String const& directives) {
- parseDirectivesIntoLeaf(directives);
-}
-NestedDirectives::NestedDirectives(String&& directives) {
- String mine = move(directives); // most useless move constructor in the world
- parseDirectivesIntoLeaf(mine);
-}
-
-void NestedDirectives::parseDirectivesIntoLeaf(String const& directives) {
- Leaf leaf;
- for (String& op : directives.split('?')) {
- if (!op.empty())
- leaf.entries.emplace_back(imageOperationFromString(op), op);
- }
- m_root = std::make_shared<Cell>(move(leaf));
+Directives::Directives() {}
+Directives::Directives(String const& directives) {
+ parse(directives);
}
-inline bool NestedDirectives::empty() const {
- return (bool)m_root;
+Directives::Directives(String&& directives) {
+ String mine = move(directives);
+ parse(mine);
}
-inline bool NestedDirectives::compare(NestedDirectives const& other) const {
- if (m_root == other.m_root)
- return true;
-
- return false;
+void Directives::parse(String const& directives) {
+ List<Entry> newList;
+ StringList split = directives.split('?');
+ newList.reserve(split.size());
+ for (String& str : split) {
+ if (!str.empty()) {
+ ImageOperation operation = imageOperationFromString(str);
+ newList.emplace_back(move(operation), move(str));
+ }
+ }
+ entries = std::make_shared<List<Entry> const>(move(newList));
+ hash = XXH3_64bits(directives.utf8Ptr(), directives.utf8Size());
}
-void NestedDirectives::append(NestedDirectives const& other) {
- convertToBranches().emplace_back(other.branch());
+void Directives::buildString(String& out) const {
+ for (auto& entry : *entries) {
+ out += "?";
+ out += entry.string;
+ }
}
-NestedDirectives& NestedDirectives::operator+=(NestedDirectives const& other) {
- append(other);
- return *this;
+DirectivesGroup::DirectivesGroup() : m_count(0) {}
+DirectivesGroup::DirectivesGroup(String const& directives) {
+ m_directives.emplace_back(directives);
+ m_count = m_directives.back().entries->size();
}
-
-String NestedDirectives::toString() const {
- String string;
- addToString(string);
- return string;
+DirectivesGroup::DirectivesGroup(String&& directives) {
+ m_directives.emplace_back(move(directives));
+ m_count = m_directives.back().entries->size();
}
-void NestedDirectives::addToString(String& string) const {
- if (m_root)
- m_root->buildString(string);
+inline bool DirectivesGroup::empty() const {
+ return m_count == 0;
}
-void NestedDirectives::forEach(LeafCallback callback) const {
- if (m_root)
- m_root->forEach(callback);
-}
+inline bool DirectivesGroup::compare(DirectivesGroup const& other) const {
+ if (m_count != other.m_count)
+ return false;
-void NestedDirectives::forEachPair(LeafPairCallback callback) const {
- if (m_root) {
- LeafCallback pairCallback = [&](Leaf const& leaf) {
- for (auto& entry : leaf.entries)
- callback(entry.operation, entry.string);
- };
- m_root->forEach(pairCallback);
- }
-}
+ if (empty())
+ return true;
-bool NestedDirectives::forEachAbortable(AbortableLeafCallback callback) const {
- if (!m_root)
- return false;
- else
- return m_root->forEachAbortable(callback);
+ return hash() == other.hash();
}
-bool NestedDirectives::forEachPairAbortable(AbortableLeafPairCallback callback) const {
- if (!m_root)
- return false;
- else {
- AbortableLeafCallback pairCallback = [&](Leaf const& leaf) -> bool {
- for (auto& entry : leaf.entries) {
- if (!callback(entry.operation, entry.string))
- return false;
- }
-
- return true;
- };
- return m_root->forEachAbortable(pairCallback);
- }
+inline bool DirectivesGroup::operator==(DirectivesGroup const& other) const {
+ return compare(other);
}
-Image NestedDirectives::apply(Image& image) const {
- Image current = image;
- forEachPair([&](ImageOperation const& operation, String const& string) {
- processImageOperation(operation, current);
- });
- return current;
+inline bool DirectivesGroup::operator!=(DirectivesGroup const& other) const {
+ return !compare(other);
}
-NestedDirectives::Branches& NestedDirectives::convertToBranches() {
- if (!m_root) {
- m_root = std::make_shared<Cell>(Branches());
- }
- else if (m_root->value.is<Branches>())
- return;
-
- Leaf& leaf = m_root->value.get<Leaf>();
- Branches newBranches;
- newBranches.emplace_back(std::make_shared<Cell const>(move(leaf)));
- m_root->value = move(newBranches);
- return m_root->value.get<Branches>();
+void DirectivesGroup::append(Directives const& directives) {
+ m_directives.push_back(directives);
+ m_count += m_directives.back().entries->size();
}
-bool NestedDirectives::Leaf::Entry::operator==(NestedDirectives::Leaf::Entry const& other) const {
- return string == other.string;
+DirectivesGroup& DirectivesGroup::operator+=(Directives const& other) {
+ append(other);
+ return *this;
}
-bool NestedDirectives::Leaf::Entry::operator!=(NestedDirectives::Leaf::Entry const& other) const {
- return string != other.string;
+inline String DirectivesGroup::toString() const {
+ String string;
+ addToString(string);
+ return string;
}
-
-size_t NestedDirectives::Leaf::length() const {
- return entries.size();
+void DirectivesGroup::addToString(String& string) const {
+ for (auto& directives : m_directives)
+ directives.buildString(string);
}
-bool NestedDirectives::Leaf::operator==(NestedDirectives::Leaf const& other) const {
- size_t len = length();
- if (len != other.length())
- return false;
-
- for (size_t i = 0; i != len; ++i) {
- if (entries[i] != other.entries[i])
- return false;
+void DirectivesGroup::forEach(DirectivesCallback callback) const {
+ for (auto& directives : m_directives) {
+ for (auto& entry : *directives.entries)
+ callback(entry);
}
- return true;
-}
-
-bool NestedDirectives::Leaf::operator!=(NestedDirectives::Leaf const& other) const {
- return !(*this == other);
}
-NestedDirectives::Cell::Cell() : value(Leaf()) {};
-NestedDirectives::Cell::Cell(Leaf&& leaf) : value(move(leaf)) {};
-NestedDirectives::Cell::Cell(Branches&& branches) : value(move(branches)) {};
-NestedDirectives::Cell::Cell(const Leaf& leaf) : value(leaf) {};
-NestedDirectives::Cell::Cell(const Branches& branches) : value(branches) {};
-
-/*
-bool NestedDirectives::Cell::operator==(NestedDirectives::Cell const& other) const {
- if (auto leaf = value.ptr<Leaf>()) {
- if (auto otherLeaf = other.value.ptr<Leaf>())
- return *leaf == *otherLeaf;
- else {
-
+bool DirectivesGroup::forEachAbortable(AbortableDirectivesCallback callback) const {
+ for (auto& directives : m_directives) {
+ for (auto& entry : *directives.entries) {
+ if (!callback(entry))
+ return false;
}
}
- else {
- for (auto& branch : value.get<Branches>()) {
- }
- }
+ return true;
}
-
-bool NestedDirectives::Cell::operator!=(NestedDirectives::Cell const& other) const {
- return !(*this == other);
+inline Image DirectivesGroup::applyNewImage(Image const& image) const {
+ Image result = image;
+ applyExistingImage(result);
+ return result;
}
-//*/
-void NestedDirectives::Cell::buildString(String& string) const {
- if (auto leaf = value.ptr<Leaf>())
- for (auto& entry : leaf->entries) {
- string += "?";
- string += entry.string;
- }
- else {
- for (auto& branch : value.get<Branches>())
- branch->buildString(string);
- }
+void DirectivesGroup::applyExistingImage(Image& image) const {
+ forEach([&](auto const& entry) {
+ processImageOperation(entry.operation, image);
+ });
}
-void NestedDirectives::Cell::forEach(LeafCallback& callback) const {
- if (auto leaf = value.ptr<Leaf>())
- callback(*leaf);
- else {
- for (auto& branch : value.get<Branches>())
- branch->forEach(callback);
- }
+inline size_t DirectivesGroup::hash() const {
+ XXHash3 hasher;
+ for (auto& directives : m_directives)
+ hasher.push((const char*)&directives.hash, sizeof(directives.hash));
+
+ return hasher.digest();
}
-bool NestedDirectives::Cell::forEachAbortable(AbortableLeafCallback& callback) const {
- if (auto leaf = value.ptr<Leaf>()) {
- if (!callback(*leaf))
- return false;
- } else {
- for (auto& branch : value.get<Branches>())
- if (!branch->forEachAbortable(callback))
- return false;
- }
- return true;
+inline size_t hash<DirectivesGroup>::operator()(DirectivesGroup const& s) const {
+ return s.hash();
}
} \ No newline at end of file
diff --git a/source/core/StarDirectives.hpp b/source/core/StarDirectives.hpp
index 924f295..92dfd46 100644
--- a/source/core/StarDirectives.hpp
+++ b/source/core/StarDirectives.hpp
@@ -2,89 +2,75 @@
#define STAR_DIRECTIVES_HPP
#include "StarImageProcessing.hpp"
+#include "StarHash.hpp"
namespace Star {
-STAR_CLASS(NestedDirectives);
+STAR_CLASS(DirectivesGroup);
STAR_EXCEPTION(DirectivesException, StarException);
// Kae: My attempt at reducing memory allocation and per-frame string parsing for extremely long directives
-class NestedDirectives {
-public:
- struct Leaf {
- struct Entry {
- ImageOperation operation;
- String string;
-
- bool operator==(Entry const& other) const;
- bool operator!=(Entry const& other) const;
- Entry(ImageOperation&& operation, String&& string);
- };
- List<Entry> entries;
-
- size_t length() const;
- bool operator==(NestedDirectives::Leaf const& other) const;
- bool operator!=(NestedDirectives::Leaf const& other) const;
- };
-
- typedef function<void(Leaf const&)> LeafCallback;
- typedef function<void(ImageOperation const&, String const&)> LeafPairCallback;
- typedef function<bool(Leaf const&)> AbortableLeafCallback;
- typedef function<bool(ImageOperation const&, String const&)> AbortableLeafPairCallback;
-
- struct Cell;
- typedef std::shared_ptr<Cell> Branch;
- typedef std::shared_ptr<Cell const> ConstBranch;
- typedef List<ConstBranch> Branches;
+struct Directives {
+ struct Entry {
+ ImageOperation operation;
+ String string;
+ Entry(ImageOperation&& operation, String&& string);
+ };
- struct Cell {
- Variant<Leaf, Branches> value;
+ Directives();
+ Directives(String const& directives);
+ Directives(String&& directives);
- Cell();
- Cell(Leaf&& leaf);
- Cell(Branches&& branches);
- Cell(const Leaf& leaf);
- Cell(const Branches& branches);
+ void parse(String const& directives);
- void buildString(String& string) const;
- void forEach(LeafCallback& callback) const;
- bool forEachAbortable(AbortableLeafCallback& callback) const;
- };
+ void buildString(String& out) const;
+ std::shared_ptr<List<Entry> const> entries;
+ size_t hash = 0;
+};
- NestedDirectives();
- NestedDirectives(String const& directives);
- NestedDirectives(String&& directives);
+class DirectivesGroup {
+public:
+ DirectivesGroup();
+ DirectivesGroup(String const& directives);
+ DirectivesGroup(String&& directives);
void parseDirectivesIntoLeaf(String const& directives);
- bool empty() const;
- bool compare(NestedDirectives const& other) const;
- void append(NestedDirectives const& other);
- NestedDirectives& operator+=(NestedDirectives const& other);
- bool operator==(NestedDirectives const& other) const;
- bool operator!=(NestedDirectives const& other) const;
-
- const ConstBranch& branch() const;
+ inline bool empty() const;
+ bool compare(DirectivesGroup const& other) const;
+ inline bool operator==(DirectivesGroup const& other) const;
+ inline bool operator!=(DirectivesGroup const& other) const;
+ void append(Directives const& other);
+ DirectivesGroup& operator+=(Directives const& other);
- String toString() const;
+ inline String toString() const;
void addToString(String& string) const;
- void forEach(LeafCallback callback) const;
- void forEachPair(LeafPairCallback callback) const;
- bool forEachAbortable(AbortableLeafCallback callback) const;
- bool forEachPairAbortable(AbortableLeafPairCallback callback) const;
+ typedef function<void(Directives::Entry const&)> DirectivesCallback;
+ typedef function<bool(Directives::Entry const&)> AbortableDirectivesCallback;
- Image apply(Image& image) const;
+ void forEach(DirectivesCallback callback) const;
+ bool forEachAbortable(AbortableDirectivesCallback callback) const;
+
+ inline Image applyNewImage(const Image& image) const;
+ void applyExistingImage(Image& image) const;
+
+ inline size_t hash() const;
private:
- void buildString(String& string, const Cell& cell) const;
- Branches& convertToBranches();
+ void buildString(String& string, const DirectivesGroup& directives) const;
+
+ List<Directives> m_directives;
+ size_t m_count;
+};
- Branch m_root;
+template <>
+struct hash<DirectivesGroup> {
+ size_t operator()(DirectivesGroup const& s) const;
};
-typedef NestedDirectives ImageDirectives;
+typedef DirectivesGroup ImageDirectives;
}
diff --git a/source/core/StarImageProcessing.cpp b/source/core/StarImageProcessing.cpp
index fc99f69..c2f980e 100644
--- a/source/core/StarImageProcessing.cpp
+++ b/source/core/StarImageProcessing.cpp
@@ -352,14 +352,17 @@ String printImageOperations(List<ImageOperation> const& list) {
return StringList(list.transformed(imageOperationToString)).join("?");
}
+void addImageOperationReferences(ImageOperation const& operation, StringList& out) {
+ if (auto op = operation.ptr<AlphaMaskImageOperation>())
+ out.appendAll(op->maskImages);
+ else if (auto op = operation.ptr<BlendImageOperation>())
+ out.appendAll(op->blendImages);
+}
+
StringList imageOperationReferences(List<ImageOperation> const& operations) {
StringList references;
- for (auto const& operation : operations) {
- if (auto op = operation.ptr<AlphaMaskImageOperation>())
- references.appendAll(op->maskImages);
- else if (auto op = operation.ptr<BlendImageOperation>())
- references.appendAll(op->blendImages);
- }
+ for (auto const& operation : operations)
+ addImageOperationReferences(operation, references);
return references;
}
@@ -417,7 +420,7 @@ void processImageOperation(ImageOperation const& operation, Image& image, ImageR
} else if (auto op = operation.ptr<AlphaMaskImageOperation>()) {
if (op->maskImages.empty())
- continue;
+ return;
if (!refCallback)
throw StarException("Missing image ref callback during AlphaMaskImageOperation in ImageProcessor::process");
@@ -449,7 +452,7 @@ void processImageOperation(ImageOperation const& operation, Image& image, ImageR
} else if (auto op = operation.ptr<BlendImageOperation>()) {
if (op->blendImages.empty())
- continue;
+ return;
if (!refCallback)
throw StarException("Missing image ref callback during BlendImageOperation in ImageProcessor::process");
diff --git a/source/core/StarImageProcessing.hpp b/source/core/StarImageProcessing.hpp
index ac6151e..30640bf 100644
--- a/source/core/StarImageProcessing.hpp
+++ b/source/core/StarImageProcessing.hpp
@@ -145,6 +145,8 @@ List<ImageOperation> parseImageOperations(String const& params);
// Each operation separated by '?', returns string with leading '?'
String printImageOperations(List<ImageOperation> const& operations);
+void addImageOperationReferences(ImageOperation const& operation, StringList& out);
+
StringList imageOperationReferences(List<ImageOperation> const& operations);
typedef function<Image const*(String const& refName)> ImageReferenceCallback;
diff --git a/source/game/StarImageMetadataDatabase.cpp b/source/game/StarImageMetadataDatabase.cpp
index 1e5c147..7c619d3 100644
--- a/source/game/StarImageMetadataDatabase.cpp
+++ b/source/game/StarImageMetadataDatabase.cpp
@@ -122,7 +122,8 @@ String ImageMetadataDatabase::filterProcessing(String const& path) {
auto directives = move(components.directives);
String joined = AssetPath::join(components);
- directives.forEachPair([&](ImageOperation const& operation, String const& string) {
+ directives.forEach([&](auto const& entry) {
+ ImageOperation const& operation = entry.operation;
if (!(operation.is<HueShiftImageOperation>() ||
operation.is<SaturationShiftImageOperation>() ||
operation.is<BrightnessMultiplyImageOperation>() ||
@@ -130,7 +131,7 @@ String ImageMetadataDatabase::filterProcessing(String const& path) {
operation.is<ScanLinesImageOperation>() ||
operation.is<SetColorImageOperation>())) {
joined += "?";
- joined += string;
+ joined += entry.string;
}
});
@@ -229,14 +230,9 @@ Vec2U ImageMetadataDatabase::calculateImageSize(String const& path) const {
OperationSizeAdjust osa(imageSize);
- bool complete = components.directives.forEachAbortable([&](auto const& leaf) -> bool {
- for (const ImageOperation& operation : leaf.operations) {
- operation.call(osa);
- if (osa.hasError())
- return false;
- else
- return true;
- }
+ bool complete = components.directives.forEachAbortable([&](auto const& entry) -> bool {
+ entry.operation.call(osa);
+ return !osa.hasError;
});
if (!complete)