$$ This is a pump file for generating file templates.  Pump is a python
$$ script that is part of the Google Test suite of utilities.  Description
$$ can be found here:
$$
$$ http://code.google.com/p/googletest/wiki/PumpManual
$$

$var MAX_ARITY = 6

// Copyright (c) 2011 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 BASE_BIND_INTERNAL_H_
#define BASE_BIND_INTERNAL_H_
#pragma once

#include "base/bind_helpers.h"
#include "base/callback_internal.h"
#include "base/template_util.h"
#include "build/build_config.h"

#if defined(OS_WIN)
#include "base/bind_internal_win.h"
#endif

namespace base {
namespace internal {

// The method by which a function is invoked is determined by 3 different
// dimensions:
//
//   1) The type of function (normal or method).
//   2) The arity of the function.
//   3) The number of bound parameters.
//
// The templates below handle the determination of each of these dimensions.
// In brief:
//
//   FunctionTraits<> -- Provides a normalied signature, and other traits.
//   InvokerN<> -- Provides a DoInvoke() function that actually executes
//                 a calback.
//   InvokerStorageN<> -- Provides storage for the bound parameters, and
//                        typedefs to the above.
//
// More details about the design of each class is included in a comment closer
// to their defition.

// FunctionTraits<>
//
// The FunctionTraits<> template determines the type of function, and also
// creates a NormalizedType used to select the InvokerN classes.  It turns out
// that syntactically, you only really have 2 variations when invoking a
// funciton pointer: normal, and method.  One is invoked func_ptr(arg1). The
// other is invoked (*obj_->method_ptr(arg1)).
//
// However, in the type system, there are many more distinctions. In standard
// C++, there's all variations of const, and volatile on the function pointer.
// In Windows, there are additional calling conventions (eg., __stdcall,
// __fastcall, etc.). FunctionTraits<> handles categorizing each of these into
// a normalized signature.
//
// Having a NormalizedSignature signature, reduces the combinatoric
// complexity of defintions for the InvokerN<> later.  Even though there are
// only 2 syntactic variations on invoking a function, without normalizing the
// signature, there would need to be one specialization of InvokerN for each
// unique (function_type, bound_arg, unbound_args) tuple in order to match all
// function signatures.
//
// By normalizing the function signature, we reduce function_type to exactly 2.

template <typename Sig>
struct FunctionTraits;

$range ARITY 0..MAX_ARITY
$for ARITY [[
$range ARG 1..ARITY

// Function: Arity $(ARITY).
template <typename R[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> {
  typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]);
  typedef false_type IsMethod;

$if ARITY > 0 [[

  // Target type for each bound parameter.

$for ARG [[
  typedef X$(ARG) B$(ARG);

]]  $$ for ARG
]]  $$ if ARITY > 0

};

// Method: Arity $(ARITY).
template <typename R, typename T[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> {
  typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;

$for ARG [[
  typedef X$(ARG) B$(ARG + 1);

]]  $$ for ARG

};

// Const Method: Arity $(ARITY).
template <typename R, typename T[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> {
  typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]);
  typedef true_type IsMethod;

  // Target type for each bound parameter.
  typedef T B1;

$for ARG [[
  typedef X$(ARG) B$(ARG + 1);

]]  $$ for ARG

};

]]  $$for ARITY

// InvokerN<>
//
// The InvokerN templates contain a static DoInvoke() function that is the key
// to implementing type erasure in the Callback() classes.
//
// DoInvoke() is a static function with a fixed signature that is independent
// of StorageType; its first argument is a pointer to the non-templated common
// baseclass of StorageType. This lets us store pointer to DoInvoke() in a
// function pointer that has knowledge of the specific StorageType, and thus
// no knowledge of the bound function and bound parameter types.
//
// As long as we ensure that DoInvoke() is only used with pointers there were
// upcasted from the correct StorageType, we can be sure that execution is
// safe.
//
// The InvokerN templates are the only point that knows the number of bound
// and unbound arguments.  This is intentional because it allows the other
// templates classes in the system to only have as many specializations as
// the max arity of function we wish to support.

$range BOUND 0..MAX_ARITY
$for BOUND [[

template <typename StorageType, typename NormalizedSig>
struct Invoker$(BOUND);

$range ARITY 0..MAX_ARITY
$for ARITY [[

$var UNBOUND = ARITY - BOUND
$if UNBOUND >= 0 [[

$$ Variables for function traits generation.
$range ARG 1..ARITY
$range BOUND_ARG 1..BOUND
$range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY

$$ Variables for method traits generation. We are always short one arity since
$$ the first bound parameter is the object.
$var M_ARITY = ARITY - 1
$range M_ARG 1..M_ARITY
$range M_BOUND_ARG 2..BOUND
$range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY

// Function: Arity $(ARITY) -> $(UNBOUND).
template <typename StorageType, typename R[[]]
$if ARITY > 0 [[,]][[]]
$for ARG , [[typename X$(ARG)]]>
struct Invoker$(BOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> {
  static R DoInvoke(InvokerStorageBase* base[[]]
$if UNBOUND != 0 [[, ]][[]]
$for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]]
$$ Add comma if there are both boudn and unbound args.
$if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]]
$for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]);
  }
};

$if BOUND > 0 [[

// Method: Arity $(M_ARITY) -> $(UNBOUND).
template <typename StorageType, typename R, typename T[[]]
$if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
struct Invoker$(BOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> {
  static R DoInvoke(InvokerStorageBase* base[[]]
$if UNBOUND > 0 [[, ]][[]]
$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) {
    StorageType* invoker = static_cast<StorageType*>(base);
    return (Unwrap(invoker->p1_)->*invoker->f_)([[]]
$for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]]
$if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]]
$for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
  }
};

]]  $$ if BOUND

]]  $$ if UNBOUND
]]  $$ for ARITY
]]  $$ for BOUND


