180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#include "SkWriter32.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkWriter32::SkWriter32(size_t minSize, void* storage, size_t storageSize) {
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMinSize = minSize;
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSize = 0;
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fWrittenBeforeLastBlock = 0;
14d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    fHead = fTail = NULL;
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (storageSize) {
17d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this->reset(storage, storageSize);
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkWriter32::~SkWriter32() {
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->reset();
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkWriter32::reset() {
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Block* block = fHead;
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (this->isHeadExternallyAllocated()) {
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(block);
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // don't 'free' the first block, since it is owned by the caller
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block = block->fNext;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (block) {
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Block* next = block->fNext;
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_free(block);
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block = next;
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSize = 0;
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fWrittenBeforeLastBlock = 0;
41d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    fHead = fTail = NULL;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkWriter32::reset(void* storage, size_t storageSize) {
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->reset();
46d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
47d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    storageSize &= ~3;  // trunc down to multiple of 4
48d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (storageSize > 0 && SkIsAlign4((intptr_t)storage)) {
49d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        fHead = fTail = fExternalBlock.initFromStorage(storage, storageSize);
50d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerSkWriter32::Block* SkWriter32::doReserve(size_t size) {
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SkAlign4(size) == size);
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Block* block = fTail;
57d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkASSERT(NULL == block || block->available() < size);
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == block) {
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL == fHead);
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fHead = fTail = block = Block::Create(SkMax32(size, fMinSize));
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkASSERT(0 == fWrittenBeforeLastBlock);
63d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    } else {
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkASSERT(fSize > 0);
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fWrittenBeforeLastBlock = fSize;
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTail = Block::Create(SkMax32(size, fMinSize));
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block->fNext = fTail;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block = fTail;
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
71d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return block;
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruuint32_t* SkWriter32::peek32(size_t offset) {
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(this->validate();)
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SkAlign4(offset) == offset);
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(offset <= fSize);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // try the fast case, where offset is within fTail
81363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (offset >= fWrittenBeforeLastBlock) {
82363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return fTail->peek32(offset - fWrittenBeforeLastBlock);
83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Block* block = fHead;
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(NULL != block);
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (offset >= block->fAllocatedSoFar) {
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        offset -= block->fAllocatedSoFar;
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block = block->fNext;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL != block);
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return block->peek32(offset);
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkWriter32::rewindToOffset(size_t offset) {
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (offset >= fSize) {
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == offset) {
101d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this->reset();
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(this->validate();)
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SkAlign4(offset) == offset);
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(offset <= fSize);
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSize = offset;
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Try the fast case, where offset is within fTail
112363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (offset >= fWrittenBeforeLastBlock) {
113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fTail->fAllocatedSoFar = offset - fWrittenBeforeLastBlock;
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Similar to peek32, except that we free up any following blocks.
116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // We have to re-compute fWrittenBeforeLastBlock as well.
117363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
118363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        size_t globalOffset = offset;
119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Block* block = fHead;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL != block);
121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        while (offset >= block->fAllocatedSoFar) {
122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            offset -= block->fAllocatedSoFar;
123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            block = block->fNext;
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkASSERT(NULL != block);
125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // this has to be recomputed, since we may free up fTail
128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fWrittenBeforeLastBlock = globalOffset - offset;
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // update the size on the "last" block
131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        block->fAllocatedSoFar = offset;
132363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // end our list
133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fTail = block;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Block* next = block->fNext;
135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        block->fNext = NULL;
136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // free up any trailing blocks
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block = next;
138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        while (block) {
139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            Block* next = block->fNext;
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            sk_free(block);
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            block = next;
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(this->validate();)
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkWriter32::flatten(void* dst) const {
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Block* block = fHead;
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(size_t total = 0;)
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (block) {
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t allocated = block->fAllocatedSoFar;
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(dst, block->base(), allocated);
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst = (char*)dst + allocated;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block = block->fNext;
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGCODE(total += allocated;)
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(total <= fSize);
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(total == fSize);
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruuint32_t* SkWriter32::reservePad(size_t size) {
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (size > 0) {
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t alignedSize = SkAlign4(size);
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char* dst = (char*)this->reserve(alignedSize);
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Pad the last four bytes with zeroes in one step.
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint32_t* padding = (uint32_t*)(dst + (alignedSize - 4));
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *padding = 0;
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return (uint32_t*) dst;
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->reserve(0);
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkWriter32::writePad(const void* src, size_t size) {
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (size > 0) {
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char* dst = (char*)this->reservePad(size);
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Copy the actual data.
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(dst, src, size);
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h"
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkWriter32::readFromStream(SkStream* stream, size_t length) {
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char scratch[1024];
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const size_t MAX = sizeof(scratch);
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t remaining = length;
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (remaining != 0) {
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t n = remaining;
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (n > MAX) {
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            n = MAX;
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t bytes = stream->read(scratch, n);
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->writePad(scratch, bytes);
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        remaining -= bytes;
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (bytes != n) {
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return length - remaining;
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkWriter32::writeToStream(SkWStream* stream) {
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Block* block = fHead;
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (block) {
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!stream->write(block->base(), block->fAllocatedSoFar)) {
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block = block->fNext;
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkWriter32::validate() const {
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SkIsAlign4(fSize));
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t accum = 0;
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Block* block = fHead;
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (block) {
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkIsAlign4(block->fSizeOfBlock));
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkIsAlign4(block->fAllocatedSoFar));
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(block->fAllocatedSoFar <= block->fSizeOfBlock);
226363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (NULL == block->fNext) {
227363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkASSERT(fTail == block);
228363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkASSERT(fWrittenBeforeLastBlock == accum);
229363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        accum += block->fAllocatedSoFar;
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(accum <= fSize);
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        block = block->fNext;
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(accum == fSize);
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkReader32.h"
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkString.h"
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  Strings are stored as: length[4-bytes] + string_data + '\0' + pad_to_mul_4
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkReader32::readString(size_t* outLen) {
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t len = this->readInt();
249e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (0xFFFF == len) {
250e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (outLen) {
251e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            *outLen = 0;
252e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
253e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return NULL;
254e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const void* ptr = this->peek();
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // skip over teh string + '\0' and then pad to a multiple of 4
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t alignedSize = SkAlign4(len + 1);
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->skip(alignedSize);
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (outLen) {
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *outLen = len;
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (const char*)ptr;
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkReader32::readIntoString(SkString* copy) {
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t len;
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* ptr = this->readString(&len);
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (copy) {
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        copy->set(ptr, len);
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return len;
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkWriter32::writeString(const char str[], size_t len) {
277e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (NULL == str) {
278e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        // We're already requiring len < 0xFFFF, so we can use that to mark NULL.
279e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        this->write32(0xFFFF);
280e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return;
281e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((long)len < 0) {
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        len = strlen(str);
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->write32(len);
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // add 1 since we also write a terminating 0
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t alignedLen = SkAlign4(len + 1);
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char* ptr = (char*)this->reserve(alignedLen);
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Write the terminating 0 and fill in the rest with zeroes
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint32_t* padding = (uint32_t*)(ptr + (alignedLen - 4));
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *padding = 0;
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Copy the string itself.
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memcpy(ptr, str, len);
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkWriter32::WriteStringSize(const char* str, size_t len) {
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((long)len < 0) {
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(str);
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        len = strlen(str);
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const size_t lenBytes = 4;    // we use 4 bytes to record the length
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // add 1 since we also write a terminating 0
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkAlign4(lenBytes + len + 1);
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
307