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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1
michael@0 2 /*
michael@0 3 * Copyright 2006 The Android Open Source Project
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10 #include "SkStream.h"
michael@0 11 #include "SkData.h"
michael@0 12 #include "SkFixed.h"
michael@0 13 #include "SkString.h"
michael@0 14 #include "SkOSFile.h"
michael@0 15
michael@0 16 ///////////////////////////////////////////////////////////////////////////////
michael@0 17
michael@0 18
michael@0 19 int8_t SkStream::readS8() {
michael@0 20 int8_t value;
michael@0 21 SkDEBUGCODE(size_t len =) this->read(&value, 1);
michael@0 22 SkASSERT(1 == len);
michael@0 23 return value;
michael@0 24 }
michael@0 25
michael@0 26 int16_t SkStream::readS16() {
michael@0 27 int16_t value;
michael@0 28 SkDEBUGCODE(size_t len =) this->read(&value, 2);
michael@0 29 SkASSERT(2 == len);
michael@0 30 return value;
michael@0 31 }
michael@0 32
michael@0 33 int32_t SkStream::readS32() {
michael@0 34 int32_t value;
michael@0 35 SkDEBUGCODE(size_t len =) this->read(&value, 4);
michael@0 36 SkASSERT(4 == len);
michael@0 37 return value;
michael@0 38 }
michael@0 39
michael@0 40 SkScalar SkStream::readScalar() {
michael@0 41 SkScalar value;
michael@0 42 SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
michael@0 43 SkASSERT(sizeof(SkScalar) == len);
michael@0 44 return value;
michael@0 45 }
michael@0 46
michael@0 47 #define SK_MAX_BYTE_FOR_U8 0xFD
michael@0 48 #define SK_BYTE_SENTINEL_FOR_U16 0xFE
michael@0 49 #define SK_BYTE_SENTINEL_FOR_U32 0xFF
michael@0 50
michael@0 51 size_t SkStream::readPackedUInt() {
michael@0 52 uint8_t byte;
michael@0 53 if (!this->read(&byte, 1)) {
michael@0 54 return 0;
michael@0 55 }
michael@0 56 if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
michael@0 57 return this->readU16();
michael@0 58 } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
michael@0 59 return this->readU32();
michael@0 60 } else {
michael@0 61 return byte;
michael@0 62 }
michael@0 63 }
michael@0 64
michael@0 65 SkData* SkStream::readData() {
michael@0 66 size_t size = this->readU32();
michael@0 67 if (0 == size) {
michael@0 68 return SkData::NewEmpty();
michael@0 69 } else {
michael@0 70 void* buffer = sk_malloc_throw(size);
michael@0 71 this->read(buffer, size);
michael@0 72 return SkData::NewFromMalloc(buffer, size);
michael@0 73 }
michael@0 74 }
michael@0 75
michael@0 76 //////////////////////////////////////////////////////////////////////////////////////
michael@0 77
michael@0 78 SkWStream::~SkWStream()
michael@0 79 {
michael@0 80 }
michael@0 81
michael@0 82 void SkWStream::newline()
michael@0 83 {
michael@0 84 this->write("\n", 1);
michael@0 85 }
michael@0 86
michael@0 87 void SkWStream::flush()
michael@0 88 {
michael@0 89 }
michael@0 90
michael@0 91 bool SkWStream::writeText(const char text[])
michael@0 92 {
michael@0 93 SkASSERT(text);
michael@0 94 return this->write(text, strlen(text));
michael@0 95 }
michael@0 96
michael@0 97 bool SkWStream::writeDecAsText(int32_t dec)
michael@0 98 {
michael@0 99 SkString tmp;
michael@0 100 tmp.appendS32(dec);
michael@0 101 return this->write(tmp.c_str(), tmp.size());
michael@0 102 }
michael@0 103
michael@0 104 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
michael@0 105 {
michael@0 106 SkString tmp;
michael@0 107 tmp.appendS64(dec, minDigits);
michael@0 108 return this->write(tmp.c_str(), tmp.size());
michael@0 109 }
michael@0 110
michael@0 111 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
michael@0 112 {
michael@0 113 SkString tmp;
michael@0 114 tmp.appendHex(hex, digits);
michael@0 115 return this->write(tmp.c_str(), tmp.size());
michael@0 116 }
michael@0 117
michael@0 118 bool SkWStream::writeScalarAsText(SkScalar value)
michael@0 119 {
michael@0 120 SkString tmp;
michael@0 121 tmp.appendScalar(value);
michael@0 122 return this->write(tmp.c_str(), tmp.size());
michael@0 123 }
michael@0 124
michael@0 125 bool SkWStream::write8(U8CPU value) {
michael@0 126 uint8_t v = SkToU8(value);
michael@0 127 return this->write(&v, 1);
michael@0 128 }
michael@0 129
michael@0 130 bool SkWStream::write16(U16CPU value) {
michael@0 131 uint16_t v = SkToU16(value);
michael@0 132 return this->write(&v, 2);
michael@0 133 }
michael@0 134
michael@0 135 bool SkWStream::write32(uint32_t value) {
michael@0 136 return this->write(&value, 4);
michael@0 137 }
michael@0 138
michael@0 139 bool SkWStream::writeScalar(SkScalar value) {
michael@0 140 return this->write(&value, sizeof(value));
michael@0 141 }
michael@0 142
michael@0 143 int SkWStream::SizeOfPackedUInt(size_t value) {
michael@0 144 if (value <= SK_MAX_BYTE_FOR_U8) {
michael@0 145 return 1;
michael@0 146 } else if (value <= 0xFFFF) {
michael@0 147 return 3;
michael@0 148 }
michael@0 149 return 5;
michael@0 150 }
michael@0 151
michael@0 152 bool SkWStream::writePackedUInt(size_t value) {
michael@0 153 uint8_t data[5];
michael@0 154 size_t len = 1;
michael@0 155 if (value <= SK_MAX_BYTE_FOR_U8) {
michael@0 156 data[0] = value;
michael@0 157 len = 1;
michael@0 158 } else if (value <= 0xFFFF) {
michael@0 159 uint16_t value16 = value;
michael@0 160 data[0] = SK_BYTE_SENTINEL_FOR_U16;
michael@0 161 memcpy(&data[1], &value16, 2);
michael@0 162 len = 3;
michael@0 163 } else {
michael@0 164 uint32_t value32 = value;
michael@0 165 data[0] = SK_BYTE_SENTINEL_FOR_U32;
michael@0 166 memcpy(&data[1], &value32, 4);
michael@0 167 len = 5;
michael@0 168 }
michael@0 169 return this->write(data, len);
michael@0 170 }
michael@0 171
michael@0 172 bool SkWStream::writeStream(SkStream* stream, size_t length) {
michael@0 173 char scratch[1024];
michael@0 174 const size_t MAX = sizeof(scratch);
michael@0 175
michael@0 176 while (length != 0) {
michael@0 177 size_t n = length;
michael@0 178 if (n > MAX) {
michael@0 179 n = MAX;
michael@0 180 }
michael@0 181 stream->read(scratch, n);
michael@0 182 if (!this->write(scratch, n)) {
michael@0 183 return false;
michael@0 184 }
michael@0 185 length -= n;
michael@0 186 }
michael@0 187 return true;
michael@0 188 }
michael@0 189
michael@0 190 bool SkWStream::writeData(const SkData* data) {
michael@0 191 if (data) {
michael@0 192 this->write32(data->size());
michael@0 193 this->write(data->data(), data->size());
michael@0 194 } else {
michael@0 195 this->write32(0);
michael@0 196 }
michael@0 197 return true;
michael@0 198 }
michael@0 199
michael@0 200 ///////////////////////////////////////////////////////////////////////////////
michael@0 201
michael@0 202 SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
michael@0 203 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
michael@0 204 }
michael@0 205
michael@0 206 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
michael@0 207 : fFILE((SkFILE*)file)
michael@0 208 , fOwnership(ownership) {
michael@0 209 }
michael@0 210
michael@0 211 SkFILEStream::~SkFILEStream() {
michael@0 212 if (fFILE && fOwnership != kCallerRetains_Ownership) {
michael@0 213 sk_fclose(fFILE);
michael@0 214 }
michael@0 215 }
michael@0 216
michael@0 217 void SkFILEStream::setPath(const char path[]) {
michael@0 218 fName.set(path);
michael@0 219 if (fFILE) {
michael@0 220 sk_fclose(fFILE);
michael@0 221 fFILE = NULL;
michael@0 222 }
michael@0 223 if (path) {
michael@0 224 fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
michael@0 225 }
michael@0 226 }
michael@0 227
michael@0 228 size_t SkFILEStream::read(void* buffer, size_t size) {
michael@0 229 if (fFILE) {
michael@0 230 return sk_fread(buffer, size, fFILE);
michael@0 231 }
michael@0 232 return 0;
michael@0 233 }
michael@0 234
michael@0 235 bool SkFILEStream::isAtEnd() const {
michael@0 236 return sk_feof(fFILE);
michael@0 237 }
michael@0 238
michael@0 239 bool SkFILEStream::rewind() {
michael@0 240 if (fFILE) {
michael@0 241 if (sk_frewind(fFILE)) {
michael@0 242 return true;
michael@0 243 }
michael@0 244 // we hit an error
michael@0 245 sk_fclose(fFILE);
michael@0 246 fFILE = NULL;
michael@0 247 }
michael@0 248 return false;
michael@0 249 }
michael@0 250
michael@0 251 SkStreamAsset* SkFILEStream::duplicate() const {
michael@0 252 if (NULL == fFILE) {
michael@0 253 return new SkMemoryStream();
michael@0 254 }
michael@0 255
michael@0 256 if (NULL != fData.get()) {
michael@0 257 return new SkMemoryStream(fData);
michael@0 258 }
michael@0 259
michael@0 260 if (!fName.isEmpty()) {
michael@0 261 SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
michael@0 262 if (sk_fidentical(that->fFILE, this->fFILE)) {
michael@0 263 return that.detach();
michael@0 264 }
michael@0 265 }
michael@0 266
michael@0 267 fData.reset(SkData::NewFromFILE(fFILE));
michael@0 268 if (NULL == fData.get()) {
michael@0 269 return NULL;
michael@0 270 }
michael@0 271 return new SkMemoryStream(fData);
michael@0 272 }
michael@0 273
michael@0 274 size_t SkFILEStream::getPosition() const {
michael@0 275 return sk_ftell(fFILE);
michael@0 276 }
michael@0 277
michael@0 278 bool SkFILEStream::seek(size_t position) {
michael@0 279 return sk_fseek(fFILE, position);
michael@0 280 }
michael@0 281
michael@0 282 bool SkFILEStream::move(long offset) {
michael@0 283 return sk_fmove(fFILE, offset);
michael@0 284 }
michael@0 285
michael@0 286 SkStreamAsset* SkFILEStream::fork() const {
michael@0 287 SkAutoTUnref<SkStreamAsset> that(this->duplicate());
michael@0 288 that->seek(this->getPosition());
michael@0 289 return that.detach();
michael@0 290 }
michael@0 291
michael@0 292 size_t SkFILEStream::getLength() const {
michael@0 293 return sk_fgetsize(fFILE);
michael@0 294 }
michael@0 295
michael@0 296 const void* SkFILEStream::getMemoryBase() {
michael@0 297 if (NULL == fData.get()) {
michael@0 298 return NULL;
michael@0 299 }
michael@0 300 return fData->data();
michael@0 301 }
michael@0 302
michael@0 303 ///////////////////////////////////////////////////////////////////////////////
michael@0 304
michael@0 305 static SkData* newFromParams(const void* src, size_t size, bool copyData) {
michael@0 306 if (copyData) {
michael@0 307 return SkData::NewWithCopy(src, size);
michael@0 308 } else {
michael@0 309 return SkData::NewWithProc(src, size, NULL, NULL);
michael@0 310 }
michael@0 311 }
michael@0 312
michael@0 313 SkMemoryStream::SkMemoryStream() {
michael@0 314 fData = SkData::NewEmpty();
michael@0 315 fOffset = 0;
michael@0 316 }
michael@0 317
michael@0 318 SkMemoryStream::SkMemoryStream(size_t size) {
michael@0 319 fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
michael@0 320 fOffset = 0;
michael@0 321 }
michael@0 322
michael@0 323 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
michael@0 324 fData = newFromParams(src, size, copyData);
michael@0 325 fOffset = 0;
michael@0 326 }
michael@0 327
michael@0 328 SkMemoryStream::SkMemoryStream(SkData* data) {
michael@0 329 if (NULL == data) {
michael@0 330 fData = SkData::NewEmpty();
michael@0 331 } else {
michael@0 332 fData = data;
michael@0 333 fData->ref();
michael@0 334 }
michael@0 335 fOffset = 0;
michael@0 336 }
michael@0 337
michael@0 338 SkMemoryStream::~SkMemoryStream() {
michael@0 339 fData->unref();
michael@0 340 }
michael@0 341
michael@0 342 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
michael@0 343 fData->unref();
michael@0 344 fData = SkData::NewFromMalloc(src, size);
michael@0 345 fOffset = 0;
michael@0 346 }
michael@0 347
michael@0 348 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
michael@0 349 fData->unref();
michael@0 350 fData = newFromParams(src, size, copyData);
michael@0 351 fOffset = 0;
michael@0 352 }
michael@0 353
michael@0 354 SkData* SkMemoryStream::copyToData() const {
michael@0 355 fData->ref();
michael@0 356 return fData;
michael@0 357 }
michael@0 358
michael@0 359 SkData* SkMemoryStream::setData(SkData* data) {
michael@0 360 fData->unref();
michael@0 361 if (NULL == data) {
michael@0 362 fData = SkData::NewEmpty();
michael@0 363 } else {
michael@0 364 fData = data;
michael@0 365 fData->ref();
michael@0 366 }
michael@0 367 fOffset = 0;
michael@0 368 return data;
michael@0 369 }
michael@0 370
michael@0 371 void SkMemoryStream::skipToAlign4() {
michael@0 372 // cast to remove unary-minus warning
michael@0 373 fOffset += -(int)fOffset & 0x03;
michael@0 374 }
michael@0 375
michael@0 376 size_t SkMemoryStream::read(void* buffer, size_t size) {
michael@0 377 size_t dataSize = fData->size();
michael@0 378
michael@0 379 if (size > dataSize - fOffset) {
michael@0 380 size = dataSize - fOffset;
michael@0 381 }
michael@0 382 if (buffer) {
michael@0 383 memcpy(buffer, fData->bytes() + fOffset, size);
michael@0 384 }
michael@0 385 fOffset += size;
michael@0 386 return size;
michael@0 387 }
michael@0 388
michael@0 389 bool SkMemoryStream::isAtEnd() const {
michael@0 390 return fOffset == fData->size();
michael@0 391 }
michael@0 392
michael@0 393 bool SkMemoryStream::rewind() {
michael@0 394 fOffset = 0;
michael@0 395 return true;
michael@0 396 }
michael@0 397
michael@0 398 SkMemoryStream* SkMemoryStream::duplicate() const {
michael@0 399 return SkNEW_ARGS(SkMemoryStream, (fData));
michael@0 400 }
michael@0 401
michael@0 402 size_t SkMemoryStream::getPosition() const {
michael@0 403 return fOffset;
michael@0 404 }
michael@0 405
michael@0 406 bool SkMemoryStream::seek(size_t position) {
michael@0 407 fOffset = position > fData->size()
michael@0 408 ? fData->size()
michael@0 409 : position;
michael@0 410 return true;
michael@0 411 }
michael@0 412
michael@0 413 bool SkMemoryStream::move(long offset) {
michael@0 414 return this->seek(fOffset + offset);
michael@0 415 }
michael@0 416
michael@0 417 SkMemoryStream* SkMemoryStream::fork() const {
michael@0 418 SkAutoTUnref<SkMemoryStream> that(this->duplicate());
michael@0 419 that->seek(fOffset);
michael@0 420 return that.detach();
michael@0 421 }
michael@0 422
michael@0 423 size_t SkMemoryStream::getLength() const {
michael@0 424 return fData->size();
michael@0 425 }
michael@0 426
michael@0 427 const void* SkMemoryStream::getMemoryBase() {
michael@0 428 return fData->data();
michael@0 429 }
michael@0 430
michael@0 431 const void* SkMemoryStream::getAtPos() {
michael@0 432 return fData->bytes() + fOffset;
michael@0 433 }
michael@0 434
michael@0 435 /////////////////////////////////////////////////////////////////////////////////////////////////////////
michael@0 436 /////////////////////////////////////////////////////////////////////////////////////////////////////////
michael@0 437
michael@0 438 SkFILEWStream::SkFILEWStream(const char path[])
michael@0 439 {
michael@0 440 fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
michael@0 441 }
michael@0 442
michael@0 443 SkFILEWStream::~SkFILEWStream()
michael@0 444 {
michael@0 445 if (fFILE) {
michael@0 446 sk_fclose(fFILE);
michael@0 447 }
michael@0 448 }
michael@0 449
michael@0 450 size_t SkFILEWStream::bytesWritten() const {
michael@0 451 return sk_ftell(fFILE);
michael@0 452 }
michael@0 453
michael@0 454 bool SkFILEWStream::write(const void* buffer, size_t size)
michael@0 455 {
michael@0 456 if (fFILE == NULL) {
michael@0 457 return false;
michael@0 458 }
michael@0 459
michael@0 460 if (sk_fwrite(buffer, size, fFILE) != size)
michael@0 461 {
michael@0 462 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
michael@0 463 sk_fclose(fFILE);
michael@0 464 fFILE = NULL;
michael@0 465 return false;
michael@0 466 }
michael@0 467 return true;
michael@0 468 }
michael@0 469
michael@0 470 void SkFILEWStream::flush()
michael@0 471 {
michael@0 472 if (fFILE) {
michael@0 473 sk_fflush(fFILE);
michael@0 474 }
michael@0 475 }
michael@0 476
michael@0 477 ////////////////////////////////////////////////////////////////////////
michael@0 478
michael@0 479 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
michael@0 480 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
michael@0 481 {
michael@0 482 }
michael@0 483
michael@0 484 bool SkMemoryWStream::write(const void* buffer, size_t size)
michael@0 485 {
michael@0 486 size = SkMin32(size, fMaxLength - fBytesWritten);
michael@0 487 if (size > 0)
michael@0 488 {
michael@0 489 memcpy(fBuffer + fBytesWritten, buffer, size);
michael@0 490 fBytesWritten += size;
michael@0 491 return true;
michael@0 492 }
michael@0 493 return false;
michael@0 494 }
michael@0 495
michael@0 496 ////////////////////////////////////////////////////////////////////////
michael@0 497
michael@0 498 #define SkDynamicMemoryWStream_MinBlockSize 256
michael@0 499
michael@0 500 struct SkDynamicMemoryWStream::Block {
michael@0 501 Block* fNext;
michael@0 502 char* fCurr;
michael@0 503 char* fStop;
michael@0 504
michael@0 505 const char* start() const { return (const char*)(this + 1); }
michael@0 506 char* start() { return (char*)(this + 1); }
michael@0 507 size_t avail() const { return fStop - fCurr; }
michael@0 508 size_t written() const { return fCurr - this->start(); }
michael@0 509
michael@0 510 void init(size_t size)
michael@0 511 {
michael@0 512 fNext = NULL;
michael@0 513 fCurr = this->start();
michael@0 514 fStop = this->start() + size;
michael@0 515 }
michael@0 516
michael@0 517 const void* append(const void* data, size_t size)
michael@0 518 {
michael@0 519 SkASSERT((size_t)(fStop - fCurr) >= size);
michael@0 520 memcpy(fCurr, data, size);
michael@0 521 fCurr += size;
michael@0 522 return (const void*)((const char*)data + size);
michael@0 523 }
michael@0 524 };
michael@0 525
michael@0 526 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
michael@0 527 : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
michael@0 528 {
michael@0 529 }
michael@0 530
michael@0 531 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
michael@0 532 {
michael@0 533 reset();
michael@0 534 }
michael@0 535
michael@0 536 void SkDynamicMemoryWStream::reset()
michael@0 537 {
michael@0 538 this->invalidateCopy();
michael@0 539
michael@0 540 Block* block = fHead;
michael@0 541
michael@0 542 while (block != NULL) {
michael@0 543 Block* next = block->fNext;
michael@0 544 sk_free(block);
michael@0 545 block = next;
michael@0 546 }
michael@0 547 fHead = fTail = NULL;
michael@0 548 fBytesWritten = 0;
michael@0 549 }
michael@0 550
michael@0 551 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
michael@0 552 {
michael@0 553 if (count > 0) {
michael@0 554 this->invalidateCopy();
michael@0 555
michael@0 556 fBytesWritten += count;
michael@0 557
michael@0 558 size_t size;
michael@0 559
michael@0 560 if (fTail != NULL && fTail->avail() > 0) {
michael@0 561 size = SkMin32(fTail->avail(), count);
michael@0 562 buffer = fTail->append(buffer, size);
michael@0 563 SkASSERT(count >= size);
michael@0 564 count -= size;
michael@0 565 if (count == 0)
michael@0 566 return true;
michael@0 567 }
michael@0 568
michael@0 569 size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
michael@0 570 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
michael@0 571 block->init(size);
michael@0 572 block->append(buffer, count);
michael@0 573
michael@0 574 if (fTail != NULL)
michael@0 575 fTail->fNext = block;
michael@0 576 else
michael@0 577 fHead = fTail = block;
michael@0 578 fTail = block;
michael@0 579 }
michael@0 580 return true;
michael@0 581 }
michael@0 582
michael@0 583 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
michael@0 584 {
michael@0 585 if (offset + count > fBytesWritten) {
michael@0 586 return false; // test does not partially modify
michael@0 587 }
michael@0 588
michael@0 589 this->invalidateCopy();
michael@0 590
michael@0 591 Block* block = fHead;
michael@0 592 while (block != NULL) {
michael@0 593 size_t size = block->written();
michael@0 594 if (offset < size) {
michael@0 595 size_t part = offset + count > size ? size - offset : count;
michael@0 596 memcpy(block->start() + offset, buffer, part);
michael@0 597 if (count <= part)
michael@0 598 return true;
michael@0 599 count -= part;
michael@0 600 buffer = (const void*) ((char* ) buffer + part);
michael@0 601 }
michael@0 602 offset = offset > size ? offset - size : 0;
michael@0 603 block = block->fNext;
michael@0 604 }
michael@0 605 return false;
michael@0 606 }
michael@0 607
michael@0 608 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
michael@0 609 {
michael@0 610 if (offset + count > fBytesWritten)
michael@0 611 return false; // test does not partially modify
michael@0 612 Block* block = fHead;
michael@0 613 while (block != NULL) {
michael@0 614 size_t size = block->written();
michael@0 615 if (offset < size) {
michael@0 616 size_t part = offset + count > size ? size - offset : count;
michael@0 617 memcpy(buffer, block->start() + offset, part);
michael@0 618 if (count <= part)
michael@0 619 return true;
michael@0 620 count -= part;
michael@0 621 buffer = (void*) ((char* ) buffer + part);
michael@0 622 }
michael@0 623 offset = offset > size ? offset - size : 0;
michael@0 624 block = block->fNext;
michael@0 625 }
michael@0 626 return false;
michael@0 627 }
michael@0 628
michael@0 629 void SkDynamicMemoryWStream::copyTo(void* dst) const
michael@0 630 {
michael@0 631 if (fCopy) {
michael@0 632 memcpy(dst, fCopy->data(), fBytesWritten);
michael@0 633 } else {
michael@0 634 Block* block = fHead;
michael@0 635
michael@0 636 while (block != NULL) {
michael@0 637 size_t size = block->written();
michael@0 638 memcpy(dst, block->start(), size);
michael@0 639 dst = (void*)((char*)dst + size);
michael@0 640 block = block->fNext;
michael@0 641 }
michael@0 642 }
michael@0 643 }
michael@0 644
michael@0 645 void SkDynamicMemoryWStream::padToAlign4()
michael@0 646 {
michael@0 647 // cast to remove unary-minus warning
michael@0 648 int padBytes = -(int)fBytesWritten & 0x03;
michael@0 649 if (padBytes == 0)
michael@0 650 return;
michael@0 651 int zero = 0;
michael@0 652 write(&zero, padBytes);
michael@0 653 }
michael@0 654
michael@0 655 SkData* SkDynamicMemoryWStream::copyToData() const {
michael@0 656 if (NULL == fCopy) {
michael@0 657 void* buffer = sk_malloc_throw(fBytesWritten);
michael@0 658 this->copyTo(buffer);
michael@0 659 fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
michael@0 660 }
michael@0 661 fCopy->ref();
michael@0 662 return fCopy;
michael@0 663 }
michael@0 664
michael@0 665 void SkDynamicMemoryWStream::invalidateCopy() {
michael@0 666 if (fCopy) {
michael@0 667 fCopy->unref();
michael@0 668 fCopy = NULL;
michael@0 669 }
michael@0 670 }
michael@0 671
michael@0 672 class SkBlockMemoryRefCnt : public SkRefCnt {
michael@0 673 public:
michael@0 674 explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
michael@0 675
michael@0 676 virtual ~SkBlockMemoryRefCnt() {
michael@0 677 SkDynamicMemoryWStream::Block* block = fHead;
michael@0 678 while (block != NULL) {
michael@0 679 SkDynamicMemoryWStream::Block* next = block->fNext;
michael@0 680 sk_free(block);
michael@0 681 block = next;
michael@0 682 }
michael@0 683 }
michael@0 684
michael@0 685 SkDynamicMemoryWStream::Block* const fHead;
michael@0 686 };
michael@0 687
michael@0 688 class SkBlockMemoryStream : public SkStreamAsset {
michael@0 689 public:
michael@0 690 SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
michael@0 691 : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
michael@0 692 , fSize(size) , fOffset(0), fCurrentOffset(0) { }
michael@0 693
michael@0 694 SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
michael@0 695 : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
michael@0 696 , fSize(size) , fOffset(0), fCurrentOffset(0) { }
michael@0 697
michael@0 698 virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
michael@0 699 size_t count = rawCount;
michael@0 700 if (fOffset + count > fSize) {
michael@0 701 count = fSize - fOffset;
michael@0 702 }
michael@0 703 size_t bytesLeftToRead = count;
michael@0 704 while (fCurrent != NULL) {
michael@0 705 size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
michael@0 706 size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
michael@0 707 if (buffer) {
michael@0 708 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
michael@0 709 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
michael@0 710 }
michael@0 711 if (bytesLeftToRead <= bytesFromCurrent) {
michael@0 712 fCurrentOffset += bytesFromCurrent;
michael@0 713 fOffset += count;
michael@0 714 return count;
michael@0 715 }
michael@0 716 bytesLeftToRead -= bytesFromCurrent;
michael@0 717 fCurrent = fCurrent->fNext;
michael@0 718 fCurrentOffset = 0;
michael@0 719 }
michael@0 720 SkASSERT(false);
michael@0 721 return 0;
michael@0 722 }
michael@0 723
michael@0 724 virtual bool isAtEnd() const SK_OVERRIDE {
michael@0 725 return fOffset == fSize;
michael@0 726 }
michael@0 727
michael@0 728 virtual bool rewind() SK_OVERRIDE {
michael@0 729 fCurrent = fBlockMemory->fHead;
michael@0 730 fOffset = 0;
michael@0 731 fCurrentOffset = 0;
michael@0 732 return true;
michael@0 733 }
michael@0 734
michael@0 735 virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
michael@0 736 return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
michael@0 737 }
michael@0 738
michael@0 739 virtual size_t getPosition() const SK_OVERRIDE {
michael@0 740 return fOffset;
michael@0 741 }
michael@0 742
michael@0 743 virtual bool seek(size_t position) SK_OVERRIDE {
michael@0 744 // If possible, skip forward.
michael@0 745 if (position >= fOffset) {
michael@0 746 size_t skipAmount = position - fOffset;
michael@0 747 return this->skip(skipAmount) == skipAmount;
michael@0 748 }
michael@0 749 // If possible, move backward within the current block.
michael@0 750 size_t moveBackAmount = fOffset - position;
michael@0 751 if (moveBackAmount <= fCurrentOffset) {
michael@0 752 fCurrentOffset -= moveBackAmount;
michael@0 753 fOffset -= moveBackAmount;
michael@0 754 return true;
michael@0 755 }
michael@0 756 // Otherwise rewind and move forward.
michael@0 757 return this->rewind() && this->skip(position) == position;
michael@0 758 }
michael@0 759
michael@0 760 virtual bool move(long offset) SK_OVERRIDE {
michael@0 761 return seek(fOffset + offset);
michael@0 762 }
michael@0 763
michael@0 764 virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
michael@0 765 SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
michael@0 766 that->fCurrent = this->fCurrent;
michael@0 767 that->fOffset = this->fOffset;
michael@0 768 that->fCurrentOffset = this->fCurrentOffset;
michael@0 769 return that.detach();
michael@0 770 }
michael@0 771
michael@0 772 virtual size_t getLength() const SK_OVERRIDE {
michael@0 773 return fSize;
michael@0 774 }
michael@0 775
michael@0 776 virtual const void* getMemoryBase() SK_OVERRIDE {
michael@0 777 if (NULL == fBlockMemory->fHead->fNext) {
michael@0 778 return fBlockMemory->fHead->start();
michael@0 779 }
michael@0 780 return NULL;
michael@0 781 }
michael@0 782
michael@0 783 private:
michael@0 784 SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
michael@0 785 SkDynamicMemoryWStream::Block const * fCurrent;
michael@0 786 size_t const fSize;
michael@0 787 size_t fOffset;
michael@0 788 size_t fCurrentOffset;
michael@0 789 };
michael@0 790
michael@0 791 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
michael@0 792 if (fCopy) {
michael@0 793 SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
michael@0 794 this->reset();
michael@0 795 return stream;
michael@0 796 }
michael@0 797 SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
michael@0 798 fHead = 0;
michael@0 799 this->reset();
michael@0 800 return stream;
michael@0 801 }
michael@0 802
michael@0 803 ///////////////////////////////////////////////////////////////////////////////
michael@0 804
michael@0 805 void SkDebugWStream::newline()
michael@0 806 {
michael@0 807 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
michael@0 808 SkDebugf("\n");
michael@0 809 fBytesWritten++;
michael@0 810 #endif
michael@0 811 }
michael@0 812
michael@0 813 bool SkDebugWStream::write(const void* buffer, size_t size)
michael@0 814 {
michael@0 815 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
michael@0 816 char* s = new char[size+1];
michael@0 817 memcpy(s, buffer, size);
michael@0 818 s[size] = 0;
michael@0 819 SkDebugf("%s", s);
michael@0 820 delete[] s;
michael@0 821 fBytesWritten += size;
michael@0 822 #endif
michael@0 823 return true;
michael@0 824 }
michael@0 825
michael@0 826 ///////////////////////////////////////////////////////////////////////////////
michael@0 827 ///////////////////////////////////////////////////////////////////////////////
michael@0 828
michael@0 829
michael@0 830 static SkData* mmap_filename(const char path[]) {
michael@0 831 SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
michael@0 832 if (NULL == file) {
michael@0 833 return NULL;
michael@0 834 }
michael@0 835
michael@0 836 SkData* data = SkData::NewFromFILE(file);
michael@0 837 sk_fclose(file);
michael@0 838 return data;
michael@0 839 }
michael@0 840
michael@0 841 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
michael@0 842 SkAutoTUnref<SkData> data(mmap_filename(path));
michael@0 843 if (data.get()) {
michael@0 844 return SkNEW_ARGS(SkMemoryStream, (data.get()));
michael@0 845 }
michael@0 846
michael@0 847 // If we get here, then our attempt at using mmap failed, so try normal
michael@0 848 // file access.
michael@0 849 SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
michael@0 850 if (!stream->isValid()) {
michael@0 851 stream->unref();
michael@0 852 stream = NULL;
michael@0 853 }
michael@0 854 return stream;
michael@0 855 }

mercurial