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