1 2 /* 3 * Copyright 2008 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 SkReader32_DEFINED 11 #define SkReader32_DEFINED 12 13 #include "SkMatrix.h" 14 #include "SkPath.h" 15 #include "SkRegion.h" 16 #include "SkRRect.h" 17 #include "SkScalar.h" 18 19 class SkString; 20 21 class SkReader32 : SkNoncopyable { 22 public: SkReader32()23 SkReader32() : fCurr(NULL), fStop(NULL), fBase(NULL) {} SkReader32(const void * data,size_t size)24 SkReader32(const void* data, size_t size) { 25 this->setMemory(data, size); 26 } 27 setMemory(const void * data,size_t size)28 void setMemory(const void* data, size_t size) { 29 SkASSERT(ptr_align_4(data)); 30 SkASSERT(SkAlign4(size) == size); 31 32 fBase = fCurr = (const char*)data; 33 fStop = (const char*)data + size; 34 } 35 size()36 size_t size() const { return fStop - fBase; } offset()37 size_t offset() const { return fCurr - fBase; } eof()38 bool eof() const { return fCurr >= fStop; } base()39 const void* base() const { return fBase; } peek()40 const void* peek() const { return fCurr; } 41 available()42 size_t available() const { return fStop - fCurr; } isAvailable(size_t size)43 bool isAvailable(size_t size) const { return size <= this->available(); } 44 rewind()45 void rewind() { fCurr = fBase; } 46 setOffset(size_t offset)47 void setOffset(size_t offset) { 48 SkASSERT(SkAlign4(offset) == offset); 49 SkASSERT(offset <= this->size()); 50 fCurr = fBase + offset; 51 } 52 readBool()53 bool readBool() { return this->readInt() != 0; } 54 readInt()55 int32_t readInt() { 56 SkASSERT(ptr_align_4(fCurr)); 57 int32_t value = *(const int32_t*)fCurr; 58 fCurr += sizeof(value); 59 SkASSERT(fCurr <= fStop); 60 return value; 61 } 62 readPtr()63 void* readPtr() { 64 void* ptr; 65 // we presume this "if" is resolved at compile-time 66 if (4 == sizeof(void*)) { 67 ptr = *(void**)fCurr; 68 } else { 69 memcpy(&ptr, fCurr, sizeof(void*)); 70 } 71 fCurr += sizeof(void*); 72 return ptr; 73 } 74 readScalar()75 SkScalar readScalar() { 76 SkASSERT(ptr_align_4(fCurr)); 77 SkScalar value = *(const SkScalar*)fCurr; 78 fCurr += sizeof(value); 79 SkASSERT(fCurr <= fStop); 80 return value; 81 } 82 skip(size_t size)83 const void* skip(size_t size) { 84 SkASSERT(ptr_align_4(fCurr)); 85 const void* addr = fCurr; 86 fCurr += SkAlign4(size); 87 SkASSERT(fCurr <= fStop); 88 return addr; 89 } 90 skipT()91 template <typename T> const T& skipT() { 92 SkASSERT(SkAlign4(sizeof(T)) == sizeof(T)); 93 return *(const T*)this->skip(sizeof(T)); 94 } 95 read(void * dst,size_t size)96 void read(void* dst, size_t size) { 97 SkASSERT(0 == size || dst != NULL); 98 SkASSERT(ptr_align_4(fCurr)); 99 memcpy(dst, fCurr, size); 100 fCurr += SkAlign4(size); 101 SkASSERT(fCurr <= fStop); 102 } 103 readU8()104 uint8_t readU8() { return (uint8_t)this->readInt(); } readU16()105 uint16_t readU16() { return (uint16_t)this->readInt(); } readS32()106 int32_t readS32() { return this->readInt(); } readU32()107 uint32_t readU32() { return this->readInt(); } 108 readPath(SkPath * path)109 bool readPath(SkPath* path) { 110 return this->readObjectFromMemory(path); 111 } 112 readMatrix(SkMatrix * matrix)113 bool readMatrix(SkMatrix* matrix) { 114 return this->readObjectFromMemory(matrix); 115 } 116 readRRect(SkRRect * rrect)117 bool readRRect(SkRRect* rrect) { 118 return this->readObjectFromMemory(rrect); 119 } 120 readRegion(SkRegion * rgn)121 bool readRegion(SkRegion* rgn) { 122 return this->readObjectFromMemory(rgn); 123 } 124 125 /** 126 * Read the length of a string (written by SkWriter32::writeString) into 127 * len (if len is not NULL) and return the null-ternimated address of the 128 * string within the reader's buffer. 129 */ 130 const char* readString(size_t* len = NULL); 131 132 /** 133 * Read the string (written by SkWriter32::writeString) and return it in 134 * copy (if copy is not null). Return the length of the string. 135 */ 136 size_t readIntoString(SkString* copy); 137 138 private: readObjectFromMemory(T * obj)139 template <typename T> bool readObjectFromMemory(T* obj) { 140 size_t size = obj->readFromMemory(this->peek(), this->available()); 141 // If readFromMemory() fails (which means that available() was too small), it returns 0 142 bool success = (size > 0) && (size <= this->available()) && (SkAlign4(size) == size); 143 // In case of failure, we want to skip to the end 144 (void)this->skip(success ? size : this->available()); 145 return success; 146 } 147 148 // these are always 4-byte aligned 149 const char* fCurr; // current position within buffer 150 const char* fStop; // end of buffer 151 const char* fBase; // beginning of buffer 152 153 #ifdef SK_DEBUG ptr_align_4(const void * ptr)154 static bool ptr_align_4(const void* ptr) { 155 return (((const char*)ptr - (const char*)NULL) & 3) == 0; 156 } 157 #endif 158 }; 159 160 #endif 161