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