• 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 "include/core/SkData.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkScalar.h"
14 #include "include/core/SkTypes.h"
15 #include "include/private/base/SkCPUTypes.h"
16 #include "include/private/base/SkTo.h"
17 
18 #include <cstdint>
19 #include <cstdio>
20 #include <cstring>
21 #include <memory>
22 #include <utility>
23 class SkStreamAsset;
24 
25 /**
26  *  SkStream -- abstraction for a source of bytes. Subclasses can be backed by
27  *  memory, or a file, or something else.
28  *
29  *  NOTE:
30  *
31  *  Classic "streams" APIs are sort of async, in that on a request for N
32  *  bytes, they may return fewer than N bytes on a given call, in which case
33  *  the caller can "try again" to get more bytes, eventually (modulo an error)
34  *  receiving their total N bytes.
35  *
36  *  Skia streams behave differently. They are effectively synchronous, and will
37  *  always return all N bytes of the request if possible. If they return fewer
38  *  (the read() call returns the number of bytes read) then that means there is
39  *  no more data (at EOF or hit an error). The caller should *not* call again
40  *  in hopes of fulfilling more of the request.
41  */
42 class SK_API SkStream {
43 public:
~SkStream()44     virtual ~SkStream() {}
SkStream()45     SkStream() {}
46 
47     /**
48      *  Attempts to open the specified file as a stream, returns nullptr on failure.
49      */
50     static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]);
51 
52     /** Reads or skips size number of bytes.
53      *  If buffer == NULL, skip size bytes, return how many were skipped.
54      *  If buffer != NULL, copy size bytes into buffer, return how many were copied.
55      *  @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
56      *  @param size the number of bytes to skip or copy
57      *  @return the number of bytes actually read.
58      */
59     virtual size_t read(void* buffer, size_t size) = 0;
60 
61     /** Skip size number of bytes.
62      *  @return the actual number bytes that could be skipped.
63      */
skip(size_t size)64     size_t skip(size_t size) {
65         return this->read(nullptr, size);
66     }
67 
68     /**
69      *  Attempt to peek at size bytes.
70      *  If this stream supports peeking, copy min(size, peekable bytes) into
71      *  buffer, and return the number of bytes copied.
72      *  If the stream does not support peeking, or cannot peek any bytes,
73      *  return 0 and leave buffer unchanged.
74      *  The stream is guaranteed to be in the same visible state after this
75      *  call, regardless of success or failure.
76      *  @param buffer Must not be NULL, and must be at least size bytes. Destination
77      *      to copy bytes.
78      *  @param size Number of bytes to copy.
79      *  @return The number of bytes peeked/copied.
80      */
peek(void *,size_t)81     virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
82 
83     /** Returns true when all the bytes in the stream have been read.
84      *  This may return true early (when there are no more bytes to be read)
85      *  or late (after the first unsuccessful read).
86      */
87     virtual bool isAtEnd() const = 0;
88 
89     bool SK_WARN_UNUSED_RESULT readS8(int8_t*);
90     bool SK_WARN_UNUSED_RESULT readS16(int16_t*);
91     bool SK_WARN_UNUSED_RESULT readS32(int32_t*);
92 
readU8(uint8_t * i)93     bool SK_WARN_UNUSED_RESULT readU8(uint8_t* i) { return this->readS8((int8_t*)i); }
readU16(uint16_t * i)94     bool SK_WARN_UNUSED_RESULT readU16(uint16_t* i) { return this->readS16((int16_t*)i); }
readU32(uint32_t * i)95     bool SK_WARN_UNUSED_RESULT readU32(uint32_t* i) { return this->readS32((int32_t*)i); }
96 
readBool(bool * b)97     bool SK_WARN_UNUSED_RESULT readBool(bool* b) {
98         uint8_t i;
99         if (!this->readU8(&i)) { return false; }
100         *b = (i != 0);
101         return true;
102     }
103     bool SK_WARN_UNUSED_RESULT readScalar(SkScalar*);
104     bool SK_WARN_UNUSED_RESULT readPackedUInt(size_t*);
105 
106 //SkStreamRewindable
107     /** Rewinds to the beginning of the stream. Returns true if the stream is known
108      *  to be at the beginning after this call returns.
109      */
rewind()110     virtual bool rewind() { return false; }
111 
112     /** Duplicates this stream. If this cannot be done, returns NULL.
113      *  The returned stream will be positioned at the beginning of its data.
114      */
duplicate()115     std::unique_ptr<SkStream> duplicate() const {
116         return std::unique_ptr<SkStream>(this->onDuplicate());
117     }
118     /** Duplicates this stream. If this cannot be done, returns NULL.
119      *  The returned stream will be positioned the same as this stream.
120      */
fork()121     std::unique_ptr<SkStream> fork() const {
122         return std::unique_ptr<SkStream>(this->onFork());
123     }
124 
125 //SkStreamSeekable
126     /** Returns true if this stream can report its current position. */
hasPosition()127     virtual bool hasPosition() const { return false; }
128     /** Returns the current position in the stream. If this cannot be done, returns 0. */
getPosition()129     virtual size_t getPosition() const { return 0; }
130 
131     /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
132      *  If an attempt is made to seek past the end of the stream, the position will be set
133      *  to the end of the stream.
134      */
seek(size_t)135     virtual bool seek(size_t /*position*/) { return false; }
136 
137     /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
138      *  If an attempt is made to move to a position outside the stream, the position will be set
139      *  to the closest point within the stream (beginning or end).
140      */
move(long)141     virtual bool move(long /*offset*/) { return false; }
142 
143 //SkStreamAsset
144     /** Returns true if this stream can report its total length. */
hasLength()145     virtual bool hasLength() const { return false; }
146     /** Returns the total length of the stream. If this cannot be done, returns 0. */
getLength()147     virtual size_t getLength() const { return 0; }
148 
149 //SkStreamMemory
150     /** Returns the starting address for the data. If this cannot be done, returns NULL. */
151     //TODO: replace with virtual const SkData* getData()
getMemoryBase()152     virtual const void* getMemoryBase() { return nullptr; }
153 
154 private:
onDuplicate()155     virtual SkStream* onDuplicate() const { return nullptr; }
onFork()156     virtual SkStream* onFork() const { return nullptr; }
157 
158     SkStream(SkStream&&) = delete;
159     SkStream(const SkStream&) = delete;
160     SkStream& operator=(SkStream&&) = delete;
161     SkStream& operator=(const SkStream&) = delete;
162 };
163 
164 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
165 class SK_API SkStreamRewindable : public SkStream {
166 public:
167     bool rewind() override = 0;
duplicate()168     std::unique_ptr<SkStreamRewindable> duplicate() const {
169         return std::unique_ptr<SkStreamRewindable>(this->onDuplicate());
170     }
171 private:
172     SkStreamRewindable* onDuplicate() const override = 0;
173 };
174 
175 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
176 class SK_API SkStreamSeekable : public SkStreamRewindable {
177 public:
duplicate()178     std::unique_ptr<SkStreamSeekable> duplicate() const {
179         return std::unique_ptr<SkStreamSeekable>(this->onDuplicate());
180     }
181 
hasPosition()182     bool hasPosition() const override { return true; }
183     size_t getPosition() const override = 0;
184     bool seek(size_t position) override = 0;
185     bool move(long offset) override = 0;
186 
fork()187     std::unique_ptr<SkStreamSeekable> fork() const {
188         return std::unique_ptr<SkStreamSeekable>(this->onFork());
189     }
190 private:
191     SkStreamSeekable* onDuplicate() const override = 0;
192     SkStreamSeekable* onFork() const override = 0;
193 };
194 
195 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
196 class SK_API SkStreamAsset : public SkStreamSeekable {
197 public:
hasLength()198     bool hasLength() const override { return true; }
199     size_t getLength() const override = 0;
200 
duplicate()201     std::unique_ptr<SkStreamAsset> duplicate() const {
202         return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
203     }
fork()204     std::unique_ptr<SkStreamAsset> fork() const {
205         return std::unique_ptr<SkStreamAsset>(this->onFork());
206     }
207 private:
208     SkStreamAsset* onDuplicate() const override = 0;
209     SkStreamAsset* onFork() const override = 0;
210 };
211 
212 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
213 class SK_API SkStreamMemory : public SkStreamAsset {
214 public:
215     const void* getMemoryBase() override = 0;
216 
duplicate()217     std::unique_ptr<SkStreamMemory> duplicate() const {
218         return std::unique_ptr<SkStreamMemory>(this->onDuplicate());
219     }
fork()220     std::unique_ptr<SkStreamMemory> fork() const {
221         return std::unique_ptr<SkStreamMemory>(this->onFork());
222     }
223 private:
224     SkStreamMemory* onDuplicate() const override = 0;
225     SkStreamMemory* onFork() const override = 0;
226 };
227 
228 class SK_API SkWStream {
229 public:
230     virtual ~SkWStream();
SkWStream()231     SkWStream() {}
232 
233     /** Called to write bytes to a SkWStream. Returns true on success
234         @param buffer the address of at least size bytes to be written to the stream
235         @param size The number of bytes in buffer to write to the stream
236         @return true on success
237     */
238     virtual bool write(const void* buffer, size_t size) = 0;
239     virtual void flush();
240 
241     virtual size_t bytesWritten() const = 0;
242 
243     // helpers
244 
write8(U8CPU value)245     bool write8(U8CPU value)   {
246         uint8_t v = SkToU8(value);
247         return this->write(&v, 1);
248     }
write16(U16CPU value)249     bool write16(U16CPU value) {
250         uint16_t v = SkToU16(value);
251         return this->write(&v, 2);
252     }
write32(uint32_t v)253     bool write32(uint32_t v) {
254         return this->write(&v, 4);
255     }
256 
writeText(const char text[])257     bool writeText(const char text[]) {
258         SkASSERT(text);
259         return this->write(text, std::strlen(text));
260     }
261 
newline()262     bool newline() { return this->write("\n", std::strlen("\n")); }
263 
264     bool writeDecAsText(int32_t);
265     bool writeBigDecAsText(int64_t, int minDigits = 0);
266     bool writeHexAsText(uint32_t, int minDigits = 0);
267     bool writeScalarAsText(SkScalar);
268 
writeBool(bool v)269     bool writeBool(bool v) { return this->write8(v); }
270     bool writeScalar(SkScalar);
271     bool writePackedUInt(size_t);
272 
273     bool writeStream(SkStream* input, size_t length);
274 
275     /**
276      * This returns the number of bytes in the stream required to store
277      * 'value'.
278      */
279     static int SizeOfPackedUInt(size_t value);
280 
281 private:
282     SkWStream(const SkWStream&) = delete;
283     SkWStream& operator=(const SkWStream&) = delete;
284 };
285 
286 class SK_API SkNullWStream : public SkWStream {
287 public:
SkNullWStream()288     SkNullWStream() : fBytesWritten(0) {}
289 
write(const void *,size_t n)290     bool write(const void* , size_t n) override { fBytesWritten += n; return true; }
flush()291     void flush() override {}
bytesWritten()292     size_t bytesWritten() const override { return fBytesWritten; }
293 
294 private:
295     size_t fBytesWritten;
296 };
297 
298 ////////////////////////////////////////////////////////////////////////////////////////
299 
300 /** A stream that wraps a C FILE* file stream. */
301 class SK_API SkFILEStream : public SkStreamAsset {
302 public:
303     /** Initialize the stream by calling sk_fopen on the specified path.
304      *  This internal stream will be closed in the destructor.
305      */
306     explicit SkFILEStream(const char path[] = nullptr);
307 
308     /** Initialize the stream with an existing C FILE stream.
309      *  The current position of the C FILE stream will be considered the
310      *  beginning of the SkFILEStream and the current seek end of the FILE will be the end.
311      *  The C FILE stream will be closed in the destructor.
312      */
313     explicit SkFILEStream(FILE* file);
314 
315     /** Initialize the stream with an existing C FILE stream.
316      *  The current position of the C FILE stream will be considered the
317      *  beginning of the SkFILEStream and size bytes later will be the end.
318      *  The C FILE stream will be closed in the destructor.
319      */
320     explicit SkFILEStream(FILE* file, size_t size);
321 
322     ~SkFILEStream() override;
323 
Make(const char path[])324     static std::unique_ptr<SkFILEStream> Make(const char path[]) {
325         std::unique_ptr<SkFILEStream> stream(new SkFILEStream(path));
326         return stream->isValid() ? std::move(stream) : nullptr;
327     }
328 
329     /** Returns true if the current path could be opened. */
isValid()330     bool isValid() const { return fFILE != nullptr; }
331 
332     /** Close this SkFILEStream. */
333     void close();
334 
335     size_t read(void* buffer, size_t size) override;
336     bool isAtEnd() const override;
337 
338     bool rewind() override;
duplicate()339     std::unique_ptr<SkStreamAsset> duplicate() const {
340         return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
341     }
342 
343     size_t getPosition() const override;
344     bool seek(size_t position) override;
345     bool move(long offset) override;
346 
fork()347     std::unique_ptr<SkStreamAsset> fork() const {
348         return std::unique_ptr<SkStreamAsset>(this->onFork());
349     }
350 
351     size_t getLength() const override;
352 
353 private:
354     explicit SkFILEStream(FILE*, size_t size, size_t start);
355     explicit SkFILEStream(std::shared_ptr<FILE>, size_t end, size_t start);
356     explicit SkFILEStream(std::shared_ptr<FILE>, size_t end, size_t start, size_t current);
357 
358     SkStreamAsset* onDuplicate() const override;
359     SkStreamAsset* onFork() const override;
360 
361     std::shared_ptr<FILE> fFILE;
362     // My own council will I keep on sizes and offsets.
363     // These are seek positions in the underling FILE, not offsets into the stream.
364     size_t fEnd;
365     size_t fStart;
366     size_t fCurrent;
367 
368     using INHERITED = SkStreamAsset;
369 };
370 
371 class SK_API SkMemoryStream : public SkStreamMemory {
372 public:
373     SkMemoryStream();
374 
375     /** We allocate (and free) the memory. Write to it via getMemoryBase() */
376     SkMemoryStream(size_t length);
377 
378     /** If copyData is true, the stream makes a private copy of the data. */
379     SkMemoryStream(const void* data, size_t length, bool copyData = false);
380 
381     /** Creates the stream to read from the specified data */
382     SkMemoryStream(sk_sp<SkData> data);
383 
384     /** Returns a stream with a copy of the input data. */
385     static std::unique_ptr<SkMemoryStream> MakeCopy(const void* data, size_t length);
386 
387     /** Returns a stream with a bare pointer reference to the input data. */
388     static std::unique_ptr<SkMemoryStream> MakeDirect(const void* data, size_t length);
389 
390     /** Returns a stream with a shared reference to the input data. */
391     static std::unique_ptr<SkMemoryStream> Make(sk_sp<SkData> data);
392 
393     /** Resets the stream to the specified data and length,
394         just like the constructor.
395         if copyData is true, the stream makes a private copy of the data
396     */
397     virtual void setMemory(const void* data, size_t length,
398                            bool copyData = false);
399     /** Replace any memory buffer with the specified buffer. The caller
400         must have allocated data with sk_malloc or sk_realloc, since it
401         will be freed with sk_free.
402     */
403     void setMemoryOwned(const void* data, size_t length);
404 
asData()405     sk_sp<SkData> asData() const { return fData; }
406     void setData(sk_sp<SkData> data);
407 
408     void skipToAlign4();
409     const void* getAtPos();
410 
411     size_t read(void* buffer, size_t size) override;
412     bool isAtEnd() const override;
413 
414     size_t peek(void* buffer, size_t size) const override;
415 
416     bool rewind() override;
417 
duplicate()418     std::unique_ptr<SkMemoryStream> duplicate() const {
419         return std::unique_ptr<SkMemoryStream>(this->onDuplicate());
420     }
421 
422     size_t getPosition() const override;
423     bool seek(size_t position) override;
424     bool move(long offset) override;
425 
fork()426     std::unique_ptr<SkMemoryStream> fork() const {
427         return std::unique_ptr<SkMemoryStream>(this->onFork());
428     }
429 
430     size_t getLength() const override;
431 
432     const void* getMemoryBase() override;
433 
434 private:
435     SkMemoryStream* onDuplicate() const override;
436     SkMemoryStream* onFork() const override;
437 
438     sk_sp<SkData>   fData;
439     size_t          fOffset;
440 
441     using INHERITED = SkStreamMemory;
442 };
443 
444 /////////////////////////////////////////////////////////////////////////////////////////////
445 
446 class SK_API SkFILEWStream : public SkWStream {
447 public:
448     SkFILEWStream(const char path[]);
449     ~SkFILEWStream() override;
450 
451     /** Returns true if the current path could be opened.
452     */
isValid()453     bool isValid() const { return fFILE != nullptr; }
454 
455     bool write(const void* buffer, size_t size) override;
456     void flush() override;
457     void fsync();
458     size_t bytesWritten() const override;
459 
460 private:
461     FILE* fFILE;
462 
463     using INHERITED = SkWStream;
464 };
465 
466 class SK_API SkDynamicMemoryWStream : public SkWStream {
467 public:
468     SkDynamicMemoryWStream() = default;
469     SkDynamicMemoryWStream(SkDynamicMemoryWStream&&);
470     SkDynamicMemoryWStream& operator=(SkDynamicMemoryWStream&&);
471     ~SkDynamicMemoryWStream() override;
472 
473     bool write(const void* buffer, size_t size) override;
474     size_t bytesWritten() const override;
475 
476     bool read(void* buffer, size_t offset, size_t size);
477 
478     /** More efficient version of read(dst, 0, bytesWritten()). */
479     void copyTo(void* dst) const;
480     bool writeToStream(SkWStream* dst) const;
481 
482     /** Equivalent to copyTo() followed by reset(), but may save memory use. */
483     void copyToAndReset(void* dst);
484 
485     /** Equivalent to writeToStream() followed by reset(), but may save memory use. */
486     bool writeToAndReset(SkWStream* dst);
487 
488     /** Equivalent to writeToStream() followed by reset(), but may save memory use.
489         When the dst is also a SkDynamicMemoryWStream, the implementation is constant time. */
490     bool writeToAndReset(SkDynamicMemoryWStream* dst);
491 
492     /** Prepend this stream to dst, resetting this. */
493     void prependToAndReset(SkDynamicMemoryWStream* dst);
494 
495     /** Return the contents as SkData, and then reset the stream. */
496     sk_sp<SkData> detachAsData();
497 
498     /** Reset, returning a reader stream with the current content. */
499     std::unique_ptr<SkStreamAsset> detachAsStream();
500 
501     /** Reset the stream to its original, empty, state. */
502     void reset();
503     void padToAlign4();
504 private:
505     struct Block;
506     Block*  fHead = nullptr;
507     Block*  fTail = nullptr;
508     size_t  fBytesWrittenBeforeTail = 0;
509 
510 #ifdef SK_DEBUG
511     void validate() const;
512 #else
validate()513     void validate() const {}
514 #endif
515 
516     // For access to the Block type.
517     friend class SkBlockMemoryStream;
518     friend class SkBlockMemoryRefCnt;
519 
520     using INHERITED = SkWStream;
521 };
522 
523 #endif
524