| Index: include/core/SkWriter32.h
|
| diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h
|
| index b193cbe7c407663f7a82a613b8a65b5e1e637a47..df1275f7b656829ad132f7b481508e42b53d99e7 100644
|
| --- a/include/core/SkWriter32.h
|
| +++ b/include/core/SkWriter32.h
|
| @@ -30,12 +30,17 @@ public:
|
| * first time an allocation doesn't fit. From then it will use dynamically allocated storage.
|
| * This used to be optional behavior, but pipe now relies on it.
|
| */
|
| - SkWriter32(void* external = NULL, size_t externalBytes = 0) {
|
| + SkWriter32(void* external = NULL, size_t externalBytes = 0)
|
| + : fData(0)
|
| + , fCapacity(0)
|
| + , fUsed(0)
|
| + , fExternal(0)
|
| + {
|
| this->reset(external, externalBytes);
|
| }
|
|
|
| // return the current offset (will always be a multiple of 4)
|
| - size_t bytesWritten() const { return fCount * 4; }
|
| + size_t bytesWritten() const { return fUsed; }
|
|
|
| SK_ATTR_DEPRECATED("use bytesWritten")
|
| size_t size() const { return this->bytesWritten(); }
|
| @@ -43,45 +48,43 @@ public:
|
| void reset(void* external = NULL, size_t externalBytes = 0) {
|
| SkASSERT(SkIsAlign4((uintptr_t)external));
|
| SkASSERT(SkIsAlign4(externalBytes));
|
| - fExternal = (uint32_t*)external;
|
| - fExternalLimit = SkToInt(externalBytes/4);
|
| - fCount = 0;
|
| - fInternal.rewind();
|
| +
|
| + fData = (uint8_t*)external;
|
| + fCapacity = externalBytes;
|
| + fUsed = 0;
|
| + fExternal = external;
|
| }
|
|
|
| - // If all data written is contiguous, then this returns a pointer to it, otherwise NULL.
|
| - // This will work if we've only written to the externally supplied block of storage, or if we've
|
| - // only written to our internal dynamic storage, but will fail if we have written into both.
|
| + // Returns the current buffer.
|
| + // The pointer may be invalidated by any future write calls.
|
| const uint32_t* contiguousArray() const {
|
| - if (this->externalCount() == 0) {
|
| - return fInternal.begin();
|
| - } else if (fInternal.isEmpty()) {
|
| - return fExternal;
|
| - }
|
| - return NULL;
|
| + return (uint32_t*)fData;
|
| }
|
|
|
| // size MUST be multiple of 4
|
| uint32_t* reserve(size_t size) {
|
| SkASSERT(SkAlign4(size) == size);
|
| - const int count = SkToInt(size/4);
|
| -
|
| - uint32_t* p;
|
| - // Once we start writing to fInternal, we never write to fExternal again.
|
| - // This simplifies tracking what data is where.
|
| - if (fInternal.isEmpty() && this->externalCount() + count <= fExternalLimit) {
|
| - p = fExternal + fCount;
|
| - } else {
|
| - p = fInternal.append(count);
|
| + size_t offset = fUsed;
|
| + size_t totalRequired = fUsed + size;
|
| + if (totalRequired > fCapacity) {
|
| + growToAtLeast(totalRequired);
|
| }
|
| -
|
| - fCount += count;
|
| - return p;
|
| + fUsed = totalRequired;
|
| + return (uint32_t*)(fData + offset);
|
| }
|
|
|
| // Read or write 4 bytes at offset, which must be a multiple of 4 <= size().
|
| - uint32_t read32At(size_t offset) { return this->atOffset(offset); }
|
| - void write32At(size_t offset, uint32_t val) { this->atOffset(offset) = val; }
|
| + uint32_t read32At(size_t offset) {
|
| + SkASSERT(SkAlign4(offset) == offset);
|
| + SkASSERT(offset < fUsed);
|
| + return *(uint32_t*)(fData + offset);
|
| + }
|
| +
|
| + void write32At(size_t offset, uint32_t val) {
|
| + SkASSERT(SkAlign4(offset) == offset);
|
| + SkASSERT(offset < fUsed);
|
| + *(uint32_t*)(fData + offset) = val;
|
| + }
|
|
|
| bool writeBool(bool value) {
|
| this->write32(value);
|
| @@ -157,8 +160,6 @@ public:
|
| */
|
| void write(const void* values, size_t size) {
|
| SkASSERT(SkAlign4(size) == size);
|
| - // TODO: If we're going to spill from fExternal to fInternal, we might want to fill
|
| - // fExternal as much as possible before writing to fInternal.
|
| memcpy(this->reserve(size), values, size);
|
| }
|
|
|
| @@ -209,26 +210,17 @@ public:
|
| */
|
| void rewindToOffset(size_t offset) {
|
| SkASSERT(SkAlign4(offset) == offset);
|
| - const int count = SkToInt(offset/4);
|
| - if (count < this->externalCount()) {
|
| - fInternal.setCount(0);
|
| - } else {
|
| - fInternal.setCount(count - this->externalCount());
|
| - }
|
| - fCount = count;
|
| + SkASSERT(offset <= bytesWritten());
|
| + fUsed = offset;
|
| }
|
|
|
| // copy into a single buffer (allocated by caller). Must be at least size()
|
| void flatten(void* dst) const {
|
| - const size_t externalBytes = this->externalCount()*4;
|
| - memcpy(dst, fExternal, externalBytes);
|
| - dst = (uint8_t*)dst + externalBytes;
|
| - memcpy(dst, fInternal.begin(), fInternal.bytes());
|
| + memcpy(dst, fData, fUsed);
|
| }
|
|
|
| bool writeToStream(SkWStream* stream) const {
|
| - return stream->write(fExternal, this->externalCount()*4)
|
| - && stream->write(fInternal.begin(), fInternal.bytes());
|
| + return stream->write(fData, fUsed);
|
| }
|
|
|
| // read from the stream, and write up to length bytes. Return the actual
|
| @@ -238,25 +230,13 @@ public:
|
| }
|
|
|
| private:
|
| - uint32_t& atOffset(size_t offset) {
|
| - SkASSERT(SkAlign4(offset) == offset);
|
| - const int count = SkToInt(offset/4);
|
| - SkASSERT(count < fCount);
|
| -
|
| - if (count < this->externalCount()) {
|
| - return fExternal[count];
|
| - }
|
| - return fInternal[count - this->externalCount()];
|
| - }
|
| -
|
| -
|
| - // Number of uint32_t written into fExternal. <= fExternalLimit.
|
| - int externalCount() const { return fCount - fInternal.count(); }
|
| + void growToAtLeast(size_t size);
|
|
|
| - int fCount; // Total number of uint32_t written.
|
| - int fExternalLimit; // Number of uint32_t we can write to fExternal.
|
| - uint32_t* fExternal; // Unmanaged memory block.
|
| - SkTDArray<uint32_t> fInternal; // Managed memory block.
|
| + uint8_t* fData; // Points to either fInternal or fExternal.
|
| + size_t fCapacity; // Number of bytes we can write to fData.
|
| + size_t fUsed; // Number of bytes written.
|
| + void* fExternal; // Unmanaged memory block.
|
| + SkTDArray<uint8_t> fInternal; // Managed memory block.
|
| };
|
|
|
| /**
|
|
|