[consider merging] properly conveying string encoding for Ruby, so that UTF-8 encoding is maintained when returning such strings from C++

This commit is contained in:
Matthias Koefferlein 2025-05-25 16:28:46 +02:00
parent 4dd4524da9
commit dec7ad9da1
9 changed files with 166 additions and 87 deletions

View File

@ -218,7 +218,7 @@ A::ia_cref_to_qs (const std::vector<int> &ia)
{
QString s;
for (std::vector<int>::const_iterator i = ia.begin (); i != ia.end (); ++i) {
s.push_back (char (*i));
s.push_back (QChar (*i));
}
return s;
}
@ -229,7 +229,7 @@ A::ia_cref_to_qs_ref (const std::vector<int> &ia)
static QString s;
s.clear ();
for (std::vector<int>::const_iterator i = ia.begin (); i != ia.end (); ++i) {
s.push_back (char (*i));
s.push_back (QChar (*i));
}
return s;
}
@ -243,7 +243,7 @@ A::ql1s_cref_to_ia (const QLatin1String &ql1s)
const char *cp = ql1s.data ();
size_t n = ql1s.size ();
for (size_t i = 0; i < n; ++i) {
ia.push_back (*cp++);
ia.push_back ((unsigned char) *cp++);
}
return ia;
}
@ -1270,7 +1270,15 @@ static gsi::Class<A> decl_a ("", "A",
gsi::method ("to_s", &A::to_s) +
gsi::iterator ("a6", &A::a6b, &A::a6e) +
gsi::iterator ("a7", &A::a7b, &A::a7e) +
gsi::iterator ("a8", &A::a8b, &A::a8e)
gsi::iterator ("a8", &A::a8b, &A::a8e) +
#if defined(HAVE_QT)
gsi::method ("ft_qba", &A::ft_qba) +
gsi::method ("ft_qs", &A::ft_qs) +
#endif
gsi::method ("ft_str", &A::ft_str) +
gsi::method ("ft_cv", &A::ft_cv) +
gsi::method ("ft_cptr", &A::ft_cptr) +
gsi::method ("ft_var", &A::ft_var)
);
static gsi::Class<A_NC> decl_a_nc (decl_a, "", "A_NC");

View File

@ -419,6 +419,17 @@ struct A
static int sp_i_get ();
static void sp_i_set (int v);
// feed-through values for full cycle tests
// (mainly for string encoding and binary strings)
static std::string ft_str (const std::string &v) { return v; }
static std::vector<char> ft_cv (const std::vector<char> &v) { return v; }
static const char *ft_cptr (const char *v) { return v; }
static tl::Variant ft_var (const tl::Variant &v) { return v; }
#if defined(HAVE_QT)
static QString ft_qs (const QString &v) { return v; }
static QByteArray ft_qba (const QByteArray &v) { return v; }
#endif
// members
std::vector<double> m_d;
int n;

View File

@ -501,7 +501,7 @@ PyObject *c2python_func<const tl::Variant &>::operator() (const tl::Variant &c)
} else if (c.is_bool ()) {
return c2python (c.to_bool ());
} else if (c.is_a_string ()) {
return c2python (c.to_string ());
return c2python (c.to_stdstring ());
} else if (c.is_a_bytearray ()) {
return c2python (c.to_bytearray ());
} else if (c.is_long ()) {

View File

@ -29,6 +29,8 @@
#include "gsiDecl.h"
#include <ruby/encoding.h>
namespace rba
{
@ -120,9 +122,17 @@ tl::Variant ruby2c<tl::Variant> (VALUE rval)
}
} else if (TYPE (rval) == T_STRING) {
return tl::Variant (ruby2c<const char *> (rval));
// UTF-8 encoded strings are taken to be string, others are byte strings
// At least this ensures consistency for a full Ruby-C++ turnaround cycle.
if (rb_enc_from_index (rb_enc_get_index (rval)) == rb_utf8_encoding ()) {
return tl::Variant (ruby2c<std::string> (rval));
} else {
return tl::Variant (ruby2c<std::vector<char> > (rval));
}
} else {
return tl::Variant (ruby2c<const char *> (rba_safe_obj_as_string (rval)));
return tl::Variant (ruby2c<std::string> (rba_safe_obj_as_string (rval)));
}
}
@ -261,7 +271,7 @@ VALUE c2ruby<tl::Variant> (const tl::Variant &c)
} else if (c.is_bool ()) {
return c2ruby<bool> (c.to_bool ());
} else if (c.is_a_string ()) {
return c2ruby<std::string> (c.to_string ());
return c2ruby<std::string> (c.to_stdstring ());
} else if (c.is_a_bytearray ()) {
return c2ruby<std::vector<char> > (c.to_bytearray ());
} else if (c.is_long () || c.is_char ()) {

View File

@ -461,7 +461,7 @@ inline VALUE c2ruby<float> (const float &c)
template <>
inline VALUE c2ruby<std::string> (const std::string &c)
{
return rb_str_new (c.c_str (), long (c.size ()));
return rb_utf8_str_new (c.c_str (), long (c.size ()));
}
template <>
@ -488,7 +488,7 @@ inline VALUE c2ruby<QString> (const QString &qs)
return Qnil;
} else {
std::string c (tl::to_string (qs));
return rb_str_new (c.c_str (), long (c.size ()));
return rb_utf8_str_new (c.c_str (), long (c.size ()));
}
}
#endif
@ -509,7 +509,7 @@ inline VALUE c2ruby<const char *> (const char * const & s)
static const char null_string[] = "(null)";
return rb_str_new (null_string, sizeof (null_string) - 1);
} else {
return rb_str_new (s, long (strlen (s)));
return rb_utf8_str_new (s, long (strlen (s)));
}
}

