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