|
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->readInt(); |
|
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 = 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 } |