OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef PPAPI_CPP_DEV_ARRAY_DEV_H_ | |
6 #define PPAPI_CPP_DEV_ARRAY_DEV_H_ | |
7 | |
8 #include <cstdlib> | |
9 | |
10 #include "ppapi/c/dev/pp_array_structs_dev.h" | |
11 #include "ppapi/cpp/dev/may_own_ptr_dev.h" | |
12 #include "ppapi/cpp/logging.h" | |
13 | |
14 namespace pp { | |
15 | |
16 namespace internal { | |
17 | |
18 class ArrayAllocator { | |
19 public: | |
20 static PP_ArrayOutput Get() { | |
21 PP_ArrayOutput array_output = { &ArrayAllocator::GetDataBuffer, NULL }; | |
22 return array_output; | |
23 } | |
24 | |
25 static void Free(void* mem) { | |
26 free(mem); | |
27 } | |
28 | |
29 private: | |
30 static void* GetDataBuffer(void* /* user_data */, | |
31 uint32_t element_count, | |
32 uint32_t element_size) { | |
33 if (element_count == 0 || element_size == 0) | |
34 return NULL; | |
35 | |
36 return calloc(element_count, element_size); | |
37 } | |
38 }; | |
39 | |
40 } // namespace internal | |
41 | |
42 template <class T> | |
43 class Array { | |
44 public: | |
45 typedef typename T::CArrayType CArrayType; | |
46 typedef typename T::CType CType; | |
47 typedef CArrayType* COutputType; | |
48 | |
49 Array() { | |
50 } | |
51 | |
52 Array(CArrayType* storage, NotOwned) : storage_(storage, NOT_OWNED) { | |
53 PP_DCHECK(storage_->size == 0); | |
54 PP_DCHECK(storage_->elements == NULL); | |
55 } | |
56 | |
57 explicit Array(uint32_t size) { | |
58 Reset(size); | |
59 } | |
60 | |
61 Array(const Array<T>& other) { | |
62 DeepCopy(*other.storage_); | |
63 } | |
64 | |
65 ~Array() { | |
66 Reset(0); | |
67 } | |
68 | |
69 Array<T>& operator=(const Array<T>& other) { | |
70 return operator=(*other.storage_); | |
71 } | |
72 | |
73 Array<T>& operator=(const CArrayType& other) { | |
74 if (storage_.get() == &other) | |
75 return *this; | |
76 | |
77 Reset(0); | |
78 DeepCopy(other); | |
79 | |
80 return *this; | |
81 } | |
82 | |
83 uint32_t size() const { | |
84 return storage_->size; | |
85 } | |
86 | |
87 T& operator[](uint32_t index) { | |
88 PP_DCHECK(storage_->size == wrappers_.size()); | |
89 PP_DCHECK(index < storage_->size); | |
90 PP_DCHECK(wrappers_[index]->ToStruct() == storage_->elements + index); | |
91 return *wrappers_[index]; | |
92 } | |
93 | |
94 const T& operator[](uint32_t index) const { | |
95 PP_DCHECK(storage_->size == wrappers_.size()); | |
96 PP_DCHECK(index < storage_->size); | |
97 PP_DCHECK(wrappers_[index]->ToStruct() == storage_->elements + index); | |
98 return *wrappers_[index]; | |
99 } | |
100 | |
101 void Reset(uint32_t size) { | |
102 internal::ArrayAllocator::Free(storage_->elements); | |
103 storage_->elements = NULL; | |
104 | |
105 storage_->size = size; | |
106 if (size > 0) { | |
107 storage_->elements = new CType[size]; | |
108 memset(storage_->elements, 0, sizeof(CType) * size); | |
109 } | |
110 | |
111 UpdateWrappers(); | |
Sam McNally
2013/12/11 08:10:43
This is unsafe for wrappers with a destructor that
yzshen1
2013/12/11 18:01:32
Good catch!
Thanks! :)
On 2013/12/11 08:10:43, Sa
| |
112 } | |
113 | |
114 CArrayType* StartRawUpdate() { | |
115 Reset(0); | |
116 return storage_.get(); | |
117 } | |
118 | |
119 void EndRawUpdate() { | |
120 PP_DCHECK(wrappers_.empty()); | |
121 UpdateWrappers(); | |
122 } | |
123 | |
124 private: | |
125 void DeepCopy(const CArrayType& other) { | |
126 storage_->size = other.size; | |
127 | |
128 if (storage_->size > 0) { | |
129 storage_->elements = new CType[storage_->size]; | |
130 memset(storage_->elements, 0, sizeof(CType) * storage_->size); | |
131 } | |
132 | |
133 UpdateWrappers(); | |
134 | |
135 for (size_t i = 0; i < storage_->size; ++i) | |
136 wrappers_[i] = other.elements[i]; | |
137 } | |
138 | |
139 void UpdateWrappers() { | |
140 for (typename std::vector<T*>::iterator iter = wrappers_.begin(); | |
141 iter != wrappers_.end(); | |
142 ++iter) { | |
143 delete *iter; | |
144 } | |
145 wrappers_.clear(); | |
146 | |
147 uint32_t size = storage_->size; | |
148 if (size == 0) | |
149 return; | |
150 | |
151 wrappers_.reserve(size); | |
152 for (size_t i = 0; i < size; ++i) | |
153 wrappers_.push_back(new T(&storage_->elements[i], NOT_OWNED)); | |
154 } | |
155 | |
156 internal::MayOwnPtr<CArrayType> storage_; | |
157 std::vector<T*> wrappers_; | |
158 }; | |
159 | |
160 template <> | |
161 class Array<double> { | |
162 public: | |
163 typedef PP_Double_Array* COutputType; | |
164 | |
165 Array(PP_Double_Array* storage, NotOwned) : storage_(storage, NOT_OWNED) { | |
166 PP_DCHECK(storage_->size == 0); | |
167 PP_DCHECK(storage_->elements == NULL); | |
168 } | |
169 | |
170 explicit Array(uint32_t size) { | |
171 Reset(size); | |
172 } | |
173 | |
174 Array(const Array<double>& other) { | |
175 DeepCopy(*other.storage_); | |
176 } | |
177 | |
178 ~Array() { | |
179 Reset(0); | |
180 } | |
181 | |
182 Array<double>& operator=(const Array<double>& other) { | |
183 return operator=(*other.storage_); | |
184 } | |
185 | |
186 Array<double>& operator=(const PP_Double_Array& other) { | |
187 if (storage_.get() == &other) | |
188 return *this; | |
189 | |
190 Reset(0); | |
191 DeepCopy(other); | |
192 | |
193 return *this; | |
194 } | |
195 | |
196 uint32_t size() const { | |
197 return storage_->size; | |
198 } | |
199 | |
200 double& operator[](uint32_t index) { | |
201 PP_DCHECK(index < storage_->size); | |
202 return storage_->elements[index]; | |
203 } | |
204 | |
205 double operator[](uint32_t index) const { | |
206 PP_DCHECK(index < storage_->size); | |
207 return storage_->elements[index]; | |
208 } | |
209 | |
210 void Reset(uint32_t size) { | |
211 internal::ArrayAllocator::Free(storage_->elements); | |
212 storage_->elements = NULL; | |
213 | |
214 storage_->size = size; | |
215 if (size == 0) | |
216 return; | |
217 | |
218 storage_->elements = new double[size]; | |
219 memset(storage_->elements, 0, sizeof(double) * size); | |
220 } | |
221 | |
222 PP_Double_Array* StartRawUpdate() { | |
223 Reset(0); | |
224 return storage_.get(); | |
225 } | |
226 | |
227 void EndRawUpdate() {} | |
228 | |
229 private: | |
230 void DeepCopy(const PP_Double_Array& other) { | |
231 storage_->size = other.size; | |
232 | |
233 if (storage_->size == 0) | |
234 return; | |
235 | |
236 storage_->elements = new double[storage_->size]; | |
237 // TODO(yzshen): for different things, this needs different handling. | |
238 memcpy(storage_->elements, other.elements, sizeof(double) * storage_->size); | |
239 } | |
240 | |
241 internal::MayOwnPtr<PP_Double_Array> storage_; | |
242 }; | |
243 | |
244 } // namespace pp | |
245 | |
246 #endif // PPAPI_CPP_DEV_ARRAY_DEV_H_ | |
OLD | NEW |