blob: 92ed7059dbf9654cc2ff59625b03815788e19374 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkBuffer_DEFINED
11#define SkBuffer_DEFINED
12
13#include "SkScalar.h"
bungemand3ebb482015-08-05 13:57:49 -070014#include "SkTypes.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015
16/** \class SkRBuffer
17
18 Light weight class for reading data from a memory block.
19 The RBuffer is given the buffer to read from, with either a specified size
20 or no size (in which case no range checking is performed). It is iillegal
rmistry@google.comfbfcd562012-08-23 18:09:54 +000021 to attempt to read a value from an empty RBuffer (data == null).
reed@android.com8a1c16f2008-12-17 15:59:43 +000022*/
23class SkRBuffer : SkNoncopyable {
24public:
25 SkRBuffer() : fData(0), fPos(0), fStop(0) {}
26 /** Initialize RBuffer with a data pointer, but no specified length.
27 This signals the RBuffer to not perform range checks during reading.
28 */
reed@google.com7894b922011-05-03 15:41:49 +000029 SkRBuffer(const void* data) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000030 fData = (const char*)data;
31 fPos = (const char*)data;
32 fStop = 0; // no bounds checking
33 }
34 /** Initialize RBuffer with a data point and length.
35 */
reed@google.com7894b922011-05-03 15:41:49 +000036 SkRBuffer(const void* data, size_t size) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037 SkASSERT(data != 0 || size == 0);
38 fData = (const char*)data;
39 fPos = (const char*)data;
40 fStop = (const char*)data + size;
41 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000042
mtklein@google.comf1077f92013-11-20 15:13:49 +000043 virtual ~SkRBuffer() { }
44
reed@android.com8a1c16f2008-12-17 15:59:43 +000045 /** Return the number of bytes that have been read from the beginning
46 of the data pointer.
47 */
48 size_t pos() const { return fPos - fData; }
49 /** Return the total size of the data pointer. Only defined if the length was
50 specified in the constructor or in a call to reset().
51 */
52 size_t size() const { return fStop - fData; }
53 /** Return true if the buffer has read to the end of the data pointer.
54 Only defined if the length was specified in the constructor or in a call
55 to reset(). Always returns true if the length was not specified.
56 */
57 bool eof() const { return fPos >= fStop; }
58
59 /** Read the specified number of bytes from the data pointer. If buffer is not
60 null, copy those bytes into buffer.
61 */
commit-bot@chromium.org8f457e32013-11-08 19:22:57 +000062 virtual bool read(void* buffer, size_t size) {
reed@google.com7894b922011-05-03 15:41:49 +000063 if (size) {
64 this->readNoSizeCheck(buffer, size);
65 }
commit-bot@chromium.org8f457e32013-11-08 19:22:57 +000066 return true;
reed@google.com7894b922011-05-03 15:41:49 +000067 }
68
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 const void* skip(size_t size); // return start of skipped data
70 size_t skipToAlign4();
71
commit-bot@chromium.org8f457e32013-11-08 19:22:57 +000072 bool readPtr(void** ptr) { return read(ptr, sizeof(void*)); }
73 bool readScalar(SkScalar* x) { return read(x, 4); }
74 bool readU32(uint32_t* x) { return read(x, 4); }
75 bool readS32(int32_t* x) { return read(x, 4); }
76 bool readU16(uint16_t* x) { return read(x, 2); }
77 bool readS16(int16_t* x) { return read(x, 2); }
78 bool readU8(uint8_t* x) { return read(x, 1); }
79 bool readBool(bool* x) {
80 uint8_t u8;
81 if (this->readU8(&u8)) {
82 *x = (u8 != 0);
83 return true;
84 }
85 return false;
86 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000087
commit-bot@chromium.org4faa8692013-11-05 15:46:56 +000088protected:
reed@android.com8a1c16f2008-12-17 15:59:43 +000089 void readNoSizeCheck(void* buffer, size_t size);
90
91 const char* fData;
92 const char* fPos;
93 const char* fStop;
94};
95
commit-bot@chromium.org4faa8692013-11-05 15:46:56 +000096/** \class SkRBufferWithSizeCheck
97
98 Same as SkRBuffer, except that a size check is performed before the read operation and an
99 error is set if the read operation is attempting to read past the end of the data.
100*/
101class SkRBufferWithSizeCheck : public SkRBuffer {
102public:
103 SkRBufferWithSizeCheck(const void* data, size_t size) : SkRBuffer(data, size), fError(false) {}
104
105 /** Read the specified number of bytes from the data pointer. If buffer is not
106 null and the number of bytes to read does not overflow this object's data,
107 copy those bytes into buffer.
108 */
mtklein36352bf2015-03-25 18:17:31 -0700109 bool read(void* buffer, size_t size) override;
commit-bot@chromium.org4faa8692013-11-05 15:46:56 +0000110
111 /** Returns whether or not a read operation attempted to read past the end of the data.
112 */
113 bool isValid() const { return !fError; }
114private:
115 bool fError;
116};
117
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118/** \class SkWBuffer
119
120 Light weight class for writing data to a memory block.
121 The WBuffer is given the buffer to write into, with either a specified size
122 or no size, in which case no range checking is performed. An empty WBuffer
123 is legal, in which case no data is ever written, but the relative pos()
124 is updated.
125*/
126class SkWBuffer : SkNoncopyable {
127public:
128 SkWBuffer() : fData(0), fPos(0), fStop(0) {}
129 SkWBuffer(void* data) { reset(data); }
130 SkWBuffer(void* data, size_t size) { reset(data, size); }
131
reed@google.com7894b922011-05-03 15:41:49 +0000132 void reset(void* data) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133 fData = (char*)data;
134 fPos = (char*)data;
135 fStop = 0; // no bounds checking
136 }
reed@google.com7894b922011-05-03 15:41:49 +0000137
138 void reset(void* data, size_t size) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 SkASSERT(data != 0 || size == 0);
140 fData = (char*)data;
141 fPos = (char*)data;
142 fStop = (char*)data + size;
143 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000144
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 size_t pos() const { return fPos - fData; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146 void* skip(size_t size); // return start of skipped data
reed@google.com7894b922011-05-03 15:41:49 +0000147
148 void write(const void* buffer, size_t size) {
149 if (size) {
150 this->writeNoSizeCheck(buffer, size);
151 }
152 }
153
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154 size_t padToAlign4();
155
156 void writePtr(const void* x) { this->writeNoSizeCheck(&x, sizeof(x)); }
157 void writeScalar(SkScalar x) { this->writeNoSizeCheck(&x, 4); }
158 void write32(int32_t x) { this->writeNoSizeCheck(&x, 4); }
159 void write16(int16_t x) { this->writeNoSizeCheck(&x, 2); }
160 void write8(int8_t x) { this->writeNoSizeCheck(&x, 1); }
161 void writeBool(bool x) { this->write8(x); }
162
reed@google.combc4b66f2012-08-16 16:46:27 +0000163private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164 void writeNoSizeCheck(const void* buffer, size_t size);
165
166 char* fData;
167 char* fPos;
168 char* fStop;
169};
170
171#endif