gfx/skia/trunk/src/core/SkWriter32.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial