1 /* 2 * Copyright 2020 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "experimental/skrive/src/reader/StreamReader.h" 9 #include "include/core/SkStream.h" 10 #include "include/core/SkString.h" 11 12 #include <vector> 13 14 namespace skrive::internal { 15 16 namespace { 17 18 class BinaryReader final : public StreamReader { 19 public: BinaryReader(std::unique_ptr<SkStreamAsset> stream)20 explicit BinaryReader(std::unique_ptr<SkStreamAsset> stream) 21 : fStream(std::move(stream)) {} 22 23 private: validateSize(size_t sz) const24 bool validateSize(size_t sz) const { 25 const auto next_pos = fStream->getPosition() + sz, 26 block_end = fBlockStack.empty() ? fStream->getLength() 27 : fBlockStack.back().block_end; 28 return next_pos <= block_end; 29 } 30 readId(const char label[])31 uint16_t readId(const char label[]) override { 32 return this->readUInt16(label); 33 } 34 readBool(const char[])35 bool readBool(const char[]) override { 36 uint8_t v; 37 38 return validateSize(sizeof(v)) && fStream->readU8(&v) 39 ? v == 1 40 : false; 41 } 42 readFloat(const char[])43 float readFloat(const char[]) override { 44 float v; 45 46 return validateSize(sizeof(v)) && fStream->readScalar(&v) 47 ? v 48 : 0.0f; 49 } 50 readUInt8(const char[])51 uint8_t readUInt8(const char[]) override { 52 uint8_t v; 53 54 return validateSize(sizeof(v)) && fStream->readU8(&v) 55 ? v 56 : 0; 57 } 58 readUInt16(const char[])59 uint16_t readUInt16(const char[]) override { 60 uint16_t v; 61 62 return validateSize(sizeof(v)) && fStream->readU16(&v) 63 ? v 64 : 0; 65 } 66 readUInt32(const char[])67 uint32_t readUInt32(const char[]) override { 68 uint32_t v; 69 70 return validateSize(sizeof(v)) && fStream->readU32(&v) 71 ? v 72 : 0; 73 } 74 readString(const char[])75 SkString readString(const char[]) override { 76 uint32_t length; 77 if (!validateSize(sizeof(length)) || !fStream->readU32(&length)) { 78 return SkString(); 79 } 80 81 SkString str(length); 82 return validateSize(length) && fStream->read(str.writable_str(), length) == length 83 ? str 84 : SkString(); 85 } 86 readFloatArray(const char[],float dst[],size_t count)87 size_t readFloatArray(const char[], float dst[], size_t count) override { 88 if (!validateSize(count * sizeof(float))) { 89 return 0; 90 } 91 92 return fStream->read(dst, count * sizeof(float)) / sizeof(float); 93 } 94 readLength8()95 uint8_t readLength8() override { 96 return this->readUInt8(nullptr); 97 } 98 readLength16()99 uint16_t readLength16() override { 100 return this->readUInt16(nullptr); 101 } 102 103 // nops openArray(const char[])104 bool openArray(const char[]) override { return true; } closeArray()105 void closeArray() override {} openObject(const char[])106 bool openObject(const char[]) override { return true; } closeObject()107 void closeObject() override {} 108 openBlock()109 BlockType openBlock() override { 110 uint8_t block_type; 111 uint32_t block_size; 112 113 if (this->validateSize(sizeof(block_type) + sizeof(block_size)) && 114 fStream->readU8 (&block_type) && 115 fStream->readU32(&block_size)) { 116 const auto block_end = std::min(fStream->getPosition() + block_size, 117 fStream->getLength()); 118 fBlockStack.push_back({block_end}); 119 return static_cast<BlockType>(block_type); 120 } 121 122 return BlockType::kEoB; 123 } 124 closeBlock()125 void closeBlock() override { 126 SkASSERT(!fBlockStack.empty()); 127 SkASSERT(fStream->getPosition() <= fBlockStack.back().block_end); 128 129 if (fStream->getPosition() < fBlockStack.back().block_end) { 130 const auto skip = fBlockStack.back().block_end - fStream->getPosition(); 131 SkDebugf("!! skipping %zu bytes in block\n", skip); 132 fStream->skip(skip); 133 } 134 135 fBlockStack.pop_back(); 136 } 137 138 const std::unique_ptr<SkStreamAsset> fStream; 139 140 struct BlockRec { 141 size_t block_end; 142 }; 143 144 std::vector<BlockRec> fBlockStack; 145 }; 146 147 } // namespace 148 MakeBinaryStreamReader(std::unique_ptr<SkStreamAsset> stream)149std::unique_ptr<StreamReader> MakeBinaryStreamReader(std::unique_ptr<SkStreamAsset> stream) { 150 return std::make_unique<BinaryReader>(std::move(stream)); 151 } 152 153 } // namespace skrive::internal 154