1 #include "SkWriter32.h" 2 3 struct SkWriter32::Block { 4 Block* fNext; 5 size_t fSize; 6 size_t fAllocated; 7 8 size_t available() const { return fSize - fAllocated; } 9 char* base() { return (char*)(this + 1); } 10 const char* base() const { return (const char*)(this + 1); } 11 12 uint32_t* alloc(size_t size) 13 { 14 SkASSERT(SkAlign4(size) == size); 15 SkASSERT(this->available() >= size); 16 void* ptr = this->base() + fAllocated; 17 fAllocated += size; 18 SkASSERT(fAllocated <= fSize); 19 return (uint32_t*)ptr; 20 } 21 22 uint32_t* peek32(size_t offset) 23 { 24 SkASSERT(offset <= fAllocated + 4); 25 void* ptr = this->base() + offset; 26 return (uint32_t*)ptr; 27 } 28 29 static Block* Create(size_t size) 30 { 31 SkASSERT(SkAlign4(size) == size); 32 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); 33 block->fNext = NULL; 34 block->fSize = size; 35 block->fAllocated = 0; 36 return block; 37 } 38 }; 39 40 /////////////////////////////////////////////////////////////////////////////// 41 42 SkWriter32::~SkWriter32() 43 { 44 this->reset(); 45 } 46 47 void SkWriter32::reset() 48 { 49 Block* block = fHead; 50 while (block) 51 { 52 Block* next = block->fNext; 53 sk_free(block); 54 block = next; 55 } 56 fHead = fTail = NULL; 57 fSize = 0; 58 } 59 60 uint32_t* SkWriter32::reserve(size_t size) 61 { 62 SkASSERT(SkAlign4(size) == size); 63 64 Block* block = fTail; 65 66 if (NULL == block) 67 { 68 SkASSERT(NULL == fHead); 69 fHead = fTail = block = Block::Create(SkMax32(size, fMinSize)); 70 } 71 else if (block->available() < size) 72 { 73 fTail = Block::Create(SkMax32(size, fMinSize)); 74 block->fNext = fTail; 75 block = fTail; 76 } 77 78 fSize += size; 79 80 return block->alloc(size); 81 } 82 83 uint32_t* SkWriter32::peek32(size_t offset) 84 { 85 SkASSERT(SkAlign4(offset) == offset); 86 SkASSERT(offset <= fSize); 87 88 Block* block = fHead; 89 SkASSERT(NULL != block); 90 91 while (offset >= block->fAllocated) 92 { 93 offset -= block->fAllocated; 94 block = block->fNext; 95 SkASSERT(NULL != block); 96 } 97 return block->peek32(offset); 98 } 99 100 void SkWriter32::flatten(void* dst) const 101 { 102 const Block* block = fHead; 103 SkDEBUGCODE(size_t total = 0;) 104 105 while (block) 106 { 107 size_t allocated = block->fAllocated; 108 memcpy(dst, block->base(), allocated); 109 dst = (char*)dst + allocated; 110 block = block->fNext; 111 112 SkDEBUGCODE(total += allocated;) 113 SkASSERT(total <= fSize); 114 } 115 SkASSERT(total == fSize); 116 } 117 118 void SkWriter32::writePad(const void* src, size_t size) { 119 size_t alignedSize = SkAlign4(size); 120 char* dst = (char*)this->reserve(alignedSize); 121 memcpy(dst, src, size); 122 dst += size; 123 int n = alignedSize - size; 124 while (--n >= 0) { 125 *dst++ = 0; 126 } 127 } 128 129 #include "SkStream.h" 130 131 size_t SkWriter32::readFromStream(SkStream* stream, size_t length) { 132 char scratch[1024]; 133 const size_t MAX = sizeof(scratch); 134 size_t remaining = length; 135 136 while (remaining != 0) { 137 size_t n = remaining; 138 if (n > MAX) { 139 n = MAX; 140 } 141 size_t bytes = stream->read(scratch, n); 142 this->writePad(scratch, bytes); 143 remaining -= bytes; 144 if (bytes != n) { 145 break; 146 } 147 } 148 return length - remaining; 149 } 150 151 bool SkWriter32::writeToStream(SkWStream* stream) { 152 const Block* block = fHead; 153 while (block) { 154 if (!stream->write(block->base(), block->fAllocated)) { 155 return false; 156 } 157 block = block->fNext; 158 } 159 return true; 160 } 161 162