Home | History | Annotate | Download | only in ruby
      1 /**
      2  * @file   rubystdfunctors.swg
      3  * @date   Sun May  6 00:44:33 2007
      4  *
      5  * @brief  This file provides unary and binary functors for STL
      6  *         containers, that will invoke a Ruby proc or method to do
      7  *         their operation.
      8  *
      9  *         You can use them in a swig file like:
     10  *
     11  *         %include <std_set.i>
     12  *         %include <std_functors.i>
     13  *
     14  *         %template< IntSet > std::set< int, swig::BinaryPredicate<> >;
     15  *
     16  *
     17  *         which will then allow calling them from Ruby either like:
     18  *
     19  *            # order of set is defined by C++ default
     20  *            a = IntSet.new
     21  *
     22  *            # sort order defined by Ruby proc
     23  *            b = IntSet.new( proc { |a,b| a > b } )
     24  *
     25  */
     26 
     27 %include rubyclasses.swg
     28 
     29 
     30 namespace swig {
     31 
     32   %apply GC_VALUE { UnaryPredicate, BinaryPredicate, UnaryFunction,
     33 		      BinaryFunction };
     34 
     35   %typecheck(SWIG_TYPECHECK_POINTER,noblock=1)
     36     UnaryPredicate, UnaryPredicate&, UnaryFunction, UnaryFunction&
     37   {
     38     $1 = SWIG_Ruby_isCallable($input) && SWIG_Ruby_arity($input, 1);
     39   }
     40 
     41   %typecheck(SWIG_TYPECHECK_POINTER,noblock=1)
     42     BinaryPredicate, BinaryPredicate&, BinaryFunction, BinaryFunction& {
     43     $1 = SWIG_Ruby_isCallable($input) && SWIG_Ruby_arity($input, 2);
     44   }
     45 
     46   %typemap(in,noblock=1)  BinaryFunction&, BinaryFunction {
     47     $1 = new swig::BinaryFunction< >($input);
     48   }
     49   %typemap(in,noblock=1) UnaryFunction&, UnaryFunction {
     50     $1 = new swig::UnaryFunction< >($input);
     51   }
     52 
     53   %typemap(in,noblock=1) BinaryPredicate&, BinaryPredicate {
     54     $1 = new swig::BinaryPredicate<>($input);
     55   }
     56 
     57   %typemap(in,noblock=1) UnaryPredicate&, UnaryPredicate {
     58     $1 = new swig::UnaryPredicate< >($input);
     59   }
     60 
     61 
     62   %ignore BinaryFunction;
     63   template< class _T = GC_VALUE >
     64   struct BinaryFunction {
     65   };
     66 
     67   %ignore UnaryFunction;
     68   template< class _T = GC_VALUE >
     69   struct UnaryFunction {
     70   };
     71 
     72   %ignore BinaryPredicate;
     73   template< class _T = GC_VALUE >
     74   struct BinaryPredicate {
     75   };
     76 
     77   %ignore UnaryPredicate;
     78   template< class _T = GC_VALUE >
     79   struct UnaryPredicate {
     80 
     81   };
     82 
     83 }
     84 
     85 
     86 %fragment("StdFunctors","header",fragment="StdTraits",fragment="GC_VALUE_definition")
     87 {
     88 namespace swig {
     89 
     90   static ID call_id = rb_intern("call");
     91 
     92   template <class _T = GC_VALUE, class _DefaultFunc = std::less<GC_VALUE> >
     93   struct BinaryPredicate : GC_VALUE, std::binary_function< _T, _T, bool >
     94   {
     95     BinaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { }
     96     bool operator()(_T a, _T b) const
     97     {
     98       if (_obj != Qnil) {
     99         SWIG_RUBY_THREAD_BEGIN_BLOCK;
    100 	VALUE arg1 = swig::from(a);
    101 	VALUE arg2 = swig::from(b);
    102 	VALUE res = rb_funcall( _obj, swig::call_id, 2, arg1, arg2);
    103         SWIG_RUBY_THREAD_END_BLOCK;
    104         return RTEST(res);
    105       } else {
    106         return _DefaultFunc()(a, b);
    107       }
    108     }
    109   };
    110 
    111   template <class _T = GC_VALUE, class _DefaultFunc = std::less< _T > >
    112   struct BinaryFunction : GC_VALUE, std::binary_function< _T, _T, _T >
    113   {
    114     BinaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { }
    115     _T operator()(_T a, _T b) const
    116     {
    117       if (_obj != Qnil) {
    118         SWIG_RUBY_THREAD_BEGIN_BLOCK;
    119 	VALUE arg1 = swig::from(a);
    120 	VALUE arg2 = swig::from(b);
    121 	VALUE res = rb_funcall( _obj, swig::call_id, 2, arg1, arg2);
    122         SWIG_RUBY_THREAD_END_BLOCK;
    123         return swig::as<_T >(res);
    124       } else {
    125         return _DefaultFunc()(a, b);
    126       }
    127     }
    128   };
    129 
    130   template< class _T = GC_VALUE >
    131   struct UnaryPredicate : GC_VALUE, std::unary_function< _T, bool >
    132   {
    133     UnaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { }
    134     bool operator()(_T a) const
    135     {
    136       SWIG_RUBY_THREAD_BEGIN_BLOCK;
    137       VALUE arg1 = swig::from<_T >(a);
    138       VALUE res = rb_funcall( _obj, swig::call_id, 1, arg1);
    139       SWIG_RUBY_THREAD_END_BLOCK;
    140       return RTEST(res);
    141     }
    142   };
    143 
    144   template< class _T = GC_VALUE >
    145   struct UnaryFunction : GC_VALUE, std::unary_function< _T, _T >
    146   {
    147     UnaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { }
    148     _T operator()(_T a) const
    149     {
    150       SWIG_RUBY_THREAD_BEGIN_BLOCK;
    151       VALUE arg1 = swig::from(a);
    152       VALUE res = rb_funcall( _obj, swig::call_id, 1, VALUE(arg1));
    153       SWIG_RUBY_THREAD_END_BLOCK;
    154       return swig::as< _T >(res);
    155     }
    156   };
    157 
    158 } // namespace swig
    159 
    160 }
    161 
    162 
    163