// 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_
