SkStream.h revision fbfcd5602128ec010c82cb733c9cdc0a3254f9f3
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 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 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 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 virtual ~SkMemoryStream(); 192 193 /** Resets the stream to the specified data and length, 194 just like the constructor. 195 if copyData is true, the stream makes a private copy of the data 196 */ 197 virtual void setMemory(const void* data, size_t length, 198 bool copyData = false); 199 /** Replace any memory buffer with the specified buffer. The caller 200 must have allocated data with sk_malloc or sk_realloc, since it 201 will be freed with sk_free. 202 */ 203 void setMemoryOwned(const void* data, size_t length); 204 205 /** 206 * Return the stream's data in a SkData. The caller must call unref() when 207 * it is finished using the data. 208 */ 209 SkData* copyToData() const; 210 211 /** 212 * Use the specified data as the memory for this stream. The stream will 213 * call ref() on the data (assuming it is not null). The function returns 214 * the data parameter as a convenience. 215 */ 216 SkData* setData(SkData*); 217 218 void skipToAlign4(); 219 virtual bool rewind() SK_OVERRIDE; 220 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; 221 virtual const void* getMemoryBase() SK_OVERRIDE; 222 const void* getAtPos(); 223 size_t seek(size_t offset); 224 size_t peek() const { return fOffset; } 225 226private: 227 SkData* fData; 228 size_t fOffset; 229 230 typedef SkStream INHERITED; 231}; 232 233/** \class SkBufferStream 234 This is a wrapper class that adds buffering to another stream. 235 The caller can provide the buffer, or ask SkBufferStream to allocated/free 236 it automatically. 237*/ 238class SkBufferStream : public SkStream { 239public: 240 SK_DECLARE_INST_COUNT(SkBufferStream) 241 242 /** Provide the stream to be buffered (proxy), and the size of the buffer that 243 should be used. This will be allocated and freed automatically. If bufferSize is 0, 244 a default buffer size will be used. 245 The proxy stream is referenced, and will be unreferenced in when the 246 bufferstream is destroyed. 247 */ 248 SkBufferStream(SkStream* proxy, size_t bufferSize = 0); 249 /** Provide the stream to be buffered (proxy), and a buffer and size to be used. 250 This buffer is owned by the caller, and must be at least bufferSize bytes big. 251 Passing NULL for buffer will cause the buffer to be allocated/freed automatically. 252 If buffer is not NULL, it is an error for bufferSize to be 0. 253 The proxy stream is referenced, and will be unreferenced in when the 254 bufferstream is destroyed. 255 */ 256 SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize); 257 virtual ~SkBufferStream(); 258 259 virtual bool rewind() SK_OVERRIDE; 260 virtual const char* getFileName() SK_OVERRIDE; 261 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; 262 virtual const void* getMemoryBase() SK_OVERRIDE; 263 264private: 265 enum { 266 kDefaultBufferSize = 128 267 }; 268 // illegal 269 SkBufferStream(const SkBufferStream&); 270 SkBufferStream& operator=(const SkBufferStream&); 271 272 SkStream* fProxy; 273 char* fBuffer; 274 size_t fOrigBufferSize, fBufferSize, fBufferOffset; 275 bool fWeOwnTheBuffer; 276 277 void init(void*, size_t); 278 279 typedef SkStream INHERITED; 280}; 281 282///////////////////////////////////////////////////////////////////////////////////////////// 283 284class SK_API SkFILEWStream : public SkWStream { 285public: 286 SK_DECLARE_INST_COUNT(SkFILEWStream) 287 288 SkFILEWStream(const char path[]); 289 virtual ~SkFILEWStream(); 290 291 /** Returns true if the current path could be opened. 292 */ 293 bool isValid() const { return fFILE != NULL; } 294 295 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; 296 virtual void flush() SK_OVERRIDE; 297 298private: 299 SkFILE* fFILE; 300 301 typedef SkWStream INHERITED; 302}; 303 304class SkMemoryWStream : public SkWStream { 305public: 306 SK_DECLARE_INST_COUNT(SkMemoryWStream) 307 308 SkMemoryWStream(void* buffer, size_t size); 309 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; 310 size_t bytesWritten() const { return fBytesWritten; } 311 312private: 313 char* fBuffer; 314 size_t fMaxLength; 315 size_t fBytesWritten; 316 317 typedef SkWStream INHERITED; 318}; 319 320class SK_API SkDynamicMemoryWStream : public SkWStream { 321public: 322 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream) 323 324 SkDynamicMemoryWStream(); 325 virtual ~SkDynamicMemoryWStream(); 326 327 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; 328 // random access write 329 // modifies stream and returns true if offset + size is less than or equal to getOffset() 330 bool write(const void* buffer, size_t offset, size_t size); 331 bool read(void* buffer, size_t offset, size_t size); 332 size_t getOffset() const { return fBytesWritten; } 333 size_t bytesWritten() const { return fBytesWritten; } 334 335 // copy what has been written to the stream into dst 336 void copyTo(void* dst) const; 337 338 /** 339 * Return a copy of the data written so far. This call is responsible for 340 * calling unref() when they are finished with the data. 341 */ 342 SkData* copyToData() const; 343 344 // reset the stream to its original state 345 void reset(); 346 void padToAlign4(); 347private: 348 struct Block; 349 Block* fHead; 350 Block* fTail; 351 size_t fBytesWritten; 352 mutable SkData* fCopy; // is invalidated if we write after it is created 353 354 void invalidateCopy(); 355 356 typedef SkWStream INHERITED; 357}; 358 359 360class SkDebugWStream : public SkWStream { 361public: 362 SK_DECLARE_INST_COUNT(SkDebugWStream) 363 364 // overrides 365 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; 366 virtual void newline() SK_OVERRIDE; 367 368private: 369 typedef SkWStream INHERITED; 370}; 371 372// for now 373typedef SkFILEStream SkURLStream; 374 375#endif 376