1/*
2 * Copyright (C) 2015 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <wtf/ThreadSafeRefCounted.h>
29#include <wtf/Vector.h>
30
31namespace WebCore {
32
33class ThreadSafeDataBuffer;
34
35class ThreadSafeDataBufferImpl : public ThreadSafeRefCounted<ThreadSafeDataBufferImpl> {
36friend class ThreadSafeDataBuffer;
37private:
38 ThreadSafeDataBufferImpl(Vector<uint8_t>&& data)
39 {
40 m_data = WTFMove(data);
41 }
42
43 ThreadSafeDataBufferImpl(const Vector<uint8_t>& data)
44 : m_data(data)
45 {
46 }
47
48 ThreadSafeDataBufferImpl(const void* data, unsigned length)
49 : m_data(length)
50 {
51 memcpy(m_data.data(), data, length);
52 }
53
54 Vector<uint8_t> m_data;
55};
56
57class ThreadSafeDataBuffer {
58public:
59 static ThreadSafeDataBuffer create(Vector<uint8_t>&& data)
60 {
61 return ThreadSafeDataBuffer(WTFMove(data));
62 }
63
64 static ThreadSafeDataBuffer copyVector(const Vector<uint8_t>& data)
65 {
66 return ThreadSafeDataBuffer(data);
67 }
68
69 static ThreadSafeDataBuffer copyData(const void* data, unsigned length)
70 {
71 return ThreadSafeDataBuffer(data, length);
72 }
73
74 ThreadSafeDataBuffer()
75 {
76 }
77
78 const Vector<uint8_t>* data() const
79 {
80 return m_impl ? &m_impl->m_data : nullptr;
81 }
82
83 size_t size() const
84 {
85 return m_impl ? m_impl->m_data.size() : 0;
86 }
87
88 bool operator==(const ThreadSafeDataBuffer& other) const
89 {
90 if (!m_impl)
91 return !other.m_impl;
92
93 return m_impl->m_data == other.m_impl->m_data;
94 }
95
96 template<class Encoder> void encode(Encoder&) const;
97 template<class Decoder> static bool decode(Decoder&, ThreadSafeDataBuffer&);
98
99private:
100 explicit ThreadSafeDataBuffer(Vector<uint8_t>&& data)
101 {
102 m_impl = adoptRef(new ThreadSafeDataBufferImpl(WTFMove(data)));
103 }
104
105 explicit ThreadSafeDataBuffer(const Vector<uint8_t>& data)
106 {
107 m_impl = adoptRef(new ThreadSafeDataBufferImpl(data));
108 }
109
110 explicit ThreadSafeDataBuffer(const void* data, unsigned length)
111 {
112 m_impl = adoptRef(new ThreadSafeDataBufferImpl(data, length));
113 }
114
115 RefPtr<ThreadSafeDataBufferImpl> m_impl;
116};
117
118template<class Encoder>
119void ThreadSafeDataBuffer::encode(Encoder& encoder) const
120{
121 bool hasData = m_impl;
122 encoder << hasData;
123
124 if (hasData)
125 encoder << m_impl->m_data;
126}
127
128template<class Decoder>
129bool ThreadSafeDataBuffer::decode(Decoder& decoder, ThreadSafeDataBuffer& result)
130{
131 bool hasData;
132 if (!decoder.decode(hasData))
133 return false;
134
135 if (hasData) {
136 Vector<uint8_t> data;
137 if (!decoder.decode(data))
138 return false;
139
140 result = ThreadSafeDataBuffer::create(WTFMove(data));
141 }
142
143 return true;
144}
145
146} // namespace WebCore
147