// InvokerStorageN<>
//
// These are the actual storage classes for the Invokers.
//
// Though these types are "classes", they are being used as structs with
// all member variable public.  We cannot make it a struct because it inherits
// from a class which causes a compiler warning.  We cannot add a "Run()" method
// that forwards the unbound arguments because that would require we unwrap the
// Sig type like in InvokerN above to know the return type, and the arity
// of Run().
//
// An alternate solution would be to merge InvokerN and InvokerStorageN,
// but the generated code seemed harder to read.

$for BOUND [[
$range BOUND_ARG 1..BOUND

template <typename Sig[[]]
$if BOUND > 0 [[, ]]
$for BOUND_ARG , [[typename P$(BOUND_ARG)]]>
class InvokerStorage$(BOUND) : public InvokerStorageBase {
 public:
  typedef InvokerStorage$(BOUND) StorageType;
  typedef FunctionTraits<Sig> TargetTraits;
  typedef Invoker$(BOUND)<StorageType, typename TargetTraits::NormalizedSig> Invoker;
  typedef typename TargetTraits::IsMethod IsMethod;

$for BOUND_ARG [[
$if BOUND_ARG == 1 [[

  // For methods, we need to be careful for parameter 1.  We skip the
  // scoped_refptr check because the binder itself takes care of this. We also
  // disallow binding of an array as the method's target object.
  COMPILE_ASSERT(IsMethod::value ||
                 !internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value,
                 p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!IsMethod::value || !is_array<P$(BOUND_ARG)>::value,
                 first_bound_argument_to_method_cannot_be_array);
]] $else [[

  COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value,
                 p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
]]  $$ $if BOUND_ARG
]]  $$ $for BOUND_ARG


$if BOUND > 0 [[

  // Do not allow binding a non-const reference parameter. Non-const reference
  // parameters are disallowed by the Google style guide.  Also, binding a
  // non-const reference parameter can make for subtle bugs because the
  // invoked function will receive a reference to the stored copy of the
  // argument and not the original.
  COMPILE_ASSERT(
      !($for BOUND_ARG || [[ is_non_const_reference<typename TargetTraits::B$(BOUND_ARG)>::value ]]),
      do_not_bind_functions_with_nonconst_ref);

]]


  InvokerStorage$(BOUND)(Sig f
$if BOUND > 0 [[, ]]
$for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]])
      : f_(f)[[]]
$if BOUND == 0 [[
 {

]] $else [[
, $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename ParamTraits<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] {
    MaybeRefcount<IsMethod, P1>::AddRef(p1_);

]]
  }

  virtual ~InvokerStorage$(BOUND)() {
$if BOUND > 0 [[

    MaybeRefcount<IsMethod, P1>::Release(p1_);

]]
  }

  Sig f_;

$for BOUND_ARG [[
  typename ParamTraits<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_;

]]
};

]]  $$ for BOUND

}  // namespace internal
}  // namespace base

#endif  // BASE_BIND_INTERNAL_H_