Line data Source code
1 : /*
2 : * Copyright 2008 The Android Open Source Project
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 :
9 : #ifndef SkReader32_DEFINED
10 : #define SkReader32_DEFINED
11 :
12 : #include "SkData.h"
13 : #include "SkMatrix.h"
14 : #include "SkPath.h"
15 : #include "SkRegion.h"
16 : #include "SkRRect.h"
17 : #include "SkScalar.h"
18 :
19 : class SkString;
20 :
21 : class SkReader32 : SkNoncopyable {
22 : public:
23 0 : SkReader32() : fCurr(nullptr), fStop(nullptr), fBase(nullptr) {}
24 0 : SkReader32(const void* data, size_t size) {
25 0 : this->setMemory(data, size);
26 0 : }
27 :
28 0 : void setMemory(const void* data, size_t size) {
29 0 : SkASSERT(ptr_align_4(data));
30 0 : SkASSERT(SkAlign4(size) == size);
31 :
32 0 : fBase = fCurr = (const char*)data;
33 0 : fStop = (const char*)data + size;
34 0 : }
35 :
36 : size_t size() const { return fStop - fBase; }
37 0 : size_t offset() const { return fCurr - fBase; }
38 0 : bool eof() const { return fCurr >= fStop; }
39 : const void* base() const { return fBase; }
40 0 : const void* peek() const { return fCurr; }
41 :
42 0 : size_t available() const { return fStop - fCurr; }
43 0 : bool isAvailable(size_t size) const { return size <= this->available(); }
44 :
45 : void rewind() { fCurr = fBase; }
46 :
47 : void setOffset(size_t offset) {
48 : SkASSERT(SkAlign4(offset) == offset);
49 : SkASSERT(offset <= this->size());
50 : fCurr = fBase + offset;
51 : }
52 :
53 0 : bool readBool() { return this->readInt() != 0; }
54 :
55 0 : int32_t readInt() {
56 0 : SkASSERT(ptr_align_4(fCurr));
57 0 : int32_t value = *(const int32_t*)fCurr;
58 0 : fCurr += sizeof(value);
59 0 : SkASSERT(fCurr <= fStop);
60 0 : return value;
61 : }
62 :
63 : void* readPtr() {
64 : void* ptr;
65 : // we presume this "if" is resolved at compile-time
66 : if (4 == sizeof(void*)) {
67 : ptr = *(void**)fCurr;
68 : } else {
69 : memcpy(&ptr, fCurr, sizeof(void*));
70 : }
71 : fCurr += sizeof(void*);
72 : return ptr;
73 : }
74 :
75 0 : SkScalar readScalar() {
76 0 : SkASSERT(ptr_align_4(fCurr));
77 0 : SkScalar value = *(const SkScalar*)fCurr;
78 0 : fCurr += sizeof(value);
79 0 : SkASSERT(fCurr <= fStop);
80 0 : return value;
81 : }
82 :
83 0 : const void* skip(size_t size) {
84 0 : SkASSERT(ptr_align_4(fCurr));
85 0 : const void* addr = fCurr;
86 0 : fCurr += SkAlign4(size);
87 0 : SkASSERT(fCurr <= fStop);
88 0 : return addr;
89 : }
90 :
91 : template <typename T> const T& skipT() {
92 : SkASSERT(SkAlign4(sizeof(T)) == sizeof(T));
93 : return *(const T*)this->skip(sizeof(T));
94 : }
95 :
96 0 : void read(void* dst, size_t size) {
97 0 : SkASSERT(0 == size || dst != nullptr);
98 0 : SkASSERT(ptr_align_4(fCurr));
99 0 : sk_careful_memcpy(dst, fCurr, size);
100 0 : fCurr += SkAlign4(size);
101 0 : SkASSERT(fCurr <= fStop);
102 0 : }
103 :
104 : uint8_t readU8() { return (uint8_t)this->readInt(); }
105 : uint16_t readU16() { return (uint16_t)this->readInt(); }
106 : int32_t readS32() { return this->readInt(); }
107 0 : uint32_t readU32() { return this->readInt(); }
108 :
109 0 : bool readPath(SkPath* path) {
110 0 : return this->readObjectFromMemory(path);
111 : }
112 :
113 0 : bool readMatrix(SkMatrix* matrix) {
114 0 : return this->readObjectFromMemory(matrix);
115 : }
116 :
117 0 : bool readRRect(SkRRect* rrect) {
118 0 : return this->readObjectFromMemory(rrect);
119 : }
120 :
121 0 : bool readRegion(SkRegion* rgn) {
122 0 : return this->readObjectFromMemory(rgn);
123 : }
124 :
125 : /**
126 : * Read the length of a string (written by SkWriter32::writeString) into
127 : * len (if len is not nullptr) and return the null-ternimated address of the
128 : * string within the reader's buffer.
129 : */
130 : const char* readString(size_t* len = nullptr);
131 :
132 : /**
133 : * Read the string (written by SkWriter32::writeString) and return it in
134 : * copy (if copy is not null). Return the length of the string.
135 : */
136 : size_t readIntoString(SkString* copy);
137 :
138 : sk_sp<SkData> readData() {
139 : uint32_t byteLength = this->readU32();
140 : if (0 == byteLength) {
141 : return SkData::MakeEmpty();
142 : }
143 : return SkData::MakeWithCopy(this->skip(byteLength), byteLength);
144 : }
145 :
146 : private:
147 0 : template <typename T> bool readObjectFromMemory(T* obj) {
148 0 : size_t size = obj->readFromMemory(this->peek(), this->available());
149 : // If readFromMemory() fails (which means that available() was too small), it returns 0
150 0 : bool success = (size > 0) && (size <= this->available()) && (SkAlign4(size) == size);
151 : // In case of failure, we want to skip to the end
152 0 : (void)this->skip(success ? size : this->available());
153 0 : return success;
154 : }
155 :
156 : // these are always 4-byte aligned
157 : const char* fCurr; // current position within buffer
158 : const char* fStop; // end of buffer
159 : const char* fBase; // beginning of buffer
160 :
161 : #ifdef SK_DEBUG
162 0 : static bool ptr_align_4(const void* ptr) {
163 0 : return (((const char*)ptr - (const char*)nullptr) & 3) == 0;
164 : }
165 : #endif
166 : };
167 :
168 : #endif
|