1/*
2 * Copyright 2015 Google Inc.
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 SkRWBuffer_DEFINED
9#define SkRWBuffer_DEFINED
10
11#include "include/core/SkRefCnt.h"
12
13struct SkBufferBlock;
14struct SkBufferHead;
15class SkRWBuffer;
16class SkStreamAsset;
17
18/**
19 * Contains a read-only, thread-sharable block of memory. To access the memory, the caller must
20 * instantiate a local iterator, as the memory is stored in 1 or more contiguous blocks.
21 */
22class SK_API SkROBuffer : public SkRefCnt {
23public:
24 /**
25 * Return the logical length of the data owned/shared by this buffer. It may be stored in
26 * multiple contiguous blocks, accessible via the iterator.
27 */
28 size_t size() const { return fAvailable; }
29
30 class SK_API Iter {
31 public:
32 Iter(const SkROBuffer*);
33 Iter(const sk_sp<SkROBuffer>&);
34
35 void reset(const SkROBuffer*);
36
37 /**
38 * Return the current continuous block of memory, or nullptr if the iterator is exhausted
39 */
40 const void* data() const;
41
42 /**
43 * Returns the number of bytes in the current continguous block of memory, or 0 if the
44 * iterator is exhausted.
45 */
46 size_t size() const;
47
48 /**
49 * Advance to the next contiguous block of memory, returning true if there is another
50 * block, or false if the iterator is exhausted.
51 */
52 bool next();
53
54 private:
55 const SkBufferBlock* fBlock;
56 size_t fRemaining;
57 const SkROBuffer* fBuffer;
58 };
59
60private:
61 SkROBuffer(const SkBufferHead* head, size_t available, const SkBufferBlock* fTail);
62 virtual ~SkROBuffer();
63
64 const SkBufferHead* fHead;
65 const size_t fAvailable;
66 const SkBufferBlock* fTail;
67
68 friend class SkRWBuffer;
69};
70
71/**
72 * Accumulates bytes of memory that are "appended" to it, growing internal storage as needed.
73 * The growth is done such that at any time in the writer's thread, an RBuffer or StreamAsset
74 * can be snapped off (and safely passed to another thread). The RBuffer/StreamAsset snapshot
75 * can see the previously stored bytes, but will be unaware of any future writes.
76 */
77class SK_API SkRWBuffer {
78public:
79 SkRWBuffer(size_t initialCapacity = 0);
80 ~SkRWBuffer();
81
82 size_t size() const { return fTotalUsed; }
83
84 /**
85 * Append |length| bytes from |buffer|.
86 *
87 * If the caller knows in advance how much more data they are going to append, they can
88 * pass a |reserve| hint (representing the number of upcoming bytes *in addition* to the
89 * current append), to minimize the number of internal allocations.
90 */
91 void append(const void* buffer, size_t length, size_t reserve = 0);
92
93 sk_sp<SkROBuffer> makeROBufferSnapshot() const {
94 return sk_sp<SkROBuffer>(new SkROBuffer(fHead, fTotalUsed, fTail));
95 }
96
97 std::unique_ptr<SkStreamAsset> makeStreamSnapshot() const;
98
99#ifdef SK_DEBUG
100 void validate() const;
101#else
102 void validate() const {}
103#endif
104
105private:
106 SkBufferHead* fHead;
107 SkBufferBlock* fTail;
108 size_t fTotalUsed;
109};
110
111#endif
112