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