michael@0: michael@0: /* michael@0: * Copyright 2008 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #ifndef SkReader32_DEFINED michael@0: #define SkReader32_DEFINED michael@0: michael@0: #include "SkMatrix.h" michael@0: #include "SkPath.h" michael@0: #include "SkRegion.h" michael@0: #include "SkRRect.h" michael@0: #include "SkScalar.h" michael@0: michael@0: class SkString; michael@0: michael@0: class SkReader32 : SkNoncopyable { michael@0: public: michael@0: SkReader32() : fCurr(NULL), fStop(NULL), fBase(NULL) {} michael@0: SkReader32(const void* data, size_t size) { michael@0: this->setMemory(data, size); michael@0: } michael@0: michael@0: void setMemory(const void* data, size_t size) { michael@0: SkASSERT(ptr_align_4(data)); michael@0: SkASSERT(SkAlign4(size) == size); michael@0: michael@0: fBase = fCurr = (const char*)data; michael@0: fStop = (const char*)data + size; michael@0: } michael@0: michael@0: uint32_t size() const { return SkToU32(fStop - fBase); } michael@0: uint32_t offset() const { return SkToU32(fCurr - fBase); } michael@0: bool eof() const { return fCurr >= fStop; } michael@0: const void* base() const { return fBase; } michael@0: const void* peek() const { return fCurr; } michael@0: michael@0: uint32_t available() const { return SkToU32(fStop - fCurr); } michael@0: bool isAvailable(uint32_t size) const { return fCurr + size <= fStop; } michael@0: michael@0: void rewind() { fCurr = fBase; } michael@0: michael@0: void setOffset(size_t offset) { michael@0: SkASSERT(SkAlign4(offset) == offset); michael@0: SkASSERT(offset <= this->size()); michael@0: fCurr = fBase + offset; michael@0: } michael@0: michael@0: bool readBool() { return this->readInt() != 0; } michael@0: michael@0: int32_t readInt() { michael@0: SkASSERT(ptr_align_4(fCurr)); michael@0: int32_t value = *(const int32_t*)fCurr; michael@0: fCurr += sizeof(value); michael@0: SkASSERT(fCurr <= fStop); michael@0: return value; michael@0: } michael@0: michael@0: void* readPtr() { michael@0: void* ptr; michael@0: // we presume this "if" is resolved at compile-time michael@0: if (4 == sizeof(void*)) { michael@0: ptr = *(void**)fCurr; michael@0: } else { michael@0: memcpy(&ptr, fCurr, sizeof(void*)); michael@0: } michael@0: fCurr += sizeof(void*); michael@0: return ptr; michael@0: } michael@0: michael@0: SkScalar readScalar() { michael@0: SkASSERT(ptr_align_4(fCurr)); michael@0: SkScalar value = *(const SkScalar*)fCurr; michael@0: fCurr += sizeof(value); michael@0: SkASSERT(fCurr <= fStop); michael@0: return value; michael@0: } michael@0: michael@0: const void* skip(size_t size) { michael@0: SkASSERT(ptr_align_4(fCurr)); michael@0: const void* addr = fCurr; michael@0: fCurr += SkAlign4(size); michael@0: SkASSERT(fCurr <= fStop); michael@0: return addr; michael@0: } michael@0: michael@0: template const T& skipT() { michael@0: SkASSERT(SkAlign4(sizeof(T)) == sizeof(T)); michael@0: return *(const T*)this->skip(sizeof(T)); michael@0: } michael@0: michael@0: void read(void* dst, size_t size) { michael@0: SkASSERT(0 == size || dst != NULL); michael@0: SkASSERT(ptr_align_4(fCurr)); michael@0: memcpy(dst, fCurr, size); michael@0: fCurr += SkAlign4(size); michael@0: SkASSERT(fCurr <= fStop); michael@0: } michael@0: michael@0: uint8_t readU8() { return (uint8_t)this->readInt(); } michael@0: uint16_t readU16() { return (uint16_t)this->readInt(); } michael@0: int32_t readS32() { return this->readInt(); } michael@0: uint32_t readU32() { return this->readInt(); } michael@0: michael@0: bool readPath(SkPath* path) { michael@0: return readObjectFromMemory(path); michael@0: } michael@0: michael@0: bool readMatrix(SkMatrix* matrix) { michael@0: return readObjectFromMemory(matrix); michael@0: } michael@0: michael@0: bool readRRect(SkRRect* rrect) { michael@0: return readObjectFromMemory(rrect); michael@0: } michael@0: michael@0: bool readRegion(SkRegion* rgn) { michael@0: return readObjectFromMemory(rgn); michael@0: } michael@0: michael@0: /** michael@0: * Read the length of a string (written by SkWriter32::writeString) into michael@0: * len (if len is not NULL) and return the null-ternimated address of the michael@0: * string within the reader's buffer. michael@0: */ michael@0: const char* readString(size_t* len = NULL); michael@0: michael@0: /** michael@0: * Read the string (written by SkWriter32::writeString) and return it in michael@0: * copy (if copy is not null). Return the length of the string. michael@0: */ michael@0: size_t readIntoString(SkString* copy); michael@0: michael@0: private: michael@0: template bool readObjectFromMemory(T* obj) { michael@0: size_t size = obj->readFromMemory(this->peek(), this->available()); michael@0: // If readFromMemory() fails (which means that available() was too small), it returns 0 michael@0: bool success = (size > 0) && (size <= this->available()) && (SkAlign4(size) == size); michael@0: // In case of failure, we want to skip to the end michael@0: (void)this->skip(success ? size : this->available()); michael@0: return success; michael@0: } michael@0: michael@0: // these are always 4-byte aligned michael@0: const char* fCurr; // current position within buffer michael@0: const char* fStop; // end of buffer michael@0: const char* fBase; // beginning of buffer michael@0: michael@0: #ifdef SK_DEBUG michael@0: static bool ptr_align_4(const void* ptr) { michael@0: return (((const char*)ptr - (const char*)NULL) & 3) == 0; michael@0: } michael@0: #endif michael@0: }; michael@0: michael@0: #endif