/* * Copyright 2020 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "experimental/skrive/src/reader/StreamReader.h" #include "include/core/SkStream.h" #include "include/core/SkString.h" #include namespace skrive::internal { namespace { class BinaryReader final : public StreamReader { public: explicit BinaryReader(std::unique_ptr stream) : fStream(std::move(stream)) {} private: bool validateSize(size_t sz) const { const auto next_pos = fStream->getPosition() + sz, block_end = fBlockStack.empty() ? fStream->getLength() : fBlockStack.back().block_end; return next_pos <= block_end; } uint16_t readId(const char label[]) override { return this->readUInt16(label); } bool readBool(const char[]) override { uint8_t v; return validateSize(sizeof(v)) && fStream->readU8(&v) ? v == 1 : false; } float readFloat(const char[]) override { float v; return validateSize(sizeof(v)) && fStream->readScalar(&v) ? v : 0.0f; } uint8_t readUInt8(const char[]) override { uint8_t v; return validateSize(sizeof(v)) && fStream->readU8(&v) ? v : 0; } uint16_t readUInt16(const char[]) override { uint16_t v; return validateSize(sizeof(v)) && fStream->readU16(&v) ? v : 0; } uint32_t readUInt32(const char[]) override { uint32_t v; return validateSize(sizeof(v)) && fStream->readU32(&v) ? v : 0; } SkString readString(const char[]) override { uint32_t length; if (!validateSize(sizeof(length)) || !fStream->readU32(&length)) { return SkString(); } SkString str(length); return validateSize(length) && fStream->read(str.writable_str(), length) == length ? str : SkString(); } size_t readFloatArray(const char[], float dst[], size_t count) override { if (!validateSize(count * sizeof(float))) { return 0; } return fStream->read(dst, count * sizeof(float)) / sizeof(float); } uint8_t readLength8() override { return this->readUInt8(nullptr); } uint16_t readLength16() override { return this->readUInt16(nullptr); } // nops bool openArray(const char[]) override { return true; } void closeArray() override {} bool openObject(const char[]) override { return true; } void closeObject() override {} BlockType openBlock() override { uint8_t block_type; uint32_t block_size; if (this->validateSize(sizeof(block_type) + sizeof(block_size)) && fStream->readU8 (&block_type) && fStream->readU32(&block_size)) { const auto block_end = std::min(fStream->getPosition() + block_size, fStream->getLength()); fBlockStack.push_back({block_end}); return static_cast(block_type); } return BlockType::kEoB; } void closeBlock() override { SkASSERT(!fBlockStack.empty()); SkASSERT(fStream->getPosition() <= fBlockStack.back().block_end); if (fStream->getPosition() < fBlockStack.back().block_end) { const auto skip = fBlockStack.back().block_end - fStream->getPosition(); SkDebugf("!! skipping %zu bytes in block\n", skip); fStream->skip(skip); } fBlockStack.pop_back(); } const std::unique_ptr fStream; struct BlockRec { size_t block_end; }; std::vector fBlockStack; }; } // namespace std::unique_ptr MakeBinaryStreamReader(std::unique_ptr stream) { return std::make_unique(std::move(stream)); } } // namespace skrive::internal