/*
  The %implict macro allows a SwigType (Class) to be accepted
  as an input parameter and use its implicit constructors when needed.

  For example:


  %implicit(A, int, double, B);

  %inline 
  {
    struct B { };  
    struct A
    {
      int ii;
      A(int i) { ii = 1; }
      A(double d) { ii = 2; }
      A(const B& b) { ii = 3; }
    };
  
    int get(A a) { return a.ii; }
  }

  Here, you can call 'get' as 

    get(1)    ==> get(A(1))
    get(2.0)  ==> get(A(2.0))
    get(B())  ==> get(A(B()))

   and swig will construct an 'A' temporal variable using the
   corresponding implicit constructor.


  The plain implicit macro takes care of simple type list. If it doesn't
  work because you are passing template types with commas, then use
  the %implicit_{1,2,3} versions and/or the %arg macro.

*/

%define %implicit_type(Type...)
%traits_swigtype(Type);
%enddef

%define %implicit_frag(Type...) ,fragment=SWIG_Traits_frag(Type) %enddef

%define %implicit_code(Type...)
{
  Type _v;
  int res = swig::asval<Type >(obj, &_v);  
  if (SWIG_IsOK(res)) {
    if (val) *val = new value_type(static_cast<const Type& >(_v));
    return SWIG_AddNewMask(res);
  }
}
%enddef

/* implicit */

%define %implicit(Type, ...)

%formacro_1(%implicit_type,__VA_ARGS__);

%fragment(SWIG_Traits_frag(Type),"header",
	  fragment="StdTraits"
          %formacro_1(%implicit_frag,__VA_ARGS__)) %{
namespace swig {
  template <>  struct traits<Type > {   
    typedef pointer_category category;
    static const char* type_name() { return "Type"; }
  };
   
  template <> struct traits_asptr< Type > {
  typedef Type value_type;
  static int asptr(SWIG_Object obj, value_type **val) { 
    Type *vptr;
    static swig_type_info* desc = SWIG_TypeQuery("Type *");
    int res = SWIG_ConvertPtr(obj, (void **)&vptr, desc, 0);
    if (SWIG_IsOK(res)) {
      if (val) *val = vptr;
      return res;
    } else {
      %formacro_1(%implicit_code,__VA_ARGS__)
    }
    return SWIG_TypeError;
  }
 };
}
%}

%typemap_traits_ptr(%checkcode(POINTER),Type);
%enddef

/* implicit_1 */


%define %implicit_1(Type, Imp1)
%traits_swigtype(Imp1);

%fragment(SWIG_Traits_frag(Type),"header",
	  fragment="StdTraits",
	  fragment=SWIG_Traits_frag(Imp1)) %{
namespace swig {
  template <>  struct traits< Type > {   
    typedef pointer_category category;
    static const char* type_name() { return "Type"; }
  };
   
  template <> struct traits_asptr< Type > {   
  typedef Type value_type;
  static int asptr(SWIG_Object obj, value_type **val) { 
    Type *vptr;
    static swig_type_info* desc = SWIG_TypeQuery("Type *");
    int res = SWIG_ConvertPtr(obj, (void **)&vptr, desc, 0);
    if (SWIG_IsOK(res)) {
      if (val) *val = vptr;
      return res;
    } else {
      %implicit_code(Imp1);
    }
    return SWIG_TypeError;
  }
 };
}
%}

%typemap_traits_ptr(%checkcode(POINTER),Type);

%enddef

/* implicit_2 */

%define %implicit_2(Type, Imp1, Imp2)
%traits_swigtype(Imp1);
%traits_swigtype(Imp2);

%fragment(SWIG_Traits_frag(Type),"header",
	  fragment="StdTraits",
	  fragment=SWIG_Traits_frag(Imp1),
	  fragment=SWIG_Traits_frag(Imp2)) %{
namespace swig {
  template <>  struct traits< Type > {   
    typedef pointer_category category;
    static const char* type_name() { return "Type"; }
  };

  template <> struct traits_asptr< Type > {   
  typedef Type value_type;
  static int asptr(SWIG_Object obj, value_type **val) { 
    Type *vptr;
    static swig_type_info* desc = SWIG_TypeQuery("Type *");
    int res = SWIG_ConvertPtr(obj, (void **)&vptr, desc, 0);
    if (SWIG_IsOK(res)) {
      if (val) *val = vptr;
      return SWIG_OLDOBJ;
    } else {
      %implicit_code(Imp1);
      %implicit_code(Imp2);
    }
    return SWIG_TypeError;
  }
 };
}
%}

%typemap_traits_ptr(%checkcode(POINTER),Type);
%enddef


/* implicit_3 */

%define %implicit_3(Type, Imp1, Imp2, Imp3)
%traits_swigtype(Imp1);
%traits_swigtype(Imp2);
%traits_swigtype(Imp3);

%fragment(SWIG_Traits_frag(Type),"header",
	  fragment="StdTraits",
	  fragment=SWIG_Traits_frag(Imp1),
	  fragment=SWIG_Traits_frag(Imp2),
	  fragment=SWIG_Traits_frag(Imp3)) %{
namespace swig {
  template <>  struct traits< Type > {   
    typedef pointer_category category;
    static const char* type_name() { return "Type"; }
  };

  template <> struct traits_asptr< Type > {   
    typedef Type value_type;
    static int asptr(SWIG_Object obj, value_type **val) { 
    Type *vptr;
    static swig_type_info* desc = SWIG_TypeQuery("Type *");
    int res = SWIG_ConvertPtr(obj, (void **)&vptr, desc, 0);
    if (SWIG_IsOK(res)) {
      if (val) *val = vptr;
      return res;
    } else {
      %implicit_code(Imp1);
      %implicit_code(Imp2);
      %implicit_code(Imp3);
    }
    return SWIG_TypeError;
  }
 };
}
%}

%typemap_traits_ptr(%checkcode(POINTER),Type);
%enddef
