diff options
Diffstat (limited to 'source/core')
-rw-r--r-- | source/core/StarAssetPath.cpp | 2 | ||||
-rw-r--r-- | source/core/StarDirectives.cpp | 83 | ||||
-rw-r--r-- | source/core/StarDirectives.hpp | 16 | ||||
-rw-r--r-- | source/core/StarFormattedJson.cpp | 4 | ||||
-rw-r--r-- | source/core/StarJson.cpp | 8 | ||||
-rw-r--r-- | source/core/StarJson.hpp | 3 | ||||
-rw-r--r-- | source/core/StarJsonBuilder.hpp | 8 | ||||
-rw-r--r-- | source/core/StarJsonParser.hpp | 66 | ||||
-rw-r--r-- | source/core/StarLua.cpp | 4 | ||||
-rw-r--r-- | source/core/StarLua.hpp | 2 | ||||
-rw-r--r-- | source/core/StarText.cpp | 28 | ||||
-rw-r--r-- | source/core/StarText.hpp | 22 | ||||
-rw-r--r-- | source/core/scripting/StarUtilityLuaBindings.cpp | 4 |
13 files changed, 194 insertions, 56 deletions
diff --git a/source/core/StarAssetPath.cpp b/source/core/StarAssetPath.cpp index e54a139..23743d9 100644 --- a/source/core/StarAssetPath.cpp +++ b/source/core/StarAssetPath.cpp @@ -162,7 +162,7 @@ std::ostream& operator<<(std::ostream& os, AssetPath const& rhs) { rhs.directives.forEach([&](auto const& entry, Directives const& directives) { os << "?"; - os << entry.string(*directives.shared); + os << entry.string(*directives); }); return os; diff --git a/source/core/StarDirectives.cpp b/source/core/StarDirectives.cpp index 4770200..89985a0 100644 --- a/source/core/StarDirectives.cpp +++ b/source/core/StarDirectives.cpp @@ -42,6 +42,8 @@ bool Directives::Shared::empty() const { return entries.empty(); } +Directives::Shared::Shared() {} + Directives::Shared::Shared(List<Entry>&& givenEntries, String&& givenString, StringView givenPrefix) { entries = std::move(givenEntries); string = std::move(givenString); @@ -74,7 +76,7 @@ Directives::Directives(Directives const& directives) { Directives::~Directives() {} Directives& Directives::operator=(String const& s) { - if (shared && shared->string == s) + if (m_shared && m_shared->string == s) return *this; parse(String(s)); @@ -82,7 +84,7 @@ Directives& Directives::operator=(String const& s) { } Directives& Directives::operator=(String&& s) { - if (shared && shared->string == s) { + if (m_shared && m_shared->string == s) { s.clear(); return *this; } @@ -92,7 +94,7 @@ Directives& Directives::operator=(String&& s) { } Directives& Directives::operator=(const char* s) { - if (shared && shared->string.utf8().compare(s) == 0) + if (m_shared && m_shared->string.utf8().compare(s) == 0) return *this; parse(s); @@ -100,27 +102,29 @@ Directives& Directives::operator=(const char* s) { } Directives& Directives::operator=(Directives&& other) noexcept { - shared = std::move(other.shared); + m_shared = std::move(other.m_shared); return *this; } Directives& Directives::operator=(Directives const& other) { - shared = other.shared; + m_shared = other.m_shared; return *this; } void Directives::loadOperations() const { - if (!shared) + if (!m_shared) return; - MutexLocker lock(shared->mutex, true); - for (auto& entry : shared->entries) - entry.loadOperation(*shared); + MutexLocker locker(m_shared->mutex, false); + if (!m_shared.unique()) + locker.lock(); + for (auto& entry : m_shared->entries) + entry.loadOperation(*m_shared); } void Directives::parse(String&& directives) { if (directives.empty()) { - shared.reset(); + m_shared.reset(); return; } @@ -147,46 +151,46 @@ void Directives::parse(String&& directives) { }); if (entries.empty() && !prefix.empty()) { - shared.reset(); + m_shared.reset(); return; } - 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), prefix); if (view.utf8().size() < 1000) { // Pre-load short enough directives - for (auto& entry : shared->entries) - entry.loadOperation(*shared); + for (auto& entry : m_shared->entries) + entry.loadOperation(*m_shared); } } String Directives::string() const { - if (!shared) + if (!m_shared) return ""; else - return shared->string; + return m_shared->string; } StringView Directives::prefix() const { - if (!shared) + if (!m_shared) return ""; else - return shared->prefix; + return m_shared->prefix; } String const* Directives::stringPtr() const { - if (!shared) + if (!m_shared) return nullptr; else - return &shared->string; + return &m_shared->string; } String Directives::buildString() const { - if (shared) { - String built = shared->prefix; + if (m_shared) { + String built = m_shared->prefix; - for (auto& entry : shared->entries) { + for (auto& entry : m_shared->entries) { built += "?"; - built += entry.string(*shared); + built += entry.string(*m_shared); } return built; @@ -197,23 +201,25 @@ String Directives::buildString() const { String& Directives::addToString(String& out) const { if (!empty()) - out += shared->string; + out += m_shared->string; return out; } size_t Directives::hash() const { - return shared ? shared->hash : 0; + return m_shared ? m_shared->hash : 0; } size_t Directives::size() const { - return shared ? shared->entries.size() : 0; + return m_shared ? m_shared->entries.size() : 0; } bool Directives::empty() const { - return !shared || shared->empty(); + return !m_shared || m_shared->empty(); } -Directives::operator bool() const { return !empty(); } +Directives::operator bool() const { + return !empty(); +} bool Directives::equals(Directives const& other) const { return hash() == other.hash(); @@ -243,7 +249,7 @@ DataStream& operator>>(DataStream& ds, Directives& directives) { DataStream& operator<<(DataStream & ds, Directives const& directives) { if (directives) - ds.write(directives.shared->string); + ds.write(directives->string); else ds.write(String()); @@ -326,21 +332,22 @@ String DirectivesGroup::toString() const { } void DirectivesGroup::addToString(String& string) const { - for (auto& directives : m_directives) - if (directives.shared) { - auto& dirString = directives.shared->string; + for (auto& directives : m_directives) { + if (directives) { + auto& dirString = directives->string; if (!dirString.empty()) { if (dirString.utf8().front() != '?') string += "?"; string += dirString; } } + } } void DirectivesGroup::forEach(DirectivesCallback callback) const { for (auto& directives : m_directives) { - if (directives.shared) { - for (auto& entry : directives.shared->entries) + if (directives) { + for (auto& entry : directives->entries) callback(entry, directives); } } @@ -348,8 +355,8 @@ void DirectivesGroup::forEach(DirectivesCallback callback) const { bool DirectivesGroup::forEachAbortable(AbortableDirectivesCallback callback) const { for (auto& directives : m_directives) { - if (directives.shared) { - for (auto& entry : directives.shared->entries) { + if (directives) { + for (auto& entry : directives->entries) { if (!callback(entry, directives)) return false; } @@ -367,7 +374,7 @@ Image DirectivesGroup::applyNewImage(Image const& image) const { void DirectivesGroup::applyExistingImage(Image& image) const { forEach([&](auto const& entry, Directives const& directives) { - ImageOperation const& operation = entry.loadOperation(*directives.shared); + ImageOperation const& operation = entry.loadOperation(*directives); if (auto error = operation.ptr<ErrorImageOperation>()) std::rethrow_exception(error->exception); else diff --git a/source/core/StarDirectives.hpp b/source/core/StarDirectives.hpp index e272915..fa10a33 100644 --- a/source/core/StarDirectives.hpp +++ b/source/core/StarDirectives.hpp @@ -36,6 +36,7 @@ public: mutable Mutex mutex; bool empty() const; + Shared(); Shared(List<Entry>&& givenEntries, String&& givenString, StringView givenPrefix); }; @@ -65,6 +66,9 @@ public: bool empty() const; operator bool() const; + Shared const& operator*() const; + Shared const* operator->() const; + bool equals(Directives const& other) const; bool equals(String const& string) const; @@ -78,7 +82,7 @@ public: //friend bool operator==(Directives const& directives, String const& string); //friend bool operator==(String const& string, Directives const& directives); - std::shared_ptr<Shared const> shared; + std::shared_ptr<Shared const> m_shared; }; class DirectivesGroup { @@ -122,7 +126,6 @@ private: size_t m_count; }; - template <> struct hash<DirectivesGroup> { size_t operator()(DirectivesGroup const& s) const; @@ -130,4 +133,13 @@ struct hash<DirectivesGroup> { typedef DirectivesGroup ImageDirectives; +inline Directives::Shared const& Directives::operator*() const { + return *m_shared; +} +inline Directives::Shared const* Directives::operator->() const { + if (!m_shared) + throw DirectivesException("Directives::operator-> nullptr"); + return m_shared.get(); +} + } diff --git a/source/core/StarFormattedJson.cpp b/source/core/StarFormattedJson.cpp index d7bd8c7..a770ac6 100644 --- a/source/core/StarFormattedJson.cpp +++ b/source/core/StarFormattedJson.cpp @@ -65,12 +65,12 @@ bool CommaElement::operator==(CommaElement const&) const { FormattedJson FormattedJson::parse(String const& string) { return inputUtf32Json<String::const_iterator, FormattedJsonBuilderStream, FormattedJson>( - string.begin(), string.end(), true); + string.begin(), string.end(), JsonParseType::Value); } FormattedJson FormattedJson::parseJson(String const& string) { return inputUtf32Json<String::const_iterator, FormattedJsonBuilderStream, FormattedJson>( - string.begin(), string.end(), false); + string.begin(), string.end(), JsonParseType::Top); } FormattedJson FormattedJson::ofType(Json::Type type) { diff --git a/source/core/StarJson.cpp b/source/core/StarJson.cpp index 04ac544..7cf1cda 100644 --- a/source/core/StarJson.cpp +++ b/source/core/StarJson.cpp @@ -105,11 +105,15 @@ Json Json::ofType(Type t) { } Json Json::parse(String const& string) { - return inputUtf32Json<String::const_iterator>(string.begin(), string.end(), true); + return inputUtf32Json<String::const_iterator>(string.begin(), string.end(), JsonParseType::Value); +} + +Json Json::parseSequence(String const& sequence) { + return inputUtf32Json<String::const_iterator>(sequence.begin(), sequence.end(), JsonParseType::Sequence); } Json Json::parseJson(String const& json) { - return inputUtf32Json<String::const_iterator>(json.begin(), json.end(), false); + return inputUtf32Json<String::const_iterator>(json.begin(), json.end(), JsonParseType::Top); } Json::Json() {} diff --git a/source/core/StarJson.hpp b/source/core/StarJson.hpp index a533e47..b58b9a0 100644 --- a/source/core/StarJson.hpp +++ b/source/core/StarJson.hpp @@ -51,6 +51,9 @@ public: // Parses JSON or JSON sub-type static Json parse(String const& string); + // Parses JSON sequence + static Json parseSequence(String const& sequence); + // Parses JSON object or array only (the only top level types allowed by // JSON) static Json parseJson(String const& json); diff --git a/source/core/StarJsonBuilder.hpp b/source/core/StarJsonBuilder.hpp index ea0df46..46f192c 100644 --- a/source/core/StarJsonBuilder.hpp +++ b/source/core/StarJsonBuilder.hpp @@ -50,7 +50,7 @@ public: }; template <typename InputIterator> -Json inputUtf8Json(InputIterator begin, InputIterator end, bool fragment) { +Json inputUtf8Json(InputIterator begin, InputIterator end, JsonParseType parseType) { typedef U8ToU32Iterator<InputIterator> Utf32Input; typedef JsonParser<Utf32Input> Parser; @@ -58,7 +58,7 @@ Json inputUtf8Json(InputIterator begin, InputIterator end, bool fragment) { Parser parser(stream); Utf32Input wbegin(begin); Utf32Input wend(end); - Utf32Input pend = parser.parse(wbegin, wend, fragment); + Utf32Input pend = parser.parse(wbegin, wend, parseType); if (parser.error()) throw JsonParsingException(strf("Error parsing json: {} at {}:{}", parser.error(), parser.line(), parser.column())); @@ -77,11 +77,11 @@ void outputUtf8Json(Json const& val, OutputIterator out, int pretty, bool sort) } template <typename InputIterator, typename Stream = JsonBuilderStream, typename Jsonlike = Json> -Jsonlike inputUtf32Json(InputIterator begin, InputIterator end, bool fragment) { +Jsonlike inputUtf32Json(InputIterator begin, InputIterator end, JsonParseType parseType) { Stream stream; JsonParser<InputIterator> parser(stream); - InputIterator pend = parser.parse(begin, end, fragment); + InputIterator pend = parser.parse(begin, end, parseType); if (parser.error()) { throw JsonParsingException(strf("Error parsing json: {} at {}:{}", parser.error(), parser.line(), parser.column())); diff --git a/source/core/StarJsonParser.hpp b/source/core/StarJsonParser.hpp index d814edb..0bf7443 100644 --- a/source/core/StarJsonParser.hpp +++ b/source/core/StarJsonParser.hpp @@ -27,6 +27,12 @@ struct JsonStream { virtual void putComma() = 0; }; +enum class JsonParseType : uint8_t { + Top, // Top-level Object or Array + Value, // Any singular Json value + Sequence // Like an array, but without needing the [] or commas. +}; + // Will parse JSON and output to a given JsonStream. Parses an *extension* to // the JSON format that includes comments. template <typename InputIterator> @@ -39,15 +45,17 @@ public: // Does not throw. On error, returned iterator will not be equal to end, and // error() will be non-null. Set fragment to true to parse any JSON type // rather than just object or array. - InputIterator parse(InputIterator begin, InputIterator end, bool fragment = false) { + InputIterator parse(InputIterator begin, InputIterator end, JsonParseType parseType = JsonParseType::Top) { init(begin, end); try { white(); - if (fragment) - value(); - else + if (parseType == JsonParseType::Top) top(); + else if (parseType == JsonParseType::Value) + value(); + else if (parseType == JsonParseType::Sequence) + sequence(); white(); } catch (ParsingException const&) { } @@ -190,6 +198,56 @@ private: } } + void sequence() { + m_stream.beginArray(); + while (true) { + if (isSpace(m_char)) { + next(); + continue; + } else if (m_char == '{') + object(); + else if (m_char == '[') + array(); + else if (m_char == '"') + string(); + else if (m_char == '-') + number(); + else if (m_char == 0) + break; + else { + auto begin = m_current; + if (m_char >= '0' && m_char <= '9') { + number(); + if (m_error.empty()) { + next(); + continue; + } + } + m_error.clear(); + m_current = begin; + if (m_char == 't' || m_char == 'f' || m_char == 'n') { + word(); + if (m_error.empty()) { + next(); + continue; + } + } + m_error.clear(); + m_current = begin; + // well, shit. do a simple string parse until we hit whitespace + // no fancy things like \n, do a proper string if you want that + CharArray str; + do { + str += m_char; + next(); + } while (m_char && !isSpace(m_char)); + m_stream.putString(str.c_str(), str.length()); + } + next(); + } + m_stream.endArray(); + } + void string() { CharArray s = parseString(); m_stream.putString(s.c_str(), s.length()); diff --git a/source/core/StarLua.cpp b/source/core/StarLua.cpp index 73955f2..5a2effa 100644 --- a/source/core/StarLua.cpp +++ b/source/core/StarLua.cpp @@ -60,6 +60,10 @@ LuaInt LuaTable::rawLength() const { return engine().tableLength(true, handleIndex()); } +void LuaCallbacks::copyCallback(String srcName, String dstName) { + m_callbacks.set(dstName, m_callbacks.get(srcName)); +} + LuaCallbacks& LuaCallbacks::merge(LuaCallbacks const& callbacks) { try { for (auto const& pair : callbacks.m_callbacks) diff --git a/source/core/StarLua.hpp b/source/core/StarLua.hpp index 09e81e6..57afb98 100644 --- a/source/core/StarLua.hpp +++ b/source/core/StarLua.hpp @@ -267,6 +267,8 @@ LuaValue const LuaNil = LuaValue(); class LuaCallbacks { public: + void copyCallback(String srcName, String dstName); + template <typename Function> void registerCallback(String name, Function&& func); diff --git a/source/core/StarText.cpp b/source/core/StarText.cpp index 11fca27..86c9f25 100644 --- a/source/core/StarText.cpp +++ b/source/core/StarText.cpp @@ -1,9 +1,35 @@ #include "StarText.hpp" - +#include "StarJsonExtra.hpp" #include <regex> namespace Star { +TextStyle::TextStyle(Json const& config) : TextStyle() { + if (config.isType(Json::Type::String)) + font = config.toString(); + else + loadJson(config); +} +TextStyle& TextStyle::loadJson(Json const& config) { + if (!config) + return *this; + + lineSpacing = config.getFloat("lineSpacing", lineSpacing); + if (auto jColor = config.opt("color")) + color = jsonToColor(*jColor).toRgba(); + if (auto jShadow = config.opt("shadow")) + shadow = jsonToColor(*jShadow).toRgba(); + fontSize = config.getUInt("fontSize", fontSize); + if (auto jFont = config.optString("font")) + font = *jFont; + if (auto jDirectives = config.optString("directives")) + directives = *jDirectives; + if (auto jBackDirectives = config.optString("backDirectives")) + backDirectives = *jBackDirectives; + + return *this; +} + namespace Text { static auto stripEscapeRegex = std::regex(strf("\\{:c}[^;]*{:c}", CmdEsc, EndEsc)); String stripEscapeCodes(String const& s) { diff --git a/source/core/StarText.hpp b/source/core/StarText.hpp index 4f6a97a..ff6880c 100644 --- a/source/core/StarText.hpp +++ b/source/core/StarText.hpp @@ -2,9 +2,29 @@ #include "StarString.hpp" #include "StarStringView.hpp" +#include "StarVector.hpp" +#include "StarDirectives.hpp" +#include "StarJson.hpp" namespace Star { - + +unsigned const DefaultFontSize = 8; +float const DefaultLineSpacing = 1.3f; + +struct TextStyle { + float lineSpacing = DefaultLineSpacing; + Vec4B color = Vec4B::filled(255); + Vec4B shadow = Vec4B::filled(0); + unsigned fontSize = DefaultFontSize; + String font = ""; + Directives directives; + Directives backDirectives; + + TextStyle() = default; + TextStyle(Json const& config); + TextStyle& loadJson(Json const& config); +}; + namespace Text { unsigned char const StartEsc = '\x1b'; unsigned char const EndEsc = ';'; diff --git a/source/core/scripting/StarUtilityLuaBindings.cpp b/source/core/scripting/StarUtilityLuaBindings.cpp index 5ab6e19..98ad239 100644 --- a/source/core/scripting/StarUtilityLuaBindings.cpp +++ b/source/core/scripting/StarUtilityLuaBindings.cpp @@ -118,12 +118,14 @@ LuaCallbacks LuaBindings::makeUtilityCallbacks() { callbacks.registerCallback("print", UtilityCallbacks::print); callbacks.registerCallback("interpolateSinEase", UtilityCallbacks::interpolateSinEase); callbacks.registerCallback("replaceTags", UtilityCallbacks::replaceTags); - callbacks.registerCallback("jsonParse", [](String const& json) { return Json::parse(json); }); + callbacks.registerCallback("parseJsonSequence", [](String const& json) { return Json::parseSequence(json); }); callbacks.registerCallback("jsonMerge", [](Json const& a, Json const& b) { return jsonMerge(a, b); }); callbacks.registerCallback("jsonQuery", [](Json const& json, String const& path, Json const& def) { return json.query(path, def); }); callbacks.registerCallback("makeRandomSource", [](Maybe<uint64_t> seed) { return seed ? RandomSource(*seed) : RandomSource(); }); callbacks.registerCallback("makePerlinSource", [](Json const& config) { return PerlinF(config); }); + callbacks.copyCallback("parseJson", "jsonFromString"); // SE compat + auto hash64LuaValues = [](LuaVariadic<LuaValue> const& values) -> uint64_t { XXHash64 hash; |