summaryrefslogtreecommitdiffstats
path: root/ppapi/cpp/output_traits.h
blob: 31cdbbe11220eccddd739c7fac6f00d27be6409f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef PPAPI_CPP_OUTPUT_TRAITS_H_
#define PPAPI_CPP_OUTPUT_TRAITS_H_

#include <vector>

#include "ppapi/c/pp_resource.h"
#include "ppapi/cpp/array_output.h"
#include "ppapi/cpp/resource.h"

/// @file
/// This file defines internal templates for defining how data is passed to the
/// browser via output parameters and how to convert that data to the
/// corresponding C++ object types.
///
/// It is used by the callback system, it should not be necessary for end-users
/// to use these templates directly.

struct PP_Var;

namespace pp {

class Var;

namespace internal {

// This goop is a trick used to implement a template that can be used to
// determine if a given class is the base class of another given class. It is
// used in the resource object partial specialization below.
template<typename, typename> struct IsSame {
  static bool const value = false;
};
template<typename A> struct IsSame<A, A> {
  static bool const value = true;
};
template<typename Base, typename Derived> struct IsBaseOf {
 private:
  // This class doesn't work correctly with forward declarations.
  // Because sizeof cannot be applied to incomplete types, this line prevents us
  // from passing in forward declarations.
  typedef char (*EnsureTypesAreComplete)[sizeof(Base) + sizeof(Derived)];

  static Derived* CreateDerived();
  static char (&Check(Base*))[1];
  static char (&Check(...))[2];

 public:
  static bool const value = sizeof Check(CreateDerived()) == 1 &&
                            !IsSame<Base const, void const>::value;
};

// Template to optionally derive from a given base class T if the given
// predicate P is true.
template <class T, bool P> struct InheritIf {};
template <class T> struct InheritIf<T, true> : public T {};

// Single output parameters ----------------------------------------------------

// Output traits for all "plain old data" (POD) types. It is implemented to
// pass a pointer to the browser as an output parameter.
//
// This is used as a base class for the general CallbackOutputTraits below in
// the case where T is not a resource.
template<typename T>
struct GenericCallbackOutputTraits {
  // The type passed to the PPAPI C API for this parameter. For normal out
  // params, we pass a pointer to the object so the browser can write into it.
  typedef T* APIArgType;

  // The type used to store the value. This is used internally in asynchronous
  // callbacks by the CompletionCallbackFactory to have the browser write into
  // a temporary value associated with the callback, which is passed to the
  // plugin code when the callback is issued.
  typedef T StorageType;

  // Converts a "storage type" to a value that can be passed to the browser as
  // an output parameter. This just takes the address to convert the value to
  // a pointer.
  static inline APIArgType StorageToAPIArg(StorageType& t) { return &t; }

  // Converts the "storage type" to the value we pass to the plugin for
  // callbacks. This doesn't actually need to do anything in this case,
  // it's needed for some of more complex template specializations below.
  static inline T& StorageToPluginArg(StorageType& t) { return t; }

  // Initializes the "storage type" to a default value, if necessary. Here,
  // we do nothing, assuming that the default constructor for T suffices.
  static inline void Initialize(StorageType* /* t */) {}
};

// Output traits for all resource types. It is implemented to pass a
// PP_Resource* as an output parameter to the browser, and convert to the
// given resource object type T when passing to the plugin.
//
// Note that this class is parameterized by the resource object, for example
// ResourceCallbackOutputTraits<pp::FileRef>. This is used as a base class for
// CallbackOutputTraits below for the case where T is a derived class of
// pp::Resource.
template<typename T>
struct ResourceCallbackOutputTraits {
  // To call the browser, we just pass a PP_Resource pointer as the out param.
  typedef PP_Resource* APIArgType;
  typedef PP_Resource StorageType;

  static inline APIArgType StorageToAPIArg(StorageType& t) {
    return &t;
  }

  // Converts the PP_Resource to a pp::* object, passing any reference counted
  // object along with it. This must only be called once since there will only
  // be one reference that the browser has assigned to us for the out param!
  // When calling into the plugin, convert the PP_Resource into the requested
  // resource object type.
  static inline T StorageToPluginArg(StorageType& t) {
    return T(PASS_REF, t);
  }

  static inline void Initialize(StorageType* t) {
    *t = 0;
  }
};

// The general templatized base class for all CallbackOutputTraits. This class
// covers both resources and POD (ints, structs, etc.) by inheriting from the
// appropriate base class depending on whether the given type derives from
// pp::Resource. This trick allows us to do this once rather than writing
// specializations for every resource object type.
template<typename T>
struct CallbackOutputTraits
    : public InheritIf<GenericCallbackOutputTraits<T>,
                       !IsBaseOf<Resource, T>::value>,
      public InheritIf<ResourceCallbackOutputTraits<T>,
                       IsBaseOf<Resource, T>::value> {
};

// A specialization of CallbackOutputTraits for pp::Var output parameters.
// It passes a PP_Var* to the browser and converts to a pp::Var when passing
// to the plugin.
template<>
struct CallbackOutputTraits<Var> {
  // To call the browser, we just pass a PP_Var* as an output param.
  typedef PP_Var* APIArgType;
  typedef PP_Var StorageType;

