Go to the documentation of this file.00001 #include "typelib.hh"
00002 #include <string>
00003
00004 using namespace Typelib;
00005 using std::string;
00006 using namespace typelib_ruby;
00007
00008 static bool is_string_handler(Registry const& registry, Type const& type, bool known_size = false)
00009 {
00010 if (type.getCategory() != Type::Array && type.getCategory() != Type::Pointer)
00011 return false;
00012
00013 Type const* char_type(registry.get("/char"));
00014 if (!char_type)
00015 return false;
00016
00017 Type const& data_type(static_cast<Indirect const&>(type).getIndirection());
00018 if (data_type.getName() != char_type->getName())
00019 return false;
00020
00021 if (known_size && type.getCategory() == Type::Pointer)
00022 return false;
00023
00024 return true;
00025
00026 }
00027 static void string_buffer_get(Value const& value, char*& buffer, string::size_type& size)
00028 {
00029 Type const& type(value.getType());
00030 if (type.getCategory() == Type::Array)
00031 {
00032 buffer = reinterpret_cast<char*>(value.getData());
00033 size = static_cast<Array const&>(type).getDimension();
00034 }
00035 else
00036 {
00037 buffer = *reinterpret_cast<char**>(value.getData());
00038 size = string::npos;
00039 }
00040 }
00041
00042 static VALUE value_string_handler_p(VALUE self)
00043 {
00044 Value const& value(rb2cxx::object<Value>(self));
00045 Type const& type(value.getType());
00046 Registry const& registry = rb2cxx::object<Registry>(value_get_registry(self));
00047 return is_string_handler(registry, type) ? Qtrue : Qfalse;
00048 }
00049
00050
00051
00052
00053
00054
00055 static VALUE value_from_string(VALUE mod, VALUE self, VALUE from, VALUE known_good_type)
00056 {
00057 Value const& value(rb2cxx::object<Value>(self));
00058 Type const& type(value.getType());
00059 Registry const& registry = rb2cxx::object<Registry>(value_get_registry(self));
00060
00061 if (!RTEST(known_good_type) && !is_string_handler(registry, type, true))
00062 rb_raise(rb_eTypeError, "Ruby strings can only be converted to char arrays");
00063
00064 char * buffer;
00065 string::size_type buffer_size;
00066 string_buffer_get(value, buffer, buffer_size);
00067
00068 string::size_type from_length = RSTRING_LEN(StringValue(from));
00069 if ((buffer_size - 1) < from_length)
00070 rb_raise(rb_eArgError, "array to small: %lu, while %lu was needed", buffer_size, from_length + 1);
00071
00072 strncpy(buffer, StringValueCStr(from), buffer_size);
00073 buffer[buffer_size - 1] = 0;
00074 return self;
00075 }
00076
00081 static VALUE value_to_string(VALUE mod, VALUE self, VALUE known_good_type)
00082 {
00083 Value const& value(rb2cxx::object<Value>(self));
00084 Type const& type(value.getType());
00085 Registry const& registry = rb2cxx::object<Registry>(value_get_registry(self));
00086
00087 if (!RTEST(known_good_type) && !is_string_handler(registry, type))
00088 rb_raise(rb_eRuntimeError, "invalid conversion to string");
00089
00090 char* buffer;
00091 string::size_type buffer_size;
00092 string_buffer_get(value, buffer, buffer_size);
00093
00094 if (buffer_size == string::npos)
00095 return rb_str_new2(buffer);
00096 else
00097 {
00098
00099 string::size_type real_size;
00100 for (real_size = 0; real_size < buffer_size; ++real_size)
00101 {
00102 if (!buffer[real_size])
00103 break;
00104 }
00105 return rb_str_new(buffer, real_size);
00106 }
00107 }
00108
00109 void typelib_ruby::Typelib_init_strings()
00110 {
00111 rb_define_singleton_method(cType, "to_string", RUBY_METHOD_FUNC(&value_to_string), 2);
00112 rb_define_singleton_method(cType, "from_string", RUBY_METHOD_FUNC(&value_from_string), 3);
00113 rb_define_method(cType, "string_handler?", RUBY_METHOD_FUNC(&value_string_handler_p), 0);
00114 }
00115