Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / include / core / SkWriter32.h
index 6bb59c5..2e7c956 100644 (file)
@@ -18,7 +18,7 @@
 #include "SkRegion.h"
 #include "SkScalar.h"
 #include "SkStream.h"
-#include "SkTDArray.h"
+#include "SkTemplates.h"
 #include "SkTypes.h"
 
 class SkWriter32 : SkNoncopyable {
@@ -35,7 +35,7 @@ public:
     }
 
     // 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,54 +43,51 @@ 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) {
+            this->growToAtLeast(totalRequired);
         }
-
-        fCount += count;
-        return p;
+        fUsed = totalRequired;
+        return (uint32_t*)(fData + offset);
     }
 
-    // return the address of the 4byte int at the specified offset (which must
-    // be a multiple of 4. This does not allocate any new space, so the returned
-    // address is only valid for 1 int.
-    uint32_t* peek32(size_t offset) {
+    /**
+     *  Read a T record at offset, which must be a multiple of 4. Only legal if the record
+     *  was writtern atomically using the write methods below.
+     */
+    template<typename T>
+    const T& readTAt(size_t offset) const {
         SkASSERT(SkAlign4(offset) == offset);
-        const int count = SkToInt(offset/4);
-        SkASSERT(count < fCount);
+        SkASSERT(offset < fUsed);
+        return *(T*)(fData + offset);
+    }
 
-        if (count < this->externalCount()) {
-            return fExternal + count;
-        }
-        return &fInternal[count - this->externalCount()];
+    /**
+     *  Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record
+     *  was writtern atomically using the write methods below.
+     */
+    template<typename T>
+    void overwriteTAt(size_t offset, const T& value) {
+        SkASSERT(SkAlign4(offset) == offset);
+        SkASSERT(offset < fUsed);
+        *(T*)(fData + offset) = value;
     }
 
     bool writeBool(bool value) {
@@ -167,8 +164,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);
     }
 
@@ -177,14 +172,11 @@ public:
      *  filled in with zeroes.
      */
     uint32_t* reservePad(size_t size) {
-        uint32_t* p = this->reserve(SkAlign4(size));
-        uint8_t* tail = (uint8_t*)p + size;
-        switch (SkAlign4(size) - size) {
-            default: SkDEBUGFAIL("SkAlign4(x) - x should always be 0, 1, 2, or 3.");
-            case 3: *tail++ = 0x00;  // fallthrough is intentional
-            case 2: *tail++ = 0x00;  // fallthrough is intentional
-            case 1: *tail++ = 0x00;
-            case 0: ;/*nothing to do*/
+        size_t alignedSize = SkAlign4(size);
+        uint32_t* p = this->reserve(alignedSize);
+        if (alignedSize != size) {
+            SkASSERT(alignedSize >= 4);
+            p[alignedSize / 4 - 1] = 0;
         }
         return p;
     }
@@ -215,31 +207,21 @@ public:
 
     /**
      *  Move the cursor back to offset bytes from the beginning.
-     *  This has the same restrictions as peek32: offset must be <= size() and
-     *  offset must be a multiple of 4.
+     *  offset must be a multiple of 4 no greater than size().
      */
     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
@@ -249,13 +231,13 @@ public:
     }
 
 private:
-    // 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.
+    SkAutoTMalloc<uint8_t> fInternal;  // Managed memory block.
 };
 
 /**
@@ -266,7 +248,9 @@ private:
  */
 template <size_t SIZE> class SkSWriter32 : public SkWriter32 {
 public:
-    SkSWriter32() : SkWriter32(fData.fStorage, SIZE) {}
+    SkSWriter32() { this->reset(); }
+
+    void reset() {this->INHERITED::reset(fData.fStorage, SIZE); }
 
 private:
     union {
@@ -274,6 +258,8 @@ private:
         double  fDoubleAlignment;
         char    fStorage[SIZE];
     } fData;
+
+    typedef SkWriter32 INHERITED;
 };
 
 #endif