• 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 SkNoncopyable {
40 public:
~SkStream()41     virtual ~SkStream() {}
42 
43     /**
44      *  Attempts to open the specified file, and return a stream to it (using
45      *  mmap if available). On success, the caller is responsible for deleting.
46      *  On failure, returns NULL.
47      */
48     static SkStreamAsset* NewFromFile(const char path[]);
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     /**
67      *  Attempt to peek at size bytes.
68      *  If this stream supports peeking, copy min(size, peekable bytes) into
69      *  buffer, and return the number of bytes copied.
70      *  If the stream does not support peeking, or cannot peek any bytes,
71      *  return 0 and leave buffer unchanged.
72      *  The stream is guaranteed to be in the same visible state after this
73      *  call, regardless of success or failure.
74      *  @param buffer Must not be NULL, and must be at least size bytes. Destination
75      *      to copy bytes.
76      *  @param size Number of bytes to copy.
77      *  @return The number of bytes peeked/copied.
78      */
peek(void *,size_t)79     virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
80 
81     /** Returns true when all the bytes in the stream have been read.
82      *  This may return true early (when there are no more bytes to be read)
83      *  or late (after the first unsuccessful read).
84      */
85     virtual bool isAtEnd() const = 0;
86 
87     int8_t   readS8();
88     int16_t  readS16();
89     int32_t  readS32();
90 
readU8()91     uint8_t  readU8() { return (uint8_t)this->readS8(); }
readU16()92     uint16_t readU16() { return (uint16_t)this->readS16(); }
readU32()93     uint32_t readU32() { return (uint32_t)this->readS32(); }
94 
readBool()95     bool     readBool() { return this->readU8() != 0; }
96     SkScalar readScalar();
97     size_t   readPackedUInt();
98 
99 //SkStreamRewindable
100     /** Rewinds to the beginning of the stream. Returns true if the stream is known
101      *  to be at the beginning after this call returns.
102      */
rewind()103     virtual bool rewind() { return false; }
104 
105     /** Duplicates this stream. If this cannot be done, returns NULL.
106      *  The returned stream will be positioned at the beginning of its data.
107      */
duplicate()108     virtual SkStreamRewindable* duplicate() const { return NULL; }
109 
110 //SkStreamSeekable
111     /** Returns true if this stream can report it's current position. */
hasPosition()112     virtual bool hasPosition() const { return false; }
113     /** Returns the current position in the stream. If this cannot be done, returns 0. */
getPosition()114     virtual size_t getPosition() const { return 0; }
115 
116     /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
117      *  If an attempt is made to seek past the end of the stream, the position will be set
118      *  to the end of the stream.
119      */
seek(size_t)120     virtual bool seek(size_t /*position*/) { return false; }
121 
122     /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
123      *  If an attempt is made to move to a position outside the stream, the position will be set
124      *  to the closest point within the stream (beginning or end).
125      */
move(long)126     virtual bool move(long /*offset*/) { return false; }
127 
128     /** Duplicates this stream. If this cannot be done, returns NULL.
129      *  The returned stream will be positioned the same as this stream.
130      */
fork()131     virtual SkStreamSeekable* fork() const { return NULL; }
132 
133 //SkStreamAsset
134     /** Returns true if this stream can report it's total length. */
hasLength()135     virtual bool hasLength() const { return false; }
136     /** Returns the total length of the stream. If this cannot be done, returns 0. */
getLength()137     virtual size_t getLength() const { return 0; }
138 
139 //SkStreamMemory
140     /** Returns the starting address for the data. If this cannot be done, returns NULL. */
141     //TODO: replace with virtual const SkData* getData()
getMemoryBase()142     virtual const void* getMemoryBase() { return NULL; }
143 };
144 
145 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
146 class SK_API SkStreamRewindable : public SkStream {
147 public:
148     bool rewind() override = 0;
149     SkStreamRewindable* duplicate() const override = 0;
150 };
151 
152 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
153 class SK_API SkStreamSeekable : public SkStreamRewindable {
154 public:
155     SkStreamSeekable* duplicate() const override = 0;
156 
hasPosition()157     bool hasPosition() const override { return true; }
158     size_t getPosition() const override = 0;
159     bool seek(size_t position) override = 0;
160     bool move(long offset) override = 0;
161     SkStreamSeekable* fork() const override = 0;
162 };
163 
164 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
165 class SK_API SkStreamAsset : public SkStreamSeekable {
166 public:
167     SkStreamAsset* duplicate() const override = 0;
168     SkStreamAsset* fork() const override = 0;
169 
hasLength()170     bool hasLength() const override { return true; }
171     size_t getLength() const override = 0;
172 };
173 
174 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
175 class SK_API SkStreamMemory : public SkStreamAsset {
176 public:
177     SkStreamMemory* duplicate() const override = 0;
178     SkStreamMemory* fork() const override = 0;
179 
180     const void* getMemoryBase() override = 0;
181 };
182 
183 class SK_API SkWStream : SkNoncopyable {
184 public:
185     virtual ~SkWStream();
186 
187     /** Called to write bytes to a SkWStream. Returns true on success
188         @param buffer the address of at least size bytes to be written to the stream
189         @param size The number of bytes in buffer to write to the stream
190         @return true on success
191     */
192     virtual bool write(const void* buffer, size_t size) = 0;
193     virtual void newline();
194     virtual void flush();
195 
196     virtual size_t bytesWritten() const = 0;
197 
198     // helpers
199 
200     bool    write8(U8CPU);
201     bool    write16(U16CPU);
202     bool    write32(uint32_t);
203 
204     bool    writeText(const char text[]);
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 SkAutoTUnref<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     /** Use the specified data as the memory for this stream.
293      *  The stream will call ref() on the data (assuming it is not NULL).
294      */
295     SkMemoryStream(SkData*);
296 
297     virtual ~SkMemoryStream();
298 
299     /** Resets the stream to the specified data and length,
300         just like the constructor.
301         if copyData is true, the stream makes a private copy of the data
302     */
303     virtual void setMemory(const void* data, size_t length,
304                            bool copyData = false);
305     /** Replace any memory buffer with the specified buffer. The caller
306         must have allocated data with sk_malloc or sk_realloc, since it
307         will be freed with sk_free.
308     */
309     void setMemoryOwned(const void* data, size_t length);
310 
311     /** Return the stream's data in a SkData.
312      *  The caller must call unref() when it is finished using the data.
313      */
314     SkData* copyToData() const;
315 
316     /**
317      *  Use the specified data as the memory for this stream.
318      *  The stream will call ref() on the data (assuming it is not NULL).
319      *  The function returns the data parameter as a convenience.
320      */
321     SkData* setData(SkData*);
322 
323     void skipToAlign4();
324     const void* getAtPos();
325 
326     size_t read(void* buffer, size_t size) override;
327     bool isAtEnd() const override;
328 
329     size_t peek(void* buffer, size_t size) const override;
330 
331     bool rewind() override;
332     SkMemoryStream* duplicate() const override;
333 
334     size_t getPosition() const override;
335     bool seek(size_t position) override;
336     bool move(long offset) override;
337     SkMemoryStream* fork() const override;
338 
339     size_t getLength() const override;
340 
341     const void* getMemoryBase() override;
342 
343 private:
344     SkData* fData;
345     size_t  fOffset;
346 
347     typedef SkStreamMemory INHERITED;
348 };
349 
350 /////////////////////////////////////////////////////////////////////////////////////////////
351 
352 class SK_API SkFILEWStream : public SkWStream {
353 public:
354     SkFILEWStream(const char path[]);
355     virtual ~SkFILEWStream();
356 
357     /** Returns true if the current path could be opened.
358     */
isValid()359     bool isValid() const { return fFILE != NULL; }
360 
361     bool write(const void* buffer, size_t size) override;
362     void flush() override;
363     void fsync();
364     size_t bytesWritten() const override;
365 
366 private:
367     FILE* fFILE;
368 
369     typedef SkWStream INHERITED;
370 };
371 
372 class SkMemoryWStream : public SkWStream {
373 public:
374     SkMemoryWStream(void* buffer, size_t size);
375     bool write(const void* buffer, size_t size) override;
bytesWritten()376     size_t bytesWritten() const override { return fBytesWritten; }
377 
378 private:
379     char*   fBuffer;
380     size_t  fMaxLength;
381     size_t  fBytesWritten;
382 
383     typedef SkWStream INHERITED;
384 };
385 
386 class SK_API SkDynamicMemoryWStream : public SkWStream {
387 public:
388     SkDynamicMemoryWStream();
389     virtual ~SkDynamicMemoryWStream();
390 
391     bool write(const void* buffer, size_t size) override;
bytesWritten()392     size_t bytesWritten() const override { return fBytesWritten; }
393     // random access write
394     // modifies stream and returns true if offset + size is less than or equal to getOffset()
395     bool write(const void* buffer, size_t offset, size_t size);
396     bool read(void* buffer, size_t offset, size_t size);
getOffset()397     size_t getOffset() const { return fBytesWritten; }
398 
399     // copy what has been written to the stream into dst
400     void copyTo(void* dst) const;
401     void writeToStream(SkWStream* dst) const;
402 
403     /**
404      *  Return a copy of the data written so far. This call is responsible for
405      *  calling unref() when they are finished with the data.
406      */
407     SkData* copyToData() const;
408 
409     /** Reset, returning a reader stream with the current content. */
410     SkStreamAsset* detachAsStream();
411 
412     /** Reset the stream to its original, empty, state. */
413     void reset();
414     void padToAlign4();
415 private:
416     struct Block;
417     Block*  fHead;
418     Block*  fTail;
419     size_t  fBytesWritten;
420     mutable SkData* fCopy;  // is invalidated if we write after it is created
421 
422     void invalidateCopy();
423 
424     // For access to the Block type.
425     friend class SkBlockMemoryStream;
426     friend class SkBlockMemoryRefCnt;
427 
428     typedef SkWStream INHERITED;
429 };
430 
431 
432 class SK_API SkDebugWStream : public SkWStream {
433 public:
SkDebugWStream()434     SkDebugWStream() : fBytesWritten(0) {}
435 
436     // overrides
437     bool write(const void* buffer, size_t size) override;
438     void newline() override;
bytesWritten()439     size_t bytesWritten() const override { return fBytesWritten; }
440 
441 private:
442     size_t fBytesWritten;
443     typedef SkWStream INHERITED;
444 };
445 
446 // for now
447 typedef SkFILEStream SkURLStream;
448 
449 #endif
450