• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)149 std::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