$search
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 * Handle convertion between Ruby's String and C 'char*' types 00052 * It is a module function used to define #to_str on the relevant types 00053 * NEVER call it directly 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 // Search the real end of the string inside the buffer 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