blob: 739f6a65082830d18bb8cd887f2b3f3687394c50 [file] [log] [blame]
/*
* 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 <vector>
namespace skrive::internal {
namespace {
class BinaryReader final : public StreamReader {
public:
explicit BinaryReader(std::unique_ptr<SkStreamAsset> 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<BlockType>(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<SkStreamAsset> fStream;
struct BlockRec {
size_t block_end;
};
std::vector<BlockRec> fBlockStack;
};
} // namespace
std::unique_ptr<StreamReader> MakeBinaryStreamReader(std::unique_ptr<SkStreamAsset> stream) {
return std::make_unique<BinaryReader>(std::move(stream));
}
}