1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkBuffer_DEFINED
18#define SkBuffer_DEFINED
19
20#include "SkScalar.h"
21
22/** \class SkRBuffer
23
24    Light weight class for reading data from a memory block.
25    The RBuffer is given the buffer to read from, with either a specified size
26    or no size (in which case no range checking is performed). It is iillegal
27    to attempt to read a value from an empty RBuffer (data == null).
28*/
29class SkRBuffer : SkNoncopyable {
30public:
31    SkRBuffer() : fData(0), fPos(0), fStop(0) {}
32    /** Initialize RBuffer with a data pointer, but no specified length.
33        This signals the RBuffer to not perform range checks during reading.
34    */
35    SkRBuffer(const void* data) {
36        fData = (const char*)data;
37        fPos = (const char*)data;
38        fStop = 0;  // no bounds checking
39    }
40    /** Initialize RBuffer with a data point and length.
41    */
42    SkRBuffer(const void* data, size_t size) {
43        SkASSERT(data != 0 || size == 0);
44        fData = (const char*)data;
45        fPos = (const char*)data;
46        fStop = (const char*)data + size;
47    }
48
49    /** Return the number of bytes that have been read from the beginning
50        of the data pointer.
51    */
52    size_t  pos() const { return fPos - fData; }
53    /** Return the total size of the data pointer. Only defined if the length was
54        specified in the constructor or in a call to reset().
55    */
56    size_t  size() const { return fStop - fData; }
57    /** Return true if the buffer has read to the end of the data pointer.
58        Only defined if the length was specified in the constructor or in a call
59        to reset(). Always returns true if the length was not specified.
60    */
61    bool    eof() const { return fPos >= fStop; }
62
63    /** Read the specified number of bytes from the data pointer. If buffer is not
64        null, copy those bytes into buffer.
65    */
66    void read(void* buffer, size_t size) {
67        if (size) {
68            this->readNoSizeCheck(buffer, size);
69        }
70    }
71
72    const void* skip(size_t size); // return start of skipped data
73    size_t  skipToAlign4();
74
75    void*       readPtr() { void* ptr; read(&ptr, sizeof(ptr)); return ptr; }
76    SkScalar    readScalar() { SkScalar x; read(&x, 4); return x; }
77    uint32_t    readU32() { uint32_t x; read(&x, 4); return x; }
78    int32_t     readS32() { int32_t x; read(&x, 4); return x; }
79    uint16_t    readU16() { uint16_t x; read(&x, 2); return x; }
80    int16_t     readS16() { int16_t x; read(&x, 2); return x; }
81    uint8_t     readU8() { uint8_t x; read(&x, 1); return x; }
82    bool        readBool() { return this->readU8() != 0; }
83
84protected:
85    void    readNoSizeCheck(void* buffer, size_t size);
86
87    const char* fData;
88    const char* fPos;
89    const char* fStop;
90};
91
92/** \class SkWBuffer
93
94    Light weight class for writing data to a memory block.
95    The WBuffer is given the buffer to write into, with either a specified size
96    or no size, in which case no range checking is performed. An empty WBuffer
97    is legal, in which case no data is ever written, but the relative pos()
98    is updated.
99*/
100class SkWBuffer : SkNoncopyable {
101public:
102    SkWBuffer() : fData(0), fPos(0), fStop(0) {}
103    SkWBuffer(void* data) { reset(data); }
104    SkWBuffer(void* data, size_t size) { reset(data, size); }
105
106    void reset(void* data) {
107        fData = (char*)data;
108        fPos = (char*)data;
109        fStop = 0;  // no bounds checking
110    }
111
112    void reset(void* data, size_t size) {
113        SkASSERT(data != 0 || size == 0);
114        fData = (char*)data;
115        fPos = (char*)data;
116        fStop = (char*)data + size;
117    }
118
119    size_t  pos() const { return fPos - fData; }
120    void*   skip(size_t size); // return start of skipped data
121
122    void write(const void* buffer, size_t size) {
123        if (size) {
124            this->writeNoSizeCheck(buffer, size);
125        }
126    }
127
128    size_t  padToAlign4();
129
130    void    writePtr(const void* x) { this->writeNoSizeCheck(&x, sizeof(x)); }
131    void    writeScalar(SkScalar x) { this->writeNoSizeCheck(&x, 4); }
132    void    write32(int32_t x) { this->writeNoSizeCheck(&x, 4); }
133    void    write16(int16_t x) { this->writeNoSizeCheck(&x, 2); }
134    void    write8(int8_t x) { this->writeNoSizeCheck(&x, 1); }
135    void    writeBool(bool x) { this->write8(x); }
136
137protected:
138    void    writeNoSizeCheck(const void* buffer, size_t size);
139
140    char* fData;
141    char* fPos;
142    char* fStop;
143};
144
145#endif
146
147