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