/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkRWBuffer_DEFINED #define SkRWBuffer_DEFINED #include "SkRefCnt.h" struct SkBufferBlock; struct SkBufferHead; class SkRWBuffer; class SkStreamAsset; /** * Contains a read-only, thread-sharable block of memory. To access the memory, the caller must * instantiate a local iterator, as the memory is stored in 1 or more contiguous blocks. */ class SK_API SkROBuffer : public SkRefCnt { public: /** * Return the logical length of the data owned/shared by this buffer. It may be stored in * multiple contiguous blocks, accessible via the iterator. */ size_t size() const { return fAvailable; } class SK_API Iter { public: Iter(const SkROBuffer*); Iter(const sk_sp&); void reset(const SkROBuffer*); /** * Return the current continuous block of memory, or nullptr if the iterator is exhausted */ const void* data() const; /** * Returns the number of bytes in the current continguous block of memory, or 0 if the * iterator is exhausted. */ size_t size() const; /** * Advance to the next contiguous block of memory, returning true if there is another * block, or false if the iterator is exhausted. */ bool next(); private: const SkBufferBlock* fBlock; size_t fRemaining; const SkROBuffer* fBuffer; }; private: SkROBuffer(const SkBufferHead* head, size_t available, const SkBufferBlock* fTail); virtual ~SkROBuffer(); const SkBufferHead* fHead; const size_t fAvailable; const SkBufferBlock* fTail; friend class SkRWBuffer; }; /** * Accumulates bytes of memory that are "appended" to it, growing internal storage as needed. * The growth is done such that at any time in the writer's thread, an RBuffer or StreamAsset * can be snapped off (and safely passed to another thread). The RBuffer/StreamAsset snapshot * can see the previously stored bytes, but will be unaware of any future writes. */ class SK_API SkRWBuffer { public: SkRWBuffer(size_t initialCapacity = 0); ~SkRWBuffer(); size_t size() const { return fTotalUsed; } /** * Append |length| bytes from |buffer|. * * If the caller knows in advance how much more data they are going to append, they can * pass a |reserve| hint (representing the number of upcoming bytes *in addition* to the * current append), to minimize the number of internal allocations. */ void append(const void* buffer, size_t length, size_t reserve = 0); sk_sp makeROBufferSnapshot() const { return sk_sp(new SkROBuffer(fHead, fTotalUsed, fTail)); } std::unique_ptr makeStreamSnapshot() const; #ifdef SK_DEBUG void validate() const; #else void validate() const {} #endif private: SkBufferHead* fHead; SkBufferBlock* fTail; size_t fTotalUsed; }; #endif