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_EXTENSIONS_OUTPUT_TRAITS_H_
6#define PPAPI_CPP_EXTENSIONS_OUTPUT_TRAITS_H_
7
8#include <vector>
9
10#include "ppapi/c/pp_var.h"
11#include "ppapi/cpp/extensions/from_var_converter.h"
12#include "ppapi/cpp/logging.h"
13#include "ppapi/cpp/pass_ref.h"
14#include "ppapi/cpp/var.h"
15#include "ppapi/cpp/var_array.h"
16
17namespace pp {
18namespace ext {
19namespace internal {
20
21template <class T>
22class VarOutputAdapterWithStorage {
23 public:
24  VarOutputAdapterWithStorage() : pp_var_(PP_MakeUndefined()) {
25  }
26
27  ~VarOutputAdapterWithStorage() {
28    PP_DCHECK(pp_var_.type == PP_VARTYPE_UNDEFINED);
29  }
30
31  PP_Var& pp_var() { return pp_var_; }
32
33  T& output() {
34    Var auto_release(PASS_REF, pp_var_);
35    converter_.Set(pp_var_);
36    pp_var_ = PP_MakeUndefined();
37    return converter_.value();
38  }
39
40 private:
41  PP_Var pp_var_;
42  FromVarConverter<T> converter_;
43
44  // Disallow copying and assignment.
45  VarOutputAdapterWithStorage(const VarOutputAdapterWithStorage<T>&);
46  VarOutputAdapterWithStorage<T>& operator=(
47      const VarOutputAdapterWithStorage<T>&);
48};
49
50// ExtCallbackOutputTraits is used with ExtCompletionCallbackWithOutput. Unlike
51// pp::internal::CallbackOutputTraits, it always uses PP_Var* as output
52// parameter type to interact with the browser.
53//
54// For example, CompletionCallbackWithOutput<double> (using
55// pp::internal::CallbackOutputTraits) uses double* as the output parameter
56// type; while ExtCompletionCallbackWithOutput<double> uses PP_Var*.
57template <class T>
58struct ExtCallbackOutputTraits {
59  typedef PP_Var* APIArgType;
60  typedef VarOutputAdapterWithStorage<T> StorageType;
61
62  static inline APIArgType StorageToAPIArg(StorageType& t) {
63    return &t.pp_var();
64  }
65
66  // This must be called exactly once to consume the one PP_Var reference
67  // assigned to us by the browser.
68  static inline T& StorageToPluginArg(StorageType& t) {
69    return t.output();
70  }
71
72  static inline void Initialize(StorageType* /* t */) {}
73};
74
75// This class provides storage for a PP_Var and a vector of objects which are
76// of type T. The PP_Var is used as an output parameter to receive an array var
77// from the browser. Each element in the array var is converted to a T object,
78// using FromVarConverter, and stores in the vector.
79template <class T>
80class ArrayVarOutputAdapterWithStorage {
81 public:
82  ArrayVarOutputAdapterWithStorage() : pp_var_(PP_MakeUndefined()) {
83  }
84
85  ~ArrayVarOutputAdapterWithStorage() {
86    PP_DCHECK(pp_var_.type == PP_VARTYPE_UNDEFINED);
87  }
88
89  PP_Var& pp_var() { return pp_var_; }
90
91  std::vector<T>& output() {
92    PP_DCHECK(output_storage_.empty());
93
94    Var var(PASS_REF, pp_var_);
95    pp_var_ = PP_MakeUndefined();
96    if (var.is_array()) {
97      VarArray array(var);
98
99      uint32_t length = array.GetLength();
100      output_storage_.reserve(length);
101      for (uint32_t i = 0; i < length; ++i) {
102        FromVarConverter<T> converter(array.Get(i).pp_var());
103        output_storage_.push_back(converter.value());
104      }
105    }
106
107    return output_storage_;
108  }
109
110 private:
111  PP_Var pp_var_;
112  std::vector<T> output_storage_;
113
114  // Disallow copying and assignment.
115  ArrayVarOutputAdapterWithStorage(const ArrayVarOutputAdapterWithStorage<T>&);
116  ArrayVarOutputAdapterWithStorage<T>& operator=(
117      const ArrayVarOutputAdapterWithStorage<T>&);
118};
119
120template <class T>
121struct ExtCallbackOutputTraits< std::vector<T> > {
122  typedef PP_Var* APIArgType;
123  typedef ArrayVarOutputAdapterWithStorage<T> StorageType;
124
125  static inline APIArgType StorageToAPIArg(StorageType& t) {
126    return &t.pp_var();
127  }
128
129  // This must be called exactly once to consume the one PP_Var reference
130  // assigned to us by the browser.
131  static inline std::vector<T>& StorageToPluginArg(StorageType& t) {
132    return t.output();
133  }
134
135  static inline void Initialize(StorageType* /* t */) {}
136};
137
138}  // namespace internal
139}  // namespace ext
140}  // namespace pp
141
142#endif  // PPAPI_CPP_EXTENSIONS_OUTPUT_TRAITS_H_
143