diff options
Diffstat (limited to 'devtools/swigwin-1.3.34/Lib/ruby/rubyclasses.swg')
| -rw-r--r-- | devtools/swigwin-1.3.34/Lib/ruby/rubyclasses.swg | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/devtools/swigwin-1.3.34/Lib/ruby/rubyclasses.swg b/devtools/swigwin-1.3.34/Lib/ruby/rubyclasses.swg new file mode 100644 index 0000000..db54826 --- /dev/null +++ b/devtools/swigwin-1.3.34/Lib/ruby/rubyclasses.swg @@ -0,0 +1,395 @@ +#ifdef __cplusplus + +/* + GC_VALUE is used as a replacement of Ruby's VALUE. + GC_VALUE automatically handles registering and unregistering + of the underlying Ruby object with the GC. + + It can be used if you want to create STL containers of VALUEs, such as: + + std::vector< GC_VALUE >; + + or as a member variable: + + struct A { + GC_VALUE _obj; + A(VALUE o) : _obj(o) { + } + }; + + or as a input/output value (not much use for this, as VALUE works just as + well here, thou): + + GC_VALUE func(GC_VALUE obj) { + GC_VALUE out = rb_obj_classname(obj); + return out; + } + + + GC_VALUE is 'visible' at the wrapped side, so you can do: + + %template(RubyVector) std::vector<swig::GC_VALUE>; + + and all the proper typemaps will be used. + +*/ + +namespace swig { + + %nodirector GC_VALUE; + + // We ignore the constructor so that user can never create a GC_VALUE + // manually + %ignore GC_VALUE::GC_VALUE; + + struct GC_VALUE { + VALUE inspect() const; + VALUE to_s() const; + GC_VALUE(); + protected: + GC_VALUE( const GC_VALUE& ); + ~GC_VALUE(); + }; + + %exception GC_VALUE {}; + + + %apply VALUE {GC_VALUE}; + + // Make sure this is the last typecheck done + %typecheck(999999,noblock=1) GC_VALUE, GC_VALUE&, + const GC_VALUE& { $1 = 1; }; + + /* For input */ + %typemap(in,noblock=1) GC_VALUE* (GC_VALUE r), GC_VALUE& (GC_VALUE r) { + r = $input; $1 = &r; + } + + /* For output */ + %typemap(out,noblock=1) GC_VALUE { + $result = (VALUE)$1; + } + + %typemap(out,noblock=1) GC_VALUE*, GC_VALUE const & { + $result = (VALUE)*$1; + } + + %ignore LANGUAGE_OBJ; + typedef GC_VALUE LANGUAGE_OBJ; +} + + +%{ +namespace swig { + class GC_VALUE { + protected: + // Hash of all GC_VALUE's currently in use + static VALUE _hash; + + VALUE _obj; + + static ID hash_id; + static ID lt_id; + static ID gt_id; + static ID eq_id; + static ID le_id; + static ID ge_id; + + static ID pos_id; + static ID neg_id; + static ID inv_id; + + static ID add_id; + static ID sub_id; + static ID mul_id; + static ID div_id; + static ID mod_id; + + static ID and_id; + static ID or_id; + static ID xor_id; + + static ID lshift_id; + static ID rshift_id; + + struct OpArgs + { + VALUE src; + ID id; + int nargs; + VALUE target; + }; + + + public: + static void initialize() + { + if ( _hash == Qnil ) + { + _hash = rb_hash_new(); + rb_gc_register_address( &_hash ); + } + } + + // this function is never called. Provided for symmetry only. + static void cleanup() + { + rb_gc_unregister_address( &_hash ); + } + + GC_VALUE() : _obj( Qnil ) + { + } + + GC_VALUE(const GC_VALUE& item) : _obj(item._obj) + { + GC_register(); + } + + GC_VALUE(VALUE obj) :_obj(obj) + { + GC_register(); + } + + ~GC_VALUE() + { + GC_unregister(); + } + + GC_VALUE & operator=(const GC_VALUE& item) + { + GC_unregister(); + _obj = item._obj; + GC_register(); + return *this; + } + + void GC_register() + { + if ( FIXNUM_P(_obj) || SPECIAL_CONST_P(_obj) || SYMBOL_P(_obj) ) + return; + VALUE val = rb_hash_aref( _hash, _obj ); + unsigned n = FIXNUM_P(val) ? NUM2UINT(val) : 0; + ++n; + rb_hash_aset( _hash, _obj, INT2NUM(n) ); + } + + void GC_unregister() + { + if ( FIXNUM_P(_obj) || SPECIAL_CONST_P(_obj) || SYMBOL_P(_obj) ) + return; + // this test should not be needed but I've noticed some very erratic + // behavior of none being unregistered in some very rare situations. + if ( BUILTIN_TYPE(_obj) == T_NONE ) return; + + VALUE val = rb_hash_aref( _hash, _obj ); + unsigned n = FIXNUM_P(val) ? NUM2UINT(val) : 1; + --n; + if ( n ) + rb_hash_aset( _hash, _obj, INT2NUM(n) ); + else + rb_hash_delete( _hash, _obj ); + } + + operator VALUE() const + { + return _obj; + } + + VALUE inspect() const + { + return rb_inspect(_obj); + } + + VALUE to_s() const + { + return rb_inspect(_obj); + } + + static VALUE swig_protect_funcall( VALUE p ) + { + OpArgs* args = (OpArgs*) p; + return rb_funcall( args->src, args->id, args->nargs, args->target ); + } + + +#define GC_VALUE_CMP( op_id, op, cmp, cmpval ) \ + bool op( const GC_VALUE& other ) const \ + { \ + if ( FIXNUM_P(_obj) && FIXNUM_P(other._obj) ) \ + { \ + return _obj cmp other._obj; \ + } \ + bool res = false; \ + VALUE ret = Qnil; \ + SWIG_RUBY_THREAD_BEGIN_BLOCK; \ + if ( rb_respond_to( _obj, op_id ) == Qtrue ) \ + { \ + int status; \ + OpArgs args; \ + args.src = _obj; \ + args.id = op_id; \ + args.nargs = 1; \ + args.target = VALUE(other); \ + ret = rb_protect( PROTECTFUNC(swig_protect_funcall), \ + VALUE(&args), &status ); \ + } \ + if ( ret == Qnil ) { \ + VALUE a = rb_funcall( _obj, hash_id, 0 ); \ + VALUE b = rb_funcall( VALUE(other), hash_id, 0 ); \ + res = a cmp b; \ + } \ + else \ + { \ + res = RTEST( ret ); \ + } \ + SWIG_RUBY_THREAD_END_BLOCK; \ + return res; \ + } + + + GC_VALUE_CMP( eq_id, operator==, ==, == 0 ) + GC_VALUE_CMP( lt_id, operator<, < , < 0 ) + GC_VALUE_CMP( le_id, operator<=, <=, <= 0 ) + GC_VALUE_CMP( gt_id, operator>, > , > 0 ) + GC_VALUE_CMP( ge_id, operator>=, >=, >= 0 ) +#undef GC_VALUE_CMP + + bool operator!=( const GC_VALUE& other ) + { + return !(this->operator==(other)); + } + +#define GC_VALUE_UNARY( proc_id, op ) \ + GC_VALUE op() const \ + { \ + VALUE ret = Qnil; \ + SWIG_RUBY_THREAD_BEGIN_BLOCK; \ + int status; \ + OpArgs args; \ + args.src = _obj; \ + args.id = proc_id; \ + args.nargs = 0; \ + args.target = Qnil; \ + ret = rb_protect( PROTECTFUNC(swig_protect_funcall), VALUE(&args), \ + &status ); \ + SWIG_RUBY_THREAD_END_BLOCK; \ + return ret; \ + } + + GC_VALUE_UNARY( pos_id, operator+ ) + GC_VALUE_UNARY( neg_id, operator- ) + GC_VALUE_UNARY( inv_id, operator~ ) +#undef GC_VALUE_BINARY + +#define GC_VALUE_BINARY( proc_id, op ) \ + GC_VALUE op( const GC_VALUE& other ) const \ + { \ + VALUE ret = Qnil; \ + SWIG_RUBY_THREAD_BEGIN_BLOCK; \ + int status; \ + OpArgs args; \ + args.src = _obj; \ + args.id = proc_id; \ + args.nargs = 1; \ + args.target = VALUE(other); \ + ret = rb_protect( PROTECTFUNC(swig_protect_funcall), VALUE(&args), \ + &status ); \ + SWIG_RUBY_THREAD_END_BLOCK; \ + return GC_VALUE(ret); \ + } + + GC_VALUE_BINARY( add_id, operator+ ); + GC_VALUE_BINARY( sub_id, operator- ); + GC_VALUE_BINARY( mul_id, operator* ); + GC_VALUE_BINARY( div_id, operator/ ); + GC_VALUE_BINARY( mod_id, operator% ); + + GC_VALUE_BINARY( and_id, operator& ); + GC_VALUE_BINARY( xor_id, operator^ ); + GC_VALUE_BINARY( or_id, operator| ); + + GC_VALUE_BINARY( lshift_id, operator<< ); + GC_VALUE_BINARY( rshift_id, operator>> ); +#undef GC_VALUE_BINARY + + }; + + ID GC_VALUE::hash_id = rb_intern("hash"); + ID GC_VALUE::lt_id = rb_intern("<"); + ID GC_VALUE::gt_id = rb_intern(">"); + ID GC_VALUE::eq_id = rb_intern("=="); + ID GC_VALUE::le_id = rb_intern("<="); + ID GC_VALUE::ge_id = rb_intern(">="); + + ID GC_VALUE::pos_id = rb_intern("+@"); + ID GC_VALUE::neg_id = rb_intern("-@"); + ID GC_VALUE::inv_id = rb_intern("~"); + + ID GC_VALUE::add_id = rb_intern("+"); + ID GC_VALUE::sub_id = rb_intern("-"); + ID GC_VALUE::mul_id = rb_intern("*"); + ID GC_VALUE::div_id = rb_intern("/"); + ID GC_VALUE::mod_id = rb_intern("%"); + + ID GC_VALUE::and_id = rb_intern("&"); + ID GC_VALUE::or_id = rb_intern("|"); + ID GC_VALUE::xor_id = rb_intern("^"); + + ID GC_VALUE::lshift_id = rb_intern("<<"); + ID GC_VALUE::rshift_id = rb_intern(">>"); + + VALUE GC_VALUE::_hash = Qnil; + + typedef GC_VALUE LANGUAGE_OBJ; + +} // namespace swig + +%} + + +%init { + swig::GC_VALUE::initialize(); +} + + + +// +// Fragment that contains traits to properly deal with GC_VALUE. +// These functions may be invoked as a need of the from(), asval(), +// asptr() and as() template functors, usually used in %typemaps. +// +%fragment(SWIG_Traits_frag(swig::GC_VALUE),"header",fragment="StdTraits") { +namespace swig { + template <> struct traits<GC_VALUE > { + typedef value_category category; + static const char* type_name() { return "GC_VALUE"; } + }; + + template <> struct traits_from<GC_VALUE> { + typedef GC_VALUE value_type; + static VALUE from(const value_type& val) { + return static_cast<VALUE>(val); + } + }; + + template <> + struct traits_check<GC_VALUE, value_category> { + static bool check(GC_VALUE) { + return true; + } + }; + + template <> struct traits_asval<GC_VALUE > { + typedef GC_VALUE value_type; + static int asval(VALUE obj, value_type *val) { + if (val) *val = obj; + return SWIG_OK; + } + }; +} // swig +} // %fragment(traits for swig::GC_VALUE) + + +#endif // __cplusplus + |