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