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