convert.cc
Go to the documentation of this file.
00001 #include "typelib.hh"
00002 #include <iostream>
00003 #include <typelib/value_ops.hh>
00004 
00005 using namespace Typelib;
00006 using namespace typelib_ruby;
00007 
00008 /**********
00009  *  Define typelib_(to|from)_ruby
00010  */
00011 
00012 /* This visitor takes a Value class and a field name,
00013  * and returns the VALUE object which corresponds to
00014  * the field, or returns nil
00015  */
00016 bool RubyGetter::visit_ (int8_t  & value) { m_value = INT2FIX(value); return false; }
00017 bool RubyGetter::visit_ (uint8_t & value) { m_value = INT2FIX(value); return false; }
00018 bool RubyGetter::visit_ (int16_t & value) { m_value = INT2FIX(value); return false; }
00019 bool RubyGetter::visit_ (uint16_t& value) { m_value = INT2FIX(value); return false; }
00020 bool RubyGetter::visit_ (int32_t & value) { m_value = INT2NUM(value); return false; }
00021 bool RubyGetter::visit_ (uint32_t& value) { m_value = INT2NUM(value); return false; }
00022 bool RubyGetter::visit_ (int64_t & value) { m_value = LL2NUM(value);  return false; }
00023 bool RubyGetter::visit_ (uint64_t& value) { m_value = ULL2NUM(value); return false; }
00024 bool RubyGetter::visit_ (float   & value) { m_value = rb_float_new(value); return false; }
00025 bool RubyGetter::visit_ (double  & value) { m_value = rb_float_new(value); return false; }
00026 
00027 bool RubyGetter::visit_(Value const& v, Pointer const& p)
00028 {
00029 #   ifdef VERBOSE
00030     fprintf(stderr, "%p: wrapping from RubyGetter::visit_(pointer)\n", v.getData());
00031 #   endif
00032     m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00033     return false;
00034 }
00035 bool RubyGetter::visit_(Value const& v, Array const& a) 
00036 {
00037 #   ifdef VERBOSE
00038     fprintf(stderr, "%p: wrapping from RubyGetter::visit_(array)\n", v.getData());
00039 #   endif
00040     m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00041     return false;
00042 }
00043 bool RubyGetter::visit_(Value const& v, Compound const& c)
00044 { 
00045 #   ifdef VERBOSE
00046     fprintf(stderr, "%p: wrapping from RubyGetter::visit_(compound)\n", v.getData());
00047 #   endif
00048     m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00049     return false; 
00050 }
00051 bool RubyGetter::visit_(Value const& v, OpaqueType const& c)
00052 { 
00053 #   ifdef VERBOSE
00054     fprintf(stderr, "%p: wrapping from RubyGetter::visit_(opaque)\n", v.getData());
00055 #   endif
00056     m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00057     return false; 
00058 }
00059 bool RubyGetter::visit_(Value const& v, Container const& c)
00060 { 
00061 #   ifdef VERBOSE
00062     fprintf(stderr, "%p: wrapping from RubyGetter::visit_(container)\n", v.getData());
00063 #   endif
00064     m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00065     return false; 
00066 }
00067 bool RubyGetter::visit_(Enum::integral_type& v, Enum const& e)   
00068 { 
00069     m_value = cxx2rb::enum_symbol(v, e);
00070     return false;
00071 }
00072     
00073 RubyGetter::RubyGetter() : ValueVisitor(false) {}
00074 RubyGetter::~RubyGetter() { m_value = Qnil; m_registry = Qnil; }
00075 
00076 VALUE RubyGetter::apply(Typelib::Value value, VALUE registry, VALUE parent)
00077 {
00078     m_registry = registry;
00079     m_value    = Qnil;
00080     m_parent   = parent;
00081 
00082     ValueVisitor::apply(value);
00083     return m_value;
00084 }
00085 
00086 bool RubySetter::visit_ (int8_t  & value) { value = NUM2INT(m_value); return false; }
00087 bool RubySetter::visit_ (uint8_t & value) { value = NUM2INT(m_value); return false; }
00088 bool RubySetter::visit_ (int16_t & value) { value = NUM2INT(m_value); return false; }
00089 bool RubySetter::visit_ (uint16_t& value) { value = NUM2UINT(m_value); return false; }
00090 bool RubySetter::visit_ (int32_t & value) { value = NUM2INT(m_value); return false; }
00091 bool RubySetter::visit_ (uint32_t& value) { value = NUM2UINT(m_value); return false; }
00092 bool RubySetter::visit_ (int64_t & value) { value = NUM2LL(m_value);  return false; }
00093 bool RubySetter::visit_ (uint64_t& value) { value = NUM2LL(m_value); return false; }
00094 bool RubySetter::visit_ (float   & value) { value = NUM2DBL(m_value); return false; }
00095 bool RubySetter::visit_ (double  & value) { value = NUM2DBL(m_value); return false; }
00096 
00097 bool RubySetter::visit_(Value const& v, Array const& a)
00098 { 
00099     if (a.getIndirection().getName() == "/char")
00100     {
00101         char*  value = StringValuePtr(m_value);
00102         size_t length = strlen(value);
00103         if (length < a.getDimension())
00104         {
00105             memcpy(v.getData(), value, length + 1);
00106             return false;
00107         }
00108         throw UnsupportedType(v.getType(), "string too long"); 
00109     }
00110     throw UnsupportedType(v.getType(), "not a string"); 
00111 }
00112 bool RubySetter::visit_(Value const& v, Pointer const& c)
00113 { 
00114     throw UnsupportedType(v.getType(), "no conversion to pointers"); 
00115 }
00116 bool RubySetter::visit_(Value const& v, Compound const& c)
00117 { 
00118     throw UnsupportedType(v.getType(), "no conversion to compound"); 
00119 }
00120 bool RubySetter::visit_(Value const& v, OpaqueType const& c)
00121 { 
00122     throw UnsupportedType(v.getType(), "no conversion to opaque types"); 
00123 }
00124 bool RubySetter::visit_(Value const& v, Container const& c)
00125 { 
00126     throw UnsupportedType(v.getType(), "no conversion to containers"); 
00127 }
00128 bool RubySetter::visit_(Enum::integral_type& v, Enum const& e)
00129 { 
00130     v = rb2cxx::enum_value(m_value, e);
00131     return false;
00132 }
00133 
00134 RubySetter::RubySetter() : ValueVisitor(false) {}
00135 RubySetter::~RubySetter() { m_value = Qnil; }
00136 
00137 VALUE RubySetter::apply(Value value, VALUE new_value)
00138 {
00139     m_value = new_value;
00140     ValueVisitor::apply(value); 
00141     return new_value;
00142 }
00143 
00144 /*
00145  * Convertion function between Ruby and Typelib
00146  */
00147 
00148 /* Converts a Typelib::Value to Ruby's VALUE */
00149 VALUE typelib_to_ruby(Value v, VALUE registry, VALUE parent)
00150 { 
00151     if (! v.getData())
00152         return Qnil;
00153 
00154     RubyGetter getter;
00155     return getter.apply(v, registry, parent);
00156 }
00157 
00158 /* Returns the Value object wrapped into +value+ */
00159 Value typelib_get(VALUE value)
00160 {
00161     void* object = 0;
00162     Data_Get_Struct(value, void, object);
00163     return *reinterpret_cast<Value*>(object);
00164 }
00165 
00166 /* Tries to initialize +value+ to +new_value+ using the type in +value+ */
00167 VALUE typelib_from_ruby(Value dst, VALUE new_value)
00168 {
00169     // Special case: new_value is actually a Typelib wrapper of the right type
00170     if (rb_obj_is_kind_of(new_value, cType))
00171     {
00172         Value& src = rb2cxx::object<Value>(new_value);
00173         Type const& dst_t = dst.getType();
00174         Type const& src_t = src.getType();
00175         if (dst_t == src_t)
00176             Typelib::copy(dst, src);
00177         else
00178         {
00179             rb_raise(rb_eArgError, "wrong type in assignment: %s = %s", dst_t.getName().c_str(), src_t.getName().c_str());
00180         }
00181         return new_value;
00182     }
00183 
00184     std::string type_name;
00185     std::string reason;
00186     try {
00187         RubySetter setter;
00188         return setter.apply(dst, new_value);
00189     } catch(UnsupportedType e) { 
00190         // Avoid calling rb_raise in exception context
00191         type_name = e.type.getName(); 
00192         reason    = e.reason;
00193     }
00194 
00195     if (reason.length() == 0)
00196         rb_raise(rb_eTypeError, "cannot convert to '%s'", type_name.c_str());
00197     else
00198         rb_raise(rb_eTypeError, "cannot convert to '%s' (%s)", type_name.c_str(), reason.c_str());
00199 }
00200 


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Sat Jun 8 2019 18:49:22