Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: ppapi/cpp/dev/array_dev.h

Issue 116963003: App APIs in Pepper: C++ APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 <vector>
11
12 #include "ppapi/cpp/dev/may_own_ptr_dev.h"
13 #include "ppapi/cpp/logging.h"
14 #include "ppapi/cpp/output_traits.h"
15
16 namespace pp {
17
18 template <typename T>
19 class Array;
20
21 namespace internal {
22
23 class ArrayAllocator {
24 public:
25 // Allocates memory and zero-fills it.
26 static void* Alloc(uint32_t count, uint32_t size) {
27 if (count == 0 || size == 0)
28 return NULL;
29
30 return calloc(count, size);
31 }
32
33 static void Free(void* mem) { free(mem); }
34
35 static PP_ArrayOutput Get() {
36 PP_ArrayOutput array_output = { &ArrayAllocator::GetDataBuffer, NULL };
37 return array_output;
38 }
39
40 private:
41 static void* GetDataBuffer(void* /* user_data */,
42 uint32_t element_count,
43 uint32_t element_size) {
44 return Alloc(element_count, element_size);
45 }
46 };
47
48 // A specialization of CallbackOutputTraits for pp::Array parameters.
49 template <typename T>
50 struct CallbackOutputTraits<Array<T> > {
51 typedef typename Array<T>::CArrayType* APIArgType;
52 typedef Array<T> StorageType;
53
54 // Returns the underlying C struct of |t|, which can be passed to the browser
55 // as an output parameter.
56 static inline APIArgType StorageToAPIArg(StorageType& t) {
57 return t.StartRawUpdate();
58 }
59
60 // For each |t| passed into StorageToAPIArg(), this method must be called
61 // exactly once in order to match StartRawUpdate() and EndRawUpdate().
62 static inline Array<T>& StorageToPluginArg(StorageType& t) {
63 t.EndRawUpdate();
64 return t;
65 }
66
67 static inline void Initialize(StorageType* /* t */) {}
68 };
69
70 } // namespace internal
71
72 // Generic array for struct wrappers.
73 template <class T>
74 class Array {
75 public:
76 typedef typename T::CArrayType CArrayType;
77 typedef typename T::CType CType;
78
79 Array() {}
80
81 explicit Array(uint32_t size) { Reset(size); }
82
83 // Creates an accessor to |storage| but doesn't take ownership of it.
84 // |storage| must live longer than this object. The contents pointed to by
85 // |storage| must be zero-initialized by the caller.
86 //
87 // Although this object doesn't own the memory of |storage|, it manages the
88 // memory pointed to by |storage->elements| and resets |storage| to empty when
89 // destructed.
90 Array(CArrayType* storage, NotOwned) : storage_(storage, NOT_OWNED) {
91 PP_DCHECK(storage_->size == 0);
92 PP_DCHECK(storage_->elements == NULL);
93 }
94
95 Array(const Array<T>& other) { DeepCopy(*other.storage_); }
96
97 ~Array() { Reset(0); }
98
99 Array<T>& operator=(const Array<T>& other) {
100 return operator=(*other.storage_);
101 }
102
103 Array<T>& operator=(const CArrayType& other) {
104 if (storage_.get() == &other)
105 return *this;
106
107 Reset(0);
108 DeepCopy(other);
109
110 return *this;
111 }
112
113 uint32_t size() const { return storage_->size; }
114
115 T& operator[](uint32_t index) {
116 PP_DCHECK(storage_->size == wrappers_.size());
117 PP_DCHECK(index < storage_->size);
118 PP_DCHECK(wrappers_[index]->ToStruct() == storage_->elements + index);
119 return *wrappers_[index];
120 }
121
122 const T& operator[](uint32_t index) const {
123 PP_DCHECK(storage_->size == wrappers_.size());
124 PP_DCHECK(index < storage_->size);
125 PP_DCHECK(wrappers_[index]->ToStruct() == storage_->elements + index);
126 return *wrappers_[index];
127 }
128
129 // Clears the existing contents of the array, and resets it to |size| elements
130 // of default value.
131 void Reset(uint32_t size) {
132 // Wrappers must be destroyed before we free |storage_->elements|, because
133 // they may try to access the memory in their destructors.
134 DeleteWrappers();
135
136 internal::ArrayAllocator::Free(storage_->elements);
137 storage_->elements = NULL;
138
139 storage_->size = size;
140 if (size > 0) {
141 storage_->elements = static_cast<CType*>(
142 internal::ArrayAllocator::Alloc(size, sizeof(CType)));
143 }
144
145 CreateWrappers();
146 }
147
148 // Sets the underlying C array struct to empty before returning it.
149 CArrayType* StartRawUpdate() {
150 Reset(0);
151 return storage_.get();
152 }
153
154 void EndRawUpdate() { CreateWrappers(); }
Sam McNally 2013/12/22 22:44:33 In this case the storage passed to the wrapper con
yzshen1 2013/12/26 19:19:51 Good catch! Thanks! I didn't notice this issue wh
155
156 private:
157 void DeepCopy(const CArrayType& other) {
158 storage_->size = other.size;
159
160 if (storage_->size > 0) {
161 storage_->elements = static_cast<CType*>(
162 internal::ArrayAllocator::Alloc(storage_->size, sizeof(CType)));
163 }
164
165 CreateWrappers();
166
167 for (size_t i = 0; i < storage_->size; ++i)
168 wrappers_[i] = other.elements[i];
169 }
170
171 void DeleteWrappers() {
172 for (typename std::vector<T*>::iterator iter = wrappers_.begin();
173 iter != wrappers_.end();
174 ++iter) {
175 delete *iter;
176 }
177 wrappers_.clear();
178 }
179
180 void CreateWrappers() {
181 PP_DCHECK(wrappers_.empty());
182
183 uint32_t size = storage_->size;
184 if (size == 0)
185 return;
186
187 wrappers_.reserve(size);
188 for (size_t i = 0; i < size; ++i)
189 wrappers_.push_back(new T(&storage_->elements[i], NOT_OWNED));
190 }
191
192 internal::MayOwnPtr<CArrayType> storage_;
193 std::vector<T*> wrappers_;
194 };
195
196 } // namespace pp
197
198 #endif // PPAPI_CPP_DEV_ARRAY_DEV_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698