1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkData.h" 11cb93a386Sopenharmony_ci#include "include/core/SkString.h" 12cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 13cb93a386Sopenharmony_ci#include "include/private/SkFixed.h" 14cb93a386Sopenharmony_ci#include "include/private/SkTFitsIn.h" 15cb93a386Sopenharmony_ci#include "include/private/SkTPin.h" 16cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 17cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h" 18cb93a386Sopenharmony_ci#include "src/core/SkSafeMath.h" 19cb93a386Sopenharmony_ci#include "src/core/SkStreamPriv.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci#include <limits> 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_cibool SkStream::readS8(int8_t* i) { 26cb93a386Sopenharmony_ci return this->read(i, sizeof(*i)) == sizeof(*i); 27cb93a386Sopenharmony_ci} 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_cibool SkStream::readS16(int16_t* i) { 30cb93a386Sopenharmony_ci return this->read(i, sizeof(*i)) == sizeof(*i); 31cb93a386Sopenharmony_ci} 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_cibool SkStream::readS32(int32_t* i) { 34cb93a386Sopenharmony_ci return this->read(i, sizeof(*i)) == sizeof(*i); 35cb93a386Sopenharmony_ci} 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_cibool SkStream::readScalar(SkScalar* i) { 38cb93a386Sopenharmony_ci return this->read(i, sizeof(*i)) == sizeof(*i); 39cb93a386Sopenharmony_ci} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci#define SK_MAX_BYTE_FOR_U8 0xFD 42cb93a386Sopenharmony_ci#define SK_BYTE_SENTINEL_FOR_U16 0xFE 43cb93a386Sopenharmony_ci#define SK_BYTE_SENTINEL_FOR_U32 0xFF 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_cibool SkStream::readPackedUInt(size_t* i) { 46cb93a386Sopenharmony_ci uint8_t byte; 47cb93a386Sopenharmony_ci if (!this->read(&byte, 1)) { 48cb93a386Sopenharmony_ci return false; 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci if (SK_BYTE_SENTINEL_FOR_U16 == byte) { 51cb93a386Sopenharmony_ci uint16_t i16; 52cb93a386Sopenharmony_ci if (!this->readU16(&i16)) { return false; } 53cb93a386Sopenharmony_ci *i = i16; 54cb93a386Sopenharmony_ci } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) { 55cb93a386Sopenharmony_ci uint32_t i32; 56cb93a386Sopenharmony_ci if (!this->readU32(&i32)) { return false; } 57cb93a386Sopenharmony_ci *i = i32; 58cb93a386Sopenharmony_ci } else { 59cb93a386Sopenharmony_ci *i = byte; 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci return true; 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////// 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ciSkWStream::~SkWStream() 67cb93a386Sopenharmony_ci{ 68cb93a386Sopenharmony_ci} 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_civoid SkWStream::flush() 71cb93a386Sopenharmony_ci{ 72cb93a386Sopenharmony_ci} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_cibool SkWStream::writeDecAsText(int32_t dec) 75cb93a386Sopenharmony_ci{ 76cb93a386Sopenharmony_ci char buffer[kSkStrAppendS32_MaxSize]; 77cb93a386Sopenharmony_ci char* stop = SkStrAppendS32(buffer, dec); 78cb93a386Sopenharmony_ci return this->write(buffer, stop - buffer); 79cb93a386Sopenharmony_ci} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_cibool SkWStream::writeBigDecAsText(int64_t dec, int minDigits) 82cb93a386Sopenharmony_ci{ 83cb93a386Sopenharmony_ci char buffer[kSkStrAppendU64_MaxSize]; 84cb93a386Sopenharmony_ci char* stop = SkStrAppendU64(buffer, dec, minDigits); 85cb93a386Sopenharmony_ci return this->write(buffer, stop - buffer); 86cb93a386Sopenharmony_ci} 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_cibool SkWStream::writeHexAsText(uint32_t hex, int digits) 89cb93a386Sopenharmony_ci{ 90cb93a386Sopenharmony_ci SkString tmp; 91cb93a386Sopenharmony_ci tmp.appendHex(hex, digits); 92cb93a386Sopenharmony_ci return this->write(tmp.c_str(), tmp.size()); 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_cibool SkWStream::writeScalarAsText(SkScalar value) 96cb93a386Sopenharmony_ci{ 97cb93a386Sopenharmony_ci char buffer[kSkStrAppendScalar_MaxSize]; 98cb93a386Sopenharmony_ci char* stop = SkStrAppendScalar(buffer, value); 99cb93a386Sopenharmony_ci return this->write(buffer, stop - buffer); 100cb93a386Sopenharmony_ci} 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_cibool SkWStream::writeScalar(SkScalar value) { 103cb93a386Sopenharmony_ci return this->write(&value, sizeof(value)); 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ciint SkWStream::SizeOfPackedUInt(size_t value) { 107cb93a386Sopenharmony_ci if (value <= SK_MAX_BYTE_FOR_U8) { 108cb93a386Sopenharmony_ci return 1; 109cb93a386Sopenharmony_ci } else if (value <= 0xFFFF) { 110cb93a386Sopenharmony_ci return 3; 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci return 5; 113cb93a386Sopenharmony_ci} 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_cibool SkWStream::writePackedUInt(size_t value) { 116cb93a386Sopenharmony_ci uint8_t data[5]; 117cb93a386Sopenharmony_ci size_t len = 1; 118cb93a386Sopenharmony_ci if (value <= SK_MAX_BYTE_FOR_U8) { 119cb93a386Sopenharmony_ci data[0] = value; 120cb93a386Sopenharmony_ci len = 1; 121cb93a386Sopenharmony_ci } else if (value <= 0xFFFF) { 122cb93a386Sopenharmony_ci uint16_t value16 = value; 123cb93a386Sopenharmony_ci data[0] = SK_BYTE_SENTINEL_FOR_U16; 124cb93a386Sopenharmony_ci memcpy(&data[1], &value16, 2); 125cb93a386Sopenharmony_ci len = 3; 126cb93a386Sopenharmony_ci } else { 127cb93a386Sopenharmony_ci uint32_t value32 = SkToU32(value); 128cb93a386Sopenharmony_ci data[0] = SK_BYTE_SENTINEL_FOR_U32; 129cb93a386Sopenharmony_ci memcpy(&data[1], &value32, 4); 130cb93a386Sopenharmony_ci len = 5; 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci return this->write(data, len); 133cb93a386Sopenharmony_ci} 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_cibool SkWStream::writeStream(SkStream* stream, size_t length) { 136cb93a386Sopenharmony_ci char scratch[1024]; 137cb93a386Sopenharmony_ci const size_t MAX = sizeof(scratch); 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci while (length != 0) { 140cb93a386Sopenharmony_ci size_t n = length; 141cb93a386Sopenharmony_ci if (n > MAX) { 142cb93a386Sopenharmony_ci n = MAX; 143cb93a386Sopenharmony_ci } 144cb93a386Sopenharmony_ci stream->read(scratch, n); 145cb93a386Sopenharmony_ci if (!this->write(scratch, n)) { 146cb93a386Sopenharmony_ci return false; 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci length -= n; 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci return true; 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ciSkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t end, size_t start, size_t current) 156cb93a386Sopenharmony_ci : fFILE(std::move(file)) 157cb93a386Sopenharmony_ci , fEnd(end) 158cb93a386Sopenharmony_ci , fStart(std::min(start, fEnd)) 159cb93a386Sopenharmony_ci , fCurrent(SkTPin(current, fStart, fEnd)) 160cb93a386Sopenharmony_ci{ 161cb93a386Sopenharmony_ci SkASSERT(fStart == start); 162cb93a386Sopenharmony_ci SkASSERT(fCurrent == current); 163cb93a386Sopenharmony_ci} 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ciSkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t end, size_t start) 166cb93a386Sopenharmony_ci : SkFILEStream(std::move(file), end, start, start) 167cb93a386Sopenharmony_ci{ } 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ciSkFILEStream::SkFILEStream(FILE* file, size_t size, size_t start) 170cb93a386Sopenharmony_ci : SkFILEStream(std::shared_ptr<FILE>(file, sk_fclose), SkSafeMath::Add(start, size), start) 171cb93a386Sopenharmony_ci{ } 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ciSkFILEStream::SkFILEStream(FILE* file, size_t size) 174cb93a386Sopenharmony_ci : SkFILEStream(file, size, file ? sk_ftell(file) : 0) 175cb93a386Sopenharmony_ci{ } 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ciSkFILEStream::SkFILEStream(FILE* file) 178cb93a386Sopenharmony_ci : SkFILEStream(std::shared_ptr<FILE>(file, sk_fclose), 179cb93a386Sopenharmony_ci file ? sk_fgetsize(file) : 0, 180cb93a386Sopenharmony_ci file ? sk_ftell(file) : 0) 181cb93a386Sopenharmony_ci{ } 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ciSkFILEStream::SkFILEStream(const char path[]) 184cb93a386Sopenharmony_ci : SkFILEStream(path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr) 185cb93a386Sopenharmony_ci{ } 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ciSkFILEStream::~SkFILEStream() { 188cb93a386Sopenharmony_ci this->close(); 189cb93a386Sopenharmony_ci} 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_civoid SkFILEStream::close() { 192cb93a386Sopenharmony_ci fFILE.reset(); 193cb93a386Sopenharmony_ci fEnd = 0; 194cb93a386Sopenharmony_ci fStart = 0; 195cb93a386Sopenharmony_ci fCurrent = 0; 196cb93a386Sopenharmony_ci} 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_cisize_t SkFILEStream::read(void* buffer, size_t size) { 199cb93a386Sopenharmony_ci if (size > fEnd - fCurrent) { 200cb93a386Sopenharmony_ci size = fEnd - fCurrent; 201cb93a386Sopenharmony_ci } 202cb93a386Sopenharmony_ci size_t bytesRead = size; 203cb93a386Sopenharmony_ci if (buffer) { 204cb93a386Sopenharmony_ci bytesRead = sk_qread(fFILE.get(), buffer, size, fCurrent); 205cb93a386Sopenharmony_ci } 206cb93a386Sopenharmony_ci if (bytesRead == SIZE_MAX) { 207cb93a386Sopenharmony_ci return 0; 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci fCurrent += bytesRead; 210cb93a386Sopenharmony_ci return bytesRead; 211cb93a386Sopenharmony_ci} 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_cibool SkFILEStream::isAtEnd() const { 214cb93a386Sopenharmony_ci if (fCurrent == fEnd) { 215cb93a386Sopenharmony_ci return true; 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci return fCurrent >= sk_fgetsize(fFILE.get()); 218cb93a386Sopenharmony_ci} 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_cibool SkFILEStream::rewind() { 221cb93a386Sopenharmony_ci fCurrent = fStart; 222cb93a386Sopenharmony_ci return true; 223cb93a386Sopenharmony_ci} 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ciSkStreamAsset* SkFILEStream::onDuplicate() const { 226cb93a386Sopenharmony_ci return new SkFILEStream(fFILE, fEnd, fStart, fStart); 227cb93a386Sopenharmony_ci} 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_cisize_t SkFILEStream::getPosition() const { 230cb93a386Sopenharmony_ci SkASSERT(fCurrent >= fStart); 231cb93a386Sopenharmony_ci return fCurrent - fStart; 232cb93a386Sopenharmony_ci} 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_cibool SkFILEStream::seek(size_t position) { 235cb93a386Sopenharmony_ci fCurrent = std::min(SkSafeMath::Add(position, fStart), fEnd); 236cb93a386Sopenharmony_ci return true; 237cb93a386Sopenharmony_ci} 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_cibool SkFILEStream::move(long offset) { 240cb93a386Sopenharmony_ci if (offset < 0) { 241cb93a386Sopenharmony_ci if (offset == std::numeric_limits<long>::min() || 242cb93a386Sopenharmony_ci !SkTFitsIn<size_t>(-offset) || 243cb93a386Sopenharmony_ci (size_t) (-offset) >= this->getPosition()) 244cb93a386Sopenharmony_ci { 245cb93a386Sopenharmony_ci fCurrent = fStart; 246cb93a386Sopenharmony_ci } else { 247cb93a386Sopenharmony_ci fCurrent += offset; 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci } else if (!SkTFitsIn<size_t>(offset)) { 250cb93a386Sopenharmony_ci fCurrent = fEnd; 251cb93a386Sopenharmony_ci } else { 252cb93a386Sopenharmony_ci fCurrent = std::min(SkSafeMath::Add(fCurrent, (size_t) offset), fEnd); 253cb93a386Sopenharmony_ci } 254cb93a386Sopenharmony_ci 255cb93a386Sopenharmony_ci SkASSERT(fCurrent >= fStart && fCurrent <= fEnd); 256cb93a386Sopenharmony_ci return true; 257cb93a386Sopenharmony_ci} 258cb93a386Sopenharmony_ci 259cb93a386Sopenharmony_ciSkStreamAsset* SkFILEStream::onFork() const { 260cb93a386Sopenharmony_ci return new SkFILEStream(fFILE, fEnd, fStart, fCurrent); 261cb93a386Sopenharmony_ci} 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_cisize_t SkFILEStream::getLength() const { 264cb93a386Sopenharmony_ci return fEnd - fStart; 265cb93a386Sopenharmony_ci} 266cb93a386Sopenharmony_ci 267cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_cistatic sk_sp<SkData> newFromParams(const void* src, size_t size, bool copyData) { 270cb93a386Sopenharmony_ci if (copyData) { 271cb93a386Sopenharmony_ci return SkData::MakeWithCopy(src, size); 272cb93a386Sopenharmony_ci } else { 273cb93a386Sopenharmony_ci return SkData::MakeWithoutCopy(src, size); 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci} 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ciSkMemoryStream::SkMemoryStream() { 278cb93a386Sopenharmony_ci fData = SkData::MakeEmpty(); 279cb93a386Sopenharmony_ci fOffset = 0; 280cb93a386Sopenharmony_ci} 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_ciSkMemoryStream::SkMemoryStream(size_t size) { 283cb93a386Sopenharmony_ci fData = SkData::MakeUninitialized(size); 284cb93a386Sopenharmony_ci fOffset = 0; 285cb93a386Sopenharmony_ci} 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ciSkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) { 288cb93a386Sopenharmony_ci fData = newFromParams(src, size, copyData); 289cb93a386Sopenharmony_ci fOffset = 0; 290cb93a386Sopenharmony_ci} 291cb93a386Sopenharmony_ci 292cb93a386Sopenharmony_ciSkMemoryStream::SkMemoryStream(sk_sp<SkData> data) : fData(std::move(data)) { 293cb93a386Sopenharmony_ci if (nullptr == fData) { 294cb93a386Sopenharmony_ci fData = SkData::MakeEmpty(); 295cb93a386Sopenharmony_ci } 296cb93a386Sopenharmony_ci fOffset = 0; 297cb93a386Sopenharmony_ci} 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_cistd::unique_ptr<SkMemoryStream> SkMemoryStream::MakeCopy(const void* data, size_t length) { 300cb93a386Sopenharmony_ci return std::make_unique<SkMemoryStream>(data, length, true); 301cb93a386Sopenharmony_ci} 302cb93a386Sopenharmony_ci 303cb93a386Sopenharmony_cistd::unique_ptr<SkMemoryStream> SkMemoryStream::MakeDirect(const void* data, size_t length) { 304cb93a386Sopenharmony_ci return std::make_unique<SkMemoryStream>(data, length, false); 305cb93a386Sopenharmony_ci} 306cb93a386Sopenharmony_ci 307cb93a386Sopenharmony_cistd::unique_ptr<SkMemoryStream> SkMemoryStream::Make(sk_sp<SkData> data) { 308cb93a386Sopenharmony_ci return std::make_unique<SkMemoryStream>(std::move(data)); 309cb93a386Sopenharmony_ci} 310cb93a386Sopenharmony_ci 311cb93a386Sopenharmony_civoid SkMemoryStream::setMemoryOwned(const void* src, size_t size) { 312cb93a386Sopenharmony_ci fData = SkData::MakeFromMalloc(src, size); 313cb93a386Sopenharmony_ci fOffset = 0; 314cb93a386Sopenharmony_ci} 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_civoid SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) { 317cb93a386Sopenharmony_ci fData = newFromParams(src, size, copyData); 318cb93a386Sopenharmony_ci fOffset = 0; 319cb93a386Sopenharmony_ci} 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_civoid SkMemoryStream::setData(sk_sp<SkData> data) { 322cb93a386Sopenharmony_ci if (nullptr == data) { 323cb93a386Sopenharmony_ci fData = SkData::MakeEmpty(); 324cb93a386Sopenharmony_ci } else { 325cb93a386Sopenharmony_ci fData = data; 326cb93a386Sopenharmony_ci } 327cb93a386Sopenharmony_ci fOffset = 0; 328cb93a386Sopenharmony_ci} 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_civoid SkMemoryStream::skipToAlign4() { 331cb93a386Sopenharmony_ci // cast to remove unary-minus warning 332cb93a386Sopenharmony_ci fOffset += -(int)fOffset & 0x03; 333cb93a386Sopenharmony_ci} 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_cisize_t SkMemoryStream::read(void* buffer, size_t size) { 336cb93a386Sopenharmony_ci size_t dataSize = fData->size(); 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_ci if (size > dataSize - fOffset) { 339cb93a386Sopenharmony_ci size = dataSize - fOffset; 340cb93a386Sopenharmony_ci } 341cb93a386Sopenharmony_ci if (buffer) { 342cb93a386Sopenharmony_ci memcpy(buffer, fData->bytes() + fOffset, size); 343cb93a386Sopenharmony_ci } 344cb93a386Sopenharmony_ci fOffset += size; 345cb93a386Sopenharmony_ci return size; 346cb93a386Sopenharmony_ci} 347cb93a386Sopenharmony_ci 348cb93a386Sopenharmony_cisize_t SkMemoryStream::peek(void* buffer, size_t size) const { 349cb93a386Sopenharmony_ci SkASSERT(buffer != nullptr); 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_ci const size_t currentOffset = fOffset; 352cb93a386Sopenharmony_ci SkMemoryStream* nonConstThis = const_cast<SkMemoryStream*>(this); 353cb93a386Sopenharmony_ci const size_t bytesRead = nonConstThis->read(buffer, size); 354cb93a386Sopenharmony_ci nonConstThis->fOffset = currentOffset; 355cb93a386Sopenharmony_ci return bytesRead; 356cb93a386Sopenharmony_ci} 357cb93a386Sopenharmony_ci 358cb93a386Sopenharmony_cibool SkMemoryStream::isAtEnd() const { 359cb93a386Sopenharmony_ci return fOffset == fData->size(); 360cb93a386Sopenharmony_ci} 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_cibool SkMemoryStream::rewind() { 363cb93a386Sopenharmony_ci fOffset = 0; 364cb93a386Sopenharmony_ci return true; 365cb93a386Sopenharmony_ci} 366cb93a386Sopenharmony_ci 367cb93a386Sopenharmony_ciSkMemoryStream* SkMemoryStream::onDuplicate() const { 368cb93a386Sopenharmony_ci return new SkMemoryStream(fData); 369cb93a386Sopenharmony_ci} 370cb93a386Sopenharmony_ci 371cb93a386Sopenharmony_cisize_t SkMemoryStream::getPosition() const { 372cb93a386Sopenharmony_ci return fOffset; 373cb93a386Sopenharmony_ci} 374cb93a386Sopenharmony_ci 375cb93a386Sopenharmony_cibool SkMemoryStream::seek(size_t position) { 376cb93a386Sopenharmony_ci fOffset = position > fData->size() 377cb93a386Sopenharmony_ci ? fData->size() 378cb93a386Sopenharmony_ci : position; 379cb93a386Sopenharmony_ci return true; 380cb93a386Sopenharmony_ci} 381cb93a386Sopenharmony_ci 382cb93a386Sopenharmony_cibool SkMemoryStream::move(long offset) { 383cb93a386Sopenharmony_ci return this->seek(fOffset + offset); 384cb93a386Sopenharmony_ci} 385cb93a386Sopenharmony_ci 386cb93a386Sopenharmony_ciSkMemoryStream* SkMemoryStream::onFork() const { 387cb93a386Sopenharmony_ci std::unique_ptr<SkMemoryStream> that(this->duplicate()); 388cb93a386Sopenharmony_ci that->seek(fOffset); 389cb93a386Sopenharmony_ci return that.release(); 390cb93a386Sopenharmony_ci} 391cb93a386Sopenharmony_ci 392cb93a386Sopenharmony_cisize_t SkMemoryStream::getLength() const { 393cb93a386Sopenharmony_ci return fData->size(); 394cb93a386Sopenharmony_ci} 395cb93a386Sopenharmony_ci 396cb93a386Sopenharmony_ciconst void* SkMemoryStream::getMemoryBase() { 397cb93a386Sopenharmony_ci return fData->data(); 398cb93a386Sopenharmony_ci} 399cb93a386Sopenharmony_ci 400cb93a386Sopenharmony_ciconst void* SkMemoryStream::getAtPos() { 401cb93a386Sopenharmony_ci return fData->bytes() + fOffset; 402cb93a386Sopenharmony_ci} 403cb93a386Sopenharmony_ci 404cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////////// 405cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////////// 406cb93a386Sopenharmony_ci 407cb93a386Sopenharmony_ciSkFILEWStream::SkFILEWStream(const char path[]) 408cb93a386Sopenharmony_ci{ 409cb93a386Sopenharmony_ci fFILE = sk_fopen(path, kWrite_SkFILE_Flag); 410cb93a386Sopenharmony_ci} 411cb93a386Sopenharmony_ci 412cb93a386Sopenharmony_ciSkFILEWStream::~SkFILEWStream() 413cb93a386Sopenharmony_ci{ 414cb93a386Sopenharmony_ci if (fFILE) { 415cb93a386Sopenharmony_ci sk_fclose(fFILE); 416cb93a386Sopenharmony_ci } 417cb93a386Sopenharmony_ci} 418cb93a386Sopenharmony_ci 419cb93a386Sopenharmony_cisize_t SkFILEWStream::bytesWritten() const { 420cb93a386Sopenharmony_ci return sk_ftell(fFILE); 421cb93a386Sopenharmony_ci} 422cb93a386Sopenharmony_ci 423cb93a386Sopenharmony_cibool SkFILEWStream::write(const void* buffer, size_t size) 424cb93a386Sopenharmony_ci{ 425cb93a386Sopenharmony_ci if (fFILE == nullptr) { 426cb93a386Sopenharmony_ci return false; 427cb93a386Sopenharmony_ci } 428cb93a386Sopenharmony_ci 429cb93a386Sopenharmony_ci if (sk_fwrite(buffer, size, fFILE) != size) 430cb93a386Sopenharmony_ci { 431cb93a386Sopenharmony_ci SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %zu bytes\n", size);) 432cb93a386Sopenharmony_ci sk_fclose(fFILE); 433cb93a386Sopenharmony_ci fFILE = nullptr; 434cb93a386Sopenharmony_ci return false; 435cb93a386Sopenharmony_ci } 436cb93a386Sopenharmony_ci return true; 437cb93a386Sopenharmony_ci} 438cb93a386Sopenharmony_ci 439cb93a386Sopenharmony_civoid SkFILEWStream::flush() 440cb93a386Sopenharmony_ci{ 441cb93a386Sopenharmony_ci if (fFILE) { 442cb93a386Sopenharmony_ci sk_fflush(fFILE); 443cb93a386Sopenharmony_ci } 444cb93a386Sopenharmony_ci} 445cb93a386Sopenharmony_ci 446cb93a386Sopenharmony_civoid SkFILEWStream::fsync() 447cb93a386Sopenharmony_ci{ 448cb93a386Sopenharmony_ci flush(); 449cb93a386Sopenharmony_ci if (fFILE) { 450cb93a386Sopenharmony_ci sk_fsync(fFILE); 451cb93a386Sopenharmony_ci } 452cb93a386Sopenharmony_ci} 453cb93a386Sopenharmony_ci 454cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////// 455cb93a386Sopenharmony_ci 456cb93a386Sopenharmony_cistatic inline void sk_memcpy_4bytes(void* dst, const void* src, size_t size) { 457cb93a386Sopenharmony_ci if (size == 4) { 458cb93a386Sopenharmony_ci memcpy(dst, src, 4); 459cb93a386Sopenharmony_ci } else { 460cb93a386Sopenharmony_ci memcpy(dst, src, size); 461cb93a386Sopenharmony_ci } 462cb93a386Sopenharmony_ci} 463cb93a386Sopenharmony_ci 464cb93a386Sopenharmony_ci#define SkDynamicMemoryWStream_MinBlockSize 4096 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_cistruct SkDynamicMemoryWStream::Block { 467cb93a386Sopenharmony_ci Block* fNext; 468cb93a386Sopenharmony_ci char* fCurr; 469cb93a386Sopenharmony_ci char* fStop; 470cb93a386Sopenharmony_ci 471cb93a386Sopenharmony_ci const char* start() const { return (const char*)(this + 1); } 472cb93a386Sopenharmony_ci char* start() { return (char*)(this + 1); } 473cb93a386Sopenharmony_ci size_t avail() const { return fStop - fCurr; } 474cb93a386Sopenharmony_ci size_t written() const { return fCurr - this->start(); } 475cb93a386Sopenharmony_ci 476cb93a386Sopenharmony_ci void init(size_t size) { 477cb93a386Sopenharmony_ci fNext = nullptr; 478cb93a386Sopenharmony_ci fCurr = this->start(); 479cb93a386Sopenharmony_ci fStop = this->start() + size; 480cb93a386Sopenharmony_ci } 481cb93a386Sopenharmony_ci 482cb93a386Sopenharmony_ci const void* append(const void* data, size_t size) { 483cb93a386Sopenharmony_ci SkASSERT((size_t)(fStop - fCurr) >= size); 484cb93a386Sopenharmony_ci sk_memcpy_4bytes(fCurr, data, size); 485cb93a386Sopenharmony_ci fCurr += size; 486cb93a386Sopenharmony_ci return (const void*)((const char*)data + size); 487cb93a386Sopenharmony_ci } 488cb93a386Sopenharmony_ci}; 489cb93a386Sopenharmony_ci 490cb93a386Sopenharmony_ciSkDynamicMemoryWStream::SkDynamicMemoryWStream(SkDynamicMemoryWStream&& other) 491cb93a386Sopenharmony_ci : fHead(other.fHead) 492cb93a386Sopenharmony_ci , fTail(other.fTail) 493cb93a386Sopenharmony_ci , fBytesWrittenBeforeTail(other.fBytesWrittenBeforeTail) 494cb93a386Sopenharmony_ci{ 495cb93a386Sopenharmony_ci other.fHead = nullptr; 496cb93a386Sopenharmony_ci other.fTail = nullptr; 497cb93a386Sopenharmony_ci other.fBytesWrittenBeforeTail = 0; 498cb93a386Sopenharmony_ci} 499cb93a386Sopenharmony_ci 500cb93a386Sopenharmony_ciSkDynamicMemoryWStream& SkDynamicMemoryWStream::operator=(SkDynamicMemoryWStream&& other) { 501cb93a386Sopenharmony_ci if (this != &other) { 502cb93a386Sopenharmony_ci this->~SkDynamicMemoryWStream(); 503cb93a386Sopenharmony_ci new (this) SkDynamicMemoryWStream(std::move(other)); 504cb93a386Sopenharmony_ci } 505cb93a386Sopenharmony_ci return *this; 506cb93a386Sopenharmony_ci} 507cb93a386Sopenharmony_ci 508cb93a386Sopenharmony_ciSkDynamicMemoryWStream::~SkDynamicMemoryWStream() { 509cb93a386Sopenharmony_ci this->reset(); 510cb93a386Sopenharmony_ci} 511cb93a386Sopenharmony_ci 512cb93a386Sopenharmony_civoid SkDynamicMemoryWStream::reset() { 513cb93a386Sopenharmony_ci Block* block = fHead; 514cb93a386Sopenharmony_ci while (block != nullptr) { 515cb93a386Sopenharmony_ci Block* next = block->fNext; 516cb93a386Sopenharmony_ci sk_free(block); 517cb93a386Sopenharmony_ci block = next; 518cb93a386Sopenharmony_ci } 519cb93a386Sopenharmony_ci fHead = fTail = nullptr; 520cb93a386Sopenharmony_ci fBytesWrittenBeforeTail = 0; 521cb93a386Sopenharmony_ci} 522cb93a386Sopenharmony_ci 523cb93a386Sopenharmony_cisize_t SkDynamicMemoryWStream::bytesWritten() const { 524cb93a386Sopenharmony_ci this->validate(); 525cb93a386Sopenharmony_ci 526cb93a386Sopenharmony_ci if (fTail) { 527cb93a386Sopenharmony_ci return fBytesWrittenBeforeTail + fTail->written(); 528cb93a386Sopenharmony_ci } 529cb93a386Sopenharmony_ci return 0; 530cb93a386Sopenharmony_ci} 531cb93a386Sopenharmony_ci 532cb93a386Sopenharmony_cibool SkDynamicMemoryWStream::write(const void* buffer, size_t count) { 533cb93a386Sopenharmony_ci if (count > 0) { 534cb93a386Sopenharmony_ci SkASSERT(buffer); 535cb93a386Sopenharmony_ci size_t size; 536cb93a386Sopenharmony_ci 537cb93a386Sopenharmony_ci if (fTail) { 538cb93a386Sopenharmony_ci if (fTail->avail() > 0) { 539cb93a386Sopenharmony_ci size = std::min(fTail->avail(), count); 540cb93a386Sopenharmony_ci buffer = fTail->append(buffer, size); 541cb93a386Sopenharmony_ci SkASSERT(count >= size); 542cb93a386Sopenharmony_ci count -= size; 543cb93a386Sopenharmony_ci if (count == 0) { 544cb93a386Sopenharmony_ci return true; 545cb93a386Sopenharmony_ci } 546cb93a386Sopenharmony_ci } 547cb93a386Sopenharmony_ci // If we get here, we've just exhausted fTail, so update our tracker 548cb93a386Sopenharmony_ci fBytesWrittenBeforeTail += fTail->written(); 549cb93a386Sopenharmony_ci } 550cb93a386Sopenharmony_ci 551cb93a386Sopenharmony_ci size = std::max<size_t>(count, SkDynamicMemoryWStream_MinBlockSize - sizeof(Block)); 552cb93a386Sopenharmony_ci size = SkAlign4(size); // ensure we're always a multiple of 4 (see padToAlign4()) 553cb93a386Sopenharmony_ci 554cb93a386Sopenharmony_ci Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); 555cb93a386Sopenharmony_ci block->init(size); 556cb93a386Sopenharmony_ci block->append(buffer, count); 557cb93a386Sopenharmony_ci 558cb93a386Sopenharmony_ci if (fTail != nullptr) { 559cb93a386Sopenharmony_ci fTail->fNext = block; 560cb93a386Sopenharmony_ci } else { 561cb93a386Sopenharmony_ci fHead = fTail = block; 562cb93a386Sopenharmony_ci } 563cb93a386Sopenharmony_ci fTail = block; 564cb93a386Sopenharmony_ci this->validate(); 565cb93a386Sopenharmony_ci } 566cb93a386Sopenharmony_ci return true; 567cb93a386Sopenharmony_ci} 568cb93a386Sopenharmony_ci 569cb93a386Sopenharmony_cibool SkDynamicMemoryWStream::writeToAndReset(SkDynamicMemoryWStream* dst) { 570cb93a386Sopenharmony_ci SkASSERT(dst); 571cb93a386Sopenharmony_ci SkASSERT(dst != this); 572cb93a386Sopenharmony_ci if (0 == this->bytesWritten()) { 573cb93a386Sopenharmony_ci return true; 574cb93a386Sopenharmony_ci } 575cb93a386Sopenharmony_ci if (0 == dst->bytesWritten()) { 576cb93a386Sopenharmony_ci *dst = std::move(*this); 577cb93a386Sopenharmony_ci return true; 578cb93a386Sopenharmony_ci } 579cb93a386Sopenharmony_ci dst->fTail->fNext = fHead; 580cb93a386Sopenharmony_ci dst->fBytesWrittenBeforeTail += fBytesWrittenBeforeTail + dst->fTail->written(); 581cb93a386Sopenharmony_ci dst->fTail = fTail; 582cb93a386Sopenharmony_ci fHead = fTail = nullptr; 583cb93a386Sopenharmony_ci fBytesWrittenBeforeTail = 0; 584cb93a386Sopenharmony_ci return true; 585cb93a386Sopenharmony_ci} 586cb93a386Sopenharmony_ci 587cb93a386Sopenharmony_civoid SkDynamicMemoryWStream::prependToAndReset(SkDynamicMemoryWStream* dst) { 588cb93a386Sopenharmony_ci SkASSERT(dst); 589cb93a386Sopenharmony_ci SkASSERT(dst != this); 590cb93a386Sopenharmony_ci if (0 == this->bytesWritten()) { 591cb93a386Sopenharmony_ci return; 592cb93a386Sopenharmony_ci } 593cb93a386Sopenharmony_ci if (0 == dst->bytesWritten()) { 594cb93a386Sopenharmony_ci *dst = std::move(*this); 595cb93a386Sopenharmony_ci return; 596cb93a386Sopenharmony_ci } 597cb93a386Sopenharmony_ci fTail->fNext = dst->fHead; 598cb93a386Sopenharmony_ci dst->fHead = fHead; 599cb93a386Sopenharmony_ci dst->fBytesWrittenBeforeTail += fBytesWrittenBeforeTail + fTail->written(); 600cb93a386Sopenharmony_ci fHead = fTail = nullptr; 601cb93a386Sopenharmony_ci fBytesWrittenBeforeTail = 0; 602cb93a386Sopenharmony_ci return; 603cb93a386Sopenharmony_ci} 604cb93a386Sopenharmony_ci 605cb93a386Sopenharmony_ci 606cb93a386Sopenharmony_cibool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count) { 607cb93a386Sopenharmony_ci if (offset + count > this->bytesWritten()) { 608cb93a386Sopenharmony_ci return false; // test does not partially modify 609cb93a386Sopenharmony_ci } 610cb93a386Sopenharmony_ci Block* block = fHead; 611cb93a386Sopenharmony_ci while (block != nullptr) { 612cb93a386Sopenharmony_ci size_t size = block->written(); 613cb93a386Sopenharmony_ci if (offset < size) { 614cb93a386Sopenharmony_ci size_t part = offset + count > size ? size - offset : count; 615cb93a386Sopenharmony_ci memcpy(buffer, block->start() + offset, part); 616cb93a386Sopenharmony_ci if (count <= part) { 617cb93a386Sopenharmony_ci return true; 618cb93a386Sopenharmony_ci } 619cb93a386Sopenharmony_ci count -= part; 620cb93a386Sopenharmony_ci buffer = (void*) ((char* ) buffer + part); 621cb93a386Sopenharmony_ci } 622cb93a386Sopenharmony_ci offset = offset > size ? offset - size : 0; 623cb93a386Sopenharmony_ci block = block->fNext; 624cb93a386Sopenharmony_ci } 625cb93a386Sopenharmony_ci return false; 626cb93a386Sopenharmony_ci} 627cb93a386Sopenharmony_ci 628cb93a386Sopenharmony_civoid SkDynamicMemoryWStream::copyTo(void* dst) const { 629cb93a386Sopenharmony_ci SkASSERT(dst); 630cb93a386Sopenharmony_ci Block* block = fHead; 631cb93a386Sopenharmony_ci while (block != nullptr) { 632cb93a386Sopenharmony_ci size_t size = block->written(); 633cb93a386Sopenharmony_ci memcpy(dst, block->start(), size); 634cb93a386Sopenharmony_ci dst = (void*)((char*)dst + size); 635cb93a386Sopenharmony_ci block = block->fNext; 636cb93a386Sopenharmony_ci } 637cb93a386Sopenharmony_ci} 638cb93a386Sopenharmony_ci 639cb93a386Sopenharmony_cibool SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const { 640cb93a386Sopenharmony_ci SkASSERT(dst); 641cb93a386Sopenharmony_ci for (Block* block = fHead; block != nullptr; block = block->fNext) { 642cb93a386Sopenharmony_ci if (!dst->write(block->start(), block->written())) { 643cb93a386Sopenharmony_ci return false; 644cb93a386Sopenharmony_ci } 645cb93a386Sopenharmony_ci } 646cb93a386Sopenharmony_ci return true; 647cb93a386Sopenharmony_ci} 648cb93a386Sopenharmony_ci 649cb93a386Sopenharmony_civoid SkDynamicMemoryWStream::padToAlign4() { 650cb93a386Sopenharmony_ci // The contract is to write zeros until the entire stream has written a multiple of 4 bytes. 651cb93a386Sopenharmony_ci // Our Blocks are guaranteed always be (a) full (except the tail) and (b) a multiple of 4 652cb93a386Sopenharmony_ci // so it is sufficient to just examine the tail (if present). 653cb93a386Sopenharmony_ci 654cb93a386Sopenharmony_ci if (fTail) { 655cb93a386Sopenharmony_ci // cast to remove unary-minus warning 656cb93a386Sopenharmony_ci int padBytes = -(int)fTail->written() & 0x03; 657cb93a386Sopenharmony_ci if (padBytes) { 658cb93a386Sopenharmony_ci int zero = 0; 659cb93a386Sopenharmony_ci fTail->append(&zero, padBytes); 660cb93a386Sopenharmony_ci } 661cb93a386Sopenharmony_ci } 662cb93a386Sopenharmony_ci} 663cb93a386Sopenharmony_ci 664cb93a386Sopenharmony_ci 665cb93a386Sopenharmony_civoid SkDynamicMemoryWStream::copyToAndReset(void* ptr) { 666cb93a386Sopenharmony_ci if (!ptr) { 667cb93a386Sopenharmony_ci this->reset(); 668cb93a386Sopenharmony_ci return; 669cb93a386Sopenharmony_ci } 670cb93a386Sopenharmony_ci // By looping through the source and freeing as we copy, we 671cb93a386Sopenharmony_ci // can reduce real memory use with large streams. 672cb93a386Sopenharmony_ci char* dst = reinterpret_cast<char*>(ptr); 673cb93a386Sopenharmony_ci Block* block = fHead; 674cb93a386Sopenharmony_ci while (block != nullptr) { 675cb93a386Sopenharmony_ci size_t len = block->written(); 676cb93a386Sopenharmony_ci memcpy(dst, block->start(), len); 677cb93a386Sopenharmony_ci dst += len; 678cb93a386Sopenharmony_ci Block* next = block->fNext; 679cb93a386Sopenharmony_ci sk_free(block); 680cb93a386Sopenharmony_ci block = next; 681cb93a386Sopenharmony_ci } 682cb93a386Sopenharmony_ci fHead = fTail = nullptr; 683cb93a386Sopenharmony_ci fBytesWrittenBeforeTail = 0; 684cb93a386Sopenharmony_ci} 685cb93a386Sopenharmony_ci 686cb93a386Sopenharmony_cibool SkDynamicMemoryWStream::writeToAndReset(SkWStream* dst) { 687cb93a386Sopenharmony_ci SkASSERT(dst); 688cb93a386Sopenharmony_ci // By looping through the source and freeing as we copy, we 689cb93a386Sopenharmony_ci // can reduce real memory use with large streams. 690cb93a386Sopenharmony_ci bool dstStreamGood = true; 691cb93a386Sopenharmony_ci for (Block* block = fHead; block != nullptr; ) { 692cb93a386Sopenharmony_ci if (dstStreamGood && !dst->write(block->start(), block->written())) { 693cb93a386Sopenharmony_ci dstStreamGood = false; 694cb93a386Sopenharmony_ci } 695cb93a386Sopenharmony_ci Block* next = block->fNext; 696cb93a386Sopenharmony_ci sk_free(block); 697cb93a386Sopenharmony_ci block = next; 698cb93a386Sopenharmony_ci } 699cb93a386Sopenharmony_ci fHead = fTail = nullptr; 700cb93a386Sopenharmony_ci fBytesWrittenBeforeTail = 0; 701cb93a386Sopenharmony_ci return dstStreamGood; 702cb93a386Sopenharmony_ci} 703cb93a386Sopenharmony_ci 704cb93a386Sopenharmony_cisk_sp<SkData> SkDynamicMemoryWStream::detachAsData() { 705cb93a386Sopenharmony_ci const size_t size = this->bytesWritten(); 706cb93a386Sopenharmony_ci if (0 == size) { 707cb93a386Sopenharmony_ci return SkData::MakeEmpty(); 708cb93a386Sopenharmony_ci } 709cb93a386Sopenharmony_ci sk_sp<SkData> data = SkData::MakeUninitialized(size); 710cb93a386Sopenharmony_ci this->copyToAndReset(data->writable_data()); 711cb93a386Sopenharmony_ci return data; 712cb93a386Sopenharmony_ci} 713cb93a386Sopenharmony_ci 714cb93a386Sopenharmony_ci#ifdef SK_DEBUG 715cb93a386Sopenharmony_civoid SkDynamicMemoryWStream::validate() const { 716cb93a386Sopenharmony_ci if (!fHead) { 717cb93a386Sopenharmony_ci SkASSERT(!fTail); 718cb93a386Sopenharmony_ci SkASSERT(fBytesWrittenBeforeTail == 0); 719cb93a386Sopenharmony_ci return; 720cb93a386Sopenharmony_ci } 721cb93a386Sopenharmony_ci SkASSERT(fTail); 722cb93a386Sopenharmony_ci 723cb93a386Sopenharmony_ci size_t bytes = 0; 724cb93a386Sopenharmony_ci const Block* block = fHead; 725cb93a386Sopenharmony_ci while (block) { 726cb93a386Sopenharmony_ci if (block->fNext) { 727cb93a386Sopenharmony_ci bytes += block->written(); 728cb93a386Sopenharmony_ci } 729cb93a386Sopenharmony_ci block = block->fNext; 730cb93a386Sopenharmony_ci } 731cb93a386Sopenharmony_ci SkASSERT(bytes == fBytesWrittenBeforeTail); 732cb93a386Sopenharmony_ci} 733cb93a386Sopenharmony_ci#endif 734cb93a386Sopenharmony_ci 735cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////// 736cb93a386Sopenharmony_ci 737cb93a386Sopenharmony_ciclass SkBlockMemoryRefCnt : public SkRefCnt { 738cb93a386Sopenharmony_cipublic: 739cb93a386Sopenharmony_ci explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { } 740cb93a386Sopenharmony_ci 741cb93a386Sopenharmony_ci ~SkBlockMemoryRefCnt() override { 742cb93a386Sopenharmony_ci SkDynamicMemoryWStream::Block* block = fHead; 743cb93a386Sopenharmony_ci while (block != nullptr) { 744cb93a386Sopenharmony_ci SkDynamicMemoryWStream::Block* next = block->fNext; 745cb93a386Sopenharmony_ci sk_free(block); 746cb93a386Sopenharmony_ci block = next; 747cb93a386Sopenharmony_ci } 748cb93a386Sopenharmony_ci } 749cb93a386Sopenharmony_ci 750cb93a386Sopenharmony_ci SkDynamicMemoryWStream::Block* const fHead; 751cb93a386Sopenharmony_ci}; 752cb93a386Sopenharmony_ci 753cb93a386Sopenharmony_ciclass SkBlockMemoryStream : public SkStreamAsset { 754cb93a386Sopenharmony_cipublic: 755cb93a386Sopenharmony_ci SkBlockMemoryStream(sk_sp<SkBlockMemoryRefCnt> headRef, size_t size) 756cb93a386Sopenharmony_ci : fBlockMemory(std::move(headRef)), fCurrent(fBlockMemory->fHead) 757cb93a386Sopenharmony_ci , fSize(size) , fOffset(0), fCurrentOffset(0) { } 758cb93a386Sopenharmony_ci 759cb93a386Sopenharmony_ci size_t read(void* buffer, size_t rawCount) override { 760cb93a386Sopenharmony_ci size_t count = rawCount; 761cb93a386Sopenharmony_ci if (fOffset + count > fSize) { 762cb93a386Sopenharmony_ci count = fSize - fOffset; 763cb93a386Sopenharmony_ci } 764cb93a386Sopenharmony_ci size_t bytesLeftToRead = count; 765cb93a386Sopenharmony_ci while (fCurrent != nullptr) { 766cb93a386Sopenharmony_ci size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset; 767cb93a386Sopenharmony_ci size_t bytesFromCurrent = std::min(bytesLeftToRead, bytesLeftInCurrent); 768cb93a386Sopenharmony_ci if (buffer) { 769cb93a386Sopenharmony_ci memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent); 770cb93a386Sopenharmony_ci buffer = SkTAddOffset<void>(buffer, bytesFromCurrent); 771cb93a386Sopenharmony_ci } 772cb93a386Sopenharmony_ci if (bytesLeftToRead <= bytesFromCurrent) { 773cb93a386Sopenharmony_ci fCurrentOffset += bytesFromCurrent; 774cb93a386Sopenharmony_ci fOffset += count; 775cb93a386Sopenharmony_ci return count; 776cb93a386Sopenharmony_ci } 777cb93a386Sopenharmony_ci bytesLeftToRead -= bytesFromCurrent; 778cb93a386Sopenharmony_ci fCurrent = fCurrent->fNext; 779cb93a386Sopenharmony_ci fCurrentOffset = 0; 780cb93a386Sopenharmony_ci } 781cb93a386Sopenharmony_ci SkASSERT(false); 782cb93a386Sopenharmony_ci return 0; 783cb93a386Sopenharmony_ci } 784cb93a386Sopenharmony_ci 785cb93a386Sopenharmony_ci bool isAtEnd() const override { 786cb93a386Sopenharmony_ci return fOffset == fSize; 787cb93a386Sopenharmony_ci } 788cb93a386Sopenharmony_ci 789cb93a386Sopenharmony_ci size_t peek(void* buff, size_t bytesToPeek) const override { 790cb93a386Sopenharmony_ci SkASSERT(buff != nullptr); 791cb93a386Sopenharmony_ci 792cb93a386Sopenharmony_ci bytesToPeek = std::min(bytesToPeek, fSize - fOffset); 793cb93a386Sopenharmony_ci 794cb93a386Sopenharmony_ci size_t bytesLeftToPeek = bytesToPeek; 795cb93a386Sopenharmony_ci char* buffer = static_cast<char*>(buff); 796cb93a386Sopenharmony_ci const SkDynamicMemoryWStream::Block* current = fCurrent; 797cb93a386Sopenharmony_ci size_t currentOffset = fCurrentOffset; 798cb93a386Sopenharmony_ci while (bytesLeftToPeek) { 799cb93a386Sopenharmony_ci SkASSERT(current); 800cb93a386Sopenharmony_ci size_t bytesFromCurrent = std::min(current->written() - currentOffset, bytesLeftToPeek); 801cb93a386Sopenharmony_ci memcpy(buffer, current->start() + currentOffset, bytesFromCurrent); 802cb93a386Sopenharmony_ci bytesLeftToPeek -= bytesFromCurrent; 803cb93a386Sopenharmony_ci buffer += bytesFromCurrent; 804cb93a386Sopenharmony_ci current = current->fNext; 805cb93a386Sopenharmony_ci currentOffset = 0; 806cb93a386Sopenharmony_ci } 807cb93a386Sopenharmony_ci return bytesToPeek; 808cb93a386Sopenharmony_ci } 809cb93a386Sopenharmony_ci 810cb93a386Sopenharmony_ci bool rewind() override { 811cb93a386Sopenharmony_ci fCurrent = fBlockMemory->fHead; 812cb93a386Sopenharmony_ci fOffset = 0; 813cb93a386Sopenharmony_ci fCurrentOffset = 0; 814cb93a386Sopenharmony_ci return true; 815cb93a386Sopenharmony_ci } 816cb93a386Sopenharmony_ci 817cb93a386Sopenharmony_ci SkBlockMemoryStream* onDuplicate() const override { 818cb93a386Sopenharmony_ci return new SkBlockMemoryStream(fBlockMemory, fSize); 819cb93a386Sopenharmony_ci } 820cb93a386Sopenharmony_ci 821cb93a386Sopenharmony_ci size_t getPosition() const override { 822cb93a386Sopenharmony_ci return fOffset; 823cb93a386Sopenharmony_ci } 824cb93a386Sopenharmony_ci 825cb93a386Sopenharmony_ci bool seek(size_t position) override { 826cb93a386Sopenharmony_ci // If possible, skip forward. 827cb93a386Sopenharmony_ci if (position >= fOffset) { 828cb93a386Sopenharmony_ci size_t skipAmount = position - fOffset; 829cb93a386Sopenharmony_ci return this->skip(skipAmount) == skipAmount; 830cb93a386Sopenharmony_ci } 831cb93a386Sopenharmony_ci // If possible, move backward within the current block. 832cb93a386Sopenharmony_ci size_t moveBackAmount = fOffset - position; 833cb93a386Sopenharmony_ci if (moveBackAmount <= fCurrentOffset) { 834cb93a386Sopenharmony_ci fCurrentOffset -= moveBackAmount; 835cb93a386Sopenharmony_ci fOffset -= moveBackAmount; 836cb93a386Sopenharmony_ci return true; 837cb93a386Sopenharmony_ci } 838cb93a386Sopenharmony_ci // Otherwise rewind and move forward. 839cb93a386Sopenharmony_ci return this->rewind() && this->skip(position) == position; 840cb93a386Sopenharmony_ci } 841cb93a386Sopenharmony_ci 842cb93a386Sopenharmony_ci bool move(long offset) override { 843cb93a386Sopenharmony_ci return seek(fOffset + offset); 844cb93a386Sopenharmony_ci } 845cb93a386Sopenharmony_ci 846cb93a386Sopenharmony_ci SkBlockMemoryStream* onFork() const override { 847cb93a386Sopenharmony_ci SkBlockMemoryStream* that = this->onDuplicate(); 848cb93a386Sopenharmony_ci that->fCurrent = this->fCurrent; 849cb93a386Sopenharmony_ci that->fOffset = this->fOffset; 850cb93a386Sopenharmony_ci that->fCurrentOffset = this->fCurrentOffset; 851cb93a386Sopenharmony_ci return that; 852cb93a386Sopenharmony_ci } 853cb93a386Sopenharmony_ci 854cb93a386Sopenharmony_ci size_t getLength() const override { 855cb93a386Sopenharmony_ci return fSize; 856cb93a386Sopenharmony_ci } 857cb93a386Sopenharmony_ci 858cb93a386Sopenharmony_ci const void* getMemoryBase() override { 859cb93a386Sopenharmony_ci if (fBlockMemory->fHead && !fBlockMemory->fHead->fNext) { 860cb93a386Sopenharmony_ci return fBlockMemory->fHead->start(); 861cb93a386Sopenharmony_ci } 862cb93a386Sopenharmony_ci return nullptr; 863cb93a386Sopenharmony_ci } 864cb93a386Sopenharmony_ci 865cb93a386Sopenharmony_ciprivate: 866cb93a386Sopenharmony_ci sk_sp<SkBlockMemoryRefCnt> const fBlockMemory; 867cb93a386Sopenharmony_ci SkDynamicMemoryWStream::Block const * fCurrent; 868cb93a386Sopenharmony_ci size_t const fSize; 869cb93a386Sopenharmony_ci size_t fOffset; 870cb93a386Sopenharmony_ci size_t fCurrentOffset; 871cb93a386Sopenharmony_ci}; 872cb93a386Sopenharmony_ci 873cb93a386Sopenharmony_cistd::unique_ptr<SkStreamAsset> SkDynamicMemoryWStream::detachAsStream() { 874cb93a386Sopenharmony_ci if (nullptr == fHead) { 875cb93a386Sopenharmony_ci // no need to reset. 876cb93a386Sopenharmony_ci return SkMemoryStream::Make(nullptr); 877cb93a386Sopenharmony_ci } 878cb93a386Sopenharmony_ci if (fHead == fTail) { // one block, may be worth shrinking. 879cb93a386Sopenharmony_ci ptrdiff_t used = fTail->fCurr - (char*)fTail; 880cb93a386Sopenharmony_ci fHead = fTail = (SkDynamicMemoryWStream::Block*)sk_realloc_throw(fTail, SkToSizeT(used)); 881cb93a386Sopenharmony_ci fTail->fStop = fTail->fCurr = (char*)fTail + used; // Update pointers. 882cb93a386Sopenharmony_ci SkASSERT(nullptr == fTail->fNext); 883cb93a386Sopenharmony_ci SkASSERT(0 == fBytesWrittenBeforeTail); 884cb93a386Sopenharmony_ci } 885cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream 886cb93a386Sopenharmony_ci = std::make_unique<SkBlockMemoryStream>(sk_make_sp<SkBlockMemoryRefCnt>(fHead), 887cb93a386Sopenharmony_ci this->bytesWritten()); 888cb93a386Sopenharmony_ci fHead = nullptr; // signal reset() to not free anything 889cb93a386Sopenharmony_ci this->reset(); 890cb93a386Sopenharmony_ci return stream; 891cb93a386Sopenharmony_ci} 892cb93a386Sopenharmony_ci 893cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 894cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 895cb93a386Sopenharmony_ci 896cb93a386Sopenharmony_cistatic sk_sp<SkData> mmap_filename(const char path[]) { 897cb93a386Sopenharmony_ci FILE* file = sk_fopen(path, kRead_SkFILE_Flag); 898cb93a386Sopenharmony_ci if (nullptr == file) { 899cb93a386Sopenharmony_ci return nullptr; 900cb93a386Sopenharmony_ci } 901cb93a386Sopenharmony_ci 902cb93a386Sopenharmony_ci auto data = SkData::MakeFromFILE(file); 903cb93a386Sopenharmony_ci sk_fclose(file); 904cb93a386Sopenharmony_ci return data; 905cb93a386Sopenharmony_ci} 906cb93a386Sopenharmony_ci 907cb93a386Sopenharmony_cistd::unique_ptr<SkStreamAsset> SkStream::MakeFromFile(const char path[]) { 908cb93a386Sopenharmony_ci auto data(mmap_filename(path)); 909cb93a386Sopenharmony_ci if (data) { 910cb93a386Sopenharmony_ci return std::make_unique<SkMemoryStream>(std::move(data)); 911cb93a386Sopenharmony_ci } 912cb93a386Sopenharmony_ci 913cb93a386Sopenharmony_ci // If we get here, then our attempt at using mmap failed, so try normal file access. 914cb93a386Sopenharmony_ci auto stream = std::make_unique<SkFILEStream>(path); 915cb93a386Sopenharmony_ci if (!stream->isValid()) { 916cb93a386Sopenharmony_ci return nullptr; 917cb93a386Sopenharmony_ci } 918cb93a386Sopenharmony_ci return std::move(stream); 919cb93a386Sopenharmony_ci} 920cb93a386Sopenharmony_ci 921cb93a386Sopenharmony_ci// Declared in SkStreamPriv.h: 922cb93a386Sopenharmony_cisk_sp<SkData> SkCopyStreamToData(SkStream* stream) { 923cb93a386Sopenharmony_ci SkASSERT(stream != nullptr); 924cb93a386Sopenharmony_ci 925cb93a386Sopenharmony_ci if (stream->hasLength()) { 926cb93a386Sopenharmony_ci return SkData::MakeFromStream(stream, stream->getLength()); 927cb93a386Sopenharmony_ci } 928cb93a386Sopenharmony_ci 929cb93a386Sopenharmony_ci SkDynamicMemoryWStream tempStream; 930cb93a386Sopenharmony_ci const size_t bufferSize = 4096; 931cb93a386Sopenharmony_ci char buffer[bufferSize]; 932cb93a386Sopenharmony_ci do { 933cb93a386Sopenharmony_ci size_t bytesRead = stream->read(buffer, bufferSize); 934cb93a386Sopenharmony_ci tempStream.write(buffer, bytesRead); 935cb93a386Sopenharmony_ci } while (!stream->isAtEnd()); 936cb93a386Sopenharmony_ci return tempStream.detachAsData(); 937cb93a386Sopenharmony_ci} 938cb93a386Sopenharmony_ci 939cb93a386Sopenharmony_cibool SkStreamCopy(SkWStream* out, SkStream* input) { 940cb93a386Sopenharmony_ci const char* base = static_cast<const char*>(input->getMemoryBase()); 941cb93a386Sopenharmony_ci if (base && input->hasPosition() && input->hasLength()) { 942cb93a386Sopenharmony_ci // Shortcut that avoids the while loop. 943cb93a386Sopenharmony_ci size_t position = input->getPosition(); 944cb93a386Sopenharmony_ci size_t length = input->getLength(); 945cb93a386Sopenharmony_ci SkASSERT(length >= position); 946cb93a386Sopenharmony_ci return out->write(&base[position], length - position); 947cb93a386Sopenharmony_ci } 948cb93a386Sopenharmony_ci char scratch[4096]; 949cb93a386Sopenharmony_ci size_t count; 950cb93a386Sopenharmony_ci while (true) { 951cb93a386Sopenharmony_ci count = input->read(scratch, sizeof(scratch)); 952cb93a386Sopenharmony_ci if (0 == count) { 953cb93a386Sopenharmony_ci return true; 954cb93a386Sopenharmony_ci } 955cb93a386Sopenharmony_ci if (!out->write(scratch, count)) { 956cb93a386Sopenharmony_ci return false; 957cb93a386Sopenharmony_ci } 958cb93a386Sopenharmony_ci } 959cb93a386Sopenharmony_ci} 960