blob: 9791cf55a14a8c5bfde23d7a28effc9d3988f047 [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"
14
15/** \class SkRBuffer
16
17 Light weight class for reading data from a memory block.
18 The RBuffer is given the buffer to read from, with either a specified size
19 or no size (in which case no range checking is performed). It is iillegal
rmistry@google.comfbfcd562012-08-23 18:09:54 +000020 to attempt to read a value from an empty RBuffer (data == null).
reed@android.com8a1c16f2008-12-17 15:59:43 +000021*/
22class SkRBuffer : SkNoncopyable {
23public:
24 SkRBuffer() : fData(0), fPos(0), fStop(0) {}
25 /** Initialize RBuffer with a data pointer, but no specified length.
26 This signals the RBuffer to not perform range checks during reading.
27 */
reed@google.com7894b922011-05-03 15:41:49 +000028 SkRBuffer(const void* data) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000029 fData = (const char*)data;
30 fPos = (const char*)data;
31 fStop = 0; // no bounds checking
32 }
33 /** Initialize RBuffer with a data point and length.
34 */
reed@google.com7894b922011-05-03 15:41:49 +000035 SkRBuffer(const void* data, size_t size) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000036 SkASSERT(data != 0 || size == 0);
37 fData = (const char*)data;
38 fPos = (const char*)data;
39 fStop = (const char*)data + size;
40 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000041
mtklein@google.comf1077f92013-11-20 15:13:49 +000042 virtual ~SkRBuffer() { }
43
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 /** Return the number of bytes that have been read from the beginning
45 of the data pointer.
46 */
47 size_t pos() const { return fPos - fData; }
48 /** Return the total size of the data pointer. Only defined if the length was
49 specified in the constructor or in a call to reset().
50 */
51 size_t size() const { return fStop - fData; }
52 /** Return true if the buffer has read to the end of the data pointer.
53 Only defined if the length was specified in the constructor or in a call
54 to reset(). Always returns true if the length was not specified.
55 */
56 bool eof() const { return fPos >= fStop; }
57
58 /** Read the specified number of bytes from the data pointer. If buffer is not
59 null, copy those bytes into buffer.
60 */
commit-bot@chromium.org8f457e32013-11-08 19:22:57 +000061 virtual bool read(void* buffer, size_t size) {
reed@google.com7894b922011-05-03 15:41:49 +000062 if (size) {
63 this->readNoSizeCheck(buffer, size);
64 }
commit-bot@chromium.org8f457e32013-11-08 19:22:57 +000065 return true;
reed@google.com7894b922011-05-03 15:41:49 +000066 }
67
reed@android.com8a1c16f2008-12-17 15:59:43 +000068 const void* skip(size_t size); // return start of skipped data
69 size_t skipToAlign4();
70
commit-bot@chromium.org8f457e32013-11-08 19:22:57 +000071 bool readPtr(void** ptr) { return read(ptr, sizeof(void*)); }
72 bool readScalar(SkScalar* x) { return read(x, 4); }
73 bool readU32(uint32_t* x) { return read(x, 4); }
74 bool readS32(int32_t* x) { return read(x, 4); }
75 bool readU16(uint16_t* x) { return read(x, 2); }
76 bool readS16(int16_t* x) { return read(x, 2); }
77 bool readU8(uint8_t* x) { return read(x, 1); }
78 bool readBool(bool* x) {
79 uint8_t u8;
80 if (this->readU8(&u8)) {
81 *x = (u8 != 0);
82 return true;
83 }
84 return false;
85 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000086
commit-bot@chromium.org4faa8692013-11-05 15:46:56 +000087protected:
reed@android.com8a1c16f2008-12-17 15:59:43 +000088 void readNoSizeCheck(void* buffer, size_t size);
89
90 const char* fData;
91 const char* fPos;
92 const char* fStop;
93};
94
commit-bot@chromium.org4faa8692013-11-05 15:46:56 +000095/** \class SkRBufferWithSizeCheck
96
97 Same as SkRBuffer, except that a size check is performed before the read operation and an
98 error is set if the read operation is attempting to read past the end of the data.
99*/
100class SkRBufferWithSizeCheck : public SkRBuffer {
101public:
102 SkRBufferWithSizeCheck(const void* data, size_t size) : SkRBuffer(data, size), fError(false) {}
103
104 /** Read the specified number of bytes from the data pointer. If buffer is not
105 null and the number of bytes to read does not overflow this object's data,
106 copy those bytes into buffer.
107 */
commit-bot@chromium.org8f457e32013-11-08 19:22:57 +0000108 virtual bool read(void* buffer, size_t size) SK_OVERRIDE;
commit-bot@chromium.org4faa8692013-11-05 15:46:56 +0000109
110 /** Returns whether or not a read operation attempted to read past the end of the data.
111 */
112 bool isValid() const { return !fError; }
113private:
114 bool fError;
115};
116
reed@android.com8a1c16f2008-12-17 15:59:43 +0000117/** \class SkWBuffer
118
119 Light weight class for writing data to a memory block.
120 The WBuffer is given the buffer to write into, with either a specified size
121 or no size, in which case no range checking is performed. An empty WBuffer
122 is legal, in which case no data is ever written, but the relative pos()
123 is updated.
124*/
125class SkWBuffer : SkNoncopyable {
126public:
127 SkWBuffer() : fData(0), fPos(0), fStop(0) {}
128 SkWBuffer(void* data) { reset(data); }
129 SkWBuffer(void* data, size_t size) { reset(data, size); }
130
reed@google.com7894b922011-05-03 15:41:49 +0000131 void reset(void* data) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 fData = (char*)data;
133 fPos = (char*)data;
134 fStop = 0; // no bounds checking
135 }
reed@google.com7894b922011-05-03 15:41:49 +0000136
137 void reset(void* data, size_t size) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138 SkASSERT(data != 0 || size == 0);
139 fData = (char*)data;
140 fPos = (char*)data;
141 fStop = (char*)data + size;
142 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000143
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144 size_t pos() const { return fPos - fData; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 void* skip(size_t size); // return start of skipped data
reed@google.com7894b922011-05-03 15:41:49 +0000146
147 void write(const void* buffer, size_t size) {
148 if (size) {
149 this->writeNoSizeCheck(buffer, size);
150 }
151 }
152
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153 size_t padToAlign4();
154
155 void writePtr(const void* x) { this->writeNoSizeCheck(&x, sizeof(x)); }
156 void writeScalar(SkScalar x) { this->writeNoSizeCheck(&x, 4); }
157 void write32(int32_t x) { this->writeNoSizeCheck(&x, 4); }
158 void write16(int16_t x) { this->writeNoSizeCheck(&x, 2); }
159 void write8(int8_t x) { this->writeNoSizeCheck(&x, 1); }
160 void writeBool(bool x) { this->write8(x); }
161
reed@google.combc4b66f2012-08-16 16:46:27 +0000162private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163 void writeNoSizeCheck(const void* buffer, size_t size);
164
165 char* fData;
166 char* fPos;
167 char* fStop;
168};
169
170#endif