diff options
Diffstat (limited to 'libsgl/sgl/SkWriter32.cpp')
-rw-r--r-- | libsgl/sgl/SkWriter32.cpp | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/libsgl/sgl/SkWriter32.cpp b/libsgl/sgl/SkWriter32.cpp new file mode 100644 index 0000000..61d0051 --- /dev/null +++ b/libsgl/sgl/SkWriter32.cpp @@ -0,0 +1,170 @@ +#include "SkWriter32.h" + +struct SkWriter32::Block { + Block* fNext; + size_t fSize; + size_t fAllocated; + + size_t available() const { return fSize - fAllocated; } + char* base() { return (char*)(this + 1); } + const char* base() const { return (const char*)(this + 1); } + + uint32_t* alloc(size_t size) + { + SkASSERT(SkAlign4(size) == size); + SkASSERT(this->available() >= size); + void* ptr = this->base() + fAllocated; + fAllocated += size; + SkASSERT(fAllocated <= fSize); + return (uint32_t*)ptr; + } + + uint32_t* peek32(size_t offset) + { + SkASSERT(offset <= fAllocated + 4); + void* ptr = this->base() + offset; + return (uint32_t*)ptr; + } + + static Block* Create(size_t size) + { + SkASSERT(SkAlign4(size) == size); + Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); + block->fNext = NULL; + block->fSize = size; + block->fAllocated = 0; + return block; + } +}; + +static size_t compute_block_size(size_t currSize, size_t minSize) +{ + if (currSize < minSize) + currSize = minSize; + + currSize += (currSize >> 1); + return SkAlign4(currSize); +} + +/////////////////////////////////////////////////////////////////////////////// + +SkWriter32::~SkWriter32() +{ + this->reset(); +} + +void SkWriter32::reset() +{ + Block* block = fHead; + while (block) + { + Block* next = block->fNext; + sk_free(block); + block = next; + } + fHead = fTail = NULL; + fSize = 0; +} + +uint32_t* SkWriter32::reserve(size_t size) +{ + SkASSERT(SkAlign4(size) == size); + + Block* block = fTail; + + if (NULL == block) + { + SkASSERT(NULL == fHead); + fHead = fTail = block = Block::Create(SkMax32(size, fMinSize)); + } + else if (block->available() < size) + { + fTail = Block::Create(SkMax32(size, fMinSize)); + block->fNext = fTail; + block = fTail; + } + + fSize += size; + + return block->alloc(size); +} + +uint32_t* SkWriter32::peek32(size_t offset) +{ + SkASSERT(SkAlign4(offset) == offset); + SkASSERT(offset <= fSize); + + Block* block = fHead; + SkASSERT(NULL != block); + + while (offset >= block->fAllocated) + { + offset -= block->fAllocated; + block = block->fNext; + SkASSERT(NULL != block); + } + return block->peek32(offset); +} + +void SkWriter32::flatten(void* dst) const +{ + const Block* block = fHead; + SkDEBUGCODE(size_t total = 0;) + + while (block) + { + size_t allocated = block->fAllocated; + memcpy(dst, block->base(), allocated); + dst = (char*)dst + allocated; + block = block->fNext; + + SkDEBUGCODE(total += allocated;) + SkASSERT(total <= fSize); + } + SkASSERT(total == fSize); +} + +void SkWriter32::writePad(const void* src, size_t size) { + size_t alignedSize = SkAlign4(size); + char* dst = (char*)this->reserve(alignedSize); + memcpy(dst, src, size); + dst += size; + int n = alignedSize - size; + while (--n >= 0) { + *dst++ = 0; + } +} + +#include "SkStream.h" + +size_t SkWriter32::readFromStream(SkStream* stream, size_t length) { + char scratch[1024]; + const size_t MAX = sizeof(scratch); + size_t remaining = length; + + while (remaining != 0) { + size_t n = remaining; + if (n > MAX) { + n = MAX; + } + size_t bytes = stream->read(scratch, n); + this->writePad(scratch, bytes); + remaining -= bytes; + if (bytes != n) { + break; + } + } + return length - remaining; +} + +bool SkWriter32::writeToStream(SkWStream* stream) { + const Block* block = fHead; + while (block) { + if (!stream->write(block->base(), block->fAllocated)) { + return false; + } + block = block->fNext; + } + return true; +} + |