SkStream.cpp revision f515ffc3d44975a09755276e572448061df3e2fe
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::readData() { 97 size_t size = this->readU32(); 98 if (0 == size) { 99 return SkData::NewEmpty(); 100 } else { 101 void* buffer = sk_malloc_throw(size); 102 this->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(SkData *data) { 303 fData = SkSafeRef(data); 304 fOffset = 0; 305} 306 307SkMemoryStream::~SkMemoryStream() { 308 fData->unref(); 309} 310 311void SkMemoryStream::setMemoryOwned(const void* src, size_t size) { 312 fData->unref(); 313 fData = SkData::NewFromMalloc(src, size); 314 fOffset = 0; 315} 316 317void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) { 318 fData->unref(); 319 fData = newFromParams(src, size, copyData); 320 fOffset = 0; 321} 322 323SkData* SkMemoryStream::copyToData() const { 324 fData->ref(); 325 return fData; 326} 327 328SkData* SkMemoryStream::setData(SkData* data) { 329 SkRefCnt_SafeAssign(fData, data); 330 return data; 331} 332 333void SkMemoryStream::skipToAlign4() { 334 // cast to remove unary-minus warning 335 fOffset += -(int)fOffset & 0x03; 336} 337 338bool SkMemoryStream::rewind() { 339 fOffset = 0; 340 return true; 341} 342 343size_t SkMemoryStream::read(void* buffer, size_t size) { 344 size_t dataSize = fData->size(); 345 346 if (buffer == NULL && size == 0) // special signature, they want the total size 347 return dataSize; 348 349 // if buffer is NULL, seek ahead by size 350 351 if (size == 0) { 352 return 0; 353 } 354 if (size > dataSize - fOffset) { 355 size = dataSize - fOffset; 356 } 357 if (buffer) { 358 memcpy(buffer, fData->bytes() + fOffset, size); 359 } 360 fOffset += size; 361 return size; 362} 363 364const void* SkMemoryStream::getMemoryBase() { 365 return fData->data(); 366} 367 368const void* SkMemoryStream::getAtPos() { 369 return fData->bytes() + fOffset; 370} 371 372size_t SkMemoryStream::seek(size_t offset) { 373 if (offset > fData->size()) { 374 offset = fData->size(); 375 } 376 fOffset = offset; 377 return offset; 378} 379 380/////////////////////////////////////////////////////////////////////////////// 381 382SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize) 383 : fProxy(proxy) 384{ 385 SkASSERT(proxy != NULL); 386 proxy->ref(); 387 this->init(NULL, bufferSize); 388} 389 390SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize) 391 : fProxy(proxy) 392{ 393 SkASSERT(proxy != NULL); 394 SkASSERT(buffer == NULL || bufferSize != 0); // init(addr, 0) makes no sense, we must know how big their buffer is 395 proxy->ref(); 396 this->init(buffer, bufferSize); 397} 398 399void SkBufferStream::init(void* buffer, size_t bufferSize) 400{ 401 if (bufferSize == 0) 402 bufferSize = kDefaultBufferSize; 403 404 fOrigBufferSize = bufferSize; 405 fBufferSize = bufferSize; 406 fBufferOffset = bufferSize; // to trigger a reload on the first read() 407 408 if (buffer == NULL) 409 { 410 fBuffer = (char*)sk_malloc_throw(fBufferSize); 411 fWeOwnTheBuffer = true; 412 } 413 else 414 { 415 fBuffer = (char*)buffer; 416 fWeOwnTheBuffer = false; 417 } 418} 419 420SkBufferStream::~SkBufferStream() 421{ 422 fProxy->unref(); 423 if (fWeOwnTheBuffer) 424 sk_free(fBuffer); 425} 426 427bool SkBufferStream::rewind() 428{ 429 fBufferOffset = fBufferSize = fOrigBufferSize; 430 return fProxy->rewind(); 431} 432 433const char* SkBufferStream::getFileName() 434{ 435 return fProxy->getFileName(); 436} 437 438#ifdef SK_DEBUG 439// #define SK_TRACE_BUFFERSTREAM 440#endif 441 442size_t SkBufferStream::read(void* buffer, size_t size) { 443#ifdef SK_TRACE_BUFFERSTREAM 444 SkDebugf("Request %d", size); 445#endif 446 447 if (buffer == NULL && size == 0) { 448 return fProxy->read(buffer, size); // requesting total size 449 } 450 451 if (0 == size) { 452 return 0; 453 } 454 455 // skip size bytes 456 if (NULL == buffer) { 457 size_t remaining = fBufferSize - fBufferOffset; 458 if (remaining >= size) { 459 fBufferOffset += size; 460 return size; 461 } 462 // if we get here, we are being asked to skip beyond our current buffer 463 // so reset our offset to force a read next time, and skip the diff 464 // in our proxy 465 fBufferOffset = fOrigBufferSize; 466 return remaining + fProxy->read(NULL, size - remaining); 467 } 468 469 size_t s = size; 470 size_t actuallyRead = 0; 471 472 // flush what we can from our fBuffer 473 if (fBufferOffset < fBufferSize) 474 { 475 if (s > fBufferSize - fBufferOffset) 476 s = fBufferSize - fBufferOffset; 477 memcpy(buffer, fBuffer + fBufferOffset, s); 478#ifdef SK_TRACE_BUFFERSTREAM 479 SkDebugf(" flush %d", s); 480#endif 481 size -= s; 482 fBufferOffset += s; 483 buffer = (char*)buffer + s; 484 actuallyRead = s; 485 } 486 487 // check if there is more to read 488 if (size) 489 { 490 SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer 491 492 if (size < fBufferSize) // lets try to read more than the request 493 { 494 s = fProxy->read(fBuffer, fBufferSize); 495#ifdef SK_TRACE_BUFFERSTREAM 496 SkDebugf(" read %d into fBuffer", s); 497#endif 498 if (size > s) // they asked for too much 499 size = s; 500 if (size) 501 { 502 memcpy(buffer, fBuffer, size); 503 actuallyRead += size; 504#ifdef SK_TRACE_BUFFERSTREAM 505 SkDebugf(" memcpy %d into dst", size); 506#endif 507 } 508 509 fBufferOffset = size; 510 fBufferSize = s; // record the (possibly smaller) size for the buffer 511 } 512 else // just do a direct read 513 { 514 actuallyRead += fProxy->read(buffer, size); 515#ifdef SK_TRACE_BUFFERSTREAM 516 SkDebugf(" direct read %d", size); 517#endif 518 } 519 } 520#ifdef SK_TRACE_BUFFERSTREAM 521 SkDebugf("\n"); 522#endif 523 return actuallyRead; 524} 525 526const void* SkBufferStream::getMemoryBase() 527{ 528 return fProxy->getMemoryBase(); 529} 530 531///////////////////////////////////////////////////////////////////////////////////////////////////////// 532///////////////////////////////////////////////////////////////////////////////////////////////////////// 533 534SkFILEWStream::SkFILEWStream(const char path[]) 535{ 536 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); 537} 538 539SkFILEWStream::~SkFILEWStream() 540{ 541 if (fFILE) 542 sk_fclose(fFILE); 543} 544 545bool SkFILEWStream::write(const void* buffer, size_t size) 546{ 547 if (fFILE == NULL) 548 return false; 549 550 if (sk_fwrite(buffer, size, fFILE) != size) 551 { 552 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);) 553 sk_fclose(fFILE); 554 fFILE = NULL; 555 return false; 556 } 557 return true; 558} 559 560void SkFILEWStream::flush() 561{ 562 if (fFILE) 563 sk_fflush(fFILE); 564} 565 566//////////////////////////////////////////////////////////////////////// 567 568SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size) 569 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0) 570{ 571} 572 573bool SkMemoryWStream::write(const void* buffer, size_t size) 574{ 575 size = SkMin32(size, fMaxLength - fBytesWritten); 576 if (size > 0) 577 { 578 memcpy(fBuffer + fBytesWritten, buffer, size); 579 fBytesWritten += size; 580 return true; 581 } 582 return false; 583} 584 585//////////////////////////////////////////////////////////////////////// 586 587#define SkDynamicMemoryWStream_MinBlockSize 256 588 589struct SkDynamicMemoryWStream::Block { 590 Block* fNext; 591 char* fCurr; 592 char* fStop; 593 594 const char* start() const { return (const char*)(this + 1); } 595 char* start() { return (char*)(this + 1); } 596 size_t avail() const { return fStop - fCurr; } 597 size_t written() const { return fCurr - this->start(); } 598 599 void init(size_t size) 600 { 601 fNext = NULL; 602 fCurr = this->start(); 603 fStop = this->start() + size; 604 } 605 606 const void* append(const void* data, size_t size) 607 { 608 SkASSERT((size_t)(fStop - fCurr) >= size); 609 memcpy(fCurr, data, size); 610 fCurr += size; 611 return (const void*)((const char*)data + size); 612 } 613}; 614 615SkDynamicMemoryWStream::SkDynamicMemoryWStream() 616 : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL) 617{ 618} 619 620SkDynamicMemoryWStream::~SkDynamicMemoryWStream() 621{ 622 reset(); 623} 624 625void SkDynamicMemoryWStream::reset() 626{ 627 this->invalidateCopy(); 628 629 Block* block = fHead; 630 631 while (block != NULL) { 632 Block* next = block->fNext; 633 sk_free(block); 634 block = next; 635 } 636 fHead = fTail = NULL; 637 fBytesWritten = 0; 638} 639 640bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) 641{ 642 if (count > 0) { 643 this->invalidateCopy(); 644 645 fBytesWritten += count; 646 647 size_t size; 648 649 if (fTail != NULL && fTail->avail() > 0) { 650 size = SkMin32(fTail->avail(), count); 651 buffer = fTail->append(buffer, size); 652 SkASSERT(count >= size); 653 count -= size; 654 if (count == 0) 655 return true; 656 } 657 658 size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize); 659 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); 660 block->init(size); 661 block->append(buffer, count); 662 663 if (fTail != NULL) 664 fTail->fNext = block; 665 else 666 fHead = fTail = block; 667 fTail = block; 668 } 669 return true; 670} 671 672bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count) 673{ 674 if (offset + count > fBytesWritten) { 675 return false; // test does not partially modify 676 } 677 678 this->invalidateCopy(); 679 680 Block* block = fHead; 681 while (block != NULL) { 682 size_t size = block->written(); 683 if (offset < size) { 684 size_t part = offset + count > size ? size - offset : count; 685 memcpy(block->start() + offset, buffer, part); 686 if (count <= part) 687 return true; 688 count -= part; 689 buffer = (const void*) ((char* ) buffer + part); 690 } 691 offset = offset > size ? offset - size : 0; 692 block = block->fNext; 693 } 694 return false; 695} 696 697bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count) 698{ 699 if (offset + count > fBytesWritten) 700 return false; // test does not partially modify 701 Block* block = fHead; 702 while (block != NULL) { 703 size_t size = block->written(); 704 if (offset < size) { 705 size_t part = offset + count > size ? size - offset : count; 706 memcpy(buffer, block->start() + offset, part); 707 if (count <= part) 708 return true; 709 count -= part; 710 buffer = (void*) ((char* ) buffer + part); 711 } 712 offset = offset > size ? offset - size : 0; 713 block = block->fNext; 714 } 715 return false; 716} 717 718void SkDynamicMemoryWStream::copyTo(void* dst) const 719{ 720 if (fCopy) { 721 memcpy(dst, fCopy->data(), fBytesWritten); 722 } else { 723 Block* block = fHead; 724 725 while (block != NULL) { 726 size_t size = block->written(); 727 memcpy(dst, block->start(), size); 728 dst = (void*)((char*)dst + size); 729 block = block->fNext; 730 } 731 } 732} 733 734void SkDynamicMemoryWStream::padToAlign4() 735{ 736 // cast to remove unary-minus warning 737 int padBytes = -(int)fBytesWritten & 0x03; 738 if (padBytes == 0) 739 return; 740 int zero = 0; 741 write(&zero, padBytes); 742} 743 744SkData* SkDynamicMemoryWStream::copyToData() const { 745 if (NULL == fCopy) { 746 void* buffer = sk_malloc_throw(fBytesWritten); 747 this->copyTo(buffer); 748 fCopy = SkData::NewFromMalloc(buffer, fBytesWritten); 749 } 750 fCopy->ref(); 751 return fCopy; 752} 753 754void SkDynamicMemoryWStream::invalidateCopy() { 755 if (fCopy) { 756 fCopy->unref(); 757 fCopy = NULL; 758 } 759} 760 761/////////////////////////////////////////////////////////////////////////////// 762 763void SkDebugWStream::newline() 764{ 765#ifdef SK_DEBUG 766 SkDebugf("\n"); 767#endif 768} 769 770bool SkDebugWStream::write(const void* buffer, size_t size) 771{ 772#ifdef SK_DEBUG 773 char* s = new char[size+1]; 774 memcpy(s, buffer, size); 775 s[size] = 0; 776 SkDebugf("%s", s); 777 delete[] s; 778#endif 779 return true; 780} 781