1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkBuffer_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkBuffer_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalar.h"
142880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkTypes.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkRBuffer
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Light weight class for reading data from a memory block.
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The RBuffer is given the buffer to read from, with either a specified size
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    or no size (in which case no range checking is performed). It is iillegal
21fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    to attempt to read a value from an empty RBuffer (data == null).
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkRBuffer : SkNoncopyable {
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRBuffer() : fData(0), fPos(0), fStop(0) {}
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Initialize RBuffer with a data pointer, but no specified length.
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        This signals the RBuffer to not perform range checks during reading.
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
297894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com    SkRBuffer(const void* data) {
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fData = (const char*)data;
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPos = (const char*)data;
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStop = 0;  // no bounds checking
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Initialize RBuffer with a data point and length.
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
367894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com    SkRBuffer(const void* data, size_t size) {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(data != 0 || size == 0);
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fData = (const char*)data;
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPos = (const char*)data;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStop = (const char*)data + size;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
42fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
43f1077f916427c99bdec655da4c3b9eea70423685mtklein@google.com    virtual ~SkRBuffer() { }
44f1077f916427c99bdec655da4c3b9eea70423685mtklein@google.com
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the number of bytes that have been read from the beginning
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        of the data pointer.
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  pos() const { return fPos - fData; }
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the total size of the data pointer. Only defined if the length was
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        specified in the constructor or in a call to reset().
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  size() const { return fStop - fData; }
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return true if the buffer has read to the end of the data pointer.
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Only defined if the length was specified in the constructor or in a call
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to reset(). Always returns true if the length was not specified.
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool    eof() const { return fPos >= fStop; }
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Read the specified number of bytes from the data pointer. If buffer is not
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        null, copy those bytes into buffer.
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
628f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    virtual bool read(void* buffer, size_t size) {
637894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com        if (size) {
647894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com            this->readNoSizeCheck(buffer, size);
657894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com        }
668f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org        return true;
677894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com    }
687894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const void* skip(size_t size); // return start of skipped data
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  skipToAlign4();
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
728f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    bool readPtr(void** ptr) { return read(ptr, sizeof(void*)); }
738f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    bool readScalar(SkScalar* x) { return read(x, 4); }
748f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    bool readU32(uint32_t* x) { return read(x, 4); }
758f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    bool readS32(int32_t* x) { return read(x, 4); }
768f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    bool readU16(uint16_t* x) { return read(x, 2); }
778f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    bool readS16(int16_t* x) { return read(x, 2); }
788f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    bool readU8(uint8_t* x) { return read(x, 1); }
798f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    bool readBool(bool* x) {
808f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org        uint8_t u8;
818f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org        if (this->readU8(&u8)) {
828f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org            *x = (u8 != 0);
838f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org            return true;
848f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org        }
858f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org        return false;
868f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    }
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
884faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgprotected:
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    readNoSizeCheck(void* buffer, size_t size);
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* fData;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* fPos;
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* fStop;
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
964faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org/** \class SkRBufferWithSizeCheck
974faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org
984faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    Same as SkRBuffer, except that a size check is performed before the read operation and an
994faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    error is set if the read operation is attempting to read past the end of the data.
1004faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org*/
1014faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgclass SkRBufferWithSizeCheck : public SkRBuffer {
1024faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgpublic:
1034faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    SkRBufferWithSizeCheck(const void* data, size_t size) : SkRBuffer(data, size), fError(false) {}
1044faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org
1054faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    /** Read the specified number of bytes from the data pointer. If buffer is not
1064faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org        null and the number of bytes to read does not overflow this object's data,
1074faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org        copy those bytes into buffer.
1084faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    */
10936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool read(void* buffer, size_t size) override;
1104faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org
1114faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    /** Returns whether or not a read operation attempted to read past the end of the data.
1124faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    */
1134faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    bool isValid() const { return !fError; }
1144faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgprivate:
1154faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    bool fError;
1164faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org};
1174faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkWBuffer
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Light weight class for writing data to a memory block.
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The WBuffer is given the buffer to write into, with either a specified size
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    or no size, in which case no range checking is performed. An empty WBuffer
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    is legal, in which case no data is ever written, but the relative pos()
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    is updated.
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkWBuffer : SkNoncopyable {
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkWBuffer() : fData(0), fPos(0), fStop(0) {}
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkWBuffer(void* data) { reset(data); }
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkWBuffer(void* data, size_t size) { reset(data, size); }
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1327894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com    void reset(void* data) {
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fData = (char*)data;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPos = (char*)data;
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStop = 0;  // no bounds checking
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1377894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com
1387894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com    void reset(void* data, size_t size) {
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(data != 0 || size == 0);
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fData = (char*)data;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPos = (char*)data;
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStop = (char*)data + size;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
144fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  pos() const { return fPos - fData; }
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void*   skip(size_t size); // return start of skipped data
1477894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com
1487894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com    void write(const void* buffer, size_t size) {
1497894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com        if (size) {
1507894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com            this->writeNoSizeCheck(buffer, size);
1517894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com        }
1527894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com    }
1537894b92b57b19d0e80e2e0187064fc9e8862d621reed@google.com
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  padToAlign4();
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    writePtr(const void* x) { this->writeNoSizeCheck(&x, sizeof(x)); }
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    writeScalar(SkScalar x) { this->writeNoSizeCheck(&x, 4); }
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    write32(int32_t x) { this->writeNoSizeCheck(&x, 4); }
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    write16(int16_t x) { this->writeNoSizeCheck(&x, 2); }
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    write8(int8_t x) { this->writeNoSizeCheck(&x, 1); }
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    writeBool(bool x) { this->write8(x); }
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
163bc4b66f42c169b03559773f2b7181b2b95cbe8cdreed@google.comprivate:
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void    writeNoSizeCheck(const void* buffer, size_t size);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char* fData;
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char* fPos;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char* fStop;
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
172