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