123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948 |
- /*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkStream.h"
- #include "include/core/SkData.h"
- #include "include/core/SkString.h"
- #include "include/core/SkTypes.h"
- #include "include/private/SkFixed.h"
- #include "include/private/SkTFitsIn.h"
- #include "include/private/SkTo.h"
- #include "src/core/SkMakeUnique.h"
- #include "src/core/SkOSFile.h"
- #include "src/core/SkSafeMath.h"
- #include "src/core/SkStreamPriv.h"
- #include <limits>
- ///////////////////////////////////////////////////////////////////////////////
- bool SkStream::readS8(int8_t* i) {
- return this->read(i, sizeof(*i)) == sizeof(*i);
- }
- bool SkStream::readS16(int16_t* i) {
- return this->read(i, sizeof(*i)) == sizeof(*i);
- }
- bool SkStream::readS32(int32_t* i) {
- return this->read(i, sizeof(*i)) == sizeof(*i);
- }
- bool SkStream::readScalar(SkScalar* i) {
- return this->read(i, sizeof(*i)) == sizeof(*i);
- }
- #define SK_MAX_BYTE_FOR_U8 0xFD
- #define SK_BYTE_SENTINEL_FOR_U16 0xFE
- #define SK_BYTE_SENTINEL_FOR_U32 0xFF
- bool SkStream::readPackedUInt(size_t* i) {
- uint8_t byte;
- if (!this->read(&byte, 1)) {
- return false;
- }
- if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
- uint16_t i16;
- if (!this->readU16(&i16)) { return false; }
- *i = i16;
- } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
- uint32_t i32;
- if (!this->readU32(&i32)) { return false; }
- *i = i32;
- } else {
- *i = byte;
- }
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////////////
- SkWStream::~SkWStream()
- {
- }
- void SkWStream::flush()
- {
- }
- bool SkWStream::writeDecAsText(int32_t dec)
- {
- char buffer[SkStrAppendS32_MaxSize];
- char* stop = SkStrAppendS32(buffer, dec);
- return this->write(buffer, stop - buffer);
- }
- bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
- {
- char buffer[SkStrAppendU64_MaxSize];
- char* stop = SkStrAppendU64(buffer, dec, minDigits);
- return this->write(buffer, stop - buffer);
- }
- bool SkWStream::writeHexAsText(uint32_t hex, int digits)
- {
- SkString tmp;
- tmp.appendHex(hex, digits);
- return this->write(tmp.c_str(), tmp.size());
- }
- bool SkWStream::writeScalarAsText(SkScalar value)
- {
- char buffer[SkStrAppendScalar_MaxSize];
- char* stop = SkStrAppendScalar(buffer, value);
- return this->write(buffer, stop - buffer);
- }
- bool SkWStream::writeScalar(SkScalar value) {
- return this->write(&value, sizeof(value));
- }
- int SkWStream::SizeOfPackedUInt(size_t value) {
- if (value <= SK_MAX_BYTE_FOR_U8) {
- return 1;
- } else if (value <= 0xFFFF) {
- return 3;
- }
- return 5;
- }
- bool SkWStream::writePackedUInt(size_t value) {
- uint8_t data[5];
- size_t len = 1;
- if (value <= SK_MAX_BYTE_FOR_U8) {
- data[0] = value;
- len = 1;
- } else if (value <= 0xFFFF) {
- uint16_t value16 = value;
- data[0] = SK_BYTE_SENTINEL_FOR_U16;
- memcpy(&data[1], &value16, 2);
- len = 3;
- } else {
- uint32_t value32 = SkToU32(value);
- data[0] = SK_BYTE_SENTINEL_FOR_U32;
- memcpy(&data[1], &value32, 4);
- len = 5;
- }
- return this->write(data, len);
- }
- bool SkWStream::writeStream(SkStream* stream, size_t length) {
- char scratch[1024];
- const size_t MAX = sizeof(scratch);
- while (length != 0) {
- size_t n = length;
- if (n > MAX) {
- n = MAX;
- }
- stream->read(scratch, n);
- if (!this->write(scratch, n)) {
- return false;
- }
- length -= n;
- }
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t size,
- size_t offset, size_t originalOffset)
- : fFILE(std::move(file))
- , fSize(size)
- , fOffset(SkTMin(offset, fSize))
- , fOriginalOffset(SkTMin(originalOffset, fSize))
- { }
- SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t size, size_t offset)
- : SkFILEStream(std::move(file), size, offset, offset)
- { }
- SkFILEStream::SkFILEStream(FILE* file)
- : SkFILEStream(std::shared_ptr<FILE>(file, sk_fclose),
- file ? sk_fgetsize(file) : 0,
- file ? sk_ftell(file) : 0)
- { }
- SkFILEStream::SkFILEStream(const char path[])
- : SkFILEStream(path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr)
- { }
- SkFILEStream::~SkFILEStream() {
- this->close();
- }
- void SkFILEStream::close() {
- fFILE.reset();
- fSize = 0;
- fOffset = 0;
- }
- size_t SkFILEStream::read(void* buffer, size_t size) {
- if (size > fSize - fOffset) {
- size = fSize - fOffset;
- }
- size_t bytesRead = size;
- if (buffer) {
- bytesRead = sk_qread(fFILE.get(), buffer, size, fOffset);
- }
- if (bytesRead == SIZE_MAX) {
- return 0;
- }
- fOffset += bytesRead;
- return bytesRead;
- }
- bool SkFILEStream::isAtEnd() const {
- if (fOffset == fSize) {
- return true;
- }
- return fOffset >= sk_fgetsize(fFILE.get());
- }
- bool SkFILEStream::rewind() {
- fOffset = fOriginalOffset;
- return true;
- }
- SkStreamAsset* SkFILEStream::onDuplicate() const {
- return new SkFILEStream(fFILE, fSize, fOriginalOffset, fOriginalOffset);
- }
- size_t SkFILEStream::getPosition() const {
- SkASSERT(fOffset >= fOriginalOffset);
- return fOffset - fOriginalOffset;
- }
- bool SkFILEStream::seek(size_t position) {
- fOffset = SkTMin(SkSafeMath::Add(position, fOriginalOffset), fSize);
- return true;
- }
- bool SkFILEStream::move(long offset) {
- if (offset < 0) {
- if (offset == std::numeric_limits<long>::min()
- || !SkTFitsIn<size_t>(-offset)
- || (size_t) (-offset) >= this->getPosition()) {
- fOffset = fOriginalOffset;
- } else {
- fOffset += offset;
- }
- } else if (!SkTFitsIn<size_t>(offset)) {
- fOffset = fSize;
- } else {
- fOffset = SkTMin(SkSafeMath::Add(fOffset, (size_t) offset), fSize);
- }
- SkASSERT(fOffset >= fOriginalOffset && fOffset <= fSize);
- return true;
- }
- SkStreamAsset* SkFILEStream::onFork() const {
- return new SkFILEStream(fFILE, fSize, fOffset, fOriginalOffset);
- }
- size_t SkFILEStream::getLength() const {
- return fSize - fOriginalOffset;
- }
- ///////////////////////////////////////////////////////////////////////////////
- static sk_sp<SkData> newFromParams(const void* src, size_t size, bool copyData) {
- if (copyData) {
- return SkData::MakeWithCopy(src, size);
- } else {
- return SkData::MakeWithoutCopy(src, size);
- }
- }
- SkMemoryStream::SkMemoryStream() {
- fData = SkData::MakeEmpty();
- fOffset = 0;
- }
- SkMemoryStream::SkMemoryStream(size_t size) {
- fData = SkData::MakeUninitialized(size);
- fOffset = 0;
- }
- SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
- fData = newFromParams(src, size, copyData);
- fOffset = 0;
- }
- SkMemoryStream::SkMemoryStream(sk_sp<SkData> data) : fData(std::move(data)) {
- if (nullptr == fData) {
- fData = SkData::MakeEmpty();
- }
- fOffset = 0;
- }
- std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeCopy(const void* data, size_t length) {
- return skstd::make_unique<SkMemoryStream>(data, length, true);
- }
- std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeDirect(const void* data, size_t length) {
- return skstd::make_unique<SkMemoryStream>(data, length, false);
- }
- std::unique_ptr<SkMemoryStream> SkMemoryStream::Make(sk_sp<SkData> data) {
- return skstd::make_unique<SkMemoryStream>(std::move(data));
- }
- void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
- fData = SkData::MakeFromMalloc(src, size);
- fOffset = 0;
- }
- void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
- fData = newFromParams(src, size, copyData);
- fOffset = 0;
- }
- void SkMemoryStream::setData(sk_sp<SkData> data) {
- if (nullptr == data) {
- fData = SkData::MakeEmpty();
- } else {
- fData = data;
- }
- fOffset = 0;
- }
- void SkMemoryStream::skipToAlign4() {
- // cast to remove unary-minus warning
- fOffset += -(int)fOffset & 0x03;
- }
- size_t SkMemoryStream::read(void* buffer, size_t size) {
- size_t dataSize = fData->size();
- if (size > dataSize - fOffset) {
- size = dataSize - fOffset;
- }
- if (buffer) {
- memcpy(buffer, fData->bytes() + fOffset, size);
- }
- fOffset += size;
- return size;
- }
- size_t SkMemoryStream::peek(void* buffer, size_t size) const {
- SkASSERT(buffer != nullptr);
- const size_t currentOffset = fOffset;
- SkMemoryStream* nonConstThis = const_cast<SkMemoryStream*>(this);
- const size_t bytesRead = nonConstThis->read(buffer, size);
- nonConstThis->fOffset = currentOffset;
- return bytesRead;
- }
- bool SkMemoryStream::isAtEnd() const {
- return fOffset == fData->size();
- }
- bool SkMemoryStream::rewind() {
- fOffset = 0;
- return true;
- }
- SkMemoryStream* SkMemoryStream::onDuplicate() const {
- return new SkMemoryStream(fData);
- }
- size_t SkMemoryStream::getPosition() const {
- return fOffset;
- }
- bool SkMemoryStream::seek(size_t position) {
- fOffset = position > fData->size()
- ? fData->size()
- : position;
- return true;
- }
- bool SkMemoryStream::move(long offset) {
- return this->seek(fOffset + offset);
- }
- SkMemoryStream* SkMemoryStream::onFork() const {
- std::unique_ptr<SkMemoryStream> that(this->duplicate());
- that->seek(fOffset);
- return that.release();
- }
- size_t SkMemoryStream::getLength() const {
- return fData->size();
- }
- const void* SkMemoryStream::getMemoryBase() {
- return fData->data();
- }
- const void* SkMemoryStream::getAtPos() {
- return fData->bytes() + fOffset;
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////////////////////
- SkFILEWStream::SkFILEWStream(const char path[])
- {
- fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
- }
- SkFILEWStream::~SkFILEWStream()
- {
- if (fFILE) {
- sk_fclose(fFILE);
- }
- }
- size_t SkFILEWStream::bytesWritten() const {
- return sk_ftell(fFILE);
- }
- bool SkFILEWStream::write(const void* buffer, size_t size)
- {
- if (fFILE == nullptr) {
- return false;
- }
- if (sk_fwrite(buffer, size, fFILE) != size)
- {
- SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
- sk_fclose(fFILE);
- fFILE = nullptr;
- return false;
- }
- return true;
- }
- void SkFILEWStream::flush()
- {
- if (fFILE) {
- sk_fflush(fFILE);
- }
- }
- void SkFILEWStream::fsync()
- {
- flush();
- if (fFILE) {
- sk_fsync(fFILE);
- }
- }
- ////////////////////////////////////////////////////////////////////////
- static inline void sk_memcpy_4bytes(void* dst, const void* src, size_t size) {
- if (size == 4) {
- memcpy(dst, src, 4);
- } else {
- memcpy(dst, src, size);
- }
- }
- #define SkDynamicMemoryWStream_MinBlockSize 4096
- struct SkDynamicMemoryWStream::Block {
- Block* fNext;
- char* fCurr;
- char* fStop;
- const char* start() const { return (const char*)(this + 1); }
- char* start() { return (char*)(this + 1); }
- size_t avail() const { return fStop - fCurr; }
- size_t written() const { return fCurr - this->start(); }
- void init(size_t size) {
- fNext = nullptr;
- fCurr = this->start();
- fStop = this->start() + size;
- }
- const void* append(const void* data, size_t size) {
- SkASSERT((size_t)(fStop - fCurr) >= size);
- sk_memcpy_4bytes(fCurr, data, size);
- fCurr += size;
- return (const void*)((const char*)data + size);
- }
- };
- SkDynamicMemoryWStream::SkDynamicMemoryWStream(SkDynamicMemoryWStream&& other)
- : fHead(other.fHead)
- , fTail(other.fTail)
- , fBytesWrittenBeforeTail(other.fBytesWrittenBeforeTail)
- {
- other.fHead = nullptr;
- other.fTail = nullptr;
- other.fBytesWrittenBeforeTail = 0;
- }
- SkDynamicMemoryWStream& SkDynamicMemoryWStream::operator=(SkDynamicMemoryWStream&& other) {
- if (this != &other) {
- this->~SkDynamicMemoryWStream();
- new (this) SkDynamicMemoryWStream(std::move(other));
- }
- return *this;
- }
- SkDynamicMemoryWStream::~SkDynamicMemoryWStream() {
- this->reset();
- }
- void SkDynamicMemoryWStream::reset() {
- Block* block = fHead;
- while (block != nullptr) {
- Block* next = block->fNext;
- sk_free(block);
- block = next;
- }
- fHead = fTail = nullptr;
- fBytesWrittenBeforeTail = 0;
- }
- size_t SkDynamicMemoryWStream::bytesWritten() const {
- this->validate();
- if (fTail) {
- return fBytesWrittenBeforeTail + fTail->written();
- }
- return 0;
- }
- bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) {
- if (count > 0) {
- SkASSERT(buffer);
- size_t size;
- if (fTail) {
- if (fTail->avail() > 0) {
- size = SkTMin(fTail->avail(), count);
- buffer = fTail->append(buffer, size);
- SkASSERT(count >= size);
- count -= size;
- if (count == 0) {
- return true;
- }
- }
- // If we get here, we've just exhausted fTail, so update our tracker
- fBytesWrittenBeforeTail += fTail->written();
- }
- size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize - sizeof(Block));
- size = SkAlign4(size); // ensure we're always a multiple of 4 (see padToAlign4())
- Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
- block->init(size);
- block->append(buffer, count);
- if (fTail != nullptr) {
- fTail->fNext = block;
- } else {
- fHead = fTail = block;
- }
- fTail = block;
- this->validate();
- }
- return true;
- }
- bool SkDynamicMemoryWStream::writeToAndReset(SkDynamicMemoryWStream* dst) {
- SkASSERT(dst);
- SkASSERT(dst != this);
- if (0 == this->bytesWritten()) {
- return true;
- }
- if (0 == dst->bytesWritten()) {
- *dst = std::move(*this);
- return true;
- }
- dst->fTail->fNext = fHead;
- dst->fBytesWrittenBeforeTail += fBytesWrittenBeforeTail + dst->fTail->written();
- dst->fTail = fTail;
- fHead = fTail = nullptr;
- fBytesWrittenBeforeTail = 0;
- return true;
- }
- void SkDynamicMemoryWStream::prependToAndReset(SkDynamicMemoryWStream* dst) {
- SkASSERT(dst);
- SkASSERT(dst != this);
- if (0 == this->bytesWritten()) {
- return;
- }
- if (0 == dst->bytesWritten()) {
- *dst = std::move(*this);
- return;
- }
- fTail->fNext = dst->fHead;
- dst->fHead = fHead;
- dst->fBytesWrittenBeforeTail += fBytesWrittenBeforeTail + fTail->written();
- fHead = fTail = nullptr;
- fBytesWrittenBeforeTail = 0;
- return;
- }
- bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count) {
- if (offset + count > this->bytesWritten()) {
- return false; // test does not partially modify
- }
- Block* block = fHead;
- while (block != nullptr) {
- size_t size = block->written();
- if (offset < size) {
- size_t part = offset + count > size ? size - offset : count;
- memcpy(buffer, block->start() + offset, part);
- if (count <= part) {
- return true;
- }
- count -= part;
- buffer = (void*) ((char* ) buffer + part);
- }
- offset = offset > size ? offset - size : 0;
- block = block->fNext;
- }
- return false;
- }
- void SkDynamicMemoryWStream::copyTo(void* dst) const {
- SkASSERT(dst);
- Block* block = fHead;
- while (block != nullptr) {
- size_t size = block->written();
- memcpy(dst, block->start(), size);
- dst = (void*)((char*)dst + size);
- block = block->fNext;
- }
- }
- bool SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const {
- SkASSERT(dst);
- for (Block* block = fHead; block != nullptr; block = block->fNext) {
- if (!dst->write(block->start(), block->written())) {
- return false;
- }
- }
- return true;
- }
- void SkDynamicMemoryWStream::padToAlign4() {
- // The contract is to write zeros until the entire stream has written a multiple of 4 bytes.
- // Our Blocks are guaranteed always be (a) full (except the tail) and (b) a multiple of 4
- // so it is sufficient to just examine the tail (if present).
- if (fTail) {
- // cast to remove unary-minus warning
- int padBytes = -(int)fTail->written() & 0x03;
- if (padBytes) {
- int zero = 0;
- fTail->append(&zero, padBytes);
- }
- }
- }
- void SkDynamicMemoryWStream::copyToAndReset(void* ptr) {
- if (!ptr) {
- this->reset();
- return;
- }
- // By looping through the source and freeing as we copy, we
- // can reduce real memory use with large streams.
- char* dst = reinterpret_cast<char*>(ptr);
- Block* block = fHead;
- while (block != nullptr) {
- size_t len = block->written();
- memcpy(dst, block->start(), len);
- dst += len;
- Block* next = block->fNext;
- sk_free(block);
- block = next;
- }
- fHead = fTail = nullptr;
- fBytesWrittenBeforeTail = 0;
- }
- bool SkDynamicMemoryWStream::writeToAndReset(SkWStream* dst) {
- SkASSERT(dst);
- // By looping through the source and freeing as we copy, we
- // can reduce real memory use with large streams.
- bool dstStreamGood = true;
- for (Block* block = fHead; block != nullptr; ) {
- if (dstStreamGood && !dst->write(block->start(), block->written())) {
- dstStreamGood = false;
- }
- Block* next = block->fNext;
- sk_free(block);
- block = next;
- }
- fHead = fTail = nullptr;
- fBytesWrittenBeforeTail = 0;
- return dstStreamGood;
- }
- sk_sp<SkData> SkDynamicMemoryWStream::detachAsData() {
- const size_t size = this->bytesWritten();
- if (0 == size) {
- return SkData::MakeEmpty();
- }
- sk_sp<SkData> data = SkData::MakeUninitialized(size);
- this->copyToAndReset(data->writable_data());
- return data;
- }
- #ifdef SK_DEBUG
- void SkDynamicMemoryWStream::validate() const {
- if (!fHead) {
- SkASSERT(!fTail);
- SkASSERT(fBytesWrittenBeforeTail == 0);
- return;
- }
- SkASSERT(fTail);
- size_t bytes = 0;
- const Block* block = fHead;
- while (block) {
- if (block->fNext) {
- bytes += block->written();
- }
- block = block->fNext;
- }
- SkASSERT(bytes == fBytesWrittenBeforeTail);
- }
- #endif
- ////////////////////////////////////////////////////////////////////////////////////////////////
- class SkBlockMemoryRefCnt : public SkRefCnt {
- public:
- explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
- virtual ~SkBlockMemoryRefCnt() {
- SkDynamicMemoryWStream::Block* block = fHead;
- while (block != nullptr) {
- SkDynamicMemoryWStream::Block* next = block->fNext;
- sk_free(block);
- block = next;
- }
- }
- SkDynamicMemoryWStream::Block* const fHead;
- };
- class SkBlockMemoryStream : public SkStreamAsset {
- public:
- SkBlockMemoryStream(sk_sp<SkBlockMemoryRefCnt> headRef, size_t size)
- : fBlockMemory(std::move(headRef)), fCurrent(fBlockMemory->fHead)
- , fSize(size) , fOffset(0), fCurrentOffset(0) { }
- size_t read(void* buffer, size_t rawCount) override {
- size_t count = rawCount;
- if (fOffset + count > fSize) {
- count = fSize - fOffset;
- }
- size_t bytesLeftToRead = count;
- while (fCurrent != nullptr) {
- size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
- size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
- if (buffer) {
- memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
- buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
- }
- if (bytesLeftToRead <= bytesFromCurrent) {
- fCurrentOffset += bytesFromCurrent;
- fOffset += count;
- return count;
- }
- bytesLeftToRead -= bytesFromCurrent;
- fCurrent = fCurrent->fNext;
- fCurrentOffset = 0;
- }
- SkASSERT(false);
- return 0;
- }
- bool isAtEnd() const override {
- return fOffset == fSize;
- }
- size_t peek(void* buff, size_t bytesToPeek) const override {
- SkASSERT(buff != nullptr);
- bytesToPeek = SkTMin(bytesToPeek, fSize - fOffset);
- size_t bytesLeftToPeek = bytesToPeek;
- char* buffer = static_cast<char*>(buff);
- const SkDynamicMemoryWStream::Block* current = fCurrent;
- size_t currentOffset = fCurrentOffset;
- while (bytesLeftToPeek) {
- SkASSERT(current);
- size_t bytesFromCurrent = SkTMin(current->written() - currentOffset, bytesLeftToPeek);
- memcpy(buffer, current->start() + currentOffset, bytesFromCurrent);
- bytesLeftToPeek -= bytesFromCurrent;
- buffer += bytesFromCurrent;
- current = current->fNext;
- currentOffset = 0;
- }
- return bytesToPeek;
- }
- bool rewind() override {
- fCurrent = fBlockMemory->fHead;
- fOffset = 0;
- fCurrentOffset = 0;
- return true;
- }
- SkBlockMemoryStream* onDuplicate() const override {
- return new SkBlockMemoryStream(fBlockMemory, fSize);
- }
- size_t getPosition() const override {
- return fOffset;
- }
- bool seek(size_t position) override {
- // If possible, skip forward.
- if (position >= fOffset) {
- size_t skipAmount = position - fOffset;
- return this->skip(skipAmount) == skipAmount;
- }
- // If possible, move backward within the current block.
- size_t moveBackAmount = fOffset - position;
- if (moveBackAmount <= fCurrentOffset) {
- fCurrentOffset -= moveBackAmount;
- fOffset -= moveBackAmount;
- return true;
- }
- // Otherwise rewind and move forward.
- return this->rewind() && this->skip(position) == position;
- }
- bool move(long offset) override {
- return seek(fOffset + offset);
- }
- SkBlockMemoryStream* onFork() const override {
- SkBlockMemoryStream* that = this->onDuplicate();
- that->fCurrent = this->fCurrent;
- that->fOffset = this->fOffset;
- that->fCurrentOffset = this->fCurrentOffset;
- return that;
- }
- size_t getLength() const override {
- return fSize;
- }
- const void* getMemoryBase() override {
- if (fBlockMemory->fHead && !fBlockMemory->fHead->fNext) {
- return fBlockMemory->fHead->start();
- }
- return nullptr;
- }
- private:
- sk_sp<SkBlockMemoryRefCnt> const fBlockMemory;
- SkDynamicMemoryWStream::Block const * fCurrent;
- size_t const fSize;
- size_t fOffset;
- size_t fCurrentOffset;
- };
- std::unique_ptr<SkStreamAsset> SkDynamicMemoryWStream::detachAsStream() {
- if (nullptr == fHead) {
- // no need to reset.
- return SkMemoryStream::Make(nullptr);
- }
- if (fHead == fTail) { // one block, may be worth shrinking.
- ptrdiff_t used = fTail->fCurr - (char*)fTail;
- fHead = fTail = (SkDynamicMemoryWStream::Block*)sk_realloc_throw(fTail, SkToSizeT(used));
- fTail->fStop = fTail->fCurr = (char*)fTail + used; // Update pointers.
- SkASSERT(nullptr == fTail->fNext);
- SkASSERT(0 == fBytesWrittenBeforeTail);
- }
- std::unique_ptr<SkStreamAsset> stream
- = skstd::make_unique<SkBlockMemoryStream>(sk_make_sp<SkBlockMemoryRefCnt>(fHead),
- this->bytesWritten());
- fHead = nullptr; // signal reset() to not free anything
- this->reset();
- return stream;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- static sk_sp<SkData> mmap_filename(const char path[]) {
- FILE* file = sk_fopen(path, kRead_SkFILE_Flag);
- if (nullptr == file) {
- return nullptr;
- }
- auto data = SkData::MakeFromFILE(file);
- sk_fclose(file);
- return data;
- }
- std::unique_ptr<SkStreamAsset> SkStream::MakeFromFile(const char path[]) {
- auto data(mmap_filename(path));
- if (data) {
- return skstd::make_unique<SkMemoryStream>(std::move(data));
- }
- // If we get here, then our attempt at using mmap failed, so try normal file access.
- auto stream = skstd::make_unique<SkFILEStream>(path);
- if (!stream->isValid()) {
- return nullptr;
- }
- return std::move(stream);
- }
- // Declared in SkStreamPriv.h:
- sk_sp<SkData> SkCopyStreamToData(SkStream* stream) {
- SkASSERT(stream != nullptr);
- if (stream->hasLength()) {
- return SkData::MakeFromStream(stream, stream->getLength());
- }
- SkDynamicMemoryWStream tempStream;
- const size_t bufferSize = 4096;
- char buffer[bufferSize];
- do {
- size_t bytesRead = stream->read(buffer, bufferSize);
- tempStream.write(buffer, bytesRead);
- } while (!stream->isAtEnd());
- return tempStream.detachAsData();
- }
- bool SkStreamCopy(SkWStream* out, SkStream* input) {
- const char* base = static_cast<const char*>(input->getMemoryBase());
- if (base && input->hasPosition() && input->hasLength()) {
- // Shortcut that avoids the while loop.
- size_t position = input->getPosition();
- size_t length = input->getLength();
- SkASSERT(length >= position);
- return out->write(&base[position], length - position);
- }
- char scratch[4096];
- size_t count;
- while (true) {
- count = input->read(scratch, sizeof(scratch));
- if (0 == count) {
- return true;
- }
- if (!out->write(scratch, count)) {
- return false;
- }
- }
- }
|