  static inline APIArgType StorageToAPIArg(StorageType& t) {
    return &t;
  }

  // Converts the PP_Var to a pp::Var object, passing any reference counted
  // object along with it. This must only be called once since there will only
  // be one reference that the browser has assigned to us for the out param!
  static inline pp::Var StorageToPluginArg(StorageType& t) {
    return Var(PASS_REF, t);
  }

  static inline void Initialize(StorageType* t) {
    *t = PP_MakeUndefined();
  }
};

// A specialization of CallbackOutputTraits for bool output parameters.
// It passes a PP_Bool* to the browser and converts to a bool when passing
// to the plugin.
template<>
struct CallbackOutputTraits<bool> {
  // To call the browser, we just pass a PP_Bool* as an output param.
  typedef PP_Bool* APIArgType;
  typedef PP_Bool StorageType;

  static inline APIArgType StorageToAPIArg(StorageType& t) {
    return &t;
  }

  // Converts the PP_Bool to a bool object.
  static inline bool StorageToPluginArg(StorageType& t) {
    return PP_ToBool(t);
  }

  static inline void Initialize(StorageType* t) {
    *t = PP_FALSE;
  }
};

// Array output parameters -----------------------------------------------------

// Output traits for vectors of all "plain old data" (POD) types. It is
// implemented to pass a pointer to the browser as an output parameter.
//
// This is used as a base class for the general vector CallbackOutputTraits
// below in the case where T is not a resource.
template<typename T>
struct GenericVectorCallbackOutputTraits {
  // All arrays are output via a PP_ArrayOutput type.
  typedef PP_ArrayOutput APIArgType;

  // We store the array as this adapter which combines the PP_ArrayOutput
  // structure with the underlying std::vector that it will write into.
  typedef ArrayOutputAdapterWithStorage<T> StorageType;

  // Retrieves the PP_ArrayOutput interface for our vector object that the
  // browser will use to write into our code.
  static inline APIArgType StorageToAPIArg(StorageType& t) {
    return t.pp_array_output();
  }

  // Retrieves the underlying vector that can be passed to the plugin.
  static inline std::vector<T>& StorageToPluginArg(StorageType& t) {
    return t.output();
  }

  static inline void Initialize(StorageType* /* t */) {}
};

// Output traits for all vectors of resource types. It is implemented to pass
// a PP_ArrayOutput parameter to the browser, and convert the returned resources
// to a vector of the given resource object type T when passing to the plugin.
//
// Note that this class is parameterized by the resource object, for example
// ResourceVectorCallbackOutputTraits<pp::FileRef>. This is used as a base
// class for CallbackOutputTraits below for the case where T is a derived
// class of pp::Resource.
template<typename T>
struct ResourceVectorCallbackOutputTraits {
  typedef PP_ArrayOutput APIArgType;
  typedef ResourceArrayOutputAdapterWithStorage<T> StorageType;

  static inline APIArgType StorageToAPIArg(StorageType& t) {
    return t.pp_array_output();
  }
  static inline std::vector<T>& StorageToPluginArg(StorageType& t) {
    return t.output();
  }

  static inline void Initialize(StorageType* /* t */) {}
};

// Specialization of CallbackOutputTraits for vectors. This struct covers both
// arrays of resources and arrays of POD (ints, structs, etc.) by inheriting
// from the appropriate base class depending on whether the given type derives
// from pp::Resource. This trick allows us to do this once rather than writing
// specializations for every resource object type.
template<typename T>
struct CallbackOutputTraits< std::vector<T> >
    : public InheritIf<GenericVectorCallbackOutputTraits<T>,
                       !IsBaseOf<Resource, T>::value>,
      public InheritIf<ResourceVectorCallbackOutputTraits<T>,
                       IsBaseOf<Resource, T>::value> {
};

// A specialization of CallbackOutputTraits to provide the callback system
// the information on how to handle vectors of pp::Var. Vectors of resources
// and plain data are handled separately. See the above definition for more.
template<>
struct CallbackOutputTraits< std::vector<pp::Var> > {
  // All arrays are output via a PP_ArrayOutput type.
  typedef PP_ArrayOutput APIArgType;

  // We store the array as this adapter which combines the PP_ArrayOutput
  // structure with the underlying std::vector that it will write into.
  typedef VarArrayOutputAdapterWithStorage StorageType;

  // Retrieves the PP_ArrayOutput interface for our vector object that the
  // browser will use to write into our code.
  static inline APIArgType StorageToAPIArg(StorageType& t) {
    return t.pp_array_output();
  }

  // Retrieves the underlying vector that can be passed to the plugin.
  static inline std::vector<pp::Var>& StorageToPluginArg(StorageType& t) {
    return t.output();
  }

  static inline void Initialize(StorageType* /* t */) {}
};

}  // namespace internal
}  // namespace pp

#endif  // PPAPI_CPP_OUTPUT_TRAITS_H_