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 "SkData.h"
12 #include "SkRefCnt.h"
13 #include "SkScalar.h"
14 
15 class SkStream;
16 class SkStreamRewindable;
17 class SkStreamSeekable;
18 class SkStreamAsset;
19 class SkStreamMemory;
20 
21 /**
22  *  SkStream -- abstraction for a source of bytes. Subclasses can be backed by
23  *  memory, or a file, or something else.
24  *
25  *  NOTE:
26  *
27  *  Classic "streams" APIs are sort of async, in that on a request for N
28  *  bytes, they may return fewer than N bytes on a given call, in which case
29  *  the caller can "try again" to get more bytes, eventually (modulo an error)
30  *  receiving their total N bytes.
31  *
32  *  Skia streams behave differently. They are effectively synchronous, and will
33  *  always return all N bytes of the request if possible. If they return fewer
34  *  (the read() call returns the number of bytes read) then that means there is
35  *  no more data (at EOF or hit an error). The caller should *not* call again
36  *  in hopes of fulfilling more of the request.
37  */
38 class SK_API SkStream : public SkNoncopyable {
39 public:
~SkStream()40     virtual ~SkStream() {}
41 
42     /**
43      *  Attempts to open the specified file as a stream, returns nullptr on failure.
44      */
45     static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]);
46 
47     /** Reads or skips size number of bytes.
48      *  If buffer == NULL, skip size bytes, return how many were skipped.
49      *  If buffer != NULL, copy size bytes into buffer, return how many were copied.
50      *  @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
51      *  @param size the number of bytes to skip or copy
52      *  @return the number of bytes actually read.
53      */
54     virtual size_t read(void* buffer, size_t size) = 0;
55 
56     /** Skip size number of bytes.
57      *  @return the actual number bytes that could be skipped.
58      */
skip(size_t size)59     size_t skip(size_t size) {
60         return this->read(NULL, size);
61     }
62 
63     /**
64      *  Attempt to peek at size bytes.
65      *  If this stream supports peeking, copy min(size, peekable bytes) into
66      *  buffer, and return the number of bytes copied.
67      *  If the stream does not support peeking, or cannot peek any bytes,
68      *  return 0 and leave buffer unchanged.
69      *  The stream is guaranteed to be in the same visible state after this
70      *  call, regardless of success or failure.
71      *  @param buffer Must not be NULL, and must be at least size bytes. Destination
72      *      to copy bytes.
73      *  @param size Number of bytes to copy.
74      *  @return The number of bytes peeked/copied.
75      */
peek(void *,size_t)76     virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
77 
78     /** Returns true when all the bytes in the stream have been read.
79      *  This may return true early (when there are no more bytes to be read)
80      *  or late (after the first unsuccessful read).
81      */
82     virtual bool isAtEnd() const = 0;
83 
84     int8_t   readS8();
85     int16_t  readS16();
86     int32_t  readS32();
87 
readU8()88     uint8_t  readU8() { return (uint8_t)this->readS8(); }
readU16()89     uint16_t readU16() { return (uint16_t)this->readS16(); }
readU32()90     uint32_t readU32() { return (uint32_t)this->readS32(); }
91 
readBool()92     bool     readBool() { return this->readU8() != 0; }
93     SkScalar readScalar();
94     size_t   readPackedUInt();
95 
96 //SkStreamRewindable
97     /** Rewinds to the beginning of the stream. Returns true if the stream is known
98      *  to be at the beginning after this call returns.
99      */
rewind()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      */
duplicate()105     virtual SkStreamRewindable* duplicate() const { return NULL; }
106 
107 //SkStreamSeekable
108     /** Returns true if this stream can report it's current position. */
hasPosition()109     virtual bool hasPosition() const { return false; }
110     /** Returns the current position in the stream. If this cannot be done, returns 0. */
getPosition()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      */
seek(size_t)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      */
move(long)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      */
fork()128     virtual SkStreamSeekable* fork() const { return NULL; }
129 
130 //SkStreamAsset
131     /** Returns true if this stream can report it's total length. */
hasLength()132     virtual bool hasLength() const { return false; }
133     /** Returns the total length of the stream. If this cannot be done, returns 0. */
getLength()134     virtual size_t getLength() const { return 0; }
135 
136 //SkStreamMemory
137     /** Returns the starting address for the data. If this cannot be done, returns NULL. */
138     //TODO: replace with virtual const SkData* getData()
getMemoryBase()139     virtual const void* getMemoryBase() { return NULL; }
140 };
141 
142 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
143 class SK_API SkStreamRewindable : public SkStream {
144 public:
145     bool rewind() override = 0;
146     SkStreamRewindable* duplicate() const override = 0;
147 };
148 
149 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
150 class SK_API SkStreamSeekable : public SkStreamRewindable {
151 public:
152     SkStreamSeekable* duplicate() const override = 0;
153 
hasPosition()154     bool hasPosition() const override { return true; }
155     size_t getPosition() const override = 0;
156     bool seek(size_t position) override = 0;
157     bool move(long offset) override = 0;
158     SkStreamSeekable* fork() const override = 0;
159 };
160 
161 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
162 class SK_API SkStreamAsset : public SkStreamSeekable {
163 public:
164     SkStreamAsset* duplicate() const override = 0;
165     SkStreamAsset* fork() const override = 0;
166 
hasLength()167     bool hasLength() const override { return true; }
168     size_t getLength() const override = 0;
169 };
170 
171 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
172 class SK_API SkStreamMemory : public SkStreamAsset {
173 public:
174     SkStreamMemory* duplicate() const override = 0;
175     SkStreamMemory* fork() const override = 0;
176 
177     const void* getMemoryBase() override = 0;
178 };
179 
180 class SK_API SkWStream : SkNoncopyable {
181 public:
182     virtual ~SkWStream();
183 
184     /** Called to write bytes to a SkWStream. Returns true on success
185         @param buffer the address of at least size bytes to be written to the stream
186         @param size The number of bytes in buffer to write to the stream
187         @return true on success
188     */
189     virtual bool write(const void* buffer, size_t size) = 0;
190     virtual void newline();
191     virtual void flush();
192 
193     virtual size_t bytesWritten() const = 0;
194 
195     // helpers
196 
197     bool    write8(U8CPU);
198     bool    write16(U16CPU);
199     bool    write32(uint32_t);
200 
writeText(const char text[])201     bool    writeText(const char text[]) {
202         SkASSERT(text);
203         return this->write(text, strlen(text));
204     }
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 sk_sp<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 #ifdef SK_SUPPORT_LEGACY_STREAM_DATA
293     /** Use the specified data as the memory for this stream.
294      *  The stream will call ref() on the data (assuming it is not NULL).
295      *  DEPRECATED
296      */
297     SkMemoryStream(SkData*);
298 #endif
299 
300     /** Creates the stream to read from the specified data */
301     SkMemoryStream(sk_sp<SkData>);
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 
asData()315     sk_sp<SkData> asData() const { return fData; }
316     void setData(sk_sp<SkData>);
317 #ifdef SK_SUPPORT_LEGACY_STREAM_DATA
318     /** Return the stream's data in a SkData.
319      *  The caller must call unref() when it is finished using the data.
320      */
copyToData()321     SkData* copyToData() const { return asData().release(); }
322 
323     /**
324      *  Use the specified data as the memory for this stream.
325      *  The stream will call ref() on the data (assuming it is not NULL).
326      *  The function returns the data parameter as a convenience.
327      */
setData(SkData * data)328     SkData* setData(SkData* data) {
329         this->setData(sk_ref_sp(data));
330         return data;
331     }
332 #endif
333 
334     void skipToAlign4();
335     const void* getAtPos();
336 
337     size_t read(void* buffer, size_t size) override;
338     bool isAtEnd() const override;
339 
340     size_t peek(void* buffer, size_t size) const override;
341 
342     bool rewind() override;
343     SkMemoryStream* duplicate() const override;
344 
345     size_t getPosition() const override;
346     bool seek(size_t position) override;
347     bool move(long offset) override;
348     SkMemoryStream* fork() const override;
349 
350     size_t getLength() const override;
351 
352     const void* getMemoryBase() override;
353 
354 private:
355     sk_sp<SkData>   fData;
356     size_t          fOffset;
357 
358     typedef SkStreamMemory INHERITED;
359 };
360 
361 /////////////////////////////////////////////////////////////////////////////////////////////
362 
363 class SK_API SkFILEWStream : public SkWStream {
364 public:
365     SkFILEWStream(const char path[]);
366     virtual ~SkFILEWStream();
367 
368     /** Returns true if the current path could be opened.
369     */
isValid()370     bool isValid() const { return fFILE != NULL; }
371 
372     bool write(const void* buffer, size_t size) override;
373     void flush() override;
374     void fsync();
375     size_t bytesWritten() const override;
376 
377 private:
378     FILE* fFILE;
379 
380     typedef SkWStream INHERITED;
381 };
382 
383 class SK_API SkMemoryWStream : public SkWStream {
384 public:
385     SkMemoryWStream(void* buffer, size_t size);
386     bool write(const void* buffer, size_t size) override;
bytesWritten()387     size_t bytesWritten() const override { return fBytesWritten; }
388 
389 private:
390     char*   fBuffer;
391     size_t  fMaxLength;
392     size_t  fBytesWritten;
393 
394     typedef SkWStream INHERITED;
395 };
396 
397 class SK_API SkDynamicMemoryWStream : public SkWStream {
398 public:
399     SkDynamicMemoryWStream();
400     virtual ~SkDynamicMemoryWStream();
401 
402     bool write(const void* buffer, size_t size) override;
bytesWritten()403     size_t bytesWritten() const override { return fBytesWritten; }
404     // random access write
405     // modifies stream and returns true if offset + size is less than or equal to getOffset()
406     bool write(const void* buffer, size_t offset, size_t size);
407     bool read(void* buffer, size_t offset, size_t size);
getOffset()408     size_t getOffset() const { return fBytesWritten; }
409 
410     // copy what has been written to the stream into dst
411     void copyTo(void* dst) const;
412     void writeToStream(SkWStream* dst) const;
413 
414     sk_sp<SkData> snapshotAsData() const;
415     // Return the contents as SkData, and then reset the stream.
416     sk_sp<SkData> detachAsData();
417 #ifdef SK_SUPPORT_LEGACY_STREAM_DATA
418     /**
419      *  Return a copy of the data written so far. This call is responsible for
420      *  calling unref() when they are finished with the data.
421      */
copyToData()422     SkData* copyToData() const {
423         return snapshotAsData().release();
424     }
425 #endif
426 
427     /** Reset, returning a reader stream with the current content. */
428     SkStreamAsset* detachAsStream();
429 
430     /** Reset the stream to its original, empty, state. */
431     void reset();
432     void padToAlign4();
433 private:
434     struct Block;
435     Block*  fHead;
436     Block*  fTail;
437     size_t  fBytesWritten;
438     mutable sk_sp<SkData> fCopy;  // is invalidated if we write after it is created
439 
440     void invalidateCopy();
441 
442     // For access to the Block type.
443     friend class SkBlockMemoryStream;
444     friend class SkBlockMemoryRefCnt;
445 
446     typedef SkWStream INHERITED;
447 };
448 
449 
450 class SK_API SkDebugWStream : public SkWStream {
451 public:
SkDebugWStream()452     SkDebugWStream() : fBytesWritten(0) {}
453 
454     // overrides
455     bool write(const void* buffer, size_t size) override;
456     void newline() override;
bytesWritten()457     size_t bytesWritten() const override { return fBytesWritten; }
458 
459 private:
460     size_t fBytesWritten;
461     typedef SkWStream INHERITED;
462 };
463 
464 // for now
465 typedef SkFILEStream SkURLStream;
466 
467 #endif
468