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: ~SkStream()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 */ skip(size_t size)61 size_t skip(size_t size) { 62 return this->read(NULL, 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 */ peek(void *,size_t)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 readU8()90 uint8_t readU8() { return (uint8_t)this->readS8(); } readU16()91 uint16_t readU16() { return (uint16_t)this->readS16(); } readU32()92 uint32_t readU32() { return (uint32_t)this->readS32(); } 93 readBool()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 */ 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 virtual SkStreamRewindable* duplicate() const { return NULL; } 108 109 //SkStreamSeekable 110 /** Returns true if this stream can report it's current position. */ hasPosition()111 virtual bool hasPosition() const { return false; } 112 /** Returns the current position in the stream. If this cannot be done, returns 0. */ getPosition()113 virtual size_t getPosition() const { return 0; } 114 115 /** Seeks to an absolute position in the stream. If this cannot be done, returns false. 116 * If an attempt is made to seek past the end of the stream, the position will be set 117 * to the end of the stream. 118 */ seek(size_t)119 virtual bool seek(size_t /*position*/) { return false; } 120 121 /** Seeks to an relative offset in the stream. If this cannot be done, returns false. 122 * If an attempt is made to move to a position outside the stream, the position will be set 123 * to the closest point within the stream (beginning or end). 124 */ move(long)125 virtual bool move(long /*offset*/) { return false; } 126 127 /** Duplicates this stream. If this cannot be done, returns NULL. 128 * The returned stream will be positioned the same as this stream. 129 */ fork()130 virtual SkStreamSeekable* fork() const { return NULL; } 131 132 //SkStreamAsset 133 /** Returns true if this stream can report it's total length. */ hasLength()134 virtual bool hasLength() const { return false; } 135 /** Returns the total length of the stream. If this cannot be done, returns 0. */ getLength()136 virtual size_t getLength() const { return 0; } 137 138 //SkStreamMemory 139 /** Returns the starting address for the data. If this cannot be done, returns NULL. */ 140 //TODO: replace with virtual const SkData* getData() getMemoryBase()141 virtual const void* getMemoryBase() { return NULL; } 142 }; 143 144 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */ 145 class SK_API SkStreamRewindable : public SkStream { 146 public: 147 bool rewind() override = 0; 148 SkStreamRewindable* duplicate() const override = 0; 149 }; 150 151 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */ 152 class SK_API SkStreamSeekable : public SkStreamRewindable { 153 public: 154 SkStreamSeekable* duplicate() const override = 0; 155 hasPosition()156 bool hasPosition() const override { return true; } 157 size_t getPosition() const override = 0; 158 bool seek(size_t position) override = 0; 159 bool move(long offset) override = 0; 160 SkStreamSeekable* fork() const override = 0; 161 }; 162 163 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */ 164 class SK_API SkStreamAsset : public SkStreamSeekable { 165 public: 166 SkStreamAsset* duplicate() const override = 0; 167 SkStreamAsset* fork() const override = 0; 168 hasLength()169 bool hasLength() const override { return true; } 170 size_t getLength() const override = 0; 171 }; 172 173 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */ 174 class SK_API SkStreamMemory : public SkStreamAsset { 175 public: 176 SkStreamMemory* duplicate() const override = 0; 177 SkStreamMemory* fork() const override = 0; 178 179 const void* getMemoryBase() override = 0; 180 }; 181 182 class SK_API SkWStream : SkNoncopyable { 183 public: 184 virtual ~SkWStream(); 185 186 /** Called to write bytes to a SkWStream. Returns true on success 187 @param buffer the address of at least size bytes to be written to the stream 188 @param size The number of bytes in buffer to write to the stream 189 @return true on success 190 */ 191 virtual bool write(const void* buffer, size_t size) = 0; 192 virtual void flush(); 193 194 virtual size_t bytesWritten() const = 0; 195 196 // helpers 197 write8(U8CPU value)198 bool write8(U8CPU value) { 199 uint8_t v = SkToU8(value); 200 return this->write(&v, 1); 201 } write16(U16CPU value)202 bool write16(U16CPU value) { 203 uint16_t v = SkToU16(value); 204 return this->write(&v, 2); 205 } write32(uint32_t v)206 bool write32(uint32_t v) { 207 return this->write(&v, 4); 208 } 209 writeText(const char text[])210 bool writeText(const char text[]) { 211 SkASSERT(text); 212 return this->write(text, strlen(text)); 213 } 214 newline()215 bool newline() { return this->write("\n", strlen("\n")); } 216 217 bool writeDecAsText(int32_t); 218 bool writeBigDecAsText(int64_t, int minDigits = 0); 219 bool writeHexAsText(uint32_t, int minDigits = 0); 220 bool writeScalarAsText(SkScalar); 221 writeBool(bool v)222 bool writeBool(bool v) { return this->write8(v); } 223 bool writeScalar(SkScalar); 224 bool writePackedUInt(size_t); 225 226 bool writeStream(SkStream* input, size_t length); 227 228 /** 229 * This returns the number of bytes in the stream required to store 230 * 'value'. 231 */ 232 static int SizeOfPackedUInt(size_t value); 233 }; 234 235 class SK_API SkNullWStream : public SkWStream { 236 public: SkNullWStream()237 SkNullWStream() : fBytesWritten(0) {} 238 write(const void *,size_t n)239 bool write(const void*, size_t n) override { fBytesWritten += n; return true; } flush()240 void flush() override {} bytesWritten()241 size_t bytesWritten() const override { return fBytesWritten; } 242 243 private: 244 size_t fBytesWritten; 245 }; 246 247 //////////////////////////////////////////////////////////////////////////////////////// 248 249 #include <stdio.h> 250 251 /** A stream that wraps a C FILE* file stream. */ 252 class SK_API SkFILEStream : public SkStreamAsset { 253 public: 254 /** Initialize the stream by calling sk_fopen on the specified path. 255 * This internal stream will be closed in the destructor. 256 */ 257 explicit SkFILEStream(const char path[] = nullptr); 258 259 /** Initialize the stream with an existing C file stream. 260 * The C file stream will be closed in the destructor. 261 */ 262 explicit SkFILEStream(FILE* file); 263 264 ~SkFILEStream() override; 265 266 /** Returns true if the current path could be opened. */ isValid()267 bool isValid() const { return fFILE != nullptr; } 268 269 /** Close this SkFILEStream. */ 270 void close(); 271 272 size_t read(void* buffer, size_t size) override; 273 bool isAtEnd() const override; 274 275 bool rewind() override; 276 SkStreamAsset* duplicate() const override; 277 278 size_t getPosition() const override; 279 bool seek(size_t position) override; 280 bool move(long offset) override; 281 SkStreamAsset* fork() const override; 282 283 size_t getLength() const override; 284 285 private: 286 explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset); 287 explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset, size_t originalOffset); 288 289 std::shared_ptr<FILE> fFILE; 290 // My own council will I keep on sizes and offsets. 291 size_t fSize; 292 size_t fOffset; 293 size_t fOriginalOffset; 294 295 typedef SkStreamAsset INHERITED; 296 }; 297 298 class SK_API SkMemoryStream : public SkStreamMemory { 299 public: 300 SkMemoryStream(); 301 302 /** We allocate (and free) the memory. Write to it via getMemoryBase() */ 303 SkMemoryStream(size_t length); 304 305 /** If copyData is true, the stream makes a private copy of the data. */ 306 SkMemoryStream(const void* data, size_t length, bool copyData = false); 307 308 /** Creates the stream to read from the specified data */ 309 SkMemoryStream(sk_sp<SkData>); 310 311 /** Resets the stream to the specified data and length, 312 just like the constructor. 313 if copyData is true, the stream makes a private copy of the data 314 */ 315 virtual void setMemory(const void* data, size_t length, 316 bool copyData = false); 317 /** Replace any memory buffer with the specified buffer. The caller 318 must have allocated data with sk_malloc or sk_realloc, since it 319 will be freed with sk_free. 320 */ 321 void setMemoryOwned(const void* data, size_t length); 322 asData()323 sk_sp<SkData> asData() const { return fData; } 324 void setData(sk_sp<SkData>); 325 326 void skipToAlign4(); 327 const void* getAtPos(); 328 329 size_t read(void* buffer, size_t size) override; 330 bool isAtEnd() const override; 331 332 size_t peek(void* buffer, size_t size) const override; 333 334 bool rewind() override; 335 SkMemoryStream* duplicate() const override; 336 337 size_t getPosition() const override; 338 bool seek(size_t position) override; 339 bool move(long offset) override; 340 SkMemoryStream* fork() const override; 341 342 size_t getLength() const override; 343 344 const void* getMemoryBase() override; 345 346 private: 347 sk_sp<SkData> fData; 348 size_t fOffset; 349 350 typedef SkStreamMemory INHERITED; 351 }; 352 353 ///////////////////////////////////////////////////////////////////////////////////////////// 354 355 class SK_API SkFILEWStream : public SkWStream { 356 public: 357 SkFILEWStream(const char path[]); 358 ~SkFILEWStream() override; 359 360 /** Returns true if the current path could be opened. 361 */ isValid()362 bool isValid() const { return fFILE != NULL; } 363 364 bool write(const void* buffer, size_t size) override; 365 void flush() override; 366 void fsync(); 367 size_t bytesWritten() const override; 368 369 private: 370 FILE* fFILE; 371 372 typedef SkWStream INHERITED; 373 }; 374 375 class SK_API SkDynamicMemoryWStream : public SkWStream { 376 public: 377 SkDynamicMemoryWStream(); 378 ~SkDynamicMemoryWStream() override; 379 380 bool write(const void* buffer, size_t size) override; 381 size_t bytesWritten() const override; 382 383 bool read(void* buffer, size_t offset, size_t size); 384 385 /** More efficient version of read(dst, 0, bytesWritten()). */ 386 void copyTo(void* dst) const; 387 bool writeToStream(SkWStream* dst) const; 388 389 /** Equivalent to copyTo() followed by reset(), but may save memory use. */ 390 void copyToAndReset(void* dst); 391 392 /** Equivalent to writeToStream() followed by reset(), but may save memory use. */ 393 bool writeToAndReset(SkWStream* dst); 394 395 /** Return the contents as SkData, and then reset the stream. */ 396 sk_sp<SkData> detachAsData(); 397 398 /** Reset, returning a reader stream with the current content. */ 399 std::unique_ptr<SkStreamAsset> detachAsStream(); 400 401 /** Reset the stream to its original, empty, state. */ 402 void reset(); 403 void padToAlign4(); 404 private: 405 struct Block; 406 Block* fHead; 407 Block* fTail; 408 size_t fBytesWrittenBeforeTail; 409 410 #ifdef SK_DEBUG 411 void validate() const; 412 #else validate()413 void validate() const {} 414 #endif 415 416 // For access to the Block type. 417 friend class SkBlockMemoryStream; 418 friend class SkBlockMemoryRefCnt; 419 420 typedef SkWStream INHERITED; 421 }; 422 423 #endif 424