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