• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
14 class SkData;
15 
16 class SkStream;
17 class SkStreamRewindable;
18 class SkStreamSeekable;
19 class SkStreamAsset;
20 class 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  */
39 class SK_API SkStream : public SkRefCnt { //TODO: remove SkRefCnt
40 public:
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      */
skip(size_t size)62     size_t skip(size_t size) {
63         return this->read(NULL, size);
64     }
65 
66     /** Returns true when all the bytes in the stream have been read.
67      *  This may return true early (when there are no more bytes to be read)
68      *  or late (after the first unsuccessful read).
69      */
70     virtual bool isAtEnd() const = 0;
71 
72     int8_t   readS8();
73     int16_t  readS16();
74     int32_t  readS32();
75 
readU8()76     uint8_t  readU8() { return (uint8_t)this->readS8(); }
readU16()77     uint16_t readU16() { return (uint16_t)this->readS16(); }
readU32()78     uint32_t readU32() { return (uint32_t)this->readS32(); }
79 
readBool()80     bool     readBool() { return this->readU8() != 0; }
81     SkScalar readScalar();
82     size_t   readPackedUInt();
83 
84     /**
85      *  Reconstitute an SkData object that was written to the stream
86      *  using SkWStream::writeData().
87      */
88     SkData* readData();
89 
90 //SkStreamRewindable
91     /** Rewinds to the beginning of the stream. Returns true if the stream is known
92      *  to be at the beginning after this call returns.
93      */
rewind()94     virtual bool rewind() { return false; }
95 
96     /** Duplicates this stream. If this cannot be done, returns NULL.
97      *  The returned stream will be positioned at the beginning of its data.
98      */
duplicate()99     virtual SkStreamRewindable* duplicate() const { return NULL; }
100 
101 //SkStreamSeekable
102     /** Returns true if this stream can report it's current position. */
hasPosition()103     virtual bool hasPosition() const { return false; }
104     /** Returns the current position in the stream. If this cannot be done, returns 0. */
getPosition()105     virtual size_t getPosition() const { return 0; }
106 
107     /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
108      *  If an attempt is made to seek past the end of the stream, the position will be set
109      *  to the end of the stream.
110      */
seek(size_t position)111     virtual bool seek(size_t position) { return false; }
112 
113     /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
114      *  If an attempt is made to move to a position outside the stream, the position will be set
115      *  to the closest point within the stream (beginning or end).
116      */
move(long offset)117     virtual bool move(long offset) { return false; }
118 
119     /** Duplicates this stream. If this cannot be done, returns NULL.
120      *  The returned stream will be positioned the same as this stream.
121      */
fork()122     virtual SkStreamSeekable* fork() const { return NULL; }
123 
124 //SkStreamAsset
125     /** Returns true if this stream can report it's total length. */
hasLength()126     virtual bool hasLength() const { return false; }
127     /** Returns the total length of the stream. If this cannot be done, returns 0. */
getLength()128     virtual size_t getLength() const { return 0; }
129 
130 //SkStreamMemory
131     /** Returns the starting address for the data. If this cannot be done, returns NULL. */
132     //TODO: replace with virtual const SkData* getData()
getMemoryBase()133     virtual const void* getMemoryBase() { return NULL; }
134 
135 private:
136     typedef SkRefCnt INHERITED;
137 };
138 
139 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
140 class SK_API SkStreamRewindable : public SkStream {
141 public:
142     virtual bool rewind() SK_OVERRIDE = 0;
143     virtual SkStreamRewindable* duplicate() const SK_OVERRIDE = 0;
144 };
145 
146 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
147 class SK_API SkStreamSeekable : public SkStreamRewindable {
148 public:
149     virtual SkStreamSeekable* duplicate() const SK_OVERRIDE = 0;
150 
hasPosition()151     virtual bool hasPosition() const SK_OVERRIDE { return true; }
152     virtual size_t getPosition() const SK_OVERRIDE = 0;
153     virtual bool seek(size_t position) SK_OVERRIDE = 0;
154     virtual bool move(long offset) SK_OVERRIDE = 0;
155     virtual SkStreamSeekable* fork() const SK_OVERRIDE = 0;
156 };
157 
158 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
159 class SK_API SkStreamAsset : public SkStreamSeekable {
160 public:
161     virtual SkStreamAsset* duplicate() const SK_OVERRIDE = 0;
162     virtual SkStreamAsset* fork() const SK_OVERRIDE = 0;
163 
hasLength()164     virtual bool hasLength() const SK_OVERRIDE { return true; }
165     virtual size_t getLength() const SK_OVERRIDE = 0;
166 };
167 
168 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
169 class SK_API SkStreamMemory : public SkStreamAsset {
170 public:
171     virtual SkStreamMemory* duplicate() const SK_OVERRIDE = 0;
172     virtual SkStreamMemory* fork() const SK_OVERRIDE = 0;
173 
174     virtual const void* getMemoryBase() SK_OVERRIDE = 0;
175 };
176 
177 class SK_API SkWStream : SkNoncopyable {
178 public:
179     SK_DECLARE_INST_COUNT_ROOT(SkWStream)
180 
181     virtual ~SkWStream();
182 
183     /** Called to write bytes to a SkWStream. Returns true on success
184         @param buffer the address of at least size bytes to be written to the stream
185         @param size The number of bytes in buffer to write to the stream
186         @return true on success
187     */
188     virtual bool write(const void* buffer, size_t size) = 0;
189     virtual void newline();
190     virtual void flush();
191 
192     // helpers
193 
194     bool    write8(U8CPU);
195     bool    write16(U16CPU);
196     bool    write32(uint32_t);
197 
198     bool    writeText(const char text[]);
199     bool    writeDecAsText(int32_t);
200     bool    writeBigDecAsText(int64_t, int minDigits = 0);
201     bool    writeHexAsText(uint32_t, int minDigits = 0);
202     bool    writeScalarAsText(SkScalar);
203 
writeBool(bool v)204     bool    writeBool(bool v) { return this->write8(v); }
205     bool    writeScalar(SkScalar);
206     bool    writePackedUInt(size_t);
207 
208     bool writeStream(SkStream* input, size_t length);
209 
210     /**
211      * Append an SkData object to the stream, such that it can be read
212      * out of the stream using SkStream::readData().
213      *
214      * Note that the encoding method used to write the SkData object
215      * to the stream may change over time.  This method DOES NOT
216      * just write the raw content of the SkData object to the stream.
217      */
218     bool writeData(const SkData*);
219 };
220 
221 ////////////////////////////////////////////////////////////////////////////////////////
222 
223 #include "SkString.h"
224 #include <stdio.h>
225 
226 struct SkFILE;
227 
228 /** A stream that wraps a C FILE* file stream. */
229 class SK_API SkFILEStream : public SkStreamAsset {
230 public:
231     SK_DECLARE_INST_COUNT(SkFILEStream)
232 
233     /** Initialize the stream by calling sk_fopen on the specified path.
234      *  This internal stream will be closed in the destructor.
235      */
236     explicit SkFILEStream(const char path[] = NULL);
237 
238     enum Ownership {
239         kCallerPasses_Ownership,
240         kCallerRetains_Ownership
241     };
242     /** Initialize the stream with an existing C file stream.
243      *  While this stream exists, it assumes exclusive access to the C file stream.
244      *  The C file stream will be closed in the destructor unless the caller specifies
245      *  kCallerRetains_Ownership.
246      */
247     explicit SkFILEStream(FILE* file, Ownership ownership = kCallerPasses_Ownership);
248 
249     virtual ~SkFILEStream();
250 
251     /** Returns true if the current path could be opened. */
isValid()252     bool isValid() const { return fFILE != NULL; }
253 
254     /** Close the current file, and open a new file with the specified path.
255      *  If path is NULL, just close the current file.
256      */
257     void setPath(const char path[]);
258 
259     virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
260     virtual bool isAtEnd() const SK_OVERRIDE;
261 
262     virtual bool rewind() SK_OVERRIDE;
263     virtual SkStreamAsset* duplicate() const SK_OVERRIDE;
264 
265     virtual size_t getPosition() const SK_OVERRIDE;
266     virtual bool seek(size_t position) SK_OVERRIDE;
267     virtual bool move(long offset) SK_OVERRIDE;
268     virtual SkStreamAsset* fork() const SK_OVERRIDE;
269 
270     virtual size_t getLength() const SK_OVERRIDE;
271 
272     virtual const void* getMemoryBase() SK_OVERRIDE;
273 
274 private:
275     SkFILE*     fFILE;
276     SkString    fName;
277     Ownership   fOwnership;
278     // fData is lazilly initialized when needed.
279     mutable SkAutoTUnref<SkData> fData;
280 
281     typedef SkStreamAsset INHERITED;
282 };
283 
284 class SK_API SkMemoryStream : public SkStreamMemory {
285 public:
286     SK_DECLARE_INST_COUNT(SkMemoryStream)
287 
288     SkMemoryStream();
289 
290     /** We allocate (and free) the memory. Write to it via getMemoryBase() */
291     SkMemoryStream(size_t length);
292 
293     /** If copyData is true, the stream makes a private copy of the data. */
294     SkMemoryStream(const void* data, size_t length, bool copyData = false);
295 
296     /** Use the specified data as the memory for this stream.
297      *  The stream will call ref() on the data (assuming it is not NULL).
298      */
299     SkMemoryStream(SkData*);
300 
301     virtual ~SkMemoryStream();
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 
315     /** Return the stream's data in a SkData.
316      *  The caller must call unref() when it is finished using the data.
317      */
318     SkData* copyToData() const;
319 
320     /**
321      *  Use the specified data as the memory for this stream.
322      *  The stream will call ref() on the data (assuming it is not NULL).
323      *  The function returns the data parameter as a convenience.
324      */
325     SkData* setData(SkData*);
326 
327     void skipToAlign4();
328     const void* getAtPos();
peek()329     size_t peek() const { return fOffset; }
330 
331     virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
332     virtual bool isAtEnd() const SK_OVERRIDE;
333 
334     virtual bool rewind() SK_OVERRIDE;
335     virtual SkMemoryStream* duplicate() const SK_OVERRIDE;
336 
337     virtual size_t getPosition() const SK_OVERRIDE;
338     virtual bool seek(size_t position) SK_OVERRIDE;
339     virtual bool move(long offset) SK_OVERRIDE;
340     virtual SkMemoryStream* fork() const SK_OVERRIDE;
341 
342     virtual size_t getLength() const SK_OVERRIDE;
343 
344     virtual const void* getMemoryBase() SK_OVERRIDE;
345 
346 private:
347     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     SK_DECLARE_INST_COUNT(SkFILEWStream)
358 
359     SkFILEWStream(const char path[]);
360     virtual ~SkFILEWStream();
361 
362     /** Returns true if the current path could be opened.
363     */
isValid()364     bool isValid() const { return fFILE != NULL; }
365 
366     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
367     virtual void flush() SK_OVERRIDE;
368 
369 private:
370     SkFILE* fFILE;
371 
372     typedef SkWStream INHERITED;
373 };
374 
375 class SkMemoryWStream : public SkWStream {
376 public:
377     SK_DECLARE_INST_COUNT(SkMemoryWStream)
378 
379     SkMemoryWStream(void* buffer, size_t size);
380     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
bytesWritten()381     size_t bytesWritten() const { return fBytesWritten; }
382 
383 private:
384     char*   fBuffer;
385     size_t  fMaxLength;
386     size_t  fBytesWritten;
387 
388     typedef SkWStream INHERITED;
389 };
390 
391 class SK_API SkDynamicMemoryWStream : public SkWStream {
392 public:
393     SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
394 
395     SkDynamicMemoryWStream();
396     virtual ~SkDynamicMemoryWStream();
397 
398     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
399     // random access write
400     // modifies stream and returns true if offset + size is less than or equal to getOffset()
401     bool write(const void* buffer, size_t offset, size_t size);
402     bool read(void* buffer, size_t offset, size_t size);
getOffset()403     size_t getOffset() const { return fBytesWritten; }
bytesWritten()404     size_t bytesWritten() const { return fBytesWritten; }
405 
406     // copy what has been written to the stream into dst
407     void copyTo(void* dst) const;
408 
409     /**
410      *  Return a copy of the data written so far. This call is responsible for
411      *  calling unref() when they are finished with the data.
412      */
413     SkData* copyToData() const;
414 
415     /** Reset, returning a reader stream with the current content. */
416     SkStreamAsset* detachAsStream();
417 
418     /** Reset the stream to its original, empty, state. */
419     void reset();
420     void padToAlign4();
421 private:
422     struct Block;
423     Block*  fHead;
424     Block*  fTail;
425     size_t  fBytesWritten;
426     mutable SkData* fCopy;  // is invalidated if we write after it is created
427 
428     void invalidateCopy();
429 
430     // For access to the Block type.
431     friend class SkBlockMemoryStream;
432     friend class SkBlockMemoryRefCnt;
433 
434     typedef SkWStream INHERITED;
435 };
436 
437 
438 class SK_API SkDebugWStream : public SkWStream {
439 public:
440     SK_DECLARE_INST_COUNT(SkDebugWStream)
441 
442     // overrides
443     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
444     virtual void newline() SK_OVERRIDE;
445 
446 private:
447     typedef SkWStream INHERITED;
448 };
449 
450 // for now
451 typedef SkFILEStream SkURLStream;
452 
453 #endif
454