1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkStream_DEFINED 9 #define SkStream_DEFINED 10 11 #include "include/core/SkData.h" 12 #include "include/core/SkRefCnt.h" 13 #include "include/core/SkScalar.h" 14 #include "include/core/SkTypes.h" 15 #include "include/private/base/SkCPUTypes.h" 16 #include "include/private/base/SkTo.h" 17 18 #include <cstdint> 19 #include <cstdio> 20 #include <cstring> 21 #include <memory> 22 #include <utility> 23 class SkStreamAsset; 24 25 /** 26 * SkStream -- abstraction for a source of bytes. Subclasses can be backed by 27 * memory, or a file, or something else. 28 */ 29 class SK_API SkStream { 30 public: ~SkStream()31 virtual ~SkStream() {} SkStream()32 SkStream() {} 33 34 /** 35 * Attempts to open the specified file as a stream, returns nullptr on failure. 36 */ 37 static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]); 38 39 /** Reads or skips size number of bytes. 40 * If buffer == NULL, skip size bytes, return how many were skipped. 41 * If buffer != NULL, copy size bytes into buffer, return how many were copied. 42 * @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer 43 * @param size the number of bytes to skip or copy 44 * @return the number of bytes actually read. 45 */ 46 virtual size_t read(void* buffer, size_t size) = 0; 47 48 /** Skip size number of bytes. 49 * @return the actual number bytes that could be skipped. 50 */ skip(size_t size)51 size_t skip(size_t size) { 52 return this->read(nullptr, size); 53 } 54 55 /** 56 * Attempt to peek at size bytes. 57 * If this stream supports peeking, copy min(size, peekable bytes) into 58 * buffer, and return the number of bytes copied. 59 * If the stream does not support peeking, or cannot peek any bytes, 60 * return 0 and leave buffer unchanged. 61 * The stream is guaranteed to be in the same visible state after this 62 * call, regardless of success or failure. 63 * @param buffer Must not be NULL, and must be at least size bytes. Destination 64 * to copy bytes. 65 * @param size Number of bytes to copy. 66 * @return The number of bytes peeked/copied. 67 */ peek(void *,size_t)68 virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; } 69 70 /** Returns true when all the bytes in the stream have been read. 71 * As SkStream represents synchronous I/O, isAtEnd returns false when the 72 * final stream length isn't known yet, even when all the bytes available 73 * so far have been read. 74 * This may return true early (when there are no more bytes to be read) 75 * or late (after the first unsuccessful read). 76 */ 77 virtual bool isAtEnd() const = 0; 78 79 [[nodiscard]] bool readS8(int8_t*); 80 [[nodiscard]] bool readS16(int16_t*); 81 [[nodiscard]] bool readS32(int32_t*); 82 [[nodiscard]] bool readS64(int64_t*); 83 readU8(uint8_t * i)84 [[nodiscard]] bool readU8(uint8_t* i) { return this->readS8((int8_t*)i); } readU16(uint16_t * i)85 [[nodiscard]] bool readU16(uint16_t* i) { return this->readS16((int16_t*)i); } readU32(uint32_t * i)86 [[nodiscard]] bool readU32(uint32_t* i) { return this->readS32((int32_t*)i); } readU64(uint64_t * i)87 [[nodiscard]] bool readU64(uint64_t* i) { return this->readS64((int64_t*)i); } 88 readBool(bool * b)89 [[nodiscard]] bool readBool(bool* b) { 90 uint8_t i; 91 if (!this->readU8(&i)) { return false; } 92 *b = (i != 0); 93 return true; 94 } 95 [[nodiscard]] bool readScalar(SkScalar*); 96 [[nodiscard]] bool readPackedUInt(size_t*); 97 98 //SkStreamRewindable 99 /** Rewinds to the beginning of the stream. Returns true if the stream is known 100 * to be at the beginning after this call returns. 101 */ rewind()102 virtual bool rewind() { return false; } 103 104 /** Duplicates this stream. If this cannot be done, returns NULL. 105 * The returned stream will be positioned at the beginning of its data. 106 */ duplicate()107 std::unique_ptr<SkStream> duplicate() const { 108 return std::unique_ptr<SkStream>(this->onDuplicate()); 109 } 110 /** Duplicates this stream. If this cannot be done, returns NULL. 111 * The returned stream will be positioned the same as this stream. 112 */ fork()113 std::unique_ptr<SkStream> fork() const { 114 return std::unique_ptr<SkStream>(this->onFork()); 115 } 116 117 //SkStreamSeekable 118 /** Returns true if this stream can report its current position. */ hasPosition()119 virtual bool hasPosition() const { return false; } 120 /** Returns the current position in the stream. If this cannot be done, returns 0. */ getPosition()121 virtual size_t getPosition() const { return 0; } 122 123 /** Seeks to an absolute position in the stream. If this cannot be done, returns false. 124 * If an attempt is made to seek past the end of the stream, the position will be set 125 * to the end of the stream. 126 */ seek(size_t)127 virtual bool seek(size_t /*position*/) { return false; } 128 129 /** Seeks to an relative offset in the stream. If this cannot be done, returns false. 130 * If an attempt is made to move to a position outside the stream, the position will be set 131 * to the closest point within the stream (beginning or end). 132 */ move(long)133 virtual bool move(long /*offset*/) { return false; } 134 135 //SkStreamAsset 136 /** Returns true if this stream can report its total length. */ hasLength()137 virtual bool hasLength() const { return false; } 138 /** Returns the total length of the stream. If this cannot be done, returns 0. */ getLength()139 virtual size_t getLength() const { return 0; } 140 141 //SkStreamMemory 142 /** Returns the starting address for the data. If this cannot be done, returns NULL. */ getMemoryBase()143 virtual const void* getMemoryBase() { return nullptr; } getData()144 virtual sk_sp<SkData> getData() const { return nullptr; } 145 146 private: onDuplicate()147 virtual SkStream* onDuplicate() const { return nullptr; } onFork()148 virtual SkStream* onFork() const { return nullptr; } 149 150 SkStream(SkStream&&) = delete; 151 SkStream(const SkStream&) = delete; 152 SkStream& operator=(SkStream&&) = delete; 153 SkStream& operator=(const SkStream&) = delete; 154 }; 155 156 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */ 157 class SK_API SkStreamRewindable : public SkStream { 158 public: 159 bool rewind() override = 0; duplicate()160 std::unique_ptr<SkStreamRewindable> duplicate() const { 161 return std::unique_ptr<SkStreamRewindable>(this->onDuplicate()); 162 } 163 private: 164 SkStreamRewindable* onDuplicate() const override = 0; 165 }; 166 167 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */ 168 class SK_API SkStreamSeekable : public SkStreamRewindable { 169 public: duplicate()170 std::unique_ptr<SkStreamSeekable> duplicate() const { 171 return std::unique_ptr<SkStreamSeekable>(this->onDuplicate()); 172 } 173 hasPosition()174 bool hasPosition() const override { return true; } 175 size_t getPosition() const override = 0; 176 bool seek(size_t position) override = 0; 177 bool move(long offset) override = 0; 178 fork()179 std::unique_ptr<SkStreamSeekable> fork() const { 180 return std::unique_ptr<SkStreamSeekable>(this->onFork()); 181 } 182 private: 183 SkStreamSeekable* onDuplicate() const override = 0; 184 SkStreamSeekable* onFork() const override = 0; 185 }; 186 187 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */ 188 class SK_API SkStreamAsset : public SkStreamSeekable { 189 public: hasLength()190 bool hasLength() const override { return true; } 191 size_t getLength() const override = 0; 192 duplicate()193 std::unique_ptr<SkStreamAsset> duplicate() const { 194 return std::unique_ptr<SkStreamAsset>(this->onDuplicate()); 195 } fork()196 std::unique_ptr<SkStreamAsset> fork() const { 197 return std::unique_ptr<SkStreamAsset>(this->onFork()); 198 } 199 private: 200 SkStreamAsset* onDuplicate() const override = 0; 201 SkStreamAsset* onFork() const override = 0; 202 }; 203 204 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */ 205 class SK_API SkStreamMemory : public SkStreamAsset { 206 public: 207 const void* getMemoryBase() override = 0; 208 duplicate()209 std::unique_ptr<SkStreamMemory> duplicate() const { 210 return std::unique_ptr<SkStreamMemory>(this->onDuplicate()); 211 } fork()212 std::unique_ptr<SkStreamMemory> fork() const { 213 return std::unique_ptr<SkStreamMemory>(this->onFork()); 214 } 215 private: 216 SkStreamMemory* onDuplicate() const override = 0; 217 SkStreamMemory* onFork() const override = 0; 218 }; 219 220 class SK_API SkWStream { 221 public: 222 virtual ~SkWStream(); SkWStream()223 SkWStream() {} 224 225 /** Called to write bytes to a SkWStream. Returns true on success 226 @param buffer the address of at least size bytes to be written to the stream 227 @param size The number of bytes in buffer to write to the stream 228 @return true on success 229 */ 230 virtual bool write(const void* buffer, size_t size) = 0; 231 virtual void flush(); 232 233 virtual size_t bytesWritten() const = 0; 234 235 // helpers 236 write8(U8CPU value)237 bool write8(U8CPU value) { 238 uint8_t v = SkToU8(value); 239 return this->write(&v, 1); 240 } write16(U16CPU value)241 bool write16(U16CPU value) { 242 uint16_t v = SkToU16(value); 243 return this->write(&v, 2); 244 } write32(uint32_t value)245 bool write32(uint32_t value) { 246 return this->write(&value, 4); 247 } write64(uint64_t value)248 bool write64(uint64_t value) { 249 return this->write(&value, 8); 250 } 251 writeText(const char text[])252 bool writeText(const char text[]) { 253 SkASSERT(text); 254 return this->write(text, std::strlen(text)); 255 } 256 newline()257 bool newline() { return this->write("\n", std::strlen("\n")); } 258 259 bool writeDecAsText(int32_t); 260 bool writeBigDecAsText(int64_t, int minDigits = 0); 261 bool writeHexAsText(uint32_t, int minDigits = 0); 262 bool writeScalarAsText(SkScalar); 263 writeBool(bool v)264 bool writeBool(bool v) { return this->write8(v); } 265 bool writeScalar(SkScalar); 266 bool writePackedUInt(size_t); 267 268 bool writeStream(SkStream* input, size_t length); 269 270 /** 271 * This returns the number of bytes in the stream required to store 272 * 'value'. 273 */ 274 static int SizeOfPackedUInt(size_t value); 275 276 private: 277 SkWStream(const SkWStream&) = delete; 278 SkWStream& operator=(const SkWStream&) = delete; 279 }; 280 281 class SK_API SkNullWStream : public SkWStream { 282 public: SkNullWStream()283 SkNullWStream() : fBytesWritten(0) {} 284 write(const void *,size_t n)285 bool write(const void* , size_t n) override { fBytesWritten += n; return true; } flush()286 void flush() override {} bytesWritten()287 size_t bytesWritten() const override { return fBytesWritten; } 288 289 private: 290 size_t fBytesWritten; 291 }; 292 293 //////////////////////////////////////////////////////////////////////////////////////// 294 295 /** A stream that wraps a C FILE* file stream. */ 296 class SK_API SkFILEStream : public SkStreamAsset { 297 public: 298 /** Initialize the stream by calling sk_fopen on the specified path. 299 * This internal stream will be closed in the destructor. 300 */ 301 explicit SkFILEStream(const char path[] = nullptr); 302 303 /** Initialize the stream with an existing C FILE stream. 304 * The current position of the C FILE stream will be considered the 305 * beginning of the SkFILEStream and the current seek end of the FILE will be the end. 306 * The C FILE stream will be closed in the destructor. 307 */ 308 explicit SkFILEStream(FILE* file); 309 310 /** Initialize the stream with an existing C FILE stream. 311 * The current position of the C FILE stream will be considered the 312 * beginning of the SkFILEStream and size bytes later will be the end. 313 * The C FILE stream will be closed in the destructor. 314 */ 315 explicit SkFILEStream(FILE* file, size_t size); 316 317 ~SkFILEStream() override; 318 Make(const char path[])319 static std::unique_ptr<SkFILEStream> Make(const char path[]) { 320 std::unique_ptr<SkFILEStream> stream(new SkFILEStream(path)); 321 return stream->isValid() ? std::move(stream) : nullptr; 322 } 323 324 /** Returns true if the current path could be opened. */ isValid()325 bool isValid() const { return fFILE != nullptr; } 326 327 /** Close this SkFILEStream. */ 328 void close(); 329 330 size_t read(void* buffer, size_t size) override; 331 bool isAtEnd() const override; 332 333 bool rewind() override; duplicate()334 std::unique_ptr<SkStreamAsset> duplicate() const { 335 return std::unique_ptr<SkStreamAsset>(this->onDuplicate()); 336 } 337 338 size_t getPosition() const override; 339 bool seek(size_t position) override; 340 bool move(long offset) override; 341 fork()342 std::unique_ptr<SkStreamAsset> fork() const { 343 return std::unique_ptr<SkStreamAsset>(this->onFork()); 344 } 345 346 size_t getLength() const override; 347 348 private: 349 explicit SkFILEStream(FILE*, size_t size, size_t start); 350 explicit SkFILEStream(std::shared_ptr<FILE>, size_t end, size_t start); 351 explicit SkFILEStream(std::shared_ptr<FILE>, size_t end, size_t start, size_t current); 352 353 SkStreamAsset* onDuplicate() const override; 354 SkStreamAsset* onFork() const override; 355 356 std::shared_ptr<FILE> fFILE; 357 // My own council will I keep on sizes and offsets. 358 // These are seek positions in the underling FILE, not offsets into the stream. 359 size_t fEnd; 360 size_t fStart; 361 size_t fCurrent; 362 363 using INHERITED = SkStreamAsset; 364 }; 365 366 class SK_API SkMemoryStream : public SkStreamMemory { 367 public: 368 SkMemoryStream(); 369 370 /** We allocate (and free) the memory. Write to it via getMemoryBase() */ 371 SkMemoryStream(size_t length); 372 373 /** If copyData is true, the stream makes a private copy of the data. */ 374 SkMemoryStream(const void* data, size_t length, bool copyData = false); 375 376 /** Creates the stream to read from the specified data */ 377 SkMemoryStream(sk_sp<SkData> data); 378 379 /** Returns a stream with a copy of the input data. */ 380 static std::unique_ptr<SkMemoryStream> MakeCopy(const void* data, size_t length); 381 382 /** Returns a stream with a bare pointer reference to the input data. */ 383 static std::unique_ptr<SkMemoryStream> MakeDirect(const void* data, size_t length); 384 385 /** Returns a stream with a shared reference to the input data. */ 386 static std::unique_ptr<SkMemoryStream> Make(sk_sp<SkData> data); 387 388 /** Resets the stream to the specified data and length, 389 just like the constructor. 390 if copyData is true, the stream makes a private copy of the data 391 */ 392 virtual void setMemory(const void* data, size_t length, 393 bool copyData = false); 394 /** Replace any memory buffer with the specified buffer. The caller 395 must have allocated data with sk_malloc or sk_realloc, since it 396 will be freed with sk_free. 397 */ 398 void setMemoryOwned(const void* data, size_t length); 399 getData()400 sk_sp<SkData> getData() const override { return fData; } 401 void setData(sk_sp<SkData> data); 402 403 const void* getAtPos(); 404 405 size_t read(void* buffer, size_t size) override; 406 bool isAtEnd() const override; 407 408 size_t peek(void* buffer, size_t size) const override; 409 410 bool rewind() override; 411 duplicate()412 std::unique_ptr<SkMemoryStream> duplicate() const { 413 return std::unique_ptr<SkMemoryStream>(this->onDuplicate()); 414 } 415 416 size_t getPosition() const override; 417 bool seek(size_t position) override; 418 bool move(long offset) override; 419 fork()420 std::unique_ptr<SkMemoryStream> fork() const { 421 return std::unique_ptr<SkMemoryStream>(this->onFork()); 422 } 423 424 size_t getLength() const override; 425 426 const void* getMemoryBase() override; 427 428 private: 429 SkMemoryStream* onDuplicate() const override; 430 SkMemoryStream* onFork() const override; 431 432 sk_sp<SkData> fData; 433 size_t fOffset; 434 435 using INHERITED = SkStreamMemory; 436 }; 437 438 ///////////////////////////////////////////////////////////////////////////////////////////// 439 440 class SK_API SkFILEWStream : public SkWStream { 441 public: 442 SkFILEWStream(const char path[]); 443 ~SkFILEWStream() override; 444 445 /** Returns true if the current path could be opened. 446 */ isValid()447 bool isValid() const { return fFILE != nullptr; } 448 449 bool write(const void* buffer, size_t size) override; 450 void flush() override; 451 void fsync(); 452 size_t bytesWritten() const override; 453 454 private: 455 FILE* fFILE; 456 457 using INHERITED = SkWStream; 458 }; 459 460 class SK_API SkDynamicMemoryWStream : public SkWStream { 461 public: 462 SkDynamicMemoryWStream() = default; 463 SkDynamicMemoryWStream(SkDynamicMemoryWStream&&); 464 SkDynamicMemoryWStream& operator=(SkDynamicMemoryWStream&&); 465 ~SkDynamicMemoryWStream() override; 466 467 bool write(const void* buffer, size_t size) override; 468 size_t bytesWritten() const override; 469 470 bool read(void* buffer, size_t offset, size_t size); 471 472 /** More efficient version of read(dst, 0, bytesWritten()). */ 473 void copyTo(void* dst) const; 474 bool writeToStream(SkWStream* dst) const; 475 476 /** Equivalent to copyTo() followed by reset(), but may save memory use. */ 477 void copyToAndReset(void* dst); 478 479 /** Equivalent to writeToStream() followed by reset(), but may save memory use. */ 480 bool writeToAndReset(SkWStream* dst); 481 482 /** Equivalent to writeToStream() followed by reset(), but may save memory use. 483 When the dst is also a SkDynamicMemoryWStream, the implementation is constant time. */ 484 bool writeToAndReset(SkDynamicMemoryWStream* dst); 485 486 /** Prepend this stream to dst, resetting this. */ 487 void prependToAndReset(SkDynamicMemoryWStream* dst); 488 489 /** Return the contents as SkData, and then reset the stream. */ 490 sk_sp<SkData> detachAsData(); 491 492 /** Reset, returning a reader stream with the current content. */ 493 std::unique_ptr<SkStreamAsset> detachAsStream(); 494 495 /** Reset the stream to its original, empty, state. */ 496 void reset(); 497 void padToAlign4(); 498 private: 499 struct Block; 500 Block* fHead = nullptr; 501 Block* fTail = nullptr; 502 size_t fBytesWrittenBeforeTail = 0; 503 504 #ifdef SK_DEBUG 505 void validate() const; 506 #else validate()507 void validate() const {} 508 #endif 509 510 // For access to the Block type. 511 friend class SkBlockMemoryStream; 512 friend class SkBlockMemoryRefCnt; 513 514 using INHERITED = SkWStream; 515 }; 516 517 #endif 518