summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/proxy_array_output.h
blob: 6d15e0b8358018f1e1f514944fbb2e3408a3b769 (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
// 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_PROXY_PROXY_ARRAY_OUTPUT_H_
#define PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_

#include <vector>

#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "ppapi/c/pp_array_output.h"

// Like ppapi/cpp/array_output.h file in the C++ wrappers but for use in the
// proxy where we can't link to the C++ wrappers. This also adds a refcounted
// version.
//
// Use ArrayOutputAdapter when calling a function that synchronously returns
// an array of data. Use RefCountedArrayOutputAdapterWithStorage for
// asynchronous returns:
//
// void OnCallbackComplete(
//     int32_t result,
//     scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output) {
//   // Vector is in output->output().
// }
//
// void ScheduleCallback() {
//   base::scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output;
//
//   callback = factory.NewOptionalCallback(&OnCallbackComplete, output);
//   DoSomethingAsynchronously(output->pp_array_output(),
//                             callback.pp_completion_callback());
//   ...
namespace ppapi {
namespace proxy {

// Non-templatized base class for the array output conversion. It provides the
// C implementation of a PP_ArrayOutput whose callback function is implemented
// as a virtual call on a derived class. Do not use directly, use one of the
// derived classes below.
class ArrayOutputAdapterBase {
 public:
  ArrayOutputAdapterBase() {
    pp_array_output_.GetDataBuffer =
        &ArrayOutputAdapterBase::GetDataBufferThunk;
    pp_array_output_.user_data = this;
  }
  virtual ~ArrayOutputAdapterBase() {}

  const PP_ArrayOutput& pp_array_output() { return pp_array_output_; }

 protected:
  virtual void* GetDataBuffer(uint32_t element_count,
                              uint32_t element_size) = 0;

 private:
  static void* GetDataBufferThunk(void* user_data,
                                  uint32_t element_count,
                                  uint32_t element_size);

  PP_ArrayOutput pp_array_output_;

  // Disallow copying and assignment. This will do the wrong thing for most
  // subclasses.
  ArrayOutputAdapterBase(const ArrayOutputAdapterBase&);
  ArrayOutputAdapterBase& operator=(const ArrayOutputAdapterBase&);
};

// This adapter provides functionality for implementing a PP_ArrayOutput
// structure as writing to a given vector object.
//
// This is generally used internally in the C++ wrapper objects to
// write into an output parameter supplied by the plugin. If the element size
// that the browser is writing does not match the size of the type we're using
// this will assert and return NULL (which will cause the browser to fail the
// call).
//
// Example that allows the browser to write into a given vector:
//   void DoFoo(std::vector<int>* results) {
//     ArrayOutputAdapter<int> adapter(results);
//     ppb_foo->DoFoo(adapter.pp_array_output());
//   }
template<typename T>
class ArrayOutputAdapter : public ArrayOutputAdapterBase {
 public:
  ArrayOutputAdapter(std::vector<T>* output) : output_(output) {}

 protected:
  // Two-step init for the "with storage" version below.
  ArrayOutputAdapter() : output_(NULL) {}
  void set_output(std::vector<T>* output) { output_ = output; }

  // ArrayOutputAdapterBase implementation.
  virtual void* GetDataBuffer(uint32_t element_count, uint32_t element_size) {
    DCHECK(element_size == sizeof(T));
    if (element_count == 0 || element_size != sizeof(T))
      return NULL;
    output_->resize(element_count);
    return &(*output_)[0];
  }

 private:
  std::vector<T>* output_;
};

template<typename T>
class ArrayOutputAdapterWithStorage : public ArrayOutputAdapter<T> {
 public:
  ArrayOutputAdapterWithStorage() {
    // Note: "this->" is required due to two-phase name lookup where it isn't
    // allowed to look in the base class during parsing.
    this->set_output(&output_storage_);
  }

  std::vector<T>& output() { return output_storage_; }

 private:
  std::vector<T> output_storage_;
};

// A reference counted version of ArrayOutputAdapterWithStorage. Since it
// doesn't make much sense to heap-allocate one without storage, we don't
// call it "with storage" to keep the name length under control.
template<typename T>
class RefCountedArrayOutputAdapter
    : public ArrayOutputAdapterWithStorage<T>,
      public base::RefCounted<RefCountedArrayOutputAdapter<T> > {
 public:
  RefCountedArrayOutputAdapter()
      : ArrayOutputAdapterWithStorage<T>() {
  }
};

}  // namespace proxy
}  // namespace ppapi

#endif  // PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_