specialized_types.cc
Go to the documentation of this file.
00001 #include "typelib.hh"
00002 #include <iostream>
00003 
00004 #include <boost/bind.hpp>
00005 #include <typelib/value_ops.hh>
00006 
00007 using namespace Typelib;
00008 using std::vector;
00009 using namespace typelib_ruby;
00010 
00011 /**********************************************
00012  * Typelib::Compound
00013  */
00014 
00015 static VALUE compound_get_fields(VALUE self)
00016 {
00017     if (self == cCompound)
00018         return rb_ary_new();
00019 
00020     Type const& type(rb2cxx::object<Type>(self));
00021     Compound const& compound(dynamic_cast<Compound const&>(type));
00022     Compound::FieldList const& fields(compound.getFields());
00023     Compound::FieldList::const_iterator it, end = fields.end();
00024 
00025     VALUE registry  = type_get_registry(self);
00026     VALUE fieldlist = rb_ary_new();
00027     for (it = fields.begin(); it != end; ++it)
00028     {
00029         VALUE field_name = rb_str_new2(it->getName().c_str());
00030         VALUE field_type = cxx2rb::type_wrap(it->getType(), registry);
00031 
00032         VALUE field_def = rb_ary_new2(4);
00033         rb_ary_store(field_def, 0, field_name);
00034         rb_ary_store(field_def, 1, INT2FIX(it->getOffset()));
00035         rb_ary_store(field_def, 2, field_type);
00036         rb_ary_store(field_def, 3, cxx2rb::metadata_wrap(it->getMetaData()));
00037         rb_ary_push(fieldlist, field_def);
00038     }
00039 
00040     return fieldlist;
00041 }
00042 
00043 /* Helper function for CompoundType#[] */
00044 static VALUE compound_field_get(VALUE rbvalue, VALUE name, VALUE raw)
00045 { 
00046     VALUE registry = value_get_registry(rbvalue);
00047     Value value = rb2cxx::object<Value>(rbvalue);
00048     if (! value.getData())
00049         return Qnil;
00050 
00051     try { 
00052         Value field_value = value_get_field(value, StringValuePtr(name));
00053         if (RTEST(raw))
00054             return cxx2rb::value_wrap(field_value, registry, rbvalue);
00055         else return typelib_to_ruby(field_value, registry, rbvalue);
00056     } 
00057     catch(FieldNotFound)
00058     { rb_raise(rb_eArgError, "no field '%s'", StringValuePtr(name)); } 
00059     catch(std::exception const& e)
00060     { rb_raise(rb_eRuntimeError, "%s", e.what()); }
00061 }
00062 /* Helper function for CompoundType#[]= */
00063 static VALUE compound_field_set(VALUE self, VALUE name, VALUE newval)
00064 { 
00065     Value& tlib_value(rb2cxx::object<Value>(self));
00066 
00067     try {
00068         Value field_value = value_get_field(tlib_value, StringValuePtr(name));
00069         typelib_from_ruby(field_value, newval);
00070         return newval;
00071     }
00072     catch(FieldNotFound)
00073     { rb_raise(rb_eArgError, "no field '%s' in '%s'", StringValuePtr(name), rb_obj_classname(self)); }
00074     catch(std::exception const& e)
00075     { rb_raise(rb_eRuntimeError, "%s", e.what()); }
00076 }
00077 
00078 /* call-seq:
00079  *  pointer.deference => pointed-to type
00080  *
00081  * Returns the value pointed to by +self+ 
00082  */
00083 static VALUE pointer_deference(VALUE self)
00084 {
00085     VALUE pointed_to = rb_iv_get(self, "@points_to");
00086     if (!NIL_P(pointed_to))
00087         return pointed_to;
00088 
00089     Value const& value(rb2cxx::object<Value>(self));
00090     Indirect const& indirect(static_cast<Indirect const&>(value.getType()));
00091     
00092     VALUE registry = value_get_registry(self);
00093 
00094     void* ptr_value = *reinterpret_cast<void**>(value.getData());
00095     if (!ptr_value)
00096         rb_raise(rb_eArgError, "cannot deference a NULL pointer");
00097 
00098     Value new_value(ptr_value, indirect.getIndirection() );
00099     return cxx2rb::value_wrap(new_value, registry, Qnil);
00100 }
00101 
00102 
00103 /* Get the C value associated with a ruby representation of an enum
00104  * Valid ruby representations are: symbols, strings and integer
00105  */
00106 Enum::integral_type rb2cxx::enum_value(VALUE rb_value, Enum const& e)
00107 {
00108     // m_value can be either an integer, a symbol or a string
00109     if (TYPE(rb_value) == T_FIXNUM)
00110     {
00111         Enum::integral_type value = FIX2INT(rb_value);
00112         try { 
00113             e.get(value); 
00114             return value;
00115         }
00116         catch(Enum::ValueNotFound) {  }
00117         rb_raise(rb_eArgError, "%i is not a valid value for %s", value, e.getName().c_str());
00118     }
00119 
00120     char const* name;
00121     if (SYMBOL_P(rb_value))
00122         name = rb_id2name(SYM2ID(rb_value));
00123     else
00124         name = StringValuePtr(rb_value);
00125 
00126     try { return e.get(name); }
00127     catch(Enum::SymbolNotFound) {  }
00128     rb_raise(rb_eArgError, "%s is not a valid symbol for %s", name, e.getName().c_str());
00129 }
00130 
00131 /* call-seq:
00132  *  enum.keys => array of keys
00133  *
00134  * Returns a string array of all the keys defined for this enumeration
00135  */
00136 VALUE enum_keys(VALUE self)
00137 {
00138     if (self == cEnum)
00139         return rb_hash_new();
00140 
00141     Enum const& type = static_cast<Enum const&>(rb2cxx::object<Type>(self));
00142 
00143     VALUE keys = rb_iv_get(self, "@values");
00144     if (!NIL_P(keys)) 
00145         return keys;
00146 
00147     keys = rb_hash_new();
00148     typedef std::list<std::string> string_list;
00149     string_list names = type.names();
00150     for (string_list::const_iterator it = names.begin(); it != names.end(); ++it)
00151         rb_hash_aset(keys, rb_str_new2(it->c_str()), INT2FIX(type.get(*it)));
00152 
00153     rb_iv_set(self, "@values", keys);
00154     return keys;
00155 }
00156 
00157 /* call-seq:
00158  *  enum.value_of(name) => integer
00159  *
00160  * Returns the integral value asoociated with the given name.
00161  */
00162 static VALUE enum_value_of(VALUE self, VALUE name)
00163 {
00164     Enum const& type = static_cast<Enum const&>(rb2cxx::object<Type>(self));
00165 
00166     try {
00167         int value = type.get(StringValuePtr(name));
00168         return INT2NUM(value);
00169     } catch (Enum::SymbolNotFound) {
00170         rb_raise(rb_eArgError, "this enumeration has no value for %s", StringValuePtr(name));
00171     }
00172 }
00173 
00174 /* call-seq:
00175  *  enum.name_of(integer) => key
00176  *
00177  * Returns the symbolic name of +integer+ in this enumeration, or raises
00178  * ArgumentError if there is no matching name.
00179  */
00180 static VALUE enum_name_of(VALUE self, VALUE integer)
00181 {
00182     Enum const& type = static_cast<Enum const&>(rb2cxx::object<Type>(self));
00183 
00184     try {
00185         std::string name = type.get(NUM2INT(integer));
00186         return rb_str_new2(name.c_str());
00187     } catch (Enum::ValueNotFound) {
00188         rb_raise(rb_eArgError, "this enumeration has no name for %i", NUM2INT(integer));
00189     }
00190 }
00191 
00192 /**********************************************
00193  * Typelib::Pointer
00194  */
00195 
00196 /* call-seq:
00197  *  type.deference => other_type
00198  *
00199  * Returns the type referenced by this one
00200  */
00201 static VALUE indirect_type_deference(VALUE self)
00202 {
00203     VALUE registry = type_get_registry(self);
00204     Type const& type(rb2cxx::object<Type>(self));
00205     Indirect const& indirect(static_cast<Indirect const&>(type));
00206     return cxx2rb::type_wrap(indirect.getIndirection(), registry);
00207 }
00208 
00209 
00210 static Value array_element(VALUE rbarray, VALUE rbindex)
00211 {
00212     Value& value(rb2cxx::object<Value>(rbarray));
00213     Array const& array(static_cast<Array const&>(value.getType()));
00214     size_t index = NUM2INT(rbindex);
00215     
00216     if (index >= array.getDimension())
00217     {
00218         rb_raise(rb_eIndexError, "Out of bounds: %lu > %lu", index, array.getDimension());
00219         return Value();
00220     }
00221 
00222     Type const& array_type(array.getIndirection());
00223 
00224     int8_t* data = reinterpret_cast<int8_t*>(value.getData());
00225     data += array_type.getSize() * index;
00226     return Value(data, array_type);
00227 }
00228 
00229 /* call-seq:
00230  *  array[index]    => value
00231  *
00232  * Returns the value at +index+ in the array. Since Typelib arrays are *not*
00233  * dynamically extensible, trying to set a non-existent index will raise an
00234  * IndexError exception.
00235  */
00236 static VALUE array_get(int argc, VALUE* argv, VALUE self)
00237 { 
00238     Value& value            = rb2cxx::object<Value>(self);
00239     Array const& array      = static_cast<Array const&>(value.getType());
00240     if (array.getDimension() == 0)
00241         return self;
00242 
00243     Type  const& array_type = array.getIndirection();
00244     VALUE registry          = value_get_registry(self);
00245 
00246     int8_t* data = reinterpret_cast<int8_t*>(value.getData());
00247     size_t index = NUM2INT(argv[0]);
00248     if (index >= array.getDimension())
00249         rb_raise(rb_eIndexError, "Out of bounds: %li > %li", index, array.getDimension());
00250 
00251     if (argc == 1)
00252     {
00253         Value v = Value(data + array_type.getSize() * index, array_type);
00254         return cxx2rb::value_wrap( v, registry, self );
00255     }
00256     else if (argc == 2)
00257     {
00258         VALUE ret = rb_ary_new();
00259         size_t size = NUM2INT(argv[1]);
00260         if (index + size > array.getDimension())
00261             rb_raise(rb_eIndexError, "Out of bounds: %li > %li", index + size - 1, array.getDimension());
00262 
00263         for (size_t i = index; i < index + size; ++i)
00264         {
00265             Value v = Value(data + array_type.getSize() * i, array_type);
00266             VALUE rb_v = cxx2rb::value_wrap( v, registry, self );
00267 
00268             rb_ary_push(ret, rb_v);
00269         }
00270 
00271         return ret;
00272     }
00273     else
00274         rb_raise(rb_eArgError, "invalid argument count (%i for 1 or 2)", argc);
00275 }
00276 
00277 /* call-seq:
00278  *  array[index] = new_value    => new_value
00279  *
00280  * Sets the value at +index+ to +new_value+. Since Typelib arrays are *not*
00281  * dynamically extensible, trying to set a non-existent index will raise an
00282  * IndexError exception.
00283  */
00284 static VALUE array_set(VALUE self, VALUE rbindex, VALUE newvalue)
00285 { 
00286     Value element = array_element(self, rbindex);
00287     return typelib_from_ruby(element, newvalue); 
00288 }
00289 
00290 /* call-seq:
00291  *  array.each { |v| ... }      => array
00292  *
00293  * Iterates on all elements of the array
00294  */
00295 static VALUE array_do_each(VALUE rbarray)
00296 {
00297     Value& value            = rb2cxx::object<Value>(rbarray);
00298     Array const& array      = static_cast<Array const&>(value.getType());
00299     if (array.getDimension() == 0)
00300         return rbarray;
00301 
00302     Type  const& array_type = array.getIndirection();
00303     VALUE registry          = value_get_registry(rbarray);
00304 
00305     int8_t* data = reinterpret_cast<int8_t*>(value.getData());
00306 
00307     for (size_t i = 0; i < array.getDimension(); ++i, data += array_type.getSize())
00308         rb_yield(cxx2rb::value_wrap( Value(data, array_type), registry, rbarray ));
00309 
00310     return rbarray;
00311 }
00312 
00313 /* call-seq:
00314  *  array.size              => size
00315  *
00316  * Returns the count of elements in +array+
00317  */
00318 static VALUE array_size(VALUE rbarray)
00319 {
00320     Value& value(rb2cxx::object<Value>(rbarray));
00321     Array const& array(static_cast<Array const&>(value.getType()));
00322     return INT2FIX(array.getDimension());
00323 }
00324 
00325 /* call-seq:
00326  *  array.length                    => length
00327  *
00328  * Returns the count of elemnts in +array+
00329  */
00330 static VALUE array_class_length(VALUE rbarray)
00331 {
00332     Array const& array(dynamic_cast<Array const&>(rb2cxx::object<Type>(rbarray)));
00333     return INT2FIX(array.getDimension());
00334 }
00335 
00336 /*
00337  * call-seq:
00338  *  pointer.null?               => boolean
00339  *
00340  * checks if this is a NULL pointer 
00341  */
00342 static VALUE pointer_nil_p(VALUE self)
00343 {
00344     Value const& value(rb2cxx::object<Value>(self));
00345     if ( *reinterpret_cast<void**>(value.getData()) == 0 )
00346         return Qtrue;
00347     return Qfalse;
00348 }
00349 
00350 /*
00351  * call-seq:
00352  *  numeric.integer?        => true or false
00353  *
00354  * Returns true if the type is an integral type and false if it is a floating-point type
00355  */
00356 static VALUE numeric_type_integer_p(VALUE self)
00357 {
00358     Numeric const& type(dynamic_cast<Numeric const&>(rb2cxx::object<Type>(self)));
00359     return type.getNumericCategory() == Numeric::Float ? Qfalse : Qtrue;
00360 }
00361 
00362 /*
00363  * call-seq:
00364  *  numeric.size            => value
00365  *
00366  * The size of this type in bytes
00367  */
00368 static VALUE numeric_type_size(VALUE self)
00369 {
00370     Numeric const& type(dynamic_cast<Numeric const&>(rb2cxx::object<Type>(self)));
00371     return INT2FIX(type.getSize());
00372 }
00373 
00374 /*
00375  * call-seq:
00376  *  numeric.unsigned?       => value
00377  *
00378  * If integer? returns true, returns whether this type is an unsigned or signed
00379  * integral type.
00380  */
00381 static VALUE numeric_type_unsigned_p(VALUE self)
00382 {
00383     Numeric const& type(dynamic_cast<Numeric const&>(rb2cxx::object<Type>(self)));
00384     switch(type.getNumericCategory())
00385     {
00386         case Numeric::SInt: return Qfalse;
00387         case Numeric::UInt: return Qtrue;
00388         case Numeric::Float:
00389             rb_raise(rb_eArgError, "not an integral type");
00390         default:
00391             return Qnil;
00392     }
00393 }
00394 
00395 
00396 /*
00397  * call-seq:
00398  *  klass.container_kind => name
00399  *
00400  * Returns the name of the generic container. For instance, a
00401  * /std/vector</double> type would return /std/vector.
00402  */
00403 static VALUE container_kind(VALUE self)
00404 {
00405     Container const& type(dynamic_cast<Container const&>(rb2cxx::object<Type>(self)));
00406     return rb_str_new2(type.kind().c_str());
00407 }
00408 
00409 /*
00410  * call-seq:
00411  *  container.natural_size => a_number
00412  *
00413  * Returns the container's size on the local machine. This can be different from
00414  * the value returned by size() in case a registry has been generated on a
00415  * different architecture.
00416  */
00417 static VALUE container_natural_size(VALUE self)
00418 {
00419     Container const& type(dynamic_cast<Container const&>(rb2cxx::object<Type>(self)));
00420     return INT2FIX(type.getNaturalSize());
00421 }
00422 
00423 /*
00424  * call-seq:
00425  *  container.random_access?
00426  *
00427  * Returns true if this container type is a random access container
00428  */
00429 static VALUE container_random_access_p(VALUE self)
00430 {
00431     Container const& type(dynamic_cast<Container const&>(rb2cxx::object<Type>(self)));
00432     return type.isRandomAccess() ? Qtrue : Qfalse;
00433 }
00434 
00435 
00436 /*
00437  * call-seq:
00438  *  container.length => value
00439  *
00440  * Returns the count of elements in +container+
00441  */
00442 static VALUE container_length(VALUE self)
00443 {
00444     Value value = rb2cxx::object<Value>(self);
00445     Container const& type(dynamic_cast<Container const&>(value.getType()));
00446 
00447     return INT2NUM(type.getElementCount(value.getData()));
00448 }
00449 
00450 /*
00451  * call-seq:
00452  *  container.clear
00453  *
00454  * Removes all elements from that container
00455  */
00456 static VALUE container_clear(VALUE self)
00457 {
00458     Value value = rb2cxx::object<Value>(self);
00459     Container const& type(dynamic_cast<Container const&>(value.getType()));
00460 
00461     type.clear(value.getData());
00462     return Qnil;
00463 }
00464 
00465 static Typelib::Value container_element(uint64_t* buffer10, Type const& element_t, VALUE obj)
00466 {
00467     Typelib::Value element_v;
00468     if (element_t.getCategory() == Type::Numeric && sizeof(int64_t) * 10 >= element_t.getSize())
00469     {
00470         // Special case: allow the caller to use Ruby numeric directly. This is
00471         // way faster if a lot of insertions need to be done
00472         element_v = Value(buffer10, element_t);
00473         typelib_from_ruby(element_v, obj);
00474     }
00475     else
00476     {
00477         element_v   = rb2cxx::object<Value>(obj);
00478         if (element_t != element_v.getType())
00479             rb_raise(rb_eArgError, "wrong type %s for new element, expected %s", element_v.getType().getName().c_str(), element_t.getName().c_str());
00480     }
00481     return element_v;
00482 }
00483 
00484 static VALUE container_do_push(VALUE self, VALUE obj)
00485 {
00486     Value container_v = rb2cxx::object<Value>(self);
00487     Container const& container_t(dynamic_cast<Container const&>(container_v.getType()));
00488 
00489     uint64_t buffer[10];
00490     Value element_v = container_element(buffer, container_t.getIndirection(), obj);
00491     container_t.push(container_v.getData(), element_v);
00492     return self;
00493 }
00494 
00495 static VALUE container_do_set(VALUE self, VALUE index, VALUE obj)
00496 {
00497     Value container_v = rb2cxx::object<Value>(self);
00498     Container const& container_t(dynamic_cast<Container const&>(container_v.getType()));
00499 
00500     uint64_t buffer[10];
00501     Value element_v = container_element(buffer, container_t.getIndirection(), obj);
00502     container_t.setElement(container_v.getData(), NUM2INT(index), element_v);
00503     return self;
00504 }
00505 
00506 static VALUE container_do_get(VALUE self, VALUE index, VALUE raw)
00507 {
00508     Value container_v = rb2cxx::object<Value>(self);
00509     Container const& container_t(dynamic_cast<Container const&>(container_v.getType()));
00510     VALUE registry = value_get_registry(self);
00511 
00512     Value v = container_t.getElement(container_v.getData(), NUM2INT(index));
00513     if (RTEST(raw))
00514         return cxx2rb::value_wrap(v, registry, self);
00515     else return typelib_to_ruby(v, registry, self);
00516 }
00517 
00518 struct ContainerIterator : public ValueVisitor
00519 {
00520     VALUE m_registry;
00521     VALUE m_parent;
00522     bool m_raw;
00523 
00524     ContainerIterator(VALUE registry, VALUE parent, bool raw)
00525     {
00526         m_registry = registry;
00527         m_parent = parent;
00528         m_raw = raw;
00529     }
00530     virtual void dispatch(Value v)
00531     {
00532         if (m_raw)
00533             rb_yield(cxx2rb::value_wrap(v, m_registry, m_parent));
00534         else
00535             rb_yield(typelib_to_ruby(v, m_registry, m_parent));
00536     }
00537 };
00538 
00539 /*
00540  * call-seq:
00541  *  container.each { |obj| ... } => container
00542  *
00543  * Iterates on the elements of the container
00544  */
00545 static VALUE container_each(VALUE self, VALUE raw)
00546 {
00547     Value value = rb2cxx::object<Value>(self);
00548     VALUE registry = value_get_registry(self);
00549     ContainerIterator iterator(registry, self, RTEST(raw));
00550     dynamic_cast<Typelib::Container const&>(value.getType()).visit(value.getData(), iterator);
00551     return self;
00552 }
00553 
00554 /*
00555  * call-seq:
00556  *  container.erase(obj) => true or false
00557  *
00558  * Removes +obj+ from the container. Returns true if +obj+ has been found and
00559  * deleted, and false otherwise
00560  */
00561 static VALUE container_erase(VALUE self, VALUE obj)
00562 {
00563     Value container_v = rb2cxx::object<Value>(self);
00564     Container const& container_t(dynamic_cast<Container const&>(container_v.getType()));
00565 
00566     uint64_t buffer[10];
00567     Value element_v = container_element(buffer, container_t.getIndirection(), obj);
00568 
00569     if (container_t.erase(container_v.getData(), element_v))
00570         return Qtrue;
00571     else
00572         return Qfalse;
00573 }
00574 
00575 bool container_delete_if_i(Value v, VALUE registry, VALUE container)
00576 {
00577     VALUE rb_v = cxx2rb::value_wrap(v, registry, container);
00578     if (RTEST(rb_yield(rb_v)))
00579         return true;
00580     return false;
00581 }
00582 
00583 /*
00584  * call-seq:
00585  *  container.delete_if { |obj| ... } => container
00586  *
00587  * Removes the elements in the container for which the block returns true.
00588  */
00589 static VALUE container_delete_if(VALUE self)
00590 {
00591     Value container_v = rb2cxx::object<Value>(self);
00592     Container const& container_t(dynamic_cast<Container const&>(container_v.getType()));
00593 
00594     VALUE registry = value_get_registry(self);
00595     container_t.delete_if(container_v.getData(), boost::bind(container_delete_if_i, _1, registry, self));
00596     return self;
00597 }
00598 
00599 /*
00600  * call-seq:
00601  *  vector.contained_memory_id => value or nil
00602  *
00603  * (see ContainerType#contained_memory_id)
00604  */
00605 static VALUE vector_contained_memory_id(VALUE self)
00606 {
00607     Value container_v = rb2cxx::object<Value>(self);
00608     std::vector<uint8_t> const* vector = reinterpret_cast<std::vector<uint8_t>*>(container_v.getData());
00609     if (vector->empty())
00610         return Qnil;
00611     return ULL2NUM(reinterpret_cast<uint64_t>(&(*vector)[0]));
00612 }
00613 
00614 /*
00615  * call-seq:
00616  *  vector.raw_memcpy(source,size) => nil
00617  *
00618  * @param [Integer] source the source raw address
00619  * @param [Integer] size the number of bytes to be copied
00620  */
00621 static VALUE vector_raw_memcpy(VALUE self,VALUE _source,VALUE _size)
00622 {
00623     Value container_v = rb2cxx::object<Value>(self);
00624     Container const& container_t = static_cast<Container const&>(container_v.getType());
00625     bool is_memcpy = false;
00626     bool no_layout = false;
00627     try
00628     {
00629         MemoryLayout ops = Typelib::layout_of(container_t.getIndirection());
00630         is_memcpy = (ops.size() == 2 && ops[0] == MemLayout::FLAG_MEMCPY);
00631     }
00632     catch(std::runtime_error) { no_layout = true; }
00633     if(no_layout)
00634         rb_raise(rb_eTypeError, "no layout available for elements of %s", container_t.getName().c_str());
00635     if(!is_memcpy)
00636         rb_raise(rb_eTypeError, "raw_memcpy is not supported for vectors of type %s", container_t.getName().c_str());
00637 
00638     unsigned int element_size = container_t.getIndirection().getSize();
00639     unsigned int size = NUM2UINT(_size);
00640     if (size % element_size)
00641         rb_raise(rb_eArgError, "provided size in bytes (%u) is not a round number of elements for vectors of type %s (each element is %u bytes in size)", size, container_t.getName().c_str(), element_size);
00642 
00643     std::vector<uint8_t> *vector = reinterpret_cast<std::vector<uint8_t>*>(container_v.getData());
00644     const void *source = reinterpret_cast<const void*>(NUM2ULL(_source));
00645     vector->resize(size);
00646     memcpy(&(*vector)[0],source,size);
00647     return Qnil;
00648 }
00649 
00650 /* 
00651  * call-seq:
00652  *   to_ruby(value)     => non-Typelib object or self
00653  *
00654  * Converts +self+ to its Ruby equivalent. If no equivalent
00655  * type is available, returns self
00656  */
00657 static VALUE numeric_to_ruby(VALUE mod, VALUE self)
00658 {
00659     Value const& value(rb2cxx::object<Value>(self));
00660     VALUE registry = value_get_registry(self);
00661     try {
00662         return typelib_to_ruby(value, registry, Qnil);
00663     } catch(Typelib::NullTypeFound) { }
00664     rb_raise(rb_eTypeError, "trying to convert 'void'");
00665 }
00666 
00667 /*
00668  * call-seq:
00669  *   value.from_ruby(ruby_object) => self
00670  *
00671  * Initializes +self+ with the information contained in +ruby_object+.
00672  *
00673  * This particular method is not type-safe. You should use Typelib.from_ruby
00674  * unless you know what you are doing.
00675  */
00676 static VALUE numeric_from_ruby(VALUE self, VALUE arg)
00677 {
00678     Value& value(rb2cxx::object<Value>(self));
00679     try {
00680         typelib_from_ruby(value, arg);
00681         return self;
00682     } catch(Typelib::UnsupportedType) { }
00683     rb_raise(rb_eTypeError, "cannot perform the requested convertion");
00684 }
00685 
00686 
00687 /* Document-class: Typelib::NumericType
00688  *
00689  * Wrapper for numeric types (int, float, ...)
00690  */
00691 
00692 /* Document-class: Typelib::IndirectType
00693  *
00694  * Base class for types which deference other objects, like pointers or arrays
00695  * See also ArrayType and PointerType
00696  */
00697 
00698 /* Document-class: Typelib::PointerType
00699  *
00700  * Base class for pointers (references to other values)
00701  */
00702 
00703 /* Document-class: Typelib::CompoundType
00704  *
00705  * Base class for types composed by other types (structures and unions in C).
00706  * Each field is assigned its type and its offset inside the structure. So
00707  * unions are represented with all fields having an offset of zero, while
00708  * structures have consecutive offsets.
00709  */
00710 
00711 void typelib_ruby::Typelib_init_specialized_types()
00712 {
00713     VALUE mTypelib  = rb_define_module("Typelib");
00714     cNumeric   = rb_define_class_under(mTypelib, "NumericType", cType);
00715     rb_define_singleton_method(cNumeric, "integer?", RUBY_METHOD_FUNC(numeric_type_integer_p), 0);
00716     rb_define_singleton_method(cNumeric, "unsigned?", RUBY_METHOD_FUNC(numeric_type_unsigned_p), 0);
00717     rb_define_singleton_method(cNumeric, "size", RUBY_METHOD_FUNC(numeric_type_size), 0);
00718     rb_define_singleton_method(cNumeric, "to_ruby", RUBY_METHOD_FUNC(&numeric_to_ruby), 1);
00719     rb_define_method(cNumeric, "typelib_from_ruby", RUBY_METHOD_FUNC(&numeric_from_ruby), 1);
00720 
00721     cOpaque    = rb_define_class_under(mTypelib, "OpaqueType", cType);
00722     cNull      = rb_define_class_under(mTypelib, "NullType", cType);
00723 
00724     cIndirect  = rb_define_class_under(mTypelib, "IndirectType", cType);
00725     rb_define_singleton_method(cIndirect, "deference",    RUBY_METHOD_FUNC(indirect_type_deference), 0);
00726 
00727     cPointer  = rb_define_class_under(mTypelib, "PointerType", cIndirect);
00728     rb_define_method(cPointer, "deference", RUBY_METHOD_FUNC(pointer_deference), 0);
00729     rb_define_method(cPointer, "null?", RUBY_METHOD_FUNC(pointer_nil_p), 0);
00730     
00731     cCompound = rb_define_class_under(mTypelib, "CompoundType", cType);
00732     rb_define_singleton_method(cCompound, "get_fields",   RUBY_METHOD_FUNC(compound_get_fields), 0);
00733     rb_define_method(cCompound, "typelib_get_field", RUBY_METHOD_FUNC(compound_field_get), 2);
00734     rb_define_method(cCompound, "typelib_set_field", RUBY_METHOD_FUNC(compound_field_set), 2);
00735 
00736     cEnum = rb_define_class_under(mTypelib, "EnumType", cType);
00737     rb_define_singleton_method(cEnum, "keys", RUBY_METHOD_FUNC(enum_keys), 0);
00738     rb_define_singleton_method(cEnum, "value_of",      RUBY_METHOD_FUNC(enum_value_of), 1);
00739     rb_define_singleton_method(cEnum, "name_of",      RUBY_METHOD_FUNC(enum_name_of), 1);
00740     rb_define_singleton_method(cEnum, "to_ruby",      RUBY_METHOD_FUNC(&numeric_to_ruby), 1);
00741     rb_define_method(cEnum, "typelib_from_ruby",    RUBY_METHOD_FUNC(&numeric_from_ruby), 1);
00742 
00743     cArray    = rb_define_class_under(mTypelib, "ArrayType", cIndirect);
00744     rb_define_singleton_method(cArray, "length", RUBY_METHOD_FUNC(array_class_length), 0);
00745     rb_define_method(cArray, "do_get",  RUBY_METHOD_FUNC(array_get), -1);
00746     rb_define_method(cArray, "do_set",  RUBY_METHOD_FUNC(array_set), 2);
00747     rb_define_method(cArray, "do_each",    RUBY_METHOD_FUNC(array_do_each), 0);
00748     rb_define_method(cArray, "size",    RUBY_METHOD_FUNC(array_size), 0);
00749 
00750     cContainer = rb_define_class_under(mTypelib, "ContainerType", cIndirect);
00751     rb_define_singleton_method(cContainer, "container_kind", RUBY_METHOD_FUNC(container_kind), 0);
00752     rb_define_singleton_method(cContainer, "natural_size",   RUBY_METHOD_FUNC(container_natural_size), 0);
00753     rb_define_singleton_method(cContainer, "random_access?",   RUBY_METHOD_FUNC(container_random_access_p), 0);
00754     rb_define_method(cContainer, "length",    RUBY_METHOD_FUNC(container_length), 0);
00755     rb_define_method(cContainer, "size",    RUBY_METHOD_FUNC(container_length), 0);
00756     rb_define_method(cContainer, "do_clear",    RUBY_METHOD_FUNC(container_clear), 0);
00757     rb_define_method(cContainer, "do_push",    RUBY_METHOD_FUNC(container_do_push), 1);
00758     rb_define_method(cContainer, "do_get",    RUBY_METHOD_FUNC(container_do_get), 2);
00759     rb_define_method(cContainer, "do_set",    RUBY_METHOD_FUNC(container_do_set), 2);
00760     rb_define_method(cContainer, "do_each",      RUBY_METHOD_FUNC(container_each), 1);
00761     rb_define_method(cContainer, "do_erase",     RUBY_METHOD_FUNC(container_erase), 1);
00762     rb_define_method(cContainer, "do_delete_if", RUBY_METHOD_FUNC(container_delete_if), 0);
00763 
00764     VALUE mVector = rb_define_module_under(cContainer, "StdVector");
00765     rb_define_method(mVector, "contained_memory_id", RUBY_METHOD_FUNC(vector_contained_memory_id), 0);
00766     rb_define_method(mVector, "raw_memcpy", RUBY_METHOD_FUNC(vector_raw_memcpy), 2);
00767 }
00768 


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