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 23SkStream::~SkStream() {} 24 25const char* SkStream::getFileName() 26{ 27 // override in subclass if you represent a file 28 return NULL; 29} 30 31const void* SkStream::getMemoryBase() 32{ 33 // override in subclass if you represent a memory block 34 return NULL; 35} 36 37size_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 46int8_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 53int16_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 60int32_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 67SkScalar 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 74size_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 100SkWStream::~SkWStream() 101{ 102} 103 104void SkWStream::newline() 105{ 106 this->write("\n", 1); 107} 108 109void SkWStream::flush() 110{ 111} 112 113bool SkWStream::writeText(const char text[]) 114{ 115 SkASSERT(text); 116 return this->write(text, strlen(text)); 117} 118 119bool SkWStream::writeDecAsText(int32_t dec) 120{ 121 SkString tmp; 122 tmp.appendS32(dec); 123 return this->write(tmp.c_str(), tmp.size()); 124} 125 126bool 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 133bool SkWStream::writeScalarAsText(SkScalar value) 134{ 135 SkString tmp; 136 tmp.appendScalar(value); 137 return this->write(tmp.c_str(), tmp.size()); 138} 139 140bool SkWStream::write8(U8CPU value) { 141 uint8_t v = SkToU8(value); 142 return this->write(&v, 1); 143} 144 145bool SkWStream::write16(U16CPU value) { 146 uint16_t v = SkToU16(value); 147 return this->write(&v, 2); 148} 149 150bool SkWStream::write32(uint32_t value) { 151 return this->write(&value, 4); 152} 153 154bool SkWStream::writeScalar(SkScalar value) { 155 return this->write(&value, sizeof(value)); 156} 157 158bool 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 168bool 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 188SkFILEStream::SkFILEStream(const char file[]) : fName(file) 189{ 190 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL; 191} 192 193SkFILEStream::~SkFILEStream() 194{ 195 if (fFILE) 196 sk_fclose(fFILE); 197} 198 199void 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 211const char* SkFILEStream::getFileName() 212{ 213 return fName.c_str(); 214} 215 216bool 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 229size_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 243SkMemoryStream::SkMemoryStream() 244{ 245 fWeOwnTheData = false; 246 this->setMemory(NULL, 0); 247} 248 249SkMemoryStream::SkMemoryStream(size_t size) { 250 fWeOwnTheData = true; 251 fOffset = 0; 252 fSize = size; 253 fSrc = sk_malloc_throw(size); 254} 255 256SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) 257{ 258 fWeOwnTheData = false; 259 this->setMemory(src, size, copyData); 260} 261 262SkMemoryStream::~SkMemoryStream() 263{ 264 if (fWeOwnTheData) 265 sk_free((void*)fSrc); 266} 267 268void 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 280void 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 298void SkMemoryStream::skipToAlign4() 299{ 300 // cast to remove unary-minus warning 301 fOffset += -(int)fOffset & 0x03; 302} 303 304bool SkMemoryStream::rewind() 305{ 306 fOffset = 0; 307 return true; 308} 309 310size_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 328const void* SkMemoryStream::getMemoryBase() 329{ 330 return fSrc; 331} 332 333const void* SkMemoryStream::getAtPos() 334{ 335 return (const char*)fSrc + fOffset; 336} 337 338size_t SkMemoryStream::seek(size_t offset) 339{ 340 if (offset > fSize) 341 offset = fSize; 342 fOffset = offset; 343 return offset; 344} 345 346///////////////////////////////////////////////////////////////////////////////////////////////////////// 347 348SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize) 349 : fProxy(proxy) 350{ 351 SkASSERT(proxy != NULL); 352 proxy->ref(); 353 this->init(NULL, bufferSize); 354} 355 356SkBufferStream::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 365void 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 386SkBufferStream::~SkBufferStream() 387{ 388 fProxy->unref(); 389 if (fWeOwnTheBuffer) 390 sk_free(fBuffer); 391} 392 393bool SkBufferStream::rewind() 394{ 395 fBufferOffset = fBufferSize = fOrigBufferSize; 396 return fProxy->rewind(); 397} 398 399const char* SkBufferStream::getFileName() 400{ 401 return fProxy->getFileName(); 402} 403 404#ifdef SK_DEBUG 405// #define SK_TRACE_BUFFERSTREAM 406#endif 407 408size_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 492const void* SkBufferStream::getMemoryBase() 493{ 494 return fProxy->getMemoryBase(); 495} 496 497///////////////////////////////////////////////////////////////////////////////////////////////////////// 498///////////////////////////////////////////////////////////////////////////////////////////////////////// 499 500SkFILEWStream::SkFILEWStream(const char path[]) 501{ 502 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); 503} 504 505SkFILEWStream::~SkFILEWStream() 506{ 507 if (fFILE) 508 sk_fclose(fFILE); 509} 510 511bool 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 526void SkFILEWStream::flush() 527{ 528 if (fFILE) 529 sk_fflush(fFILE); 530} 531 532//////////////////////////////////////////////////////////////////////// 533 534SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size) 535 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0) 536{ 537} 538 539bool 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 555struct 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 581SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopyToCache(NULL) 582{ 583} 584 585SkDynamicMemoryWStream::~SkDynamicMemoryWStream() 586{ 587 reset(); 588} 589 590const char* SkDynamicMemoryWStream::detach() 591{ 592 const char* result = getStream(); 593 fCopyToCache = NULL; 594 return result; 595} 596 597void 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 612bool 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 647bool 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 668bool 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 689void 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 701const 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 710void 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 722void SkDebugWStream::newline() 723{ 724#ifdef SK_DEBUG 725 SkDebugf("\n"); 726#endif 727} 728 729bool 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