osb/source/core/StarDirectives.cpp

244 lines
5.7 KiB
C++
Raw Normal View History

2023-06-23 15:30:55 +00:00
#include "StarImage.hpp"
#include "StarImageProcessing.hpp"
#include "StarDirectives.hpp"
2023-06-24 03:06:13 +00:00
#include "StarXXHash.hpp"
2023-06-24 13:38:27 +00:00
#include "StarLogging.hpp"
2023-06-23 15:30:55 +00:00
namespace Star {
2023-06-24 10:10:53 +00:00
Directives::Entry::Entry(ImageOperation&& newOperation, String&& newString) {
operation = move(newOperation);
string = move(newString);
}
2023-06-24 12:49:47 +00:00
Directives::Entry::Entry(ImageOperation const& newOperation, String const& newString) {
operation = newOperation;
string = newString;
}
Directives::Entry::Entry(Entry const& other) {
operation = other.operation;
string = other.string;
}
2023-06-24 13:38:27 +00:00
Directives::Directives() : hash(0) {}
Directives::Directives(String const& directives) : hash(0) {
2023-06-24 15:16:40 +00:00
string = directives;
parse(string);
2023-06-23 15:30:55 +00:00
}
2023-06-24 13:38:27 +00:00
Directives::Directives(String&& directives) : hash(0) {
2023-06-24 15:16:40 +00:00
string = move(directives);
parse(string);
2023-06-23 15:30:55 +00:00
}
2023-06-24 15:16:40 +00:00
Directives::Directives(const char* directives) : hash(0), string(directives) {
2023-06-24 12:49:47 +00:00
parse(string);
}
Directives::Directives(List<Entry>&& newEntries) {
entries = std::make_shared<List<Entry> const>(move(newEntries));
2023-06-24 15:16:40 +00:00
String newString;
string = move(buildString(newString));
hash = XXH3_64bits(string.utf8Ptr(), string.utf8Size());
2023-06-24 12:49:47 +00:00
}
2023-06-24 09:41:52 +00:00
void Directives::parse(String const& directives) {
2023-06-24 13:38:27 +00:00
if (directives.empty())
return;
2023-06-24 09:41:52 +00:00
List<Entry> newList;
StringList split = directives.split('?');
newList.reserve(split.size());
for (String& str : split) {
if (!str.empty()) {
2023-06-24 15:16:40 +00:00
try {
ImageOperation operation = imageOperationFromString(str);
newList.emplace_back(move(operation), move(str));
} catch (StarException const& e) {
newList.emplace_back(ErrorImageOperation{ std::current_exception() }, move(str));
2023-06-24 15:16:40 +00:00
}
2023-06-24 09:41:52 +00:00
}
}
2023-06-24 13:38:27 +00:00
if (newList.empty())
return;
2023-06-24 09:41:52 +00:00
entries = std::make_shared<List<Entry> const>(move(newList));
hash = XXH3_64bits(directives.utf8Ptr(), directives.utf8Size());
2023-06-24 13:38:27 +00:00
//if (directives.utf8Size() > 1000)
// Logger::logf(LogLevel::Debug, "Directives: Parsed %u character long string", directives.utf8Size());
2023-06-24 03:06:13 +00:00
}
2023-06-24 15:16:40 +00:00
String& Directives::buildString(String& out) const {
2023-06-24 13:38:27 +00:00
if (entries) {
for (auto& entry : *entries) {
out += "?";
out += entry.string;
}
2023-06-24 09:41:52 +00:00
}
2023-06-24 15:16:40 +00:00
return out;
2023-06-23 15:30:55 +00:00
}
2023-06-24 12:49:47 +00:00
String Directives::toString() const {
2023-06-24 15:16:40 +00:00
return string;
2023-06-24 12:49:47 +00:00
}
inline bool Directives::empty() const {
2023-06-24 13:38:27 +00:00
return !entries || entries->empty();
2023-06-24 12:49:47 +00:00
}
2023-06-24 15:16:40 +00:00
inline Directives::operator bool() const {
return !empty();
}
2023-06-24 12:49:47 +00:00
DataStream& operator>>(DataStream& ds, Directives& directives) {
String string;
ds.read(string);
directives.parse(string);
return ds;
}
DataStream& operator<<(DataStream& ds, Directives const& directives) {
ds.write(directives.toString());
return ds;
}
2023-06-24 09:41:52 +00:00
DirectivesGroup::DirectivesGroup() : m_count(0) {}
2023-06-24 15:16:40 +00:00
DirectivesGroup::DirectivesGroup(String const& directives) : m_count(0) {
if (directives.empty())
return;
Directives parsed(directives);
if (parsed) {
m_directives.emplace_back(move(parsed));
m_count = m_directives.back().entries->size();
}
2023-06-24 03:06:13 +00:00
}
2023-06-24 15:16:40 +00:00
DirectivesGroup::DirectivesGroup(String&& directives) : m_count(0) {
if (directives.empty()) {
directives.clear();
return;
}
Directives parsed(move(directives));
if (parsed) {
m_directives.emplace_back(move(parsed));
m_count = m_directives.back().entries->size();
}
2023-06-23 15:30:55 +00:00
}
2023-06-24 09:41:52 +00:00
inline bool DirectivesGroup::empty() const {
return m_count == 0;
2023-06-23 15:30:55 +00:00
}
2023-06-24 15:16:40 +00:00
inline DirectivesGroup::operator bool() const {
return empty();
}
2023-06-24 09:41:52 +00:00
inline bool DirectivesGroup::compare(DirectivesGroup const& other) const {
if (m_count != other.m_count)
return false;
2023-06-23 15:30:55 +00:00
2023-06-24 09:41:52 +00:00
if (empty())
return true;
2023-06-23 15:30:55 +00:00
2023-06-24 09:41:52 +00:00
return hash() == other.hash();
2023-06-23 15:30:55 +00:00
}
2023-06-24 09:41:52 +00:00
void DirectivesGroup::append(Directives const& directives) {
2023-06-24 12:49:47 +00:00
m_directives.emplace_back(directives);
2023-06-24 13:38:27 +00:00
if (directives.entries)
m_count += m_directives.back().entries->size();
2023-06-23 15:30:55 +00:00
}
2023-06-24 12:49:47 +00:00
void DirectivesGroup::append(List<Directives::Entry>&& entries) {
size_t size = entries.size();
m_directives.emplace_back(move(entries));
m_count += size;
}
void DirectivesGroup::clear() {
m_directives.clear();
m_count = 0;
}
2023-06-24 09:41:52 +00:00
DirectivesGroup& DirectivesGroup::operator+=(Directives const& other) {
append(other);
return *this;
2023-06-24 03:06:13 +00:00
}
2023-06-24 09:41:52 +00:00
inline String DirectivesGroup::toString() const {
String string;
addToString(string);
return string;
2023-06-24 03:06:13 +00:00
}
2023-06-24 09:41:52 +00:00
void DirectivesGroup::addToString(String& string) const {
for (auto& directives : m_directives)
2023-06-24 15:16:40 +00:00
string += directives.string;
2023-06-24 03:06:13 +00:00
}
2023-06-24 09:41:52 +00:00
void DirectivesGroup::forEach(DirectivesCallback callback) const {
for (auto& directives : m_directives) {
2023-06-24 13:38:27 +00:00
if (directives.entries) {
for (auto& entry : *directives.entries)
callback(entry);
}
2023-06-24 03:06:13 +00:00
}
2023-06-23 15:30:55 +00:00
}
2023-06-24 09:41:52 +00:00
bool DirectivesGroup::forEachAbortable(AbortableDirectivesCallback callback) const {
for (auto& directives : m_directives) {
2023-06-24 13:38:27 +00:00
if (directives.entries) {
for (auto& entry : *directives.entries) {
if (!callback(entry))
return false;
}
2023-06-24 03:06:13 +00:00
}
}
2023-06-24 09:41:52 +00:00
return true;
2023-06-24 03:06:13 +00:00
}
2023-06-24 09:41:52 +00:00
inline Image DirectivesGroup::applyNewImage(Image const& image) const {
Image result = image;
applyExistingImage(result);
return result;
2023-06-24 03:06:13 +00:00
}
2023-06-24 09:41:52 +00:00
void DirectivesGroup::applyExistingImage(Image& image) const {
forEach([&](auto const& entry) {
if (auto error = entry.operation.ptr<ErrorImageOperation>())
std::rethrow_exception(error->exception);
else
processImageOperation(entry.operation, image);
2023-06-24 09:41:52 +00:00
});
2023-06-23 15:30:55 +00:00
}
2023-06-24 09:41:52 +00:00
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();
2023-06-23 15:30:55 +00:00
}
2023-06-24 10:10:53 +00:00
bool operator==(DirectivesGroup const& a, DirectivesGroup const& b) {
return a.compare(b);
}
bool operator!=(DirectivesGroup const& a, DirectivesGroup const& b) {
return !a.compare(b);
}
size_t hash<DirectivesGroup>::operator()(DirectivesGroup const& s) const {
2023-06-24 09:41:52 +00:00
return s.hash();
2023-06-23 15:30:55 +00:00
}
}