Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright 2015 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 "SkData.h" | |
| 9 #include "SkRWBuffer.h" | |
| 10 #include "SkStream.h" | |
| 11 | |
| 12 struct SkBufferBlock { | |
| 13 SkBufferBlock* fNext; | |
| 14 size_t fUsed; | |
| 15 size_t fCapacity; | |
| 16 | |
| 17 const void* startData() const { return this + 1; }; | |
| 18 | |
| 19 static SkBufferBlock* Alloc(size_t length) { | |
| 20 size_t capacity = LengthToCapacity(length); | |
| 21 SkBufferBlock* block = (SkBufferBlock*)sk_malloc_throw(sizeof(SkBufferBl ock) + capacity); | |
| 22 block->fNext = NULL; | |
| 23 block->fUsed = 0; | |
| 24 block->fCapacity = capacity; | |
| 25 return block; | |
| 26 } | |
| 27 | |
| 28 // Return number of bytes actually appended | |
| 29 size_t append(const void* src, size_t length) { | |
| 30 this->validate(); | |
| 31 size_t avail = SkTMin(fCapacity - fUsed, length); | |
| 32 memcpy((char*)(this + 1) + fUsed, src, avail); | |
| 33 fUsed += avail; | |
| 34 this->validate(); | |
| 35 return avail; | |
| 36 } | |
| 37 | |
| 38 void validate() const { | |
| 39 #ifdef SK_DEBUG | |
| 40 SkASSERT(fCapacity > 0); | |
| 41 SkASSERT(fUsed <= fCapacity); | |
| 42 #endif | |
| 43 } | |
| 44 | |
| 45 private: | |
| 46 static size_t LengthToCapacity(size_t length) { | |
| 47 const size_t minSize = 4096 - sizeof(SkBufferBlock); | |
| 48 return SkTMax(length, minSize); | |
| 49 } | |
| 50 }; | |
| 51 | |
| 52 struct SkBufferHead { | |
| 53 mutable int32_t fRefCnt; | |
| 54 SkBufferBlock fBlock; | |
| 55 | |
| 56 static size_t LengthToCapacity(size_t length) { | |
| 57 const size_t minSize = 4096 - sizeof(SkBufferHead); | |
| 58 return SkTMax(length, minSize); | |
| 59 } | |
| 60 | |
| 61 static SkBufferHead* Alloc(size_t length) { | |
| 62 size_t capacity = LengthToCapacity(length); | |
| 63 size_t size = sizeof(SkBufferHead) + capacity; | |
| 64 SkBufferHead* head = (SkBufferHead*)sk_malloc_throw(size); | |
| 65 head->fRefCnt = 1; | |
| 66 head->fBlock.fNext = NULL; | |
| 67 head->fBlock.fUsed = 0; | |
| 68 head->fBlock.fCapacity = capacity; | |
| 69 return head; | |
| 70 } | |
| 71 | |
| 72 void ref() const { | |
| 73 SkASSERT(fRefCnt > 0); | |
| 74 sk_atomic_inc(&fRefCnt); | |
| 75 } | |
| 76 | |
| 77 void unref() const { | |
| 78 SkASSERT(fRefCnt > 0); | |
| 79 // A release here acts in place of all releases we "should" have been do ing in ref(). | |
| 80 if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { | |
| 81 // Like unique(), the acquire is only needed on success. | |
| 82 SkBufferBlock* block = fBlock.fNext; | |
| 83 sk_free((void*)this); | |
| 84 while (block) { | |
| 85 SkBufferBlock* next = block->fNext; | |
| 86 sk_free(block); | |
| 87 block = next; | |
| 88 } | |
| 89 SkDebugf("done\n"); | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 void validate(size_t minUsed, SkBufferBlock* tail = NULL) const { | |
| 94 #ifdef SK_DEBUG | |
| 95 SkASSERT(fRefCnt > 0); | |
| 96 size_t totalUsed = 0; | |
| 97 const SkBufferBlock* block = &fBlock; | |
| 98 const SkBufferBlock* lastBlock = block; | |
| 99 while (block) { | |
| 100 block->validate(); | |
| 101 totalUsed += block->fUsed; | |
| 102 lastBlock = block; | |
| 103 block = block->fNext; | |
| 104 } | |
| 105 SkASSERT(minUsed <= totalUsed); | |
| 106 if (tail) { | |
| 107 SkASSERT(tail == lastBlock); | |
| 108 } | |
| 109 #endif | |
| 110 } | |
| 111 }; | |
| 112 | |
| 113 SkRBuffer::SkRBuffer(const SkBufferHead* head, size_t used) : fHead(SkRef(head)) , fUsed(used) { | |
| 114 if (head) { | |
| 115 SkASSERT(used > 0); | |
| 116 head->validate(used); | |
| 117 } else { | |
| 118 SkASSERT(0 == used); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 SkRBuffer::~SkRBuffer() { | |
| 123 if (fHead) { | |
| 124 fHead->validate(fUsed); | |
| 125 fHead->unref(); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 SkRBuffer::Iter::Iter(const SkRBuffer* buffer) { | |
| 130 this->reset(buffer); | |
| 131 } | |
| 132 | |
| 133 void SkRBuffer::Iter::reset(const SkRBuffer* buffer) { | |
| 134 if (buffer) { | |
| 135 fBlock = &buffer->fHead->fBlock; | |
| 136 fRemaining = buffer->fUsed; | |
| 137 } else { | |
| 138 fBlock = NULL; | |
| 139 fRemaining = 0; | |
| 140 } | |
| 141 } | |
| 142 | |
| 143 const void* SkRBuffer::Iter::data() const { | |
| 144 return fRemaining ? fBlock->startData() : NULL; | |
| 145 } | |
| 146 | |
| 147 size_t SkRBuffer::Iter::size() const { | |
| 148 return SkTMin(fBlock->fUsed, fRemaining); | |
| 149 } | |
| 150 | |
| 151 bool SkRBuffer::Iter::next() { | |
| 152 if (fRemaining) { | |
| 153 fRemaining -= this->size(); | |
| 154 fBlock = fBlock->fNext; | |
| 155 } | |
| 156 return fRemaining != 0; | |
| 157 } | |
| 158 | |
| 159 SkRWBuffer::SkRWBuffer(size_t initialCapacity) : fHead(NULL), fTail(NULL), fTota lUsed(0) {} | |
| 160 | |
| 161 SkRWBuffer::~SkRWBuffer() { | |
| 162 this->validate(); | |
| 163 fHead->unref(); | |
| 164 } | |
| 165 | |
| 166 void SkRWBuffer::append(const void* src, size_t length) { | |
| 167 this->validate(); | |
| 168 if (0 == length) { | |
| 169 return; | |
| 170 } | |
| 171 | |
| 172 fTotalUsed += length; | |
| 173 | |
| 174 if (NULL == fHead) { | |
| 175 fHead = SkBufferHead::Alloc(length); | |
| 176 fTail = &fHead->fBlock; | |
| 177 } | |
| 178 | |
| 179 size_t written = fTail->append(src, length); | |
| 180 SkASSERT(written <= length); | |
| 181 src = (const char*)src + written; | |
| 182 length -= written; | |
| 183 | |
| 184 if (length) { | |
| 185 SkBufferBlock* block = SkBufferBlock::Alloc(length); | |
| 186 fTail->fNext = block; | |
| 187 fTail = block; | |
| 188 written = fTail->append(src, length); | |
| 189 SkASSERT(written == length); | |
| 190 } | |
| 191 this->validate(); | |
| 192 } | |
| 193 | |
| 194 #ifdef SK_DEBUG | |
| 195 void SkRWBuffer::validate() const { | |
| 196 if (fHead) { | |
| 197 fHead->validate(fTotalUsed, fTail); | |
| 198 } else { | |
| 199 SkASSERT(NULL == fTail); | |
| 200 SkASSERT(0 == fTotalUsed); | |
| 201 } | |
| 202 } | |
| 203 #endif | |
| 204 | |
| 205 SkRBuffer* SkRWBuffer::newRBufferSnapshot() const { | |
| 206 return SkNEW_ARGS(SkRBuffer, (fHead, fTotalUsed)); | |
| 207 } | |
| 208 | |
| 209 SkData* SkRWBuffer::newDataSnapshot() const { | |
| 210 SkData* data = SkData::NewUninitialized(fTotalUsed); | |
| 211 | |
| 212 const SkBufferBlock* block = &fHead->fBlock; | |
| 213 char* dst = (char*)data->writable_data(); | |
| 214 while (block) { | |
| 215 memcpy(dst, block->startData(), block->fUsed); | |
| 216 dst += block->fUsed; | |
| 217 block = block->fNext; | |
| 218 } | |
| 219 return data; | |
| 220 } | |
| 221 | |
| 222 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 223 | |
| 224 class SkRBufferStreamAsset : public SkStreamAsset { | |
|
bungeman-skia
2015/04/27 14:52:42
You may want to take a look at SkBlockMemoryStream
reed2
2015/04/28 02:25:00
Acknowledged.
| |
| 225 void validate() const { | |
| 226 #ifdef SK_DEBUG | |
| 227 SkASSERT(fGlobalOffset <= fBuffer->size()); | |
| 228 SkASSERT(fLocalOffset <= fIter.size()); | |
| 229 SkASSERT(fLocalOffset <= fGlobalOffset); | |
| 230 #endif | |
| 231 } | |
| 232 | |
| 233 class AutoValidate { | |
| 234 SkRBufferStreamAsset* fStream; | |
| 235 public: | |
| 236 AutoValidate(SkRBufferStreamAsset* stream) : fStream(stream) { stream->v alidate(); } | |
| 237 ~AutoValidate() { fStream->validate(); } | |
| 238 }; | |
| 239 | |
| 240 #ifdef SK_DEBUG | |
| 241 #define AUTO_VALIDATE AutoValidate av(this); | |
| 242 #else | |
| 243 #define AUTO_VALIDATE | |
| 244 #endif | |
| 245 | |
| 246 public: | |
| 247 SkRBufferStreamAsset(const SkRBuffer* buffer) : fBuffer(SkRef(buffer)), fIte r(buffer) { | |
| 248 fGlobalOffset = fLocalOffset = 0; | |
| 249 } | |
| 250 | |
| 251 virtual ~SkRBufferStreamAsset() { fBuffer->unref(); } | |
| 252 | |
| 253 size_t getLength() const override { return fBuffer->size(); } | |
| 254 | |
| 255 bool rewind() override { | |
| 256 AUTO_VALIDATE | |
| 257 fIter.reset(fBuffer); | |
| 258 fGlobalOffset = fLocalOffset = 0; | |
| 259 return true; | |
| 260 } | |
| 261 | |
| 262 size_t read(void* dst, size_t request) override { | |
| 263 AUTO_VALIDATE | |
| 264 size_t bytesRead = 0; | |
| 265 for (;;) { | |
| 266 size_t size = fIter.size(); | |
| 267 SkASSERT(fLocalOffset <= size); | |
| 268 size_t avail = SkTMin(size - fLocalOffset, request - bytesRead); | |
| 269 if (dst) { | |
| 270 memcpy(dst, (const char*)fIter.data() + fLocalOffset, avail); | |
| 271 dst = (char*)dst + avail; | |
| 272 } | |
| 273 bytesRead += avail; | |
| 274 fLocalOffset += avail; | |
| 275 SkASSERT(bytesRead <= request); | |
| 276 if (bytesRead == request) { | |
| 277 break; | |
| 278 } | |
| 279 // If we get here, we've exhausted the current iter | |
| 280 SkASSERT(fLocalOffset == size); | |
| 281 fLocalOffset = 0; | |
| 282 if (!fIter.next()) { | |
| 283 break; // ran out of data | |
| 284 } | |
| 285 } | |
| 286 fGlobalOffset += bytesRead; | |
| 287 SkASSERT(fGlobalOffset <= fBuffer->size()); | |
| 288 return bytesRead; | |
| 289 } | |
| 290 | |
| 291 bool isAtEnd() const override { | |
| 292 return fBuffer->size() == fGlobalOffset; | |
| 293 } | |
| 294 | |
| 295 SkStreamAsset* duplicate() const override { | |
| 296 return SkNEW_ARGS(SkRBufferStreamAsset, (fBuffer)); | |
| 297 } | |
| 298 | |
| 299 size_t getPosition() const { | |
| 300 return fGlobalOffset; | |
| 301 } | |
| 302 | |
| 303 bool seek(size_t position) { | |
| 304 AUTO_VALIDATE | |
| 305 if (position < fGlobalOffset) { | |
| 306 this->rewind(); | |
| 307 } | |
| 308 (void)this->skip(position - fGlobalOffset); | |
| 309 return true; | |
| 310 } | |
| 311 | |
| 312 bool move(long offset) { | |
| 313 AUTO_VALIDATE | |
| 314 offset += fGlobalOffset; | |
| 315 if (offset <= 0) { | |
| 316 this->rewind(); | |
| 317 } else { | |
| 318 (void)this->seek(SkToSizeT(offset)); | |
| 319 } | |
| 320 return true; | |
| 321 } | |
| 322 | |
| 323 SkStreamAsset* fork() const override { | |
| 324 SkStreamAsset* clone = this->duplicate(); | |
| 325 clone->seek(this->getPosition()); | |
| 326 return clone; | |
| 327 } | |
| 328 | |
| 329 | |
| 330 private: | |
| 331 const SkRBuffer* fBuffer; | |
| 332 SkRBuffer::Iter fIter; | |
| 333 size_t fLocalOffset; | |
| 334 size_t fGlobalOffset; | |
| 335 }; | |
| 336 | |
| 337 SkStreamAsset* SkRWBuffer::newStreamSnapshot() const { | |
| 338 SkAutoTUnref<SkRBuffer> buffer(this->newRBufferSnapshot()); | |
| 339 return SkNEW_ARGS(SkRBufferStreamAsset, (buffer)); | |
| 340 } | |
| OLD | NEW |