// Copyright (c) 2013 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_EXTENSIONS_OUTPUT_TRAITS_H_ #define PPAPI_CPP_EXTENSIONS_OUTPUT_TRAITS_H_ #include <vector> #include "ppapi/c/pp_var.h" #include "ppapi/cpp/extensions/from_var_converter.h" #include "ppapi/cpp/logging.h" #include "ppapi/cpp/pass_ref.h" #include "ppapi/cpp/var.h" #include "ppapi/cpp/var_array.h" namespace pp { namespace ext { namespace internal { template <class T> class VarOutputAdapterWithStorage { public: VarOutputAdapterWithStorage() : pp_var_(PP_MakeUndefined()) { } ~VarOutputAdapterWithStorage() { PP_DCHECK(pp_var_.type == PP_VARTYPE_UNDEFINED); } PP_Var& pp_var() { return pp_var_; } T& output() { Var auto_release(PASS_REF, pp_var_); converter_.Set(pp_var_); pp_var_ = PP_MakeUndefined(); return converter_.value(); } private: PP_Var pp_var_; FromVarConverter<T> converter_; // Disallow copying and assignment. VarOutputAdapterWithStorage(const VarOutputAdapterWithStorage<T>&); VarOutputAdapterWithStorage<T>& operator=( const VarOutputAdapterWithStorage<T>&); }; // ExtCallbackOutputTraits is used with ExtCompletionCallbackWithOutput. Unlike // pp::internal::CallbackOutputTraits, it always uses PP_Var* as output // parameter type to interact with the browser. // // For example, CompletionCallbackWithOutput<double> (using // pp::internal::CallbackOutputTraits) uses double* as the output parameter // type; while ExtCompletionCallbackWithOutput<double> uses PP_Var*. template <class T> struct ExtCallbackOutputTraits { typedef PP_Var* APIArgType; typedef VarOutputAdapterWithStorage<T> StorageType; static inline APIArgType StorageToAPIArg(StorageType& t) { return &t.pp_var(); } // This must be called exactly once to consume the one PP_Var reference // assigned to us by the browser. static inline T& StorageToPluginArg(StorageType& t) { return t.output(); } static inline void Initialize(StorageType* /* t */) {} }; // This class provides storage for a PP_Var and a vector of objects which are // of type T. The PP_Var is used as an output parameter to receive an array var // from the browser. Each element in the array var is converted to a T object, // using FromVarConverter, and stores in the vector. template <class T> class ArrayVarOutputAdapterWithStorage { public: ArrayVarOutputAdapterWithStorage() : pp_var_(PP_MakeUndefined()) { } ~ArrayVarOutputAdapterWithStorage() { PP_DCHECK(pp_var_.type == PP_VARTYPE_UNDEFINED); } PP_Var& pp_var() { return pp_var_; } std::vector<T>& output() { PP_DCHECK(output_storage_.empty()); Var var(PASS_REF, pp_var_); pp_var_ = PP_MakeUndefined(); if (var.is_array()) { VarArray array(var); uint32_t length = array.GetLength(); output_storage_.reserve(length); for (uint32_t i = 0; i < length; ++i) { FromVarConverter<T> converter(array.Get(i).pp_var()); output_storage_.push_back(converter.value()); } } return output_storage_; } private: PP_Var pp_var_; std::vector<T> output_storage_; // Disallow copying and assignment. ArrayVarOutputAdapterWithStorage(const ArrayVarOutputAdapterWithStorage<T>&); ArrayVarOutputAdapterWithStorage<T>& operator=( const ArrayVarOutputAdapterWithStorage<T>&); }; template <class T> struct ExtCallbackOutputTraits< std::vector<T> > { typedef PP_Var* APIArgType; typedef ArrayVarOutputAdapterWithStorage<T> StorageType; static inline APIArgType StorageToAPIArg(StorageType& t) { return &t.pp_var(); } // This must be called exactly once to consume the one PP_Var reference // assigned to us by the browser. static inline std::vector<T>& StorageToPluginArg(StorageType& t) { return t.output(); } static inline void Initialize(StorageType* /* t */) {} }; } // namespace internal } // namespace ext } // namespace pp #endif // PPAPI_CPP_EXTENSIONS_OUTPUT_TRAITS_H_