1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#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
20    to attempt to read a value from an empty RBuffer (data == null).
21*/
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    */
28    SkRBuffer(const void* data) {
29        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    */
35    SkRBuffer(const void* data, size_t size) {
36        SkASSERT(data != 0 || size == 0);
37        fData = (const char*)data;
38        fPos = (const char*)data;
39        fStop = (const char*)data + size;
40    }
41
42    virtual ~SkRBuffer() { }
43
44    /** 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    */
61    virtual bool read(void* buffer, size_t size) {
62        if (size) {
63            this->readNoSizeCheck(buffer, size);
64        }
65        return true;
66    }
67
68    const void* skip(size_t size); // return start of skipped data
69    size_t  skipToAlign4();
70
71    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    }
86
87protected:
88    void    readNoSizeCheck(void* buffer, size_t size);
89
90    const char* fData;
91    const char* fPos;
92    const char* fStop;
93};
94
95/** \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    */
108    virtual bool read(void* buffer, size_t size) SK_OVERRIDE;
109
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
117/** \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
131    void reset(void* data) {
132        fData = (char*)data;
133        fPos = (char*)data;
134        fStop = 0;  // no bounds checking
135    }
136
137    void reset(void* data, size_t size) {
138        SkASSERT(data != 0 || size == 0);
139        fData = (char*)data;
140        fPos = (char*)data;
141        fStop = (char*)data + size;
142    }
143
144    size_t  pos() const { return fPos - fData; }
145    void*   skip(size_t size); // return start of skipped data
146
147    void write(const void* buffer, size_t size) {
148        if (size) {
149            this->writeNoSizeCheck(buffer, size);
150        }
151    }
152
153    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
162private:
163    void    writeNoSizeCheck(const void* buffer, size_t size);
164
165    char* fData;
166    char* fPos;
167    char* fStop;
168};
169
170#endif
171