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