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
00010
00011
00012
00013
00014
00015
00016 bool RubyGetter::visit_ (int8_t & value) { m_value = CHR2FIX(value); return false; }
00017 bool RubyGetter::visit_ (uint8_t & value) { m_value = CHR2FIX(value); return false; }
00018 bool RubyGetter::visit_ (int16_t & value) { m_value = INT2NUM(value); return false; }
00019 bool RubyGetter::visit_ (uint16_t& value) { m_value = INT2NUM(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 m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00030 return false;
00031 }
00032 bool RubyGetter::visit_(Value const& v, Array const& a)
00033 {
00034 m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00035 return false;
00036 }
00037 bool RubyGetter::visit_(Value const& v, Compound const& c)
00038 {
00039 m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00040 return false;
00041 }
00042 bool RubyGetter::visit_(Value const& v, OpaqueType const& c)
00043 {
00044 m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00045 return false;
00046 }
00047 bool RubyGetter::visit_(Value const& v, Container const& c)
00048 {
00049 m_value = cxx2rb::value_wrap(v, m_registry, m_parent);
00050 return false;
00051 }
00052 bool RubyGetter::visit_(Enum::integral_type& v, Enum const& e)
00053 {
00054 m_value = cxx2rb::enum_symbol(v, e);
00055 return false;
00056 }
00057
00058 RubyGetter::RubyGetter() : ValueVisitor(false) {}
00059 RubyGetter::~RubyGetter() { m_value = Qnil; m_registry = Qnil; }
00060
00061 VALUE RubyGetter::apply(Typelib::Value value, VALUE registry, VALUE parent)
00062 {
00063 m_registry = registry;
00064 m_value = Qnil;
00065 m_parent = parent;
00066
00067 ValueVisitor::apply(value);
00068 return m_value;
00069 }
00070
00071 bool RubySetter::visit_ (int8_t & value) { value = NUM2CHR(m_value); return false; }
00072 bool RubySetter::visit_ (uint8_t & value) { value = NUM2CHR(m_value); return false; }
00073 bool RubySetter::visit_ (int16_t & value) { value = NUM2INT(m_value); return false; }
00074 bool RubySetter::visit_ (uint16_t& value) { value = NUM2UINT(m_value); return false; }
00075 bool RubySetter::visit_ (int32_t & value) { value = NUM2INT(m_value); return false; }
00076 bool RubySetter::visit_ (uint32_t& value) { value = NUM2UINT(m_value); return false; }
00077 bool RubySetter::visit_ (int64_t & value) { value = NUM2LL(m_value); return false; }
00078 bool RubySetter::visit_ (uint64_t& value) { value = NUM2LL(m_value); return false; }
00079 bool RubySetter::visit_ (float & value) { value = NUM2DBL(m_value); return false; }
00080 bool RubySetter::visit_ (double & value) { value = NUM2DBL(m_value); return false; }
00081
00082 bool RubySetter::visit_(Value const& v, Array const& a)
00083 {
00084 if (a.getIndirection().getName() == "/char")
00085 {
00086 char* value = StringValuePtr(m_value);
00087 size_t length = strlen(value);
00088 if (length < a.getDimension())
00089 {
00090 memcpy(v.getData(), value, length + 1);
00091 return false;
00092 }
00093 throw UnsupportedType(v.getType(), "string too long");
00094 }
00095 throw UnsupportedType(v.getType(), "not a string");
00096 }
00097 bool RubySetter::visit_(Value const& v, Pointer const& c)
00098 {
00099 throw UnsupportedType(v.getType(), "no conversion to pointers");
00100 }
00101 bool RubySetter::visit_(Value const& v, Compound const& c)
00102 {
00103 throw UnsupportedType(v.getType(), "no conversion to compound");
00104 }
00105 bool RubySetter::visit_(Value const& v, OpaqueType const& c)
00106 {
00107 throw UnsupportedType(v.getType(), "no conversion to opaque types");
00108 }
00109 bool RubySetter::visit_(Value const& v, Container const& c)
00110 {
00111 throw UnsupportedType(v.getType(), "no conversion to containers");
00112 }
00113 bool RubySetter::visit_(Enum::integral_type& v, Enum const& e)
00114 {
00115 v = rb2cxx::enum_value(m_value, e);
00116 return false;
00117 }
00118
00119 RubySetter::RubySetter() : ValueVisitor(false) {}
00120 RubySetter::~RubySetter() { m_value = Qnil; }
00121
00122 VALUE RubySetter::apply(Value value, VALUE new_value)
00123 {
00124 m_value = new_value;
00125 ValueVisitor::apply(value);
00126 return new_value;
00127 }
00128
00129
00130
00131
00132
00133
00134 VALUE typelib_to_ruby(Value v, VALUE registry, VALUE parent)
00135 {
00136 if (! v.getData())
00137 return Qnil;
00138
00139 RubyGetter getter;
00140 return getter.apply(v, registry, parent);
00141 }
00142
00143
00144 Value typelib_get(VALUE value)
00145 {
00146 void* object = 0;
00147 Data_Get_Struct(value, void, object);
00148 return *reinterpret_cast<Value*>(object);
00149 }
00150
00151
00152 VALUE typelib_from_ruby(Value dst, VALUE new_value)
00153 {
00154
00155 if (rb_obj_is_kind_of(new_value, cType))
00156 {
00157 Value& src = rb2cxx::object<Value>(new_value);
00158 Type const& dst_t = dst.getType();
00159 Type const& src_t = src.getType();
00160 if (dst_t == src_t)
00161 Typelib::copy(dst, src);
00162 else
00163 {
00164 rb_raise(rb_eArgError, "wrong type in assignment: %s = %s", dst_t.getName().c_str(), src_t.getName().c_str());
00165 }
00166 return new_value;
00167 }
00168
00169 std::string type_name;
00170 std::string reason;
00171 try {
00172 RubySetter setter;
00173 return setter.apply(dst, new_value);
00174 } catch(UnsupportedType e) {
00175
00176 type_name = e.type.getName();
00177 reason = e.reason;
00178 }
00179
00180 if (reason.length() == 0)
00181 rb_raise(rb_eTypeError, "cannot convert to '%s'", type_name.c_str());
00182 else
00183 rb_raise(rb_eTypeError, "cannot convert to '%s' (%s)", type_name.c_str(), reason.c_str());
00184 }
00185