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