1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "experimental/skrive/src/reader/StreamReader.h" 9cb93a386Sopenharmony_ci#include "include/core/SkString.h" 10cb93a386Sopenharmony_ci#include "src/utils/SkJSON.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include <algorithm> 13cb93a386Sopenharmony_ci#include <iterator> 14cb93a386Sopenharmony_ci#include <memory> 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_cinamespace skrive::internal { 17cb93a386Sopenharmony_cinamespace { 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ciStreamReader::BlockType block_type(const char* type_name) { 20cb93a386Sopenharmony_ci static constexpr struct TypeMapEntry { 21cb93a386Sopenharmony_ci const char* name; 22cb93a386Sopenharmony_ci StreamReader::BlockType block_type; 23cb93a386Sopenharmony_ci } gTypeMap[] = { 24cb93a386Sopenharmony_ci {"artboard" , StreamReader::BlockType::kActorArtboard }, 25cb93a386Sopenharmony_ci {"artboards" , StreamReader::BlockType::kArtboards }, 26cb93a386Sopenharmony_ci {"colorFill" , StreamReader::BlockType::kColorFill }, 27cb93a386Sopenharmony_ci {"colorStroke" , StreamReader::BlockType::kColorStroke }, 28cb93a386Sopenharmony_ci {"ellipse" , StreamReader::BlockType::kActorEllipse }, 29cb93a386Sopenharmony_ci {"gradientFill" , StreamReader::BlockType::kGradientFill }, 30cb93a386Sopenharmony_ci {"gradientStroke" , StreamReader::BlockType::kGradientStroke }, 31cb93a386Sopenharmony_ci {"node" , StreamReader::BlockType::kActorNode }, 32cb93a386Sopenharmony_ci {"nodes" , StreamReader::BlockType::kComponents }, 33cb93a386Sopenharmony_ci {"path" , StreamReader::BlockType::kActorPath }, 34cb93a386Sopenharmony_ci {"polygon" , StreamReader::BlockType::kActorPolygon }, 35cb93a386Sopenharmony_ci {"radialGradientFill" , StreamReader::BlockType::kRadialGradientFill }, 36cb93a386Sopenharmony_ci {"radialGradientStroke", StreamReader::BlockType::kRadialGradientStroke }, 37cb93a386Sopenharmony_ci {"rectangle" , StreamReader::BlockType::kActorRectangle }, 38cb93a386Sopenharmony_ci {"shape" , StreamReader::BlockType::kActorShape }, 39cb93a386Sopenharmony_ci {"star" , StreamReader::BlockType::kActorStar }, 40cb93a386Sopenharmony_ci {"triangle" , StreamReader::BlockType::kActorTriangle }, 41cb93a386Sopenharmony_ci }; 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci const TypeMapEntry key = { type_name, StreamReader::BlockType::kUnknown }; 44cb93a386Sopenharmony_ci const auto* map_entry = std::lower_bound(std::begin(gTypeMap), 45cb93a386Sopenharmony_ci std::end (gTypeMap), 46cb93a386Sopenharmony_ci key, 47cb93a386Sopenharmony_ci [](const TypeMapEntry& a, const TypeMapEntry& b) { 48cb93a386Sopenharmony_ci return strcmp(a.name, b.name) < 0; 49cb93a386Sopenharmony_ci }); 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci return (map_entry != std::end(gTypeMap) && !strcmp(map_entry->name, key.name)) 52cb93a386Sopenharmony_ci ? map_entry->block_type 53cb93a386Sopenharmony_ci : StreamReader::BlockType::kUnknown; 54cb93a386Sopenharmony_ci} 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ciclass JsonReader final : public StreamReader { 57cb93a386Sopenharmony_cipublic: 58cb93a386Sopenharmony_ci explicit JsonReader(std::unique_ptr<skjson::DOM> dom) 59cb93a386Sopenharmony_ci : fDom(std::move(dom)) { 60cb93a386Sopenharmony_ci fContextStack.push_back({&fDom->root(), 0}); 61cb93a386Sopenharmony_ci } 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci ~JsonReader() override { 64cb93a386Sopenharmony_ci SkASSERT(fContextStack.size() == 1); 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ciprivate: 68cb93a386Sopenharmony_ci template <typename T> 69cb93a386Sopenharmony_ci const T* readProp(const char label[]) { 70cb93a386Sopenharmony_ci auto& ctx = fContextStack.back(); 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci if (ctx.fContainer->is<skjson::ObjectValue>()) { 73cb93a386Sopenharmony_ci return static_cast<const T*>(ctx.fContainer->as<skjson::ObjectValue>()[label]); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci const skjson::ArrayValue* jarr = *ctx.fContainer; 77cb93a386Sopenharmony_ci SkASSERT(jarr); 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci return ctx.fMemberIndex < jarr->size() 80cb93a386Sopenharmony_ci ? static_cast<const T*>((*jarr)[ctx.fMemberIndex++]) 81cb93a386Sopenharmony_ci : nullptr; 82cb93a386Sopenharmony_ci } 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci uint16_t readId(const char label[]) override { 85cb93a386Sopenharmony_ci // unlike binary, json IDs are 0-based 86cb93a386Sopenharmony_ci return this->readUInt16(label) + 1; 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci bool readBool(const char label[]) override { 90cb93a386Sopenharmony_ci const auto* jbool = this->readProp<skjson::BoolValue>(label); 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci return jbool ? **jbool : false; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci float readFloat(const char label[]) override { 96cb93a386Sopenharmony_ci const auto* jnum = this->readProp<skjson::NumberValue>(label); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci return jnum ? static_cast<float>(**jnum) : 0.0f; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci uint8_t readUInt8(const char label[]) override { 102cb93a386Sopenharmony_ci return static_cast<uint8_t>(this->readUInt32(label)); 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci uint16_t readUInt16(const char label[]) override { 106cb93a386Sopenharmony_ci return static_cast<uint16_t>(this->readUInt32(label)); 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci uint32_t readUInt32(const char label[]) override { 110cb93a386Sopenharmony_ci const auto* jnum = this->readProp<skjson::NumberValue>(label); 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci return jnum ? static_cast<uint32_t>(**jnum) : 0; 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci SkString readString(const char label[]) override { 116cb93a386Sopenharmony_ci const auto* jstr = this->readProp<skjson::StringValue>(label); 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci return SkString(jstr ? jstr->begin() : nullptr); 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci size_t readFloatArray(const char label[], float dst[], size_t count) override { 122cb93a386Sopenharmony_ci const auto* jarr = this->readProp<skjson::ArrayValue>(label); 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci if (!jarr) { 125cb93a386Sopenharmony_ci return 0; 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci count = std::min(count, jarr->size()); 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci for (size_t i = 0; i < count; ++i) { 131cb93a386Sopenharmony_ci const skjson::NumberValue* jnum = (*jarr)[i]; 132cb93a386Sopenharmony_ci dst[i] = jnum ? static_cast<float>(**jnum) : 0.0f; 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci return count; 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci uint8_t readLength8() override { 139cb93a386Sopenharmony_ci return SkToU8(this->currentLength()); 140cb93a386Sopenharmony_ci } 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci uint16_t readLength16() override { 143cb93a386Sopenharmony_ci return SkToU16(this->currentLength()); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci size_t currentLength() const { 147cb93a386Sopenharmony_ci const auto& ctx = fContextStack.back(); 148cb93a386Sopenharmony_ci return ctx.fContainer->is<skjson::ObjectValue>() 149cb93a386Sopenharmony_ci ? ctx.fContainer->as<skjson::ObjectValue>().size() 150cb93a386Sopenharmony_ci : ctx.fContainer->as<skjson:: ArrayValue>().size(); 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci bool openArray(const char label[]) override { 154cb93a386Sopenharmony_ci const auto* jarr = this->readProp<skjson::ArrayValue>(label); 155cb93a386Sopenharmony_ci if (!jarr) { 156cb93a386Sopenharmony_ci return false; 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci fContextStack.push_back({jarr, 0}); 160cb93a386Sopenharmony_ci return true; 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci void closeArray() override { 164cb93a386Sopenharmony_ci SkASSERT(fContextStack.back().fContainer->is<skjson::ArrayValue>()); 165cb93a386Sopenharmony_ci fContextStack.pop_back(); 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci bool openObject(const char label[]) override { 169cb93a386Sopenharmony_ci const auto* jobj = this->readProp<skjson::ObjectValue>(label); 170cb93a386Sopenharmony_ci if (!jobj) { 171cb93a386Sopenharmony_ci return false; 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci fContextStack.push_back({jobj, 0}); 175cb93a386Sopenharmony_ci return true; 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci void closeObject() override { 179cb93a386Sopenharmony_ci SkASSERT(fContextStack.back().fContainer->is<skjson::ObjectValue>()); 180cb93a386Sopenharmony_ci fContextStack.pop_back(); 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci // "Blocks" map to either objects or arrays. For object containers, the block type is encoded 184cb93a386Sopenharmony_ci // as the key; for array containers, the type is an explicit "type" property *inside* the block 185cb93a386Sopenharmony_ci // entry - which must be an object in this case. 186cb93a386Sopenharmony_ci BlockType openBlock() override { 187cb93a386Sopenharmony_ci switch (fContextStack.back().fContainer->getType()) { 188cb93a386Sopenharmony_ci case skjson::Value::Type::kObject: return this->openObjectBlock(); 189cb93a386Sopenharmony_ci case skjson::Value::Type::kArray: return this->openArrayBlock(); 190cb93a386Sopenharmony_ci default: break; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci SkUNREACHABLE; 193cb93a386Sopenharmony_ci } 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci BlockType openObjectBlock() { 196cb93a386Sopenharmony_ci auto& ctx = fContextStack.back(); 197cb93a386Sopenharmony_ci const auto& container = ctx.fContainer->as<skjson::ObjectValue>(); 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci while (ctx.fMemberIndex < container.size()) { 200cb93a386Sopenharmony_ci const auto& m = container[ctx.fMemberIndex]; 201cb93a386Sopenharmony_ci if (m.fValue.is<skjson::ObjectValue>() || m.fValue.is<skjson::ArrayValue>()) { 202cb93a386Sopenharmony_ci const auto btype = block_type(m.fKey.begin()); 203cb93a386Sopenharmony_ci if (btype != BlockType::kUnknown) { 204cb93a386Sopenharmony_ci fContextStack.push_back({&m.fValue, 0}); 205cb93a386Sopenharmony_ci return btype; 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci } 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_ci ctx.fMemberIndex++; 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci return BlockType::kEoB; 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci BlockType openArrayBlock() { 216cb93a386Sopenharmony_ci auto& ctx = fContextStack.back(); 217cb93a386Sopenharmony_ci const auto& container = ctx.fContainer->as<skjson::ArrayValue>(); 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci while (ctx.fMemberIndex < container.size()) { 220cb93a386Sopenharmony_ci const auto& m = container[ctx.fMemberIndex]; 221cb93a386Sopenharmony_ci if (m.is<skjson::ObjectValue>()) { 222cb93a386Sopenharmony_ci if (const skjson::StringValue* jtype = m.as<skjson::ObjectValue>()["type"]) { 223cb93a386Sopenharmony_ci fContextStack.push_back({&m, 0}); 224cb93a386Sopenharmony_ci return block_type(jtype->begin()); 225cb93a386Sopenharmony_ci } 226cb93a386Sopenharmony_ci } 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_ci ctx.fMemberIndex++; 229cb93a386Sopenharmony_ci } 230cb93a386Sopenharmony_ci 231cb93a386Sopenharmony_ci return BlockType::kEoB; 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ci void closeBlock() override { 235cb93a386Sopenharmony_ci SkASSERT(fContextStack.size() > 1); 236cb93a386Sopenharmony_ci fContextStack.pop_back(); 237cb93a386Sopenharmony_ci fContextStack.back().fMemberIndex++; 238cb93a386Sopenharmony_ci } 239cb93a386Sopenharmony_ci 240cb93a386Sopenharmony_ci struct ContextRec { 241cb93a386Sopenharmony_ci const skjson::Value* fContainer; 242cb93a386Sopenharmony_ci size_t fMemberIndex; 243cb93a386Sopenharmony_ci }; 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci const std::unique_ptr<skjson::DOM> fDom; 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci std::vector<ContextRec> fContextStack; 248cb93a386Sopenharmony_ci}; 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci} // namespace 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_cistd::unique_ptr<StreamReader> MakeJsonStreamReader(const char json[], size_t len) { 253cb93a386Sopenharmony_ci auto dom = std::make_unique<skjson::DOM>(json, len); 254cb93a386Sopenharmony_ci 255cb93a386Sopenharmony_ci return dom->root().is<skjson::ObjectValue>() ? std::make_unique<JsonReader>(std::move(dom)) 256cb93a386Sopenharmony_ci : nullptr; 257cb93a386Sopenharmony_ci} 258cb93a386Sopenharmony_ci 259cb93a386Sopenharmony_ci} // namespace skrive::internal 260