Index: include/core/SkWriter32.h |
diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h |
index b193cbe7c407663f7a82a613b8a65b5e1e637a47..55810ade22bf4fdc64d2287515a4d5ae3064fb54 100644 |
--- a/include/core/SkWriter32.h |
+++ b/include/core/SkWriter32.h |
@@ -30,12 +30,18 @@ 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) { |
- this->reset(external, externalBytes); |
+ SkWriter32(void* external = NULL, size_t externalBytes = 0) |
+ : fData((uint8_t*)external) |
+ , fCapacity(externalBytes) |
+ , fUsed(0) |
+ , fExternal(external) |
+ { |
+ SkASSERT(SkIsAlign4((uintptr_t)external)); |
+ SkASSERT(SkIsAlign4(externalBytes)); |
reed1
2014/02/06 20:14:40
or we could just trim the low bits off of external
iancottrell
2014/02/06 21:33:06
I was staying compatible with the contract it used
reed1
2014/02/06 21:41:34
Sure, separate CL or not at all.
|
} |
// 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 +49,41 @@ 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. |
reed1
2014/02/06 20:14:40
Does this guy always return all of the space writt
iancottrell
2014/02/06 21:33:06
I am trying hard to not change the public interfac
reed1
2014/02/06 21:41:34
I'm mostly asking that we well-document the API, a
mtklein
2014/02/06 22:01:24
Right, SkPictureFlat wants read-only contiguous ac
iancottrell
2014/02/07 12:20:40
Yes, let's just deprecate this method, the two use
|
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); |
- } |
- |
- fCount += count; |
- return p; |
+ size_t offset = fUsed; |
+ size_t used = fUsed + size; |
+ if (used > fCapacity) { grow(used); } |
reed1
2014/02/06 20:14:40
style nit: skia always wants the body on the next
reed1
2014/02/06 20:14:40
Perhaps a comment that we are passing "used" as th
iancottrell
2014/02/06 21:33:06
Done.
iancottrell
2014/02/06 21:33:06
used is the space used in total after the current
reed1
2014/02/06 21:41:34
I think here the value is just knowing what the me
|
+ fUsed = used; |
+ return (uint32_t*)(fData+offset); |
reed1
2014/02/06 20:14:40
style nit: skia likes spaces around binary operato
iancottrell
2014/02/06 21:33:06
Done.
|
} |
// 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 +159,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 +209,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 +229,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 grow(size_t size); |
reed1
2014/02/06 20:14:40
// size is the number of bytes we want to grow by,
iancottrell
2014/02/06 21:33:06
size is the new minimum size. Maybe calling the fu
reed1
2014/02/06 21:41:34
That seems much clearer.
|
- 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. |
}; |
/** |