diff --git a/Examples/test-suite/li_std_wstring.i b/Examples/test-suite/li_std_wstring.i index 3c2d6f183..fe1166be3 100644 --- a/Examples/test-suite/li_std_wstring.i +++ b/Examples/test-suite/li_std_wstring.i @@ -78,6 +78,10 @@ std::wstring& test_reference_out() { return x; } +bool test_equal_abc(const std::wstring &s) { + return L"abc" == s; +} + #if defined(_MSC_VER) #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) #endif diff --git a/Examples/test-suite/ruby/li_std_wstring_runme.rb b/Examples/test-suite/ruby/li_std_wstring_runme.rb index eafb81f70..4e32fced9 100644 --- a/Examples/test-suite/ruby/li_std_wstring_runme.rb +++ b/Examples/test-suite/ruby/li_std_wstring_runme.rb @@ -2,21 +2,36 @@ require 'swig_assert' require 'li_std_wstring' -x = "h" - -swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) - - x = "abc" +swig_assert_equal("Li_std_wstring.test_wchar_overload(x)", "x", binding) +swig_assert_equal("Li_std_wstring.test_ccvalue(x)", "x", binding) +swig_assert_equal("Li_std_wstring.test_value(Li_std_wstring::Wstring.new(x))", "x", binding) +swig_assert_equal("Li_std_wstring.test_wchar_overload()", "nil", binding) + +swig_assert_equal("Li_std_wstring.test_pointer(Li_std_wstring::Wstring.new(x))", "nil", binding) +swig_assert_equal("Li_std_wstring.test_const_pointer(Li_std_wstring::Wstring.new(x))", "nil", binding) +swig_assert_equal("Li_std_wstring.test_const_pointer(Li_std_wstring::Wstring.new(x))", "nil", binding) +swig_assert_equal("Li_std_wstring.test_reference(Li_std_wstring::Wstring.new(x))", "nil", binding) + +x = "y" swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) - -x = "hello" - -swig_assert_equal("Li_std_wstring.test_const_reference(x)", "x", binding) - a = Li_std_wstring::A.new(x) - swig_assert_equal("Li_std_wstring.test_value(a)", "x", binding) -swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) +x = "hello" +swig_assert_equal("Li_std_wstring.test_const_reference(x)", "x", binding) + + +swig_assert_equal("Li_std_wstring.test_pointer_out", "'x'", binding) +swig_assert_equal("Li_std_wstring.test_const_pointer_out", "'x'", binding) +swig_assert_equal("Li_std_wstring.test_reference_out()", "'x'", binding) + +s = "abc" +swig_assert("Li_std_wstring.test_equal_abc(s)", binding) + +begin + Li_std_wstring.test_throw +rescue RuntimeError => e + swig_assert_equal("e.message", "'x'", binding) +end diff --git a/Lib/ruby/rubywstrings.swg b/Lib/ruby/rubywstrings.swg index afdeb1277..043f213bc 100644 --- a/Lib/ruby/rubywstrings.swg +++ b/Lib/ruby/rubywstrings.swg @@ -8,11 +8,28 @@ SWIGINTERN int SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) { - VALUE tmp = rb_str_conv_enc(obj, rb_enc_get(obj), - rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); - *alloc = SWIG_NEWOBJ; - return SWIG_AsCharPtrAndSize(tmp, (char**)cptr, psize, alloc); + if (TYPE(obj) == T_STRING) { + VALUE tmp = rb_str_conv_enc(obj, rb_enc_get(obj), + rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); + wchar_t* cstr = (wchar_t*) StringValuePtr(tmp); + size_t size = RSTRING_LEN(tmp) / sizeof(wchar_t) + 1; + + if( RSTRING_LEN(tmp) % sizeof(wchar_t) != 0 ) { + rb_raise(rb_eRuntimeError, + "The length of the byte sequence of converted string is not a multiplier of sizeof(wchar_t). Invalid byte sequence is given. Or invalid SWIG_RUBY_WSTRING_ENCODING is given when compiling this binding."); + } + if (cptr && alloc) { + *alloc = SWIG_NEWOBJ; + *cptr = %new_array(size, wchar_t); + memmove(*cptr, cstr, RSTRING_LEN(tmp)); + } + if(psize) *psize = size; + + return SWIG_OK; + } else { + return SWIG_TypeError; + } } } @@ -20,15 +37,19 @@ SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) SWIGINTERNINLINE VALUE SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) { - VALUE ret = SWIG_FromCharPtrAndSize( (const char*)carray, size); - rb_encoding* enc = rb_default_internal_encoding(); + if (carray && size <= LONG_MAX) { + VALUE ret = rb_str_new( (const char*)carray, %numeric_cast(size*sizeof(wchar_t),long) ); + rb_encoding* new_enc = rb_default_internal_encoding(); - rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); + rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); - if( !enc ) { - enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_INTERNAL_ENCODING )); + if( !new_enc ) { + new_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_INTERNAL_ENCODING )); + } + return rb_str_conv_enc(ret, rb_enc_get(ret), new_enc); + } else { + return Qnil; } - return rb_str_conv_enc(ret, rb_enc_get(ret), enc); } } diff --git a/Lib/ruby/std_wstring.i b/Lib/ruby/std_wstring.i index b99a71945..d41aa064b 100644 --- a/Lib/ruby/std_wstring.i +++ b/Lib/ruby/std_wstring.i @@ -15,9 +15,9 @@ extern "C" { #ifndef SWIG_RUBY_WSTRING_ENCODING #if WCHAR_MAX == 0x7fff || WCHAR_MAX == 0xffff -#define SWIG_RUBY_WSTRING_ENCODING "UTF-16" +#define SWIG_RUBY_WSTRING_ENCODING "UTF-16LE" #elif WCHAR_MAX == 0x7fffffff || WCHAR_MAX == 0xffffffff -#define SWIG_RUBY_WSTRING_ENCODING "UTF-32" +#define SWIG_RUBY_WSTRING_ENCODING "UTF-32LE" #else #error unsupported wchar_t size. SWIG_RUBY_WSTRING_ENCODING must be given. #endif