SkStream.h revision 070235e746c46f6c0a26ed6c23c832c532b974e9
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#ifndef SkStream_DEFINED 11#define SkStream_DEFINED 12 13#include "SkRefCnt.h" 14#include "SkScalar.h" 15 16class SkData; 17 18class SK_API SkStream : public SkRefCnt { 19public: 20 SK_DECLARE_INST_COUNT(SkStream) 21 22 /** Called to rewind to the beginning of the stream. If this cannot be 23 done, return false. 24 */ 25 virtual bool rewind() = 0; 26 /** If this stream represents a file, this method returns the file's name. 27 If it does not, it returns NULL (the default behavior). 28 */ 29 virtual const char* getFileName(); 30 /** Called to read or skip size number of bytes. 31 If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped. 32 If buffer is NULL and size == 0, return the total length of the stream. 33 If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied. 34 @param buffer If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer 35 @param size The number of bytes to skip or copy 36 @return bytes read on success 37 */ 38 virtual size_t read(void* buffer, size_t size) = 0; 39 40 /** Return the total length of the stream. 41 */ 42 size_t getLength() { return this->read(NULL, 0); } 43 44 /** Skip the specified number of bytes, returning the actual number 45 of bytes that could be skipped. 46 */ 47 size_t skip(size_t bytes); 48 49 /** If the stream is backed by RAM, this method returns the starting 50 address for the data. If not (i.e. it is backed by a file or other 51 structure), this method returns NULL. 52 The default implementation returns NULL. 53 */ 54 virtual const void* getMemoryBase(); 55 56 int8_t readS8(); 57 int16_t readS16(); 58 int32_t readS32(); 59 60 uint8_t readU8() { return (uint8_t)this->readS8(); } 61 uint16_t readU16() { return (uint16_t)this->readS16(); } 62 uint32_t readU32() { return (uint32_t)this->readS32(); } 63 64 bool readBool() { return this->readU8() != 0; } 65 SkScalar readScalar(); 66 size_t readPackedUInt(); 67 68 /** 69 * Create a new SkData from the stream contents. This balances the call 70 * SkWStream::writeData(). 71 */ 72 SkData* readData(); 73 74private: 75 typedef SkRefCnt INHERITED; 76}; 77 78class SK_API SkWStream : SkNoncopyable { 79public: 80 SK_DECLARE_INST_COUNT_ROOT(SkWStream) 81 82 virtual ~SkWStream(); 83 84 /** Called to write bytes to a SkWStream. Returns true on success 85 @param buffer the address of at least size bytes to be written to the stream 86 @param size The number of bytes in buffer to write to the stream 87 @return true on success 88 */ 89 virtual bool write(const void* buffer, size_t size) = 0; 90 virtual void newline(); 91 virtual void flush(); 92 93 // helpers 94 95 bool write8(U8CPU); 96 bool write16(U16CPU); 97 bool write32(uint32_t); 98 99 bool writeText(const char text[]); 100 bool writeDecAsText(int32_t); 101 bool writeBigDecAsText(int64_t, int minDigits = 0); 102 bool writeHexAsText(uint32_t, int minDigits = 0); 103 bool writeScalarAsText(SkScalar); 104 105 bool writeBool(bool v) { return this->write8(v); } 106 bool writeScalar(SkScalar); 107 bool writePackedUInt(size_t); 108 109 bool writeStream(SkStream* input, size_t length); 110 111 bool writeData(const SkData*); 112}; 113 114//////////////////////////////////////////////////////////////////////////////////////// 115 116#include "SkString.h" 117 118struct SkFILE; 119 120/** A stream that reads from a FILE*, which is opened in the constructor and 121 closed in the destructor 122 */ 123class SK_API SkFILEStream : public SkStream { 124public: 125 SK_DECLARE_INST_COUNT(SkFILEStream) 126 127 /** Initialize the stream by calling fopen on the specified path. Will be 128 closed in the destructor. 129 */ 130 explicit SkFILEStream(const char path[] = NULL); 131 virtual ~SkFILEStream(); 132 133 /** Returns true if the current path could be opened. 134 */ 135 bool isValid() const { return fFILE != NULL; } 136 /** Close the current file, and open a new file with the specified 137 path. If path is NULL, just close the current file. 138 */ 139 void setPath(const char path[]); 140 141 virtual bool rewind() SK_OVERRIDE; 142 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; 143 virtual const char* getFileName() SK_OVERRIDE; 144 145private: 146 SkFILE* fFILE; 147 SkString fName; 148 149 typedef SkStream INHERITED; 150}; 151 152/** A stream that reads from a file descriptor 153 */ 154class SK_API SkFDStream : public SkStream { 155public: 156 SK_DECLARE_INST_COUNT(SkFDStream) 157 158 /** Initialize the stream with a dup() of the specified file descriptor. 159 If closeWhenDone is true, then the descriptor will be closed in the 160 destructor. 161 */ 162 SkFDStream(int fileDesc, bool closeWhenDone); 163 virtual ~SkFDStream(); 164 165 /** Returns true if the current path could be opened. 166 */ 167 bool isValid() const { return fFD >= 0; } 168 169 virtual bool rewind() SK_OVERRIDE; 170 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; 171 virtual const char* getFileName() SK_OVERRIDE { return NULL; } 172 173private: 174 int fFD; 175 bool fCloseWhenDone; 176 177 typedef SkStream INHERITED; 178}; 179 180class SK_API SkMemoryStream : public SkStream { 181public: 182 SK_DECLARE_INST_COUNT(SkMemoryStream) 183 184 SkMemoryStream(); 185 /** We allocate (and free) the memory. Write to it via getMemoryBase() 186 */ 187 SkMemoryStream(size_t length); 188 /** if copyData is true, the stream makes a private copy of the data 189 */ 190 SkMemoryStream(const void* data, size_t length, bool copyData = false); 191 192 /** 193 * Use the specified data as the memory for this stream. The stream will 194 * call ref() on the data (assuming it is not null). 195 */ 196 SkMemoryStream(SkData*); 197 198 virtual ~SkMemoryStream(); 199 200 /** Resets the stream to the specified data and length, 201 just like the constructor. 202 if copyData is true, the stream makes a private copy of the data 203 */ 204 virtual void setMemory(const void* data, size_t length, 205 bool copyData = false); 206 /** Replace any memory buffer with the specified buffer. The caller 207 must have allocated data with sk_malloc or sk_realloc, since it 208 will be freed with sk_free. 209 */ 210 void setMemoryOwned(const void* data, size_t length); 211 212 /** 213 * Return the stream's data in a SkData. The caller must call unref() when 214 * it is finished using the data. 215 */ 216 SkData* copyToData() const; 217 218 /** 219 * Use the specified data as the memory for this stream. The stream will 220 * call ref() on the data (assuming it is not null). The function returns 221 * the data parameter as a convenience. 222 */ 223 SkData* setData(SkData*); 224 225 void skipToAlign4(); 226 virtual bool rewind() SK_OVERRIDE; 227 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; 228 virtual const void* getMemoryBase() SK_OVERRIDE; 229 const void* getAtPos(); 230 size_t seek(size_t offset); 231 size_t peek() const { return fOffset; } 232 233private: 234 SkData* fData; 235 size_t fOffset; 236 237 typedef SkStream INHERITED; 238}; 239 240/** \class SkBufferStream 241 This is a wrapper class that adds buffering to another stream. 242 The caller can provide the buffer, or ask SkBufferStream to allocated/free 243 it automatically. 244*/ 245class SK_API SkBufferStream : public SkStream { 246public: 247 SK_DECLARE_INST_COUNT(SkBufferStream) 248 249 /** Provide the stream to be buffered (proxy), and the size of the buffer that 250 should be used. This will be allocated and freed automatically. If bufferSize is 0, 251 a default buffer size will be used. 252 The proxy stream is referenced, and will be unreferenced in when the 253 bufferstream is destroyed. 254 */ 255 SkBufferStream(SkStream* proxy, size_t bufferSize = 0); 256 /** Provide the stream to be buffered (proxy), and a buffer and size to be used. 257 This buffer is owned by the caller, and must be at least bufferSize bytes big. 258 Passing NULL for buffer will cause the buffer to be allocated/freed automatically. 259 If buffer is not NULL, it is an error for bufferSize to be 0. 260 The proxy stream is referenced, and will be unreferenced in when the 261 bufferstream is destroyed. 262 */ 263 SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize); 264 virtual ~SkBufferStream(); 265 266 virtual bool rewind() SK_OVERRIDE; 267 virtual const char* getFileName() SK_OVERRIDE; 268 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; 269 virtual const void* getMemoryBase() SK_OVERRIDE; 270 271private: 272 enum { 273 kDefaultBufferSize = 128 274 }; 275 // illegal 276 SkBufferStream(const SkBufferStream&); 277 SkBufferStream& operator=(const SkBufferStream&); 278 279 SkStream* fProxy; 280 char* fBuffer; 281 size_t fOrigBufferSize, fBufferSize, fBufferOffset; 282 bool fWeOwnTheBuffer; 283 284 void init(void*, size_t); 285 286 typedef SkStream INHERITED; 287}; 288 289///////////////////////////////////////////////////////////////////////////////////////////// 290 291class SK_API SkFILEWStream : public SkWStream { 292public: 293 SK_DECLARE_INST_COUNT(SkFILEWStream) 294 295 SkFILEWStream(const char path[]); 296 virtual ~SkFILEWStream(); 297 298 /** Returns true if the current path could be opened. 299 */ 300 bool isValid() const { return fFILE != NULL; } 301 302 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; 303 virtual void flush() SK_OVERRIDE; 304 305private: 306 SkFILE* fFILE; 307 308 typedef SkWStream INHERITED; 309}; 310 311class SkMemoryWStream : public SkWStream { 312public: 313 SK_DECLARE_INST_COUNT(SkMemoryWStream) 314 315 SkMemoryWStream(void* buffer, size_t size); 316 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; 317 size_t bytesWritten() const { return fBytesWritten; } 318 319private: 320 char* fBuffer; 321 size_t fMaxLength; 322 size_t fBytesWritten; 323 324 typedef SkWStream INHERITED; 325}; 326 327class SK_API SkDynamicMemoryWStream : public SkWStream { 328public: 329 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream) 330 331 SkDynamicMemoryWStream(); 332 virtual ~SkDynamicMemoryWStream(); 333 334 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; 335 // random access write 336 // modifies stream and returns true if offset + size is less than or equal to getOffset() 337 bool write(const void* buffer, size_t offset, size_t size); 338 bool read(void* buffer, size_t offset, size_t size); 339 size_t getOffset() const { return fBytesWritten; } 340 size_t bytesWritten() const { return fBytesWritten; } 341 342 // copy what has been written to the stream into dst 343 void copyTo(void* dst) const; 344 345 /** 346 * Return a copy of the data written so far. This call is responsible for 347 * calling unref() when they are finished with the data. 348 */ 349 SkData* copyToData() const; 350 351 // reset the stream to its original state 352 void reset(); 353 void padToAlign4(); 354private: 355 struct Block; 356 Block* fHead; 357 Block* fTail; 358 size_t fBytesWritten; 359 mutable SkData* fCopy; // is invalidated if we write after it is created 360 361 void invalidateCopy(); 362 363 typedef SkWStream INHERITED; 364}; 365 366 367class SK_API SkDebugWStream : public SkWStream { 368public: 369 SK_DECLARE_INST_COUNT(SkDebugWStream) 370 371 // overrides 372 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; 373 virtual void newline() SK_OVERRIDE; 374 375private: 376 typedef SkWStream INHERITED; 377}; 378 379// for now 380typedef SkFILEStream SkURLStream; 381 382#endif 383