Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkReader32.h"
      9 #include "SkString.h"
     10 #include "SkWriter32.h"
     11 
     12 /*
     13  *  Strings are stored as: length[4-bytes] + string_data + '\0' + pad_to_mul_4
     14  */
     15 
     16 const char* SkReader32::readString(size_t* outLen) {
     17     size_t len = this->readU32();
     18     const void* ptr = this->peek();
     19 
     20     // skip over the string + '\0' and then pad to a multiple of 4
     21     size_t alignedSize = SkAlign4(len + 1);
     22     this->skip(alignedSize);
     23 
     24     if (outLen) {
     25         *outLen = len;
     26     }
     27     return (const char*)ptr;
     28 }
     29 
     30 size_t SkReader32::readIntoString(SkString* copy) {
     31     size_t len;
     32     const char* ptr = this->readString(&len);
     33     if (copy) {
     34         copy->set(ptr, len);
     35     }
     36     return len;
     37 }
     38 
     39 void SkWriter32::writeString(const char str[], size_t len) {
     40     if (NULL == str) {
     41         str = "";
     42         len = 0;
     43     }
     44     if ((long)len < 0) {
     45         len = strlen(str);
     46     }
     47 
     48     // [ 4 byte len ] [ str ... ] [1 - 4 \0s]
     49     uint32_t* ptr = this->reservePad(sizeof(uint32_t) + len + 1);
     50     *ptr = SkToU32(len);
     51     char* chars = (char*)(ptr + 1);
     52     memcpy(chars, str, len);
     53     chars[len] = '\0';
     54 }
     55 
     56 size_t SkWriter32::WriteStringSize(const char* str, size_t len) {
     57     if ((long)len < 0) {
     58         SkASSERT(str);
     59         len = strlen(str);
     60     }
     61     const size_t lenBytes = 4;    // we use 4 bytes to record the length
     62     // add 1 since we also write a terminating 0
     63     return SkAlign4(lenBytes + len + 1);
     64 }
     65 
     66 void SkWriter32::growToAtLeast(size_t size) {
     67     const bool wasExternal = (fExternal != NULL) && (fData == fExternal);
     68 
     69     fCapacity = 4096 + SkTMax(size, fCapacity + (fCapacity / 2));
     70     fInternal.realloc(fCapacity);
     71     fData = fInternal.get();
     72 
     73     if (wasExternal) {
     74         // we were external, so copy in the data
     75         memcpy(fData, fExternal, fUsed);
     76     }
     77     // Invalidate the snapshot, we know it is no longer useful.
     78     fSnapshot.reset(NULL);
     79 }
     80 
     81 SkData* SkWriter32::snapshotAsData() const {
     82     // get a non const version of this, we are only conceptually const
     83     SkWriter32& mutable_this = *const_cast<SkWriter32*>(this);
     84     // we use size change detection to invalidate the cached data
     85     if ((fSnapshot.get() != NULL) && (fSnapshot->size() != fUsed)) {
     86         mutable_this.fSnapshot.reset(NULL);
     87     }
     88     if (fSnapshot.get() == NULL) {
     89         uint8_t* buffer = NULL;
     90         if ((fExternal != NULL) && (fData == fExternal)) {
     91             // We need to copy to an allocated buffer before returning.
     92             buffer = (uint8_t*)sk_malloc_throw(fUsed);
     93             memcpy(buffer, fData, fUsed);
     94         } else {
     95             buffer = mutable_this.fInternal.detach();
     96             // prepare us to do copy on write, by pretending the data buffer
     97             // is external and size limited
     98             mutable_this.fData = buffer;
     99             mutable_this.fCapacity = fUsed;
    100             mutable_this.fExternal = buffer;
    101         }
    102         mutable_this.fSnapshot.reset(SkData::NewFromMalloc(buffer, fUsed));
    103     }
    104     return SkRef(fSnapshot.get()); // Take an extra ref for the caller.
    105 }
    106