View File

@ -679,7 +679,7 @@ struct reader<gsi::StringType>
if (!a.get ()) {
*ret = Qnil;
} else {
*ret = rb_str_new (a->c_str (), long (a->size ()));
*ret = rb_utf8_str_new (a->c_str (), long (a->size ()));
}
}
};

View File

@ -45,12 +45,13 @@ QTextCodec *ms_system_codec = 0;
QString to_qstring (const std::string &s)
{
return QString::fromUtf8 (s.c_str ());
return QString::fromUtf8 (s.c_str (), s.size ());
}
std::string to_string (const QString &s)
{
return std::string (s.toUtf8 ().constData ());
auto utf8 = s.toUtf8 ();
return std::string (utf8.constData (), utf8.size ());
}
#if !defined(_WIN32)
@ -70,7 +71,7 @@ std::string string_to_system (const std::string &s)
initialize_codecs ();
}
QString qs = QString::fromUtf8 (s.c_str ());
QString qs = QString::fromUtf8 (s.c_str (), s.size ());
return std::string (ms_system_codec->fromUnicode (qs).constData ());
}
#endif

View File

@ -2994,8 +2994,12 @@ class BasicTest(unittest.TestCase):
qba = pya.A.ia_cref_to_qba([ 16, 42, 0, 8 ])
if sys.version_info < (3, 0):
self.assertEqual(repr(qba), "bytearray(b'\\x10*\\x00\\x08')")
self.assertEqual(repr(pya.A.ft_qba(qba)), "bytearray(b'\\x10*\\x00\\x08')")
self.assertEqual(repr(pya.A.ft_var(qba)), "bytearray(b'\\x10*\\x00\\x08')")
else:
self.assertEqual(repr(qba), "b'\\x10*\\x00\\x08'")
self.assertEqual(repr(pya.A.ft_qba(qba)), "b'\\x10*\\x00\\x08'")
self.assertEqual(repr(pya.A.ft_var(qba)), "b'\\x10*\\x00\\x08'")
self.assertEqual(pya.A.qba_to_ia(qba), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.qba_cref_to_ia(qba), [ 16, 42, 0, 8 ])
@ -3079,26 +3083,29 @@ class BasicTest(unittest.TestCase):
if "ia_cref_to_qs" in pya.A.__dict__:
qs = pya.A.ia_cref_to_qs([ 16, 42, 0, 8 ])
self.assertEqual(repr(qs), "'\\x10*\\x00\\x08'")
qs = pya.A.ia_cref_to_qs([ 16, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(qs), "'\\x10*\\x00\\x08\u03a9'")
# full cycle must preserve encoding, also for var
self.assertEqual(repr(pya.A.ft_qs(qs)), "'\\x10*\\x00\\x08\u03a9'")
self.assertEqual(repr(pya.A.ft_var(qs)), "'\\x10*\\x00\\x08\u03a9'")
self.assertEqual(pya.A.qs_to_ia(qs), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.qs_cref_to_ia(qs), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.qs_cptr_to_ia(qs), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.qs_ref_to_ia(qs), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.qs_ptr_to_ia(qs), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.qs_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
self.assertEqual(pya.A.qs_cref_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
self.assertEqual(pya.A.qs_cptr_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
self.assertEqual(pya.A.qs_ref_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
self.assertEqual(pya.A.qs_ptr_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
qs = pya.A.ia_cref_to_qs_cref([ 17, 42, 0, 8 ])
self.assertEqual(repr(qs), "'\\x11*\\x00\\x08'")
qs = pya.A.ia_cref_to_qs_cref([ 17, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(qs), "'\\x11*\\x00\\x08\u03a9'")
qs = pya.A.ia_cref_to_qs_ref([ 18, 42, 0, 8 ])
self.assertEqual(repr(qs), "'\\x12*\\x00\\x08'")
qs = pya.A.ia_cref_to_qs_ref([ 18, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(qs), "'\\x12*\\x00\\x08\u03a9'")
qs = pya.A.ia_cref_to_qs_cptr([ 19, 42, 0, 8 ])
self.assertEqual(repr(qs), "'\\x13*\\x00\\x08'")
qs = pya.A.ia_cref_to_qs_cptr([ 19, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(qs), "'\\x13*\\x00\\x08\u03a9'")
qs = pya.A.ia_cref_to_qs_ptr([ 20, 42, 0, 8 ])
self.assertEqual(repr(qs), "'\\x14*\\x00\\x08'")
qs = pya.A.ia_cref_to_qs_ptr([ 20, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(qs), "'\\x14*\\x00\\x08\u03a9'")
self.assertEqual(pya.A.qs_to_ia('\x00\x01\x02'), [ 0, 1, 2 ])
@ -3137,29 +3144,42 @@ class BasicTest(unittest.TestCase):
if "ia_cref_to_ql1s" in pya.A.__dict__:
ql1s = pya.A.ia_cref_to_ql1s([ 16, 42, 0, 8 ])
self.assertEqual(repr(ql1s), "'\\x10*\\x00\\x08'")
ql1s = pya.A.ia_cref_to_ql1s([ 16, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(ql1s), "'\\x10*\\x00\\x08\u00a9'")
self.assertEqual(pya.A.ql1s_to_ia(ql1s), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.ql1s_cref_to_ia(ql1s), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.ql1s_cptr_to_ia(ql1s), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.ql1s_ref_to_ia(ql1s), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.ql1s_ptr_to_ia(ql1s), [ 16, 42, 0, 8 ])
self.assertEqual(pya.A.ql1s_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
self.assertEqual(pya.A.ql1s_cref_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
self.assertEqual(pya.A.ql1s_cptr_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
self.assertEqual(pya.A.ql1s_ref_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
self.assertEqual(pya.A.ql1s_ptr_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
ql1s = pya.A.ia_cref_to_ql1s_cref([ 17, 42, 0, 8 ])
self.assertEqual(repr(ql1s), "'\\x11*\\x00\\x08'")
ql1s = pya.A.ia_cref_to_ql1s_cref([ 17, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(ql1s), "'\\x11*\\x00\\x08\u00a9'")
ql1s = pya.A.ia_cref_to_ql1s_ref([ 18, 42, 0, 8 ])
self.assertEqual(repr(ql1s), "'\\x12*\\x00\\x08'")
ql1s = pya.A.ia_cref_to_ql1s_ref([ 18, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(ql1s), "'\\x12*\\x00\\x08\u00a9'")
ql1s = pya.A.ia_cref_to_ql1s_cptr([ 19, 42, 0, 8 ])
self.assertEqual(repr(ql1s), "'\\x13*\\x00\\x08'")
ql1s = pya.A.ia_cref_to_ql1s_cptr([ 19, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(ql1s), "'\\x13*\\x00\\x08\u00a9'")
ql1s = pya.A.ia_cref_to_ql1s_ptr([ 20, 42, 0, 8 ])
self.assertEqual(repr(ql1s), "'\\x14*\\x00\\x08'")
ql1s = pya.A.ia_cref_to_ql1s_ptr([ 20, 42, 0, 8, 0x03a9 ])
self.assertEqual(repr(ql1s), "'\\x14*\\x00\\x08\u00a9'")
self.assertEqual(pya.A.ql1s_to_ia('\x00\x01\x02'), [ 0, 1, 2 ])
def test_utf8Strings(self):
# UTF8 strings (non-Qt)
s = "\u0010*\u0000\b\u03a9"
self.assertEqual(repr(s), "'\\x10*\\x00\\x08\u03a9'")
# full cycle must preserve encoding, also for var
self.assertEqual(repr(pya.A.ft_str(s)), "'\\x10*\\x00\\x08\u03a9'")
self.assertEqual(repr(pya.A.ft_var(s)), "'\\x10*\\x00\\x08\u03a9'")
# NUL character terminates in const char * mode:
self.assertEqual(repr(pya.A.ft_cptr(s)), "'\\x10*'")
def test_binaryStrings(self):
# binary strings (non-Qt)
@ -3167,8 +3187,13 @@ class BasicTest(unittest.TestCase):
ba = pya.A.ia_cref_to_ba([ 17, 42, 0, 8 ])
if sys.version_info < (3, 0):
self.assertEqual(repr(ba), "bytearray(b'\\x11*\\x00\\x08')")
self.assertEqual(repr(pya.A.ft_cv(ba)), "bytearray(b'\\x11*\\x00\\x08')")
self.assertEqual(repr(pya.A.ft_var(ba)), "bytearray(b'\\x11*\\x00\\x08')")
else:
self.assertEqual(repr(ba), "b'\\x11*\\x00\\x08'")
self.assertEqual(repr(pya.A.ft_cv(ba)), "b'\\x11*\\x00\\x08'")
self.assertEqual(repr(pya.A.ft_var(ba)), "b'\\x11*\\x00\\x08'")
self.assertEqual(pya.A.ba_to_ia(ba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.ba_cref_to_ia(ba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.ba_cptr_to_ia(ba), [ 17, 42, 0, 8 ])

View File

@ -2958,6 +2958,9 @@ class Basic_TestClass < TestBase
qba = RBA::A::ia_cref_to_qba([ 16, 42, 0, 8 ])
assert_equal(qba.inspect, "\"\\x10*\\x00\\b\"")
# full cycle must preserve encoding, also for var
assert_equal(RBA::A::ft_qba(qba).inspect, "\"\\x10*\\x00\\b\"")
assert_equal(RBA::A::ft_var(qba).inspect, "\"\\x10*\\x00\\b\"")
assert_equal(RBA::A::qba_to_ia(qba), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::qba_cref_to_ia(qba), [ 16, 42, 0, 8 ])
@ -3016,23 +3019,26 @@ class Basic_TestClass < TestBase
if RBA::A.respond_to?(:ia_cref_to_qs)
qs = RBA::A::ia_cref_to_qs([ 16, 42, 0, 8 ])
assert_equal(qs.inspect, "\"\\x10*\\x00\\b\"")
qs = RBA::A::ia_cref_to_qs([ 16, 42, 0, 8, 0x03a9 ])
assert_equal(qs.inspect, "\"\\u0010*\\u0000\\b\u03a9\"")
# full cycle must preserve encoding, also for var
assert_equal(RBA::A::ft_qs(qs).inspect, "\"\\u0010*\\u0000\\b\u03a9\"")
assert_equal(RBA::A::ft_var(qs).inspect, "\"\\u0010*\\u0000\\b\u03a9\"")
assert_equal(RBA::A::qs_to_ia(qs), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::qs_cref_to_ia(qs), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::qs_cptr_to_ia(qs), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::qs_ref_to_ia(qs), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::qs_ptr_to_ia(qs), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::qs_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
assert_equal(RBA::A::qs_cref_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
assert_equal(RBA::A::qs_cptr_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
assert_equal(RBA::A::qs_ref_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
assert_equal(RBA::A::qs_ptr_to_ia(qs), [ 16, 42, 0, 8, 0x03a9 ])
qs = RBA::A::ia_cref_to_qs_cref([ 17, 42, 0, 8 ])
assert_equal(qs.inspect, "\"\\x11*\\x00\\b\"")
qs = RBA::A::ia_cref_to_qs_ref([ 18, 42, 0, 8 ])
assert_equal(qs.inspect, "\"\\x12*\\x00\\b\"")
qs = RBA::A::ia_cref_to_qs_cptr([ 19, 42, 0, 8 ])
assert_equal(qs.inspect, "\"\\x13*\\x00\\b\"")
qs = RBA::A::ia_cref_to_qs_ptr([ 20, 42, 0, 8 ])
assert_equal(qs.inspect, "\"\\x14*\\x00\\b\"")
qs = RBA::A::ia_cref_to_qs_cref([ 17, 42, 0, 8, 0x03a9 ])
assert_equal(qs.inspect, "\"\\u0011*\\u0000\\b\u03a9\"")
qs = RBA::A::ia_cref_to_qs_ref([ 18, 42, 0, 8, 0x03a9 ])
assert_equal(qs.inspect, "\"\\u0012*\\u0000\\b\u03a9\"")
qs = RBA::A::ia_cref_to_qs_cptr([ 19, 42, 0, 8, 0x03a9 ])
assert_equal(qs.inspect, "\"\\u0013*\\u0000\\b\u03a9\"")
qs = RBA::A::ia_cref_to_qs_ptr([ 20, 42, 0, 8, 0x03a9 ])
assert_equal(qs.inspect, "\"\\u0014*\\u0000\\b\u03a9\"")
assert_equal(RBA::A::qs_to_ia("\x00\x01\x02"), [ 0, 1, 2 ])
@ -3046,23 +3052,23 @@ class Basic_TestClass < TestBase
if RBA::A.respond_to?(:ia_cref_to_ql1s)
ql1s = RBA::A::ia_cref_to_ql1s([ 16, 42, 0, 8 ])
assert_equal(ql1s.inspect, "\"\\x10*\\x00\\b\"")
ql1s = RBA::A::ia_cref_to_ql1s([ 16, 42, 0, 8, 0x03a9 ])
assert_equal(ql1s.inspect, "\"\\u0010*\\u0000\\b\u00a9\"")
assert_equal(RBA::A::ql1s_to_ia(ql1s), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ql1s_cref_to_ia(ql1s), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ql1s_cptr_to_ia(ql1s), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ql1s_ref_to_ia(ql1s), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ql1s_ptr_to_ia(ql1s), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ql1s_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
assert_equal(RBA::A::ql1s_cref_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
assert_equal(RBA::A::ql1s_cptr_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
assert_equal(RBA::A::ql1s_ref_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
assert_equal(RBA::A::ql1s_ptr_to_ia(ql1s), [ 16, 42, 0, 8, 0xa9 ])
ql1s = RBA::A::ia_cref_to_ql1s_cref([ 17, 42, 0, 8 ])
assert_equal(ql1s.inspect, "\"\\x11*\\x00\\b\"")
ql1s = RBA::A::ia_cref_to_ql1s_ref([ 18, 42, 0, 8 ])
assert_equal(ql1s.inspect, "\"\\x12*\\x00\\b\"")
ql1s = RBA::A::ia_cref_to_ql1s_cptr([ 19, 42, 0, 8 ])
assert_equal(ql1s.inspect, "\"\\x13*\\x00\\b\"")
ql1s = RBA::A::ia_cref_to_ql1s_ptr([ 20, 42, 0, 8 ])
assert_equal(ql1s.inspect, "\"\\x14*\\x00\\b\"")
ql1s = RBA::A::ia_cref_to_ql1s_cref([ 17, 42, 0, 8, 0xa9 ])
assert_equal(ql1s.inspect, "\"\\u0011*\\u0000\\b\u00a9\"")
ql1s = RBA::A::ia_cref_to_ql1s_ref([ 18, 42, 0, 8, 0xa9 ])
assert_equal(ql1s.inspect, "\"\\u0012*\\u0000\\b\u00a9\"")
ql1s = RBA::A::ia_cref_to_ql1s_cptr([ 19, 42, 0, 8, 0xa9 ])
assert_equal(ql1s.inspect, "\"\\u0013*\\u0000\\b\u00a9\"")
ql1s = RBA::A::ia_cref_to_ql1s_ptr([ 20, 42, 0, 8, 0xa9 ])
assert_equal(ql1s.inspect, "\"\\u0014*\\u0000\\b\u00a9\"")
assert_equal(RBA::A::ql1s_to_ia("\x00\x01\x02"), [ 0, 1, 2 ])
@ -3077,7 +3083,7 @@ class Basic_TestClass < TestBase
if RBA::A.respond_to?(:ia_cref_to_qsv)
qsv = RBA::A::ia_cref_to_qsv([ 16, 42, 0, 8 ])
assert_equal(qsv.inspect, "\"\\x10*\\x00\\b\"")
assert_equal(qsv.inspect, "\"\\u0010*\\u0000\\b\"")
assert_equal(RBA::A::qsv_to_ia(qsv), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::qsv_cref_to_ia(qsv), [ 16, 42, 0, 8 ])
@ -3086,13 +3092,13 @@ class Basic_TestClass < TestBase
assert_equal(RBA::A::qsv_ptr_to_ia(qsv), [ 16, 42, 0, 8 ])
qsv = RBA::A::ia_cref_to_qsv_cref([ 17, 42, 0, 8 ])
assert_equal(qsv.inspect, "\"\\x11*\\x00\\b\"")
assert_equal(qsv.inspect, "\"\\u0011*\\u0000\\b\"")
qsv = RBA::A::ia_cref_to_qsv_ref([ 18, 42, 0, 8 ])
assert_equal(qsv.inspect, "\"\\x12*\\x00\\b\"")
assert_equal(qsv.inspect, "\"\\u0012*\\u0000\\b\"")
qsv = RBA::A::ia_cref_to_qsv_cptr([ 19, 42, 0, 8 ])
assert_equal(qsv.inspect, "\"\\x13*\\x00\\b\"")
assert_equal(qsv.inspect, "\"\\u0013*\\u0000\\b\"")
qsv = RBA::A::ia_cref_to_qsv_ptr([ 20, 42, 0, 8 ])
assert_equal(qsv.inspect, "\"\\x14*\\x00\\b\"")
assert_equal(qsv.inspect, "\"\\u0014*\\u0000\\b\"")
assert_equal(RBA::A::qsv_to_ia("\x00\x01\x02"), [ 0, 1, 2 ])
@ -3100,18 +3106,36 @@ class Basic_TestClass < TestBase
end
def test_utf8Strings
# UTF8 strings (non-Qt)
s = "\u0010*\u0000\b\u03a9"
assert_equal(s.inspect, "\"\\u0010*\\u0000\\b\u03a9\"")
# full cycle must preserve encoding, also for var
assert_equal(RBA::A::ft_str(s).inspect, "\"\\u0010*\\u0000\\b\u03a9\"")
assert_equal(RBA::A::ft_var(s).inspect, "\"\\u0010*\\u0000\\b\u03a9\"")
# NUL character terminates in const char * mode:
assert_equal(RBA::A::ft_cptr(s).inspect, "\"\\u0010*\"")
end
def test_binaryStrings
# binary strings (non-Qt)
ba = RBA::A::ia_cref_to_ba([ 16, 42, 1, 8 ])
assert_equal(ba.inspect, "\"\\x10*\\x01\\b\"")
ba = RBA::A::ia_cref_to_ba([ 16, 42, 0, 8 ])
assert_equal(ba.inspect, "\"\\x10*\\x00\\b\"")
# full cycle must preserve encoding, also for var
assert_equal(RBA::A::ft_cv(ba).inspect, "\"\\x10*\\x00\\b\"")
assert_equal(RBA::A::ft_var(ba).inspect, "\"\\x10*\\x00\\b\"")
assert_equal(RBA::A::ba_to_ia(ba), [ 16, 42, 1, 8 ])
assert_equal(RBA::A::ba_cref_to_ia(ba), [ 16, 42, 1, 8 ])
assert_equal(RBA::A::ba_cptr_to_ia(ba), [ 16, 42, 1, 8 ])
assert_equal(RBA::A::ba_ref_to_ia(ba), [ 16, 42, 1, 8 ])
assert_equal(RBA::A::ba_ptr_to_ia(ba), [ 16, 42, 1, 8 ])
assert_equal(RBA::A::ba_to_ia(ba), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ba_cref_to_ia(ba), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ba_cptr_to_ia(ba), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ba_ref_to_ia(ba), [ 16, 42, 0, 8 ])
assert_equal(RBA::A::ba_ptr_to_ia(ba), [ 16, 42, 0, 8 ])
ba = RBA::A::ia_cref_to_ba_cref([ 17, 42, 0, 8 ])
assert_equal(ba.inspect, "\"\\x11*\\x00\\b\"")