| |
| /* |
| * Copyright 2006 The Android Open Source Project |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| |
| #ifndef SkBuffer_DEFINED |
| #define SkBuffer_DEFINED |
| |
| #include "SkScalar.h" |
| |
| /** \class SkRBuffer |
| |
| Light weight class for reading data from a memory block. |
| The RBuffer is given the buffer to read from, with either a specified size |
| or no size (in which case no range checking is performed). It is iillegal |
| to attempt to read a value from an empty RBuffer (data == null). |
| */ |
| class SkRBuffer : SkNoncopyable { |
| public: |
| SkRBuffer() : fData(0), fPos(0), fStop(0) {} |
| /** Initialize RBuffer with a data pointer, but no specified length. |
| This signals the RBuffer to not perform range checks during reading. |
| */ |
| SkRBuffer(const void* data) { |
| fData = (const char*)data; |
| fPos = (const char*)data; |
| fStop = 0; // no bounds checking |
| } |
| /** Initialize RBuffer with a data point and length. |
| */ |
| SkRBuffer(const void* data, size_t size) { |
| SkASSERT(data != 0 || size == 0); |
| fData = (const char*)data; |
| fPos = (const char*)data; |
| fStop = (const char*)data + size; |
| } |
| |
| virtual ~SkRBuffer() { } |
| |
| /** Return the number of bytes that have been read from the beginning |
| of the data pointer. |
| */ |
| size_t pos() const { return fPos - fData; } |
| /** Return the total size of the data pointer. Only defined if the length was |
| specified in the constructor or in a call to reset(). |
| */ |
| size_t size() const { return fStop - fData; } |
| /** Return true if the buffer has read to the end of the data pointer. |
| Only defined if the length was specified in the constructor or in a call |
| to reset(). Always returns true if the length was not specified. |
| */ |
| bool eof() const { return fPos >= fStop; } |
| |
| /** Read the specified number of bytes from the data pointer. If buffer is not |
| null, copy those bytes into buffer. |
| */ |
| virtual bool read(void* buffer, size_t size) { |
| if (size) { |
| this->readNoSizeCheck(buffer, size); |
| } |
| return true; |
| } |
| |
| const void* skip(size_t size); // return start of skipped data |
| size_t skipToAlign4(); |
| |
| bool readPtr(void** ptr) { return read(ptr, sizeof(void*)); } |
| bool readScalar(SkScalar* x) { return read(x, 4); } |
| bool readU32(uint32_t* x) { return read(x, 4); } |
| bool readS32(int32_t* x) { return read(x, 4); } |
| bool readU16(uint16_t* x) { return read(x, 2); } |
| bool readS16(int16_t* x) { return read(x, 2); } |
| bool readU8(uint8_t* x) { return read(x, 1); } |
| bool readBool(bool* x) { |
| uint8_t u8; |
| if (this->readU8(&u8)) { |
| *x = (u8 != 0); |
| return true; |
| } |
| return false; |
| } |
| |
| protected: |
| void readNoSizeCheck(void* buffer, size_t size); |
| |
| const char* fData; |
| const char* fPos; |
| const char* fStop; |
| }; |
| |
| /** \class SkRBufferWithSizeCheck |
| |
| Same as SkRBuffer, except that a size check is performed before the read operation and an |
| error is set if the read operation is attempting to read past the end of the data. |
| */ |
| class SkRBufferWithSizeCheck : public SkRBuffer { |
| public: |
| SkRBufferWithSizeCheck(const void* data, size_t size) : SkRBuffer(data, size), fError(false) {} |
| |
| /** Read the specified number of bytes from the data pointer. If buffer is not |
| null and the number of bytes to read does not overflow this object's data, |
| copy those bytes into buffer. |
| */ |
| virtual bool read(void* buffer, size_t size) SK_OVERRIDE; |
| |
| /** Returns whether or not a read operation attempted to read past the end of the data. |
| */ |
| bool isValid() const { return !fError; } |
| private: |
| bool fError; |
| }; |
| |
| /** \class SkWBuffer |
| |
| Light weight class for writing data to a memory block. |
| The WBuffer is given the buffer to write into, with either a specified size |
| or no size, in which case no range checking is performed. An empty WBuffer |
| is legal, in which case no data is ever written, but the relative pos() |
| is updated. |
| */ |
| class SkWBuffer : SkNoncopyable { |
| public: |
| SkWBuffer() : fData(0), fPos(0), fStop(0) {} |
| SkWBuffer(void* data) { reset(data); } |
| SkWBuffer(void* data, size_t size) { reset(data, size); } |
| |
| void reset(void* data) { |
| fData = (char*)data; |
| fPos = (char*)data; |
| fStop = 0; // no bounds checking |
| } |
| |
| void reset(void* data, size_t size) { |
| SkASSERT(data != 0 || size == 0); |
| fData = (char*)data; |
| fPos = (char*)data; |
| fStop = (char*)data + size; |
| } |
| |
| size_t pos() const { return fPos - fData; } |
| void* skip(size_t size); // return start of skipped data |
| |
| void write(const void* buffer, size_t size) { |
| if (size) { |
| this->writeNoSizeCheck(buffer, size); |
| } |
| } |
| |
| size_t padToAlign4(); |
| |
| void writePtr(const void* x) { this->writeNoSizeCheck(&x, sizeof(x)); } |
| void writeScalar(SkScalar x) { this->writeNoSizeCheck(&x, 4); } |
| void write32(int32_t x) { this->writeNoSizeCheck(&x, 4); } |
| void write16(int16_t x) { this->writeNoSizeCheck(&x, 2); } |
| void write8(int8_t x) { this->writeNoSizeCheck(&x, 1); } |
| void writeBool(bool x) { this->write8(x); } |
| |
| private: |
| void writeNoSizeCheck(const void* buffer, size_t size); |
| |
| char* fData; |
| char* fPos; |
| char* fStop; |
| }; |
| |
| #endif |