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

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: changes according to David's suggestions. 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 Array(CArrayType* storage, NotOwned) : storage_(storage, NOT_OWNED) {
87 PP_DCHECK(storage_->size == 0);
88 PP_DCHECK(storage_->elements == NULL);
89 }
90
91 Array(const Array<T>& other) { DeepCopy(*other.storage_); }
92
93 ~Array() { Reset(0); }
94
95 Array<T>& operator=(const Array<T>& other) {
96 return operator=(*other.storage_);
97 }
98
99 Array<T>& operator=(const CArrayType& other) {
100 if (storage_.get() == &other)
101 return *this;
102
103 Reset(0);
104 DeepCopy(other);
105
106 return *this;
107 }
108
109 uint32_t size() const { return storage_->size; }
110
111 T& operator[](uint32_t index) {
112 PP_DCHECK(storage_->size == wrappers_.size());
113 PP_DCHECK(index < storage_->size);
114 PP_DCHECK(wrappers_[index]->ToStruct() == storage_->elements + index);
115 return *wrappers_[index];
116 }
117
118 const T& operator[](uint32_t index) const {
119 PP_DCHECK(storage_->size == wrappers_.size());
120 PP_DCHECK(index < storage_->size);
121 PP_DCHECK(wrappers_[index]->ToStruct() == storage_->elements + index);
122 return *wrappers_[index];
123 }
124
125 void Reset(uint32_t size) {
dmichael (off chromium) 2013/12/20 22:01:09 Hmm, I wonder if/when you start using Array in-par
yzshen1 2013/12/20 22:58:18 We could use a std::vector<> as underlying storage
126 // Wrappers must be destroyed before we free |storage_->elements|, because
127 // they may try to access the memory in their destructors.
128 DeleteWrappers();
129
130 internal::ArrayAllocator::Free(storage_->elements);
131 storage_->elements = NULL;
132
133 storage_->size = size;
134 if (size > 0) {
135 storage_->elements = static_cast<CType*>(
136 internal::ArrayAllocator::Alloc(size, sizeof(CType)));
137 }
138
139 CreateWrappers();
140 }
141
142 CArrayType* StartRawUpdate() {
143 Reset(0);
144 return storage_.get();
145 }
146
147 void EndRawUpdate() { CreateWrappers(); }
148
149 private:
150 void DeepCopy(const CArrayType& other) {
151 storage_->size = other.size;
152
153 if (storage_->size > 0) {
154 storage_->elements = static_cast<CType*>(
155 internal::ArrayAllocator::Alloc(storage_->size, sizeof(CType)));
156 }
157
158 CreateWrappers();
159
160 for (size_t i = 0; i < storage_->size; ++i)
161 wrappers_[i] = other.elements[i];
162 }
163
164 void DeleteWrappers() {
165 for (typename std::vector<T*>::iterator iter = wrappers_.begin();
166 iter != wrappers_.end();
167 ++iter) {
168 delete *iter;
169 }
170 wrappers_.clear();
171 }
172
173 void CreateWrappers() {
174 PP_DCHECK(wrappers_.empty());
175
176 uint32_t size = storage_->size;
177 if (size == 0)
178 return;
179
180 wrappers_.reserve(size);
181 for (size_t i = 0; i < size; ++i)
182 wrappers_.push_back(new T(&storage_->elements[i], NOT_OWNED));
183 }
184
185 internal::MayOwnPtr<CArrayType> storage_;
186 std::vector<T*> wrappers_;
187 };
188
189 } // namespace pp
190
191 #endif // PPAPI_CPP_DEV_ARRAY_DEV_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698