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 = 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
00146
00147
00148
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
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
00167 VALUE typelib_from_ruby(Value dst, VALUE new_value)
00168 {
00169
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
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