OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2008 The Android Open Source Project | 3 * Copyright 2008 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #ifndef SkWriter32_DEFINED | 10 #ifndef SkWriter32_DEFINED |
(...skipping 12 matching lines...) Expand all Loading... |
23 | 23 |
24 class SkWriter32 : SkNoncopyable { | 24 class SkWriter32 : SkNoncopyable { |
25 public: | 25 public: |
26 /** | 26 /** |
27 * The caller can specify an initial block of storage, which the caller man
ages. | 27 * The caller can specify an initial block of storage, which the caller man
ages. |
28 * | 28 * |
29 * SkWriter32 will try to back reserve and write calls with this external s
torage until the | 29 * SkWriter32 will try to back reserve and write calls with this external s
torage until the |
30 * first time an allocation doesn't fit. From then it will use dynamically
allocated storage. | 30 * first time an allocation doesn't fit. From then it will use dynamically
allocated storage. |
31 * This used to be optional behavior, but pipe now relies on it. | 31 * This used to be optional behavior, but pipe now relies on it. |
32 */ | 32 */ |
33 SkWriter32(void* external = NULL, size_t externalBytes = 0) { | 33 SkWriter32(void* external = NULL, size_t externalBytes = 0) |
| 34 : fData(0) |
| 35 , fCapacity(0) |
| 36 , fUsed(0) |
| 37 , fExternal(0) |
| 38 { |
34 this->reset(external, externalBytes); | 39 this->reset(external, externalBytes); |
35 } | 40 } |
36 | 41 |
37 // return the current offset (will always be a multiple of 4) | 42 // return the current offset (will always be a multiple of 4) |
38 size_t bytesWritten() const { return fCount * 4; } | 43 size_t bytesWritten() const { return fUsed; } |
39 | 44 |
40 SK_ATTR_DEPRECATED("use bytesWritten") | 45 SK_ATTR_DEPRECATED("use bytesWritten") |
41 size_t size() const { return this->bytesWritten(); } | 46 size_t size() const { return this->bytesWritten(); } |
42 | 47 |
43 void reset(void* external = NULL, size_t externalBytes = 0) { | 48 void reset(void* external = NULL, size_t externalBytes = 0) { |
44 SkASSERT(SkIsAlign4((uintptr_t)external)); | 49 SkASSERT(SkIsAlign4((uintptr_t)external)); |
45 SkASSERT(SkIsAlign4(externalBytes)); | 50 SkASSERT(SkIsAlign4(externalBytes)); |
46 fExternal = (uint32_t*)external; | 51 |
47 fExternalLimit = SkToInt(externalBytes/4); | 52 fData = (uint8_t*)external; |
48 fCount = 0; | 53 fCapacity = externalBytes; |
49 fInternal.rewind(); | 54 fUsed = 0; |
| 55 fExternal = external; |
50 } | 56 } |
51 | 57 |
52 // If all data written is contiguous, then this returns a pointer to it, oth
erwise NULL. | 58 // Returns the current buffer. |
53 // This will work if we've only written to the externally supplied block of
storage, or if we've | 59 // The pointer may be invalidated by any future write calls. |
54 // only written to our internal dynamic storage, but will fail if we have wr
itten into both. | |
55 const uint32_t* contiguousArray() const { | 60 const uint32_t* contiguousArray() const { |
56 if (this->externalCount() == 0) { | 61 return (uint32_t*)fData; |
57 return fInternal.begin(); | |
58 } else if (fInternal.isEmpty()) { | |
59 return fExternal; | |
60 } | |
61 return NULL; | |
62 } | 62 } |
63 | 63 |
64 // size MUST be multiple of 4 | 64 // size MUST be multiple of 4 |
65 uint32_t* reserve(size_t size) { | 65 uint32_t* reserve(size_t size) { |
66 SkASSERT(SkAlign4(size) == size); | 66 SkASSERT(SkAlign4(size) == size); |
67 const int count = SkToInt(size/4); | 67 size_t offset = fUsed; |
68 | 68 size_t totalRequired = fUsed + size; |
69 uint32_t* p; | 69 if (totalRequired > fCapacity) { |
70 // Once we start writing to fInternal, we never write to fExternal again
. | 70 growToAtLeast(totalRequired); |
71 // This simplifies tracking what data is where. | |
72 if (fInternal.isEmpty() && this->externalCount() + count <= fExternalLim
it) { | |
73 p = fExternal + fCount; | |
74 } else { | |
75 p = fInternal.append(count); | |
76 } | 71 } |
77 | 72 fUsed = totalRequired; |
78 fCount += count; | 73 return (uint32_t*)(fData + offset); |
79 return p; | |
80 } | 74 } |
81 | 75 |
82 // Read or write 4 bytes at offset, which must be a multiple of 4 <= size(). | 76 // Read or write 4 bytes at offset, which must be a multiple of 4 <= size(). |
83 uint32_t read32At(size_t offset) { return this->atOffset(offset); } | 77 uint32_t read32At(size_t offset) { |
84 void write32At(size_t offset, uint32_t val) { this->atOffset(offset) = val;
} | 78 SkASSERT(SkAlign4(offset) == offset); |
| 79 SkASSERT(offset < fUsed); |
| 80 return *(uint32_t*)(fData + offset); |
| 81 } |
| 82 |
| 83 void write32At(size_t offset, uint32_t val) { |
| 84 SkASSERT(SkAlign4(offset) == offset); |
| 85 SkASSERT(offset < fUsed); |
| 86 *(uint32_t*)(fData + offset) = val; |
| 87 } |
85 | 88 |
86 bool writeBool(bool value) { | 89 bool writeBool(bool value) { |
87 this->write32(value); | 90 this->write32(value); |
88 return value; | 91 return value; |
89 } | 92 } |
90 | 93 |
91 void writeInt(int32_t value) { | 94 void writeInt(int32_t value) { |
92 this->write32(value); | 95 this->write32(value); |
93 } | 96 } |
94 | 97 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 void writeMul4(const void* values, size_t size) { | 153 void writeMul4(const void* values, size_t size) { |
151 this->write(values, size); | 154 this->write(values, size); |
152 } | 155 } |
153 | 156 |
154 /** | 157 /** |
155 * Write size bytes from values. size must be a multiple of 4, though | 158 * Write size bytes from values. size must be a multiple of 4, though |
156 * values need not be 4-byte aligned. | 159 * values need not be 4-byte aligned. |
157 */ | 160 */ |
158 void write(const void* values, size_t size) { | 161 void write(const void* values, size_t size) { |
159 SkASSERT(SkAlign4(size) == size); | 162 SkASSERT(SkAlign4(size) == size); |
160 // TODO: If we're going to spill from fExternal to fInternal, we might w
ant to fill | |
161 // fExternal as much as possible before writing to fInternal. | |
162 memcpy(this->reserve(size), values, size); | 163 memcpy(this->reserve(size), values, size); |
163 } | 164 } |
164 | 165 |
165 /** | 166 /** |
166 * Reserve size bytes. Does not need to be 4 byte aligned. The remaining sp
ace (if any) will be | 167 * Reserve size bytes. Does not need to be 4 byte aligned. The remaining sp
ace (if any) will be |
167 * filled in with zeroes. | 168 * filled in with zeroes. |
168 */ | 169 */ |
169 uint32_t* reservePad(size_t size) { | 170 uint32_t* reservePad(size_t size) { |
170 uint32_t* p = this->reserve(SkAlign4(size)); | 171 uint32_t* p = this->reserve(SkAlign4(size)); |
171 uint8_t* tail = (uint8_t*)p + size; | 172 uint8_t* tail = (uint8_t*)p + size; |
(...skipping 30 matching lines...) Expand all Loading... |
202 * computed by calling strlen(). | 203 * computed by calling strlen(). |
203 */ | 204 */ |
204 static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); | 205 static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); |
205 | 206 |
206 /** | 207 /** |
207 * Move the cursor back to offset bytes from the beginning. | 208 * Move the cursor back to offset bytes from the beginning. |
208 * offset must be a multiple of 4 no greater than size(). | 209 * offset must be a multiple of 4 no greater than size(). |
209 */ | 210 */ |
210 void rewindToOffset(size_t offset) { | 211 void rewindToOffset(size_t offset) { |
211 SkASSERT(SkAlign4(offset) == offset); | 212 SkASSERT(SkAlign4(offset) == offset); |
212 const int count = SkToInt(offset/4); | 213 SkASSERT(offset <= bytesWritten()); |
213 if (count < this->externalCount()) { | 214 fUsed = offset; |
214 fInternal.setCount(0); | |
215 } else { | |
216 fInternal.setCount(count - this->externalCount()); | |
217 } | |
218 fCount = count; | |
219 } | 215 } |
220 | 216 |
221 // copy into a single buffer (allocated by caller). Must be at least size() | 217 // copy into a single buffer (allocated by caller). Must be at least size() |
222 void flatten(void* dst) const { | 218 void flatten(void* dst) const { |
223 const size_t externalBytes = this->externalCount()*4; | 219 memcpy(dst, fData, fUsed); |
224 memcpy(dst, fExternal, externalBytes); | |
225 dst = (uint8_t*)dst + externalBytes; | |
226 memcpy(dst, fInternal.begin(), fInternal.bytes()); | |
227 } | 220 } |
228 | 221 |
229 bool writeToStream(SkWStream* stream) const { | 222 bool writeToStream(SkWStream* stream) const { |
230 return stream->write(fExternal, this->externalCount()*4) | 223 return stream->write(fData, fUsed); |
231 && stream->write(fInternal.begin(), fInternal.bytes()); | |
232 } | 224 } |
233 | 225 |
234 // read from the stream, and write up to length bytes. Return the actual | 226 // read from the stream, and write up to length bytes. Return the actual |
235 // number of bytes written. | 227 // number of bytes written. |
236 size_t readFromStream(SkStream* stream, size_t length) { | 228 size_t readFromStream(SkStream* stream, size_t length) { |
237 return stream->read(this->reservePad(length), length); | 229 return stream->read(this->reservePad(length), length); |
238 } | 230 } |
239 | 231 |
240 private: | 232 private: |
241 uint32_t& atOffset(size_t offset) { | 233 void growToAtLeast(size_t size); |
242 SkASSERT(SkAlign4(offset) == offset); | |
243 const int count = SkToInt(offset/4); | |
244 SkASSERT(count < fCount); | |
245 | 234 |
246 if (count < this->externalCount()) { | 235 uint8_t* fData; // Points to either fInternal or fExternal. |
247 return fExternal[count]; | 236 size_t fCapacity; // Number of bytes we can write to fData. |
248 } | 237 size_t fUsed; // Number of bytes written. |
249 return fInternal[count - this->externalCount()]; | 238 void* fExternal; // Unmanaged memory block. |
250 } | 239 SkTDArray<uint8_t> fInternal; // Managed memory block. |
251 | |
252 | |
253 // Number of uint32_t written into fExternal. <= fExternalLimit. | |
254 int externalCount() const { return fCount - fInternal.count(); } | |
255 | |
256 int fCount; // Total number of uint32_t written. | |
257 int fExternalLimit; // Number of uint32_t we can write to fExter
nal. | |
258 uint32_t* fExternal; // Unmanaged memory block. | |
259 SkTDArray<uint32_t> fInternal; // Managed memory block. | |
260 }; | 240 }; |
261 | 241 |
262 /** | 242 /** |
263 * Helper class to allocated SIZE bytes as part of the writer, and to provide | 243 * Helper class to allocated SIZE bytes as part of the writer, and to provide |
264 * that storage to the constructor as its initial storage buffer. | 244 * that storage to the constructor as its initial storage buffer. |
265 * | 245 * |
266 * This wrapper ensures proper alignment rules are met for the storage. | 246 * This wrapper ensures proper alignment rules are met for the storage. |
267 */ | 247 */ |
268 template <size_t SIZE> class SkSWriter32 : public SkWriter32 { | 248 template <size_t SIZE> class SkSWriter32 : public SkWriter32 { |
269 public: | 249 public: |
270 SkSWriter32() : SkWriter32(fData.fStorage, SIZE) {} | 250 SkSWriter32() : SkWriter32(fData.fStorage, SIZE) {} |
271 | 251 |
272 private: | 252 private: |
273 union { | 253 union { |
274 void* fPtrAlignment; | 254 void* fPtrAlignment; |
275 double fDoubleAlignment; | 255 double fDoubleAlignment; |
276 char fStorage[SIZE]; | 256 char fStorage[SIZE]; |
277 } fData; | 257 } fData; |
278 }; | 258 }; |
279 | 259 |
280 #endif | 260 #endif |
OLD | NEW |