1 // Copyright (c) 2012 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.
5 #ifndef PPAPI_CPP_ARRAY_OUTPUT_H_
6 #define PPAPI_CPP_ARRAY_OUTPUT_H_
10 #include "ppapi/c/dev/ppb_directory_reader_dev.h"
11 #include "ppapi/c/pp_array_output.h"
12 #include "ppapi/c/pp_resource.h"
13 #include "ppapi/cpp/dev/directory_entry_dev.h"
14 #include "ppapi/cpp/logging.h"
15 #include "ppapi/cpp/pass_ref.h"
16 #include "ppapi/cpp/var.h"
20 // Converts the given array of PP_Resources into an array of the requested
21 // C++ resource types, passing ownership of a reference in the process.
23 // This is used to convert output arrays of resources that the browser has
24 // generated into the more convenient C++ wrappers for those resources. The
25 // initial "PassRef" parameter is there to emphasize what happens to the
26 // reference count of the input resource and to match the resource constructors
27 // that look the same.
28 template<typename ResourceObjectType
>
29 inline void ConvertPPResourceArrayToObjects(
31 const std::vector
<PP_Resource
>& input
,
32 std::vector
<ResourceObjectType
>* output
) {
34 output
->reserve(input
.size());
35 for (size_t i
= 0; i
< input
.size(); i
++)
36 output
->push_back(ResourceObjectType(PASS_REF
, input
[i
]));
39 // Non-templatized base class for the array output conversion. It provides the
40 // C implementation of a PP_ArrayOutput whose callback function is implemented
41 // as a virtual call on a derived class. Do not use directly, use one of the
42 // derived classes below.
43 class ArrayOutputAdapterBase
{
45 ArrayOutputAdapterBase() {
46 pp_array_output_
.GetDataBuffer
=
47 &ArrayOutputAdapterBase::GetDataBufferThunk
;
48 pp_array_output_
.user_data
= this;
50 virtual ~ArrayOutputAdapterBase() {}
52 const PP_ArrayOutput
& pp_array_output() { return pp_array_output_
; }
55 virtual void* GetDataBuffer(uint32_t element_count
,
56 uint32_t element_size
) = 0;
59 static void* GetDataBufferThunk(void* user_data
,
60 uint32_t element_count
,
61 uint32_t element_size
);
63 PP_ArrayOutput pp_array_output_
;
65 // Disallow copying and assignment. This will do the wrong thing for most
67 ArrayOutputAdapterBase(const ArrayOutputAdapterBase
&);
68 ArrayOutputAdapterBase
& operator=(const ArrayOutputAdapterBase
&);
71 // This adapter provides functionality for implementing a PP_ArrayOutput
72 // structure as writing to a given vector object.
74 // This is generally used internally in the C++ wrapper objects to
75 // write into an output parameter supplied by the plugin. If the element size
76 // that the browser is writing does not match the size of the type we're using
77 // this will assert and return NULL (which will cause the browser to fail the
80 // Example that allows the browser to write into a given vector:
81 // void DoFoo(std::vector<int>* results) {
82 // ArrayOutputAdapter<int> adapter(results);
83 // ppb_foo->DoFoo(adapter.pp_array_output());
86 class ArrayOutputAdapter
: public ArrayOutputAdapterBase
{
88 ArrayOutputAdapter(std::vector
<T
>* output
) : output_(output
) {}
91 // Two-step init for the "with storage" version below.
92 ArrayOutputAdapter() : output_(NULL
) {}
93 void set_output(std::vector
<T
>* output
) { output_
= output
; }
95 // ArrayOutputAdapterBase implementation.
96 virtual void* GetDataBuffer(uint32_t element_count
, uint32_t element_size
) {
97 if (element_count
== 0)
99 PP_DCHECK(element_size
== sizeof(T
));
100 if (element_size
!= sizeof(T
))
102 output_
->resize(element_count
);
103 return &(*output_
)[0];
107 std::vector
<T
>* output_
;
110 // This adapter provides functionality for implementing a PP_ArrayOutput
111 // structure as writing resources to a given vector object.
113 // When returning an array of resources, the browser will write PP_Resources
114 // via a PP_ArrayOutput. This code will automatically convert the PP_Resources
115 // to the given wrapper type, (as long as that wrapper type supports the
116 // correct constructor). The ownership of the resources that the browser passed
117 // to us will be transferred to the C++ wrapper object.
119 // Conversion of the PP_Resources to the C++ wrapper object occurs in the
120 // destructor. This object is intended to be used on the stack in a C++ wrapper
121 // object for a call.
124 // void GetFiles(std::vector<pp::FileRef>* results) {
125 // ResourceArrayOutputAdapter<pp::FileRef> adapter(results);
126 // ppb_foo->DoFoo(adapter.pp_array_output());
129 class ResourceArrayOutputAdapter
: public ArrayOutputAdapterBase
{
131 explicit ResourceArrayOutputAdapter(std::vector
<T
>* output
)
135 virtual ~ResourceArrayOutputAdapter() {
136 ConvertPPResourceArrayToObjects(PASS_REF
, intermediate_output_
, output_
);
140 // Two-step init for the "with storage" version below.
141 ResourceArrayOutputAdapter() : output_(NULL
) {}
142 void set_output(T
* output
) { output_
= output
; }
144 // ArrayOutputAdapterBase implementation.
145 virtual void* GetDataBuffer(uint32_t element_count
,
146 uint32_t element_size
) {
147 if (element_count
== 0)
149 PP_DCHECK(element_size
== sizeof(PP_Resource
));
150 if (element_size
!= sizeof(PP_Resource
))
152 intermediate_output_
.resize(element_count
);
153 return &intermediate_output_
[0];
157 std::vector
<PP_Resource
> intermediate_output_
;
158 std::vector
<T
>* output_
;
161 // This adapter is like the ArrayOutputAdapter except that it also contains
162 // the underlying std::vector that will be populated (rather than writing it to
163 // an object passed into the constructor).
165 // This is used by the CompletionCallbackFactory system to collect the output
166 // parameters from an async function call. The collected data is then passed to
167 // the plugins callback function.
169 // You can also use it directly if you want to have an array output and aren't
170 // using the CompletionCallbackFactory. For example, if you're calling a
171 // PPAPI function DoFoo that takes a PP_OutputArray that is supposed to be
172 // writing integers, do this:
174 // ArrayOutputAdapterWithStorage<int> adapter;
175 // ppb_foo->DoFoo(adapter.pp_output_array());
176 // const std::vector<int>& result = adapter.output();
178 class ArrayOutputAdapterWithStorage
: public ArrayOutputAdapter
<T
> {
180 ArrayOutputAdapterWithStorage() {
181 this->set_output(&output_storage_
);
184 std::vector
<T
>& output() { return output_storage_
; }
187 std::vector
<T
> output_storage_
;
190 // This adapter is like the ArrayOutputAdapterWithStorage except this
191 // additionally converts PP_Var structs to pp::Var objects.
193 // You can also use it directly if you want to have an array output and aren't
194 // using the CompletionCallbackFactory. For example, if you're calling a
195 // PPAPI function GetVars that takes a PP_OutputArray that is supposed to be
196 // writing PP_Vars, do this:
198 // VarArrayOutputAdapterWithStorage adapter;
199 // ppb_foo->GetVars(adapter.pp_output_array());
200 // const std::vector<pp::Var>& result = adapter.output().
202 // This one is non-inline since it's not templatized.
203 class VarArrayOutputAdapterWithStorage
: public ArrayOutputAdapter
<PP_Var
> {
205 VarArrayOutputAdapterWithStorage();
206 virtual ~VarArrayOutputAdapterWithStorage();
208 // Returns the final array of resource objects, converting the PP_Vars
209 // written by the browser to pp::Var objects.
211 // This function should only be called once or we would end up converting
212 // the array more than once, which would mess up the refcounting.
213 std::vector
<Var
>& output();
216 // The browser will write the PP_Vars into this array.
217 std::vector
<PP_Var
> temp_storage_
;
219 // When asked for the output, the resources above will be converted to the
220 // C++ resource objects in this array for passing to the calling code.
221 std::vector
<Var
> output_storage_
;
224 // This adapter is like the ArrayOutputAdapterWithStorage except this
225 // additionally converts PP_Resources to C++ wrapper objects of the given type.
227 // You can also use it directly if you want to have an array output and aren't
228 // using the CompletionCallbackFactory. For example, if you're calling a
229 // PPAPI function GetFiles that takes a PP_OutputArray that is supposed to be
230 // writing PP_Resources cooresponding to FileRefs, do this:
232 // ResourceArrayOutputAdapterWithStorage<FileRef> adapter;
233 // ppb_foo->GetFiles(adapter.pp_output_array());
234 // std::vector<FileRef> result = adapter.output().
236 class ResourceArrayOutputAdapterWithStorage
237 : public ArrayOutputAdapter
<PP_Resource
> {
239 ResourceArrayOutputAdapterWithStorage() {
240 set_output(&temp_storage_
);
243 virtual ~ResourceArrayOutputAdapterWithStorage() {
244 if (!temp_storage_
.empty()) {
245 // An easy way to release the resource references held by this object.
250 // Returns the final array of resource objects, converting the PP_Resources
251 // written by the browser to resource objects.
253 // This function should only be called once or we would end up converting
254 // the array more than once, which would mess up the refcounting.
255 std::vector
<T
>& output() {
256 PP_DCHECK(output_storage_
.empty());
258 ConvertPPResourceArrayToObjects(PASS_REF
, temp_storage_
, &output_storage_
);
259 temp_storage_
.clear();
260 return output_storage_
;
264 // The browser will write the PP_Resources into this array.
265 std::vector
<PP_Resource
> temp_storage_
;
267 // When asked for the output, the resources above will be converted to the
268 // C++ resource objects in this array for passing to the calling code.
269 std::vector
<T
> output_storage_
;
272 class DirectoryEntryArrayOutputAdapterWithStorage
273 : public ArrayOutputAdapter
<PP_DirectoryEntry_Dev
> {
275 DirectoryEntryArrayOutputAdapterWithStorage() {
276 set_output(&temp_storage_
);
279 virtual ~DirectoryEntryArrayOutputAdapterWithStorage() {
280 if (!temp_storage_
.empty()) {
281 // An easy way to release the resource references held by |temp_storage_|.
282 // A destructor for PP_DirectoryEntry_Dev will release them.
287 // Returns the final array of resource objects, converting the
288 // PP_DirectoryEntry_Dev written by the browser to pp::DirectoryEntry_Dev
291 // This function should only be called once or we would end up converting
292 // the array more than once, which would mess up the refcounting.
293 std::vector
<pp::DirectoryEntry_Dev
>& output() {
294 PP_DCHECK(output_storage_
.empty());
295 typedef std::vector
<PP_DirectoryEntry_Dev
> Entries
;
296 for (Entries::iterator it
= temp_storage_
.begin();
297 it
!= temp_storage_
.end(); ++it
)
298 output_storage_
.push_back(DirectoryEntry_Dev(PASS_REF
, *it
));
299 temp_storage_
.clear();
300 return output_storage_
;
304 // The browser will write the PP_DirectoryEntry_Devs into this array.
305 std::vector
<PP_DirectoryEntry_Dev
> temp_storage_
;
307 // When asked for the output, the PP_DirectoryEntry_Devs above will be
308 // converted to the pp::DirectoryEntry_Devs in this array for passing to the
310 std::vector
<pp::DirectoryEntry_Dev
> output_storage_
;
315 #endif // PPAPI_CPP_ARRAY_OUTPUT_H_