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