• 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 "SkData.h"
12 #include "SkRefCnt.h"
13 #include "SkScalar.h"
14 
15 #include <memory.h>
16 
17 class SkStream;
18 class SkStreamRewindable;
19 class SkStreamSeekable;
20 class SkStreamAsset;
21 class SkStreamMemory;
22 
23 /**
24  *  SkStream -- abstraction for a source of bytes. Subclasses can be backed by
25  *  memory, or a file, or something else.
26  *
27  *  NOTE:
28  *
29  *  Classic "streams" APIs are sort of async, in that on a request for N
30  *  bytes, they may return fewer than N bytes on a given call, in which case
31  *  the caller can "try again" to get more bytes, eventually (modulo an error)
32  *  receiving their total N bytes.
33  *
34  *  Skia streams behave differently. They are effectively synchronous, and will
35  *  always return all N bytes of the request if possible. If they return fewer
36  *  (the read() call returns the number of bytes read) then that means there is
37  *  no more data (at EOF or hit an error). The caller should *not* call again
38  *  in hopes of fulfilling more of the request.
39  */
40 class SK_API SkStream : public SkNoncopyable {
41 public:
~SkStream()42     virtual ~SkStream() {}
43 
44     /**
45      *  Attempts to open the specified file as a stream, returns nullptr on failure.
46      */
47     static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]);
48 
49     /** Reads or skips size number of bytes.
50      *  If buffer == NULL, skip size bytes, return how many were skipped.
51      *  If buffer != NULL, copy size bytes into buffer, return how many were copied.
52      *  @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
53      *  @param size the number of bytes to skip or copy
54      *  @return the number of bytes actually read.
55      */
56     virtual size_t read(void* buffer, size_t size) = 0;
57 
58     /** Skip size number of bytes.
59      *  @return the actual number bytes that could be skipped.
60      */
skip(size_t size)61     size_t skip(size_t size) {
62         return this->read(NULL, size);
63     }
64 
65     /**
66      *  Attempt to peek at size bytes.
67      *  If this stream supports peeking, copy min(size, peekable bytes) into
68      *  buffer, and return the number of bytes copied.
69      *  If the stream does not support peeking, or cannot peek any bytes,
70      *  return 0 and leave buffer unchanged.
71      *  The stream is guaranteed to be in the same visible state after this
72      *  call, regardless of success or failure.
73      *  @param buffer Must not be NULL, and must be at least size bytes. Destination
74      *      to copy bytes.
75      *  @param size Number of bytes to copy.
76      *  @return The number of bytes peeked/copied.
77      */
peek(void *,size_t)78     virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
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     virtual ~SkWStream();
185 
186     /** Called to write bytes to a SkWStream. Returns true on success
187         @param buffer the address of at least size bytes to be written to the stream
188         @param size The number of bytes in buffer to write to the stream
189         @return true on success
190     */
191     virtual bool write(const void* buffer, size_t size) = 0;
192     virtual void flush();
193 
194     virtual size_t bytesWritten() const = 0;
195 
196     // helpers
197 
write8(U8CPU value)198     bool write8(U8CPU value)   {
199         uint8_t v = SkToU8(value);
200         return this->write(&v, 1);
201     }
write16(U16CPU value)202     bool write16(U16CPU value) {
203         uint16_t v = SkToU16(value);
204         return this->write(&v, 2);
205     }
write32(uint32_t v)206     bool write32(uint32_t v) {
207         return this->write(&v, 4);
208     }
209 
writeText(const char text[])210     bool writeText(const char text[]) {
211         SkASSERT(text);
212         return this->write(text, strlen(text));
213     }
214 
newline()215     bool newline() { return this->write("\n", strlen("\n")); }
216 
217     bool    writeDecAsText(int32_t);
218     bool    writeBigDecAsText(int64_t, int minDigits = 0);
219     bool    writeHexAsText(uint32_t, int minDigits = 0);
220     bool    writeScalarAsText(SkScalar);
221 
writeBool(bool v)222     bool    writeBool(bool v) { return this->write8(v); }
223     bool    writeScalar(SkScalar);
224     bool    writePackedUInt(size_t);
225 
226     bool    writeStream(SkStream* input, size_t length);
227 
228     /**
229      * This returns the number of bytes in the stream required to store
230      * 'value'.
231      */
232     static int SizeOfPackedUInt(size_t value);
233 };
234 
235 class SK_API SkNullWStream : public SkWStream {
236 public:
SkNullWStream()237     SkNullWStream() : fBytesWritten(0) {}
238 
write(const void *,size_t n)239     bool write(const void*, size_t n) override { fBytesWritten += n; return true; }
flush()240     void flush() override {}
bytesWritten()241     size_t bytesWritten() const override { return fBytesWritten; }
242 
243 private:
244     size_t fBytesWritten;
245 };
246 
247 ////////////////////////////////////////////////////////////////////////////////////////
248 
249 #include <stdio.h>
250 
251 /** A stream that wraps a C FILE* file stream. */
252 class SK_API SkFILEStream : public SkStreamAsset {
253 public:
254     /** Initialize the stream by calling sk_fopen on the specified path.
255      *  This internal stream will be closed in the destructor.
256      */
257     explicit SkFILEStream(const char path[] = nullptr);
258 
259     /** Initialize the stream with an existing C file stream.
260      *  The C file stream will be closed in the destructor.
261      */
262     explicit SkFILEStream(FILE* file);
263 
264     ~SkFILEStream() override;
265 
266     /** Returns true if the current path could be opened. */
isValid()267     bool isValid() const { return fFILE != nullptr; }
268 
269     /** Close this SkFILEStream. */
270     void close();
271 
272     size_t read(void* buffer, size_t size) override;
273     bool isAtEnd() const override;
274 
275     bool rewind() override;
276     SkStreamAsset* duplicate() const override;
277 
278     size_t getPosition() const override;
279     bool seek(size_t position) override;
280     bool move(long offset) override;
281     SkStreamAsset* fork() const override;
282 
283     size_t getLength() const override;
284 
285 private:
286     explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset);
287     explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset, size_t originalOffset);
288 
289     std::shared_ptr<FILE> fFILE;
290     // My own council will I keep on sizes and offsets.
291     size_t fSize;
292     size_t fOffset;
293     size_t fOriginalOffset;
294 
295     typedef SkStreamAsset INHERITED;
296 };
297 
298 class SK_API SkMemoryStream : public SkStreamMemory {
299 public:
300     SkMemoryStream();
301 
302     /** We allocate (and free) the memory. Write to it via getMemoryBase() */
303     SkMemoryStream(size_t length);
304 
305     /** If copyData is true, the stream makes a private copy of the data. */
306     SkMemoryStream(const void* data, size_t length, bool copyData = false);
307 
308     /** Creates the stream to read from the specified data */
309     SkMemoryStream(sk_sp<SkData>);
310 
311     /** Resets the stream to the specified data and length,
312         just like the constructor.
313         if copyData is true, the stream makes a private copy of the data
314     */
315     virtual void setMemory(const void* data, size_t length,
316                            bool copyData = false);
317     /** Replace any memory buffer with the specified buffer. The caller
318         must have allocated data with sk_malloc or sk_realloc, since it
319         will be freed with sk_free.
320     */
321     void setMemoryOwned(const void* data, size_t length);
322 
asData()323     sk_sp<SkData> asData() const { return fData; }
324     void setData(sk_sp<SkData>);
325 
326     void skipToAlign4();
327     const void* getAtPos();
328 
329     size_t read(void* buffer, size_t size) override;
330     bool isAtEnd() const override;
331 
332     size_t peek(void* buffer, size_t size) const override;
333 
334     bool rewind() override;
335     SkMemoryStream* duplicate() const override;
336 
337     size_t getPosition() const override;
338     bool seek(size_t position) override;
339     bool move(long offset) override;
340     SkMemoryStream* fork() const override;
341 
342     size_t getLength() const override;
343 
344     const void* getMemoryBase() override;
345 
346 private:
347     sk_sp<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     SkFILEWStream(const char path[]);
358     ~SkFILEWStream() override;
359 
360     /** Returns true if the current path could be opened.
361     */
isValid()362     bool isValid() const { return fFILE != NULL; }
363 
364     bool write(const void* buffer, size_t size) override;
365     void flush() override;
366     void fsync();
367     size_t bytesWritten() const override;
368 
369 private:
370     FILE* fFILE;
371 
372     typedef SkWStream INHERITED;
373 };
374 
375 class SK_API SkDynamicMemoryWStream : public SkWStream {
376 public:
377     SkDynamicMemoryWStream();
378     ~SkDynamicMemoryWStream() override;
379 
380     bool write(const void* buffer, size_t size) override;
381     size_t bytesWritten() const override;
382 
383     bool read(void* buffer, size_t offset, size_t size);
384 
385     /** More efficient version of read(dst, 0, bytesWritten()). */
386     void copyTo(void* dst) const;
387     bool writeToStream(SkWStream* dst) const;
388 
389     /** Equivalent to copyTo() followed by reset(), but may save memory use. */
390     void copyToAndReset(void* dst);
391 
392     /** Equivalent to writeToStream() followed by reset(), but may save memory use. */
393     bool writeToAndReset(SkWStream* dst);
394 
395     /** Return the contents as SkData, and then reset the stream. */
396     sk_sp<SkData> detachAsData();
397 
398     /** Reset, returning a reader stream with the current content. */
399     std::unique_ptr<SkStreamAsset> detachAsStream();
400 
401     /** Reset the stream to its original, empty, state. */
402     void reset();
403     void padToAlign4();
404 private:
405     struct Block;
406     Block*  fHead;
407     Block*  fTail;
408     size_t  fBytesWrittenBeforeTail;
409 
410 #ifdef SK_DEBUG
411     void validate() const;
412 #else
validate()413     void validate() const {}
414 #endif
415 
416     // For access to the Block type.
417     friend class SkBlockMemoryStream;
418     friend class SkBlockMemoryRefCnt;
419 
420     typedef SkWStream INHERITED;
421 };
422 
423 #endif
424