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