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