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