Mapping QByteArray (and std::vector<char>) to Python 'bytes' now.

This commit is contained in:
Matthias Koefferlein 2021-01-24 17:36:40 +01:00
parent 233bff538b
commit 405445a427
14 changed files with 820 additions and 107 deletions

View File

@ -698,76 +698,6 @@ class GSI_PUBLIC_TEMPLATE StringAdaptorImpl
#if defined(HAVE_QT)
/**
* @brief Specialization for QByteArray
*/
template <>
class GSI_PUBLIC StringAdaptorImpl<QByteArray>
: public StringAdaptor
{
public:
StringAdaptorImpl (QByteArray *s)
: mp_s (s), m_is_const (false)
{
// .. nothing yet ..
}
StringAdaptorImpl (const QByteArray *s)
: mp_s (const_cast<QByteArray *> (s)), m_is_const (true)
{
// .. nothing yet ..
}
StringAdaptorImpl (const QByteArray &s)
: m_is_const (false), m_s (s)
{
mp_s = &m_s;
}
StringAdaptorImpl ()
: m_is_const (false)
{
mp_s = &m_s;
}
virtual ~StringAdaptorImpl ()
{
// .. nothing yet ..
}
virtual size_t size () const
{
return mp_s->size ();
}
virtual const char *c_str () const
{
return mp_s->constData ();
}
virtual void set (const char *c_str, size_t s, tl::Heap &)
{
if (! m_is_const) {
*mp_s = QByteArray (c_str, int (s));
}
}
virtual void copy_to (AdaptorBase *target, tl::Heap &heap) const
{
StringAdaptorImpl<QByteArray> *s = dynamic_cast<StringAdaptorImpl<QByteArray> *>(target);
if (s) {
*s->mp_s = *mp_s;
} else {
StringAdaptor::copy_to (target, heap);
}
}
private:
QByteArray *mp_s;
bool m_is_const;
QByteArray m_s;
};
/**
* @brief Specialization for QString
*/
@ -1102,6 +1032,206 @@ public:
StringAdaptorImpl (const char_type *s) : StringAdaptorImplCCP<const char_type *> (s) { }
};
// ------------------------------------------------------------
// ByteArray adaptor framework
/**
* @brief A generic adaptor for strings
* This is the base class for implementing generic access to strings
*/
class GSI_PUBLIC ByteArrayAdaptor
: public AdaptorBase
{
public:
/**
* @brief Default constructor
*/
ByteArrayAdaptor () { }
/**
* @brief Destructor
*/
virtual ~ByteArrayAdaptor () { }
/**
* @brief Returns the size of the string
*/
virtual size_t size () const = 0;
/**
* @brief Returns a pointer to a UTF8 encoded character array with size size()
*/
virtual const char *c_str () const = 0;
/**
* @brief Sets the string to the given UTF8 string with length s
*/
virtual void set (const char *c_str, size_t s, tl::Heap &heap) = 0;
/**
* @brief copy_to implementation
*/
virtual void copy_to (AdaptorBase *target, tl::Heap &heap) const
{
ByteArrayAdaptor *s = dynamic_cast<ByteArrayAdaptor *>(target);
tl_assert (s);
s->set (c_str (), size (), heap);
}
};
/**
* @brief Generic string adaptor implementation
*/
template <class X>
class GSI_PUBLIC_TEMPLATE ByteArrayAdaptorImpl
: public ByteArrayAdaptor
{
};
#if defined(HAVE_QT)
/**
* @brief Specialization for QByteArray
*/
template <>
class GSI_PUBLIC ByteArrayAdaptorImpl<QByteArray>
: public ByteArrayAdaptor
{
public:
ByteArrayAdaptorImpl (QByteArray *s)
: mp_s (s), m_is_const (false)
{
// .. nothing yet ..
}
ByteArrayAdaptorImpl (const QByteArray *s)
: mp_s (const_cast<QByteArray *> (s)), m_is_const (true)
{
// .. nothing yet ..
}
ByteArrayAdaptorImpl (const QByteArray &s)
: m_is_const (false), m_s (s)
{
mp_s = &m_s;
}
ByteArrayAdaptorImpl ()
: m_is_const (false)
{
mp_s = &m_s;
}
virtual ~ByteArrayAdaptorImpl ()
{
// .. nothing yet ..
}
virtual size_t size () const
{
return mp_s->size ();
}
virtual const char *c_str () const
{
return mp_s->constData ();
}
virtual void set (const char *c_str, size_t s, tl::Heap &)
{
if (! m_is_const) {
*mp_s = QByteArray (c_str, int (s));
}
}
virtual void copy_to (AdaptorBase *target, tl::Heap &heap) const
{
ByteArrayAdaptorImpl<QByteArray> *s = dynamic_cast<ByteArrayAdaptorImpl<QByteArray> *>(target);
if (s) {
*s->mp_s = *mp_s;
} else {
ByteArrayAdaptor::copy_to (target, heap);
}
}
private:
QByteArray *mp_s;
bool m_is_const;
QByteArray m_s;
};
#endif
/**
* @brief Specialization for std::string
*/
template <>
class GSI_PUBLIC ByteArrayAdaptorImpl<std::vector<char> >
: public ByteArrayAdaptor
{
public:
ByteArrayAdaptorImpl (std::vector<char> *s)
: mp_s (s), m_is_const (false)
{
// .. nothing yet ..
}
ByteArrayAdaptorImpl (const std::vector<char> *s)
: mp_s (const_cast<std::vector<char> *> (s)), m_is_const (true)
{
// .. nothing yet ..
}
ByteArrayAdaptorImpl (const std::vector<char> &s)
: m_is_const (false), m_s (s)
{
mp_s = &m_s;
}
ByteArrayAdaptorImpl ()
: m_is_const (false)
{
mp_s = &m_s;
}
virtual ~ByteArrayAdaptorImpl ()
{
// .. nothing yet ..
}
virtual size_t size () const
{
return mp_s->size ();
}
virtual const char *c_str () const
{
return &mp_s->front ();
}
virtual void set (const char *c_str, size_t s, tl::Heap &)
{
if (! m_is_const) {
*mp_s = std::vector<char> (c_str, c_str + s);
}
}
virtual void copy_to (AdaptorBase *target, tl::Heap &heap) const
{
ByteArrayAdaptorImpl<std::vector<char> > *s = dynamic_cast<ByteArrayAdaptorImpl<std::vector<char> > *>(target);
if (s) {
*s->mp_s = *mp_s;
} else {
ByteArrayAdaptor::copy_to (target, heap);
}
}
private:
std::vector<char> *mp_s;
bool m_is_const;
std::vector<char> m_s;
};
// ------------------------------------------------------------
// Variant adaptor framework
@ -1909,6 +2039,12 @@ inline AdaptorBase *create_adaptor_by_category(const string_adaptor_tag & /*tag*
return new StringAdaptorImpl<X> (v);
}
template <class X, class V>
inline AdaptorBase *create_adaptor_by_category(const byte_array_adaptor_tag & /*tag*/, V v)
{
return new ByteArrayAdaptorImpl<X> (v);
}
template <class X, class V>
inline AdaptorBase *create_adaptor_by_category(const variant_adaptor_tag & /*tag*/, const V &v)
{

View File

@ -76,6 +76,8 @@ ArgType::to_string () const
s += "float"; break;
case T_string:
s += "string"; break;
case T_byte_array:
s += "byte array"; break;
case T_var:
s += "variant"; break;
case T_object:

View File

@ -26,6 +26,7 @@
#include "tlInternational.h"
#include "tlException.h"
#include "tlTypeTraits.h"
#include "gsiCommon.h"
#include <string>
@ -37,6 +38,7 @@
#if defined(HAVE_QT)
#include <QString>
#include <QStringRef>
#include <QByteArray>
#include <QVariant>
#include <QMap>
#include <QHash>
@ -61,6 +63,7 @@ class GSI_PUBLIC SerialArgs;
class GSI_PUBLIC VectorAdaptor;
class GSI_PUBLIC MapAdaptor;
class GSI_PUBLIC StringAdaptor;
class GSI_PUBLIC ByteArrayAdaptor;
class GSI_PUBLIC VariantAdaptor;
class GSI_PUBLIC ClassBase;
struct NoAdaptorTag;
@ -112,6 +115,7 @@ enum BasicType
T_float = 14,
T_var = 15,
T_string = 16,
T_byte_array = 17,
T_void_ptr = 19,
T_object = 20,
T_vector = 21,
@ -175,6 +179,7 @@ struct adaptor_category_tag { };
struct vector_adaptor_tag : public adaptor_category_tag { };
struct map_adaptor_tag : public adaptor_category_tag { };
struct string_adaptor_tag : public adaptor_category_tag { };
struct byte_array_adaptor_tag : public adaptor_category_tag { };
struct variant_adaptor_tag : public adaptor_category_tag { };
struct basic_type_tag : public type_tag_base { };
@ -224,6 +229,7 @@ struct adaptor_ptr_tag : public npod_ptr_tag { };
struct vector_tag : public adaptor_direct_tag, public vector_adaptor_tag { };
struct map_tag : public adaptor_direct_tag, public map_adaptor_tag { };
struct string_tag : public adaptor_direct_tag, public string_adaptor_tag { };
struct byte_array_tag : public adaptor_direct_tag, public byte_array_adaptor_tag { };
struct var_tag : public adaptor_direct_tag, public variant_adaptor_tag { };
struct bool_cref_tag : public pod_cref_tag { };
@ -247,6 +253,7 @@ struct float_cref_tag : public pod_cref_tag { };
struct vector_cref_tag : public adaptor_cref_tag, public vector_adaptor_tag { };
struct map_cref_tag : public adaptor_cref_tag, public map_adaptor_tag { };
struct string_cref_tag : public adaptor_cref_tag, public string_adaptor_tag { };
struct byte_array_cref_tag : public adaptor_cref_tag, public byte_array_adaptor_tag { };
struct var_cref_tag : public adaptor_cref_tag, public variant_adaptor_tag { };
struct bool_ref_tag : public pod_ref_tag { };
@ -270,6 +277,7 @@ struct float_ref_tag : public pod_ref_tag { };
struct vector_ref_tag : public adaptor_ref_tag, public vector_adaptor_tag { };
struct map_ref_tag : public adaptor_ref_tag, public map_adaptor_tag { };
struct string_ref_tag : public adaptor_ref_tag, public string_adaptor_tag { };
struct byte_array_ref_tag : public adaptor_ref_tag, public byte_array_adaptor_tag { };
struct var_ref_tag : public adaptor_ref_tag, public variant_adaptor_tag { };
struct bool_cptr_tag : public pod_cptr_tag { };
@ -293,6 +301,7 @@ struct float_cptr_tag : public pod_cptr_tag { };
struct vector_cptr_tag : public adaptor_cptr_tag, public vector_adaptor_tag { };
struct map_cptr_tag : public adaptor_cptr_tag, public map_adaptor_tag { };
struct string_cptr_tag : public adaptor_cptr_tag, public string_adaptor_tag { };
struct byte_array_cptr_tag : public adaptor_cptr_tag, public byte_array_adaptor_tag { };
struct var_cptr_tag : public adaptor_cptr_tag, public variant_adaptor_tag { };
struct bool_ptr_tag : public pod_ptr_tag { };
@ -316,6 +325,7 @@ struct float_ptr_tag : public pod_ptr_tag { };
struct vector_ptr_tag : public adaptor_ptr_tag, public vector_adaptor_tag { };
struct map_ptr_tag : public adaptor_ptr_tag, public map_adaptor_tag { };
struct string_ptr_tag : public adaptor_ptr_tag, public string_adaptor_tag { };
struct byte_array_ptr_tag : public adaptor_ptr_tag, public byte_array_adaptor_tag { };
struct var_ptr_tag : public adaptor_ptr_tag, public variant_adaptor_tag { };
// all other objects
@ -427,7 +437,8 @@ template <> struct type_traits<std::string> : generic_type_trait
#if defined(HAVE_QT)
template <> struct type_traits<QString> : generic_type_traits<string_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QStringRef> : generic_type_traits<string_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QByteArray> : generic_type_traits<string_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QByteArray> : generic_type_traits<byte_array_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<std::vector<char> > : generic_type_traits<byte_array_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<QVariant> : generic_type_traits<var_tag, VariantAdaptor, T_var> { };
#endif
template <> struct type_traits<tl::Variant> : generic_type_traits<var_tag, VariantAdaptor, T_var> { };
@ -459,7 +470,8 @@ template <> struct type_traits<const std::string &> : generic_type_trait
#if defined(HAVE_QT)
template <> struct type_traits<const QString &> : generic_type_traits<string_cref_tag, StringAdaptor, T_string> { };
template <> struct type_traits<const QStringRef &> : generic_type_traits<string_cref_tag, StringAdaptor, T_string> { };
template <> struct type_traits<const QByteArray &> : generic_type_traits<string_cref_tag, StringAdaptor, T_string> { };
template <> struct type_traits<const QByteArray &> : generic_type_traits<byte_array_cref_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<const std::vector<char> &> : generic_type_traits<byte_array_cref_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<const QVariant &> : generic_type_traits<var_cref_tag, VariantAdaptor, T_var> { };
#endif
template <> struct type_traits<const tl::Variant &> : generic_type_traits<var_cref_tag, VariantAdaptor, T_var> { };
@ -488,7 +500,8 @@ template <> struct type_traits<std::string &> : generic_type_trait
#if defined(HAVE_QT)
template <> struct type_traits<QString &> : generic_type_traits<string_ref_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QStringRef &> : generic_type_traits<string_ref_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QByteArray &> : generic_type_traits<string_ref_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QByteArray &> : generic_type_traits<byte_array_ref_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<std::vector<char> &> : generic_type_traits<byte_array_ref_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<QVariant &> : generic_type_traits<var_ref_tag, VariantAdaptor, T_var> { };
#endif
template <> struct type_traits<tl::Variant &> : generic_type_traits<var_ref_tag, VariantAdaptor, T_var> { };
@ -518,7 +531,8 @@ template <> struct type_traits<const std::string *> : generic_type_trait
#if defined(HAVE_QT)
template <> struct type_traits<const QString *> : generic_type_traits<string_cptr_tag, StringAdaptor, T_string> { };
template <> struct type_traits<const QStringRef *> : generic_type_traits<string_cptr_tag, StringAdaptor, T_string> { };
template <> struct type_traits<const QByteArray *> : generic_type_traits<string_cptr_tag, StringAdaptor, T_string> { };
template <> struct type_traits<const QByteArray *> : generic_type_traits<byte_array_cptr_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<const std::vector<char> *> : generic_type_traits<byte_array_cptr_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<const QVariant *> : generic_type_traits<var_cptr_tag, VariantAdaptor, T_var> { };
#endif
template <> struct type_traits<const tl::Variant *> : generic_type_traits<var_cptr_tag, VariantAdaptor, T_var> { };
@ -548,7 +562,8 @@ template <> struct type_traits<std::string *> : generic_type_trait
#if defined(HAVE_QT)
template <> struct type_traits<QString *> : generic_type_traits<string_ptr_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QStringRef *> : generic_type_traits<string_ptr_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QByteArray *> : generic_type_traits<string_ptr_tag, StringAdaptor, T_string> { };
template <> struct type_traits<QByteArray *> : generic_type_traits<byte_array_ptr_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<std::vector<char> *> : generic_type_traits<byte_array_ptr_tag, StringAdaptor, T_byte_array> { };
template <> struct type_traits<QVariant *> : generic_type_traits<var_ptr_tag, VariantAdaptor, T_var> { };
#endif
template <> struct type_traits<tl::Variant *> : generic_type_traits<var_ptr_tag, VariantAdaptor, T_var> { };
@ -1976,6 +1991,11 @@ struct ObjectType { };
*/
struct StringType { };
/**
* @brief Represents "T_byte_array" as a C++ type
*/
struct ByteArrayType { };
/**
* @brief Represents "T_var" as a C++ type
*/
@ -2053,7 +2073,10 @@ void do_on_type_impl (gsi::BasicType type, const A1 *arg1, const A2 *arg2, const
case gsi::T_string:
call_variadic_function<F<StringType>, A1, A2, A3, A4, A5> () (arg1, arg2, arg3, arg4, arg5);
break;
case gsi::T_var:
case gsi::T_byte_array:
call_variadic_function<F<ByteArrayType>, A1, A2, A3, A4, A5> () (arg1, arg2, arg3, arg4, arg5);
break;
case gsi::T_var:
call_variadic_function<F<VariantType>, A1, A2, A3, A4, A5> () (arg1, arg2, arg3, arg4, arg5);
break;
case gsi::T_object:

View File

@ -107,6 +107,48 @@ const char *A::a_static ()
return "static_a";
}
std::vector<int>
A::qba_cref_to_ia (const QByteArray &ba)
{
const char *cp = ba.constData ();
size_t n = ba.size ();
std::vector<int> ia;
for (size_t i = 0; i < n; ++i) {
ia.push_back (int (*cp++));
}
return ia;
}
QByteArray
A::ia_cref_to_qba (const std::vector<int> &ia)
{
QByteArray ba;
for (std::vector<int>::const_iterator i = ia.begin (); i != ia.end (); ++i) {
ba.push_back (char (*i));
}
return ba;
}
std::vector<int>
A::ba_cref_to_ia (const std::vector<char> &ba)
{
std::vector<int> ia;
for (std::vector<char>::const_iterator i = ba.begin (); i != ba.end (); ++i) {
ia.push_back (int (*i));
}
return ia;
}
std::vector<char>
A::ia_cref_to_ba (const std::vector<int> &ia)
{
std::vector<char> ba;
for (std::vector<int>::const_iterator i = ia.begin (); i != ia.end (); ++i) {
ba.push_back (char (*i));
}
return ba;
}
static A *a_ctor (int i)
{
return new A (i);
@ -781,6 +823,22 @@ static gsi::QFlagsClass<Enum> decl_qflags_enum ("", "Enums");
static gsi::Class<A> decl_a ("", "A",
gsi::constructor ("new_a|new", &a_ctor) +
gsi::method ("instance_count", &A::instance_count) +
#if defined(HAVE_QT)
gsi::method ("qba_cref_to_ia", &A::qba_cref_to_ia) +
gsi::method ("qba_ref_to_ia", &A::qba_ref_to_ia) +
gsi::method ("qba_cptr_to_ia", &A::qba_cptr_to_ia) +
gsi::method ("qba_ptr_to_ia", &A::qba_ptr_to_ia) +
gsi::method ("qba_to_ia", &A::qba_to_ia) +
gsi::method ("ia_cref_to_qba", &A::ia_cref_to_qba) +
#endif
gsi::method ("ba_cref_to_ia", &A::ba_cref_to_ia) +
gsi::method ("ba_ref_to_ia", &A::ba_ref_to_ia) +
gsi::method ("ba_cptr_to_ia", &A::ba_cptr_to_ia) +
gsi::method ("ba_ptr_to_ia", &A::ba_ptr_to_ia) +
gsi::method ("ba_to_ia", &A::ba_to_ia) +
gsi::method ("ia_cref_to_ba", &A::ia_cref_to_ba) +
gsi::method ("br", &A::br) +
gsi::method ("get_e", &A::get_e) +
gsi::method ("get_eptr", &A::get_eptr) +

View File

@ -93,6 +93,36 @@ struct A
*/
static const char *a_static ();
#if defined(HAVE_QT)
/**
* @brief Byte sequences: tests access to QByteArray
*/
static std::vector<int> qba_cref_to_ia (const QByteArray &ba);
static std::vector<int> qba_ref_to_ia (QByteArray &ba) { return qba_cref_to_ia (ba); }
static std::vector<int> qba_cptr_to_ia (const QByteArray *ba) { return qba_cref_to_ia (*ba); }
static std::vector<int> qba_ptr_to_ia (QByteArray *ba) { return qba_cref_to_ia (*ba); }
static std::vector<int> qba_to_ia (QByteArray ba) { return qba_cref_to_ia (ba); }
/**
* @brief Byte sequences: tests return of QByteArray
*/
static QByteArray ia_cref_to_qba (const std::vector<int> &ia);
#endif
/**
* @brief Byte sequences: tests access to std::vector<char> (another byte array)
*/
static std::vector<int> ba_cref_to_ia (const std::vector<char> &ba);
static std::vector<int> ba_ref_to_ia (std::vector<char> &ba) { return ba_cref_to_ia (ba); }
static std::vector<int> ba_cptr_to_ia (const std::vector<char> *ba) { return ba_cref_to_ia (*ba); }
static std::vector<int> ba_ptr_to_ia (std::vector<char> *ba) { return ba_cref_to_ia (*ba); }
static std::vector<int> ba_to_ia (std::vector<char> ba) { return ba_cref_to_ia (ba); }
/**
* @brief Byte sequences: tests return of std::vector<char>
*/
static std::vector<char> ia_cref_to_ba (const std::vector<int> &ia);
/*
* @brief A dummy method providing a chance to set a breakpoint in the script
*/
@ -115,6 +145,9 @@ struct A
int a3 (const std::string &x) {
return int (x.size ());
}
int a3_ba (const std::vector<char> &x) {
return x.size ();
}
#if defined(HAVE_QT)
int a3_qstr (const QString &x) {
return x.size ();
@ -126,7 +159,7 @@ struct A
return x.size ();
}
#endif
double a4 (const std::vector<double> &d) {
double a4 (const std::vector<double> &d) {
m_d = d;
return d.back ();
}
@ -165,6 +198,7 @@ struct A
unsigned long long a11_ull (double f) { return (unsigned long long)(f); }
std::string a10_d (double f) { return tl::to_string (f); }
std::vector<char> a10_d_ba (double f) { std::string s = tl::to_string (f); return std::vector<char> (s.begin (), s.end ()); }
#if defined(HAVE_QT)
QByteArray a10_d_qba (double f) { return tl::to_qstring (tl::to_string (f)).toUtf8 (); }
QString a10_d_qstr (double f) { return tl::to_qstring (tl::to_string (f)); }

View File

@ -192,6 +192,42 @@ std::string python2c_func<std::string>::operator() (PyObject *rval)
}
}
template <>
std::vector<char> python2c_func<std::vector<char> >::operator() (PyObject *rval)
{
#if PY_MAJOR_VERSION < 3
if (PyString_Check (rval)) {
const char *cp = PyString_AsString (rval);
return std::vector<char> (cp, cp + PyString_Size (rval));
} else
#else
if (PyBytes_Check (rval)) {
char *cp = 0;
ssize_t sz = 0;
PyBytes_AsStringAndSize (rval, &cp, &sz);
tl_assert (cp != 0);
return std::vector<char> (cp, cp + sz);
} else
#endif
if (PyUnicode_Check (rval)) {
PythonRef ba (PyUnicode_AsUTF8String (rval));
if (! ba) {
check_error ();
}
char *cp = 0;
ssize_t sz = 0;
PyBytes_AsStringAndSize (ba.get (), &cp, &sz);
tl_assert (cp != 0);
return std::vector<char> (cp, cp + sz);
} else if (PyByteArray_Check (rval)) {
char *cp = PyByteArray_AsString (rval);
ssize_t sz = PyByteArray_Size (rval);
return std::vector<char> (cp, cp + sz);
} else {
throw tl::Exception (tl::to_string (tr ("Argument cannot be converted to a byte array")));
}
}
#if defined(HAVE_QT)
template <>
QByteArray python2c_func<QByteArray>::operator() (PyObject *rval)
@ -515,6 +551,16 @@ PyObject *c2python_func<const std::string &>::operator() (const std::string &c)
#endif
}
template <>
PyObject *c2python_func<const std::vector<char> &>::operator() (const std::vector<char> &c)
{
#if PY_MAJOR_VERSION < 3
return PyByteArray_FromStringAndSize (&c.front (), Py_ssize_t (c.size ()));
#else
return PyBytes_FromStringAndSize (&c.front (), Py_ssize_t (c.size ()));
#endif
}
template <>
PyObject *c2python_func<const char *>::operator() (const char *p)
{
@ -542,9 +588,9 @@ PyObject *c2python_func<const QByteArray &>::operator() (const QByteArray &qba)
Py_RETURN_NONE;
} else {
#if PY_MAJOR_VERSION < 3
return PyString_FromStringAndSize (qba.constData (), Py_ssize_t (qba.size ()));
#else
return PyByteArray_FromStringAndSize (qba.constData (), Py_ssize_t (qba.size ()));
#else
return PyBytes_FromStringAndSize (qba.constData (), Py_ssize_t (qba.size ()));
#endif
}
}

View File

@ -185,6 +185,7 @@ struct test_type_func<const char *>
};
template <> struct test_type_func<std::string> : public test_type_func<const char *> { };
template <> struct test_type_func<std::vector<char> > : public test_type_func<const char *> { };
#if defined(HAVE_QT)
template <> struct test_type_func<QString> : public test_type_func<const char *> { };
template <> struct test_type_func<QByteArray> : public test_type_func<const char *> { };
@ -333,6 +334,7 @@ template <> PYA_PUBLIC double python2c_func<double>::operator() (PyObject *rval)
template <> struct python2c_func<float> : public python2c_func_cast<float, double> { };
template <> PYA_PUBLIC std::string python2c_func<std::string>::operator() (PyObject *rval);
template <> PYA_PUBLIC std::vector<char> python2c_func<std::vector<char> >::operator() (PyObject *rval);
#if defined(HAVE_QT)
template <> PYA_PUBLIC QByteArray python2c_func<QByteArray>::operator() (PyObject *rval);
template <> PYA_PUBLIC QString python2c_func<QString>::operator() (PyObject *rval);
@ -620,6 +622,7 @@ template <> struct c2python_func<QByteArray> : public c2python_func<const QByteA
template <> PYA_PUBLIC PyObject *c2python_func<const std::string &>::operator() (const std::string &c);
template <> struct c2python_func<std::string> : public c2python_func<const std::string &> { };
template <> struct c2python_func<std::vector<char> > : public c2python_func<const std::vector<char> &> { };
template <>
struct c2python_func<void *>

View File

@ -61,6 +61,7 @@ public:
virtual void set (const char * /*c_str*/, size_t /*s*/, tl::Heap & /*heap*/)
{
// TODO: is there a setter for a string?
// So far it's not possible to have string OUT parameter
}
private:
@ -68,6 +69,40 @@ private:
PythonPtr m_string;
};
/**
* @brief An adaptor for a byte array from ruby objects
*/
class PythonBasedByteArrayAdaptor
: public gsi::ByteArrayAdaptor
{
public:
PythonBasedByteArrayAdaptor (const PythonPtr &ba)
: m_bytearray (python2c<std::vector<char> > (ba.get ())), m_bytes (ba)
{
// .. nothing yet ..
}
virtual const char *c_str () const
{
return &m_bytearray.front ();
}
virtual size_t size () const
{
return m_bytearray.size ();
}
virtual void set (const char * /*c_str*/, size_t /*s*/, tl::Heap & /*heap*/)
{
// TODO: is there a setter for a byte array?
// So far it's not possible to have bytes OUT parameter
}
private:
std::vector<char> m_bytearray;
PythonPtr m_bytes;
};
/**
* @brief An adaptor for a variant from ruby objects
*/
@ -303,6 +338,55 @@ struct writer<gsi::StringType>
}
};
/**
* @brief Serialization for strings
*/
template <>
struct writer<gsi::ByteArrayType>
{
void operator() (gsi::SerialArgs *aa, PyObject *arg, const gsi::ArgType &atype, tl::Heap *heap)
{
// Cannot pass ownership currently
tl_assert (!atype.pass_obj ());
if (arg == Py_None || arg == NULL) {
if (! (atype.is_ptr () || atype.is_cptr ())) {
// nil is treated as an empty string for references
aa->write<void *> ((void *)new gsi::ByteArrayAdaptorImpl<std::vector<char> > (std::vector<char> ()));
} else {
aa->write<void *> ((void *)0);
}
} else {
if (atype.is_ref () || atype.is_ptr ()) {
// references or pointers require a boxed object. Pointers also allow nil.
void *vc = 0;
get_boxed_value_func<std::vector<char> > () (&vc, arg, heap);
if (! vc && atype.is_ref ()) {
throw tl::Exception (tl::to_string (tr ("Arguments or return values of reference or direct type cannot be passed nil or an empty boxed value object")));
}
// NOTE: by convention we pass the ownership to the receiver for adaptors.
if (! vc) {
aa->write<void *> (0);
} else {
aa->write<void *> ((void *)new gsi::ByteArrayAdaptorImpl<std::vector<char> > ((std::vector<char> *) vc));
}
} else {
// NOTE: by convention we pass the ownership to the receiver for adaptors.
aa->write<void *> ((void *)new PythonBasedByteArrayAdaptor (arg));
}
}
}
};
/**
* @brief Specialization for Variant
*/
@ -533,6 +617,25 @@ struct reader<gsi::StringType>
}
};
/**
* @brief Deseralisation wrapper: specialization for byte arrays
*/
template <>
struct reader<gsi::ByteArrayType>
{
void operator() (gsi::SerialArgs *rr, PythonRef *ret, PYAObjectBase * /*self*/, const gsi::ArgType &, tl::Heap *heap)
{
std::unique_ptr<gsi::ByteArrayAdaptor> a ((gsi::ByteArrayAdaptor *) rr->read<void *>(*heap));
if (!a.get ()) {
*ret = PythonRef (Py_None, false /*borrowed*/);
} else {
const char *cp = a->c_str ();
size_t sz = a->size ();
*ret = c2python (std::vector<char> (cp, cp + sz));
}
}
};
static
PyObject *object_from_variant (const tl::Variant &var, PYAObjectBase *self, const gsi::ArgType &atype)
{

View File

@ -182,6 +182,12 @@ inline bool test_type<gsi::StringType> (VALUE rval, bool /*loose*/)
return TYPE (rval) == T_STRING;
}
template <>
inline bool test_type<gsi::ByteArrayType> (VALUE rval, bool /*loose*/)
{
return TYPE (rval) == T_STRING;
}
template <>
inline bool test_type<gsi::VariantType> (VALUE /*rval*/, bool /*loose*/)
{
@ -313,6 +319,15 @@ inline std::string ruby2c<std::string> (VALUE rval)
return std::string (RSTRING_PTR(str), RSTRING_LEN(str));
}
template <>
inline std::vector<char> ruby2c<std::vector<char> > (VALUE rval)
{
VALUE str = rba_safe_string_value (rval);
char *cp = RSTRING_PTR(str);
size_t sz = RSTRING_LEN(str);
return std::vector<char> (cp, cp + sz);
}
#if defined(HAVE_QT)
template <>
inline QByteArray ruby2c<QByteArray> (VALUE rval)
@ -450,6 +465,12 @@ inline VALUE c2ruby<std::string> (const std::string &c)
return rb_str_new (c.c_str (), long (c.size ()));
}
template <>
inline VALUE c2ruby<std::vector<char> > (const std::vector<char> &c)
{
return rb_str_new (&c.front (), c.size ());
}
#if defined(HAVE_QT)
template <>
inline VALUE c2ruby<QByteArray> (const QByteArray &qba)

View File

@ -68,12 +68,51 @@ public:
virtual void set (const char * /*c_str*/, size_t /*s*/, tl::Heap & /*heap*/)
{
// TODO: is there a setter for a string?
// -> so far, string OUT parameters are not supported
}
private:
VALUE m_string;
};
/**
* @brief An adaptor for a byte array from ruby objects
*/
class RubyBasedByteArrayAdaptor
: public gsi::ByteArrayAdaptor
{
public:
RubyBasedByteArrayAdaptor (VALUE value)
{
m_bytes = rba_safe_string_value (value);
gc_lock_object (m_bytes);
}
~RubyBasedByteArrayAdaptor ()
{
gc_unlock_object (m_bytes);
}
virtual const char *c_str () const
{
return RSTRING_PTR (m_bytes);
}
virtual size_t size () const
{
return RSTRING_LEN (m_bytes);
}
virtual void set (const char * /*c_str*/, size_t /*s*/, tl::Heap & /*heap*/)
{
// TODO: is there a setter for a string?
// -> so far, byte array OUT parameters are not supported
}
private:
VALUE m_bytes;
};
/**
* @brief An adaptor for a variant from ruby objects
*/
@ -214,6 +253,7 @@ struct get_boxed_value_func_error
template <> struct get_boxed_value_func<gsi::VariantType> : get_boxed_value_func_error { };
template <> struct get_boxed_value_func<gsi::StringType> : get_boxed_value_func_error { };
template <> struct get_boxed_value_func<gsi::ByteArrayType> : get_boxed_value_func_error { };
template <> struct get_boxed_value_func<gsi::ObjectType> : get_boxed_value_func_error { };
template <> struct get_boxed_value_func<gsi::VectorType> : get_boxed_value_func_error { };
template <> struct get_boxed_value_func<gsi::MapType> : get_boxed_value_func_error { };
@ -321,6 +361,55 @@ struct writer<gsi::StringType>
}
};
/**
* @brief Serialization for strings
*/
template <>
struct writer<gsi::ByteArrayType>
{
void operator() (gsi::SerialArgs *aa, VALUE arg, const gsi::ArgType &atype, tl::Heap *heap)
{
// Cannot pass ownership currently
tl_assert (!atype.pass_obj ());
if (arg == Qnil) {
if (! (atype.is_ptr () || atype.is_cptr ())) {
// nil is treated as an empty string for references
aa->write<void *> ((void *)new gsi::ByteArrayAdaptorImpl<std::vector<char> > (std::vector<char> ()));
} else {
aa->write<void *> ((void *)0);
}
} else {
if (atype.is_ref () || atype.is_ptr ()) {
// references or pointers require a boxed object. Pointers also allow nil.
void *vc = 0;
get_boxed_value_func<std::vector<char> > () (&vc, arg, heap);
if (! vc && atype.is_ref ()) {
throw tl::Exception (tl::to_string (tr ("Arguments or return values of reference or direct type cannot be passed nil or an empty boxed value object")));
}
// NOTE: by convention we pass the ownership to the receiver for adaptors.
if (! vc) {
aa->write<void *> (0);
} else {
aa->write<void *> ((void *)new gsi::ByteArrayAdaptorImpl<std::vector<char> > ((std::vector<char> *) vc));
}
} else {
// NOTE: by convention we pass the ownership to the receiver for adaptors.
aa->write<void *> ((void *)new RubyBasedByteArrayAdaptor (arg));
}
}
}
};
/**
* @brief Specialization for Variant
*/
@ -556,6 +645,23 @@ struct reader<gsi::StringType>
}
};
/**
* @brief Deseralisation wrapper: specialization for strings
*/
template <>
struct reader<gsi::ByteArrayType>
{
void operator() (gsi::SerialArgs *rr, VALUE *ret, Proxy * /*self*/, const gsi::ArgType &, tl::Heap *heap)
{
std::unique_ptr<gsi::ByteArrayAdaptor> a ((gsi::ByteArrayAdaptor *) rr->read<void *>(*heap));
if (!a.get ()) {
*ret = Qnil;
} else {
*ret = rb_str_new (a->c_str (), long (a->size ()));
}
}
};
static VALUE object_from_variant (const tl::Variant &var, Proxy *self, const gsi::ArgType &atype)
{
if (var.is_user()) {

View File

@ -238,6 +238,12 @@ Variant::Variant ()
// .. nothing yet ..
}
Variant::Variant (const std::vector<char> &ba)
: m_type (t_bytearray), m_string (0)
{
m_var.m_bytearray = new std::vector<char> (ba);
}
#if defined(HAVE_QT)
Variant::Variant (const QByteArray &qba)
@ -574,6 +580,8 @@ Variant::reset ()
delete m_var.m_list;
} else if (m_type == t_array) {
delete m_var.m_array;
} else if (m_type == t_bytearray) {
delete m_var.m_bytearray;
#if defined(HAVE_QT)
} else if (m_type == t_qstring) {
delete m_var.m_qstring;
@ -622,6 +630,20 @@ Variant::operator= (const std::string &s)
return *this;
}
Variant &
Variant::operator= (const std::vector<char> &s)
{
if (m_type == t_bytearray && &s == m_var.m_bytearray) {
// we are assigning to ourselves
} else {
std::vector<char> *snew = new std::vector<char> (s);
reset ();
m_type = t_bytearray;
m_var.m_bytearray = snew;
}
return *this;
}
#if defined(HAVE_QT)
Variant &
@ -837,6 +859,8 @@ Variant::operator= (const Variant &v)
#endif
} else if (m_type == t_id) {
m_var.m_id = v.m_var.m_id;
} else if (m_type == t_bytearray) {
m_var.m_bytearray = new std::vector<char> (*v.m_var.m_bytearray);
#if defined(HAVE_QT)
} else if (m_type == t_qstring) {
m_var.m_qstring = new QString (*v.m_var.m_qstring);
@ -922,6 +946,8 @@ normalized_type (Variant::type type)
case Variant::t_stdstring:
case Variant::t_string:
return Variant::t_string;
case Variant::t_bytearray:
return Variant::t_bytearray;
default:
#if defined(HAVE_64BIT_COORD)
case Variant::t_int128:
@ -989,6 +1015,9 @@ Variant::operator== (const tl::Variant &d) const
return to_double () == d.to_double ();
} else if (t == t_string) {
return strcmp (to_string (), d.to_string ()) == 0;
} else if (t == t_bytearray) {
// TODO: can't compare std::vector<char> with QByteArray currently
return *m_var.m_bytearray == *d.m_var.m_bytearray;
#if defined(HAVE_QT)
} else if (t == t_qstring) {
return *m_var.m_qstring == *d.m_var.m_qstring;
@ -1042,6 +1071,9 @@ Variant::operator< (const tl::Variant &d) const
return to_double () < d.to_double ();
} else if (t == t_string) {
return strcmp (to_string (), d.to_string ()) < 0;
} else if (t == t_bytearray) {
// TODO: can't compare std::vector<char> with QByteArray currently
return *m_var.m_bytearray < *d.m_var.m_bytearray;
#if defined(HAVE_QT)
} else if (t == t_qstring) {
return *m_var.m_qstring < *d.m_var.m_qstring;
@ -1099,6 +1131,7 @@ Variant::can_convert_to_float () const
case t_qstring:
case t_qbytearray:
#endif
case t_bytearray:
case t_stdstring:
case t_string:
{
@ -1138,6 +1171,7 @@ Variant::can_convert_to_double () const
case t_qstring:
case t_qbytearray:
#endif
case t_bytearray:
case t_stdstring:
case t_string:
{
@ -1177,6 +1211,7 @@ Variant::can_convert_to_int128 () const
case t_qstring:
case t_qbytearray:
#endif
case t_bytearray:
case t_stdstring:
// TODO: there is no range checking currently
return true;
@ -1191,7 +1226,7 @@ Variant::can_convert_to_ulonglong () const
{
switch (m_type) {
case t_double:
return m_var.m_double <= std::numeric_limits<unsigned long long>::max () && m_var.m_double >= std::numeric_limits<unsigned long long>::min ();
return m_var.m_double <= double (std::numeric_limits<unsigned long long>::max ()) && m_var.m_double >= double (std::numeric_limits<unsigned long long>::min ());
case t_float:
return m_var.m_float <= float (std::numeric_limits<unsigned long long>::max ()) && m_var.m_float >= float (std::numeric_limits<unsigned long long>::min ());
case t_longlong:
@ -1224,6 +1259,7 @@ Variant::can_convert_to_ulonglong () const
case t_qbytearray:
#endif
case t_stdstring:
case t_bytearray:
{
tl::Extractor ex (to_string ());
try {
@ -1243,7 +1279,7 @@ Variant::can_convert_to_longlong () const
{
switch (m_type) {
case t_double:
return m_var.m_double <= std::numeric_limits<long long>::max () && m_var.m_double >= std::numeric_limits<long long>::min ();
return m_var.m_double <= double (std::numeric_limits<long long>::max ()) && m_var.m_double >= double (std::numeric_limits<long long>::min ());
case t_float:
return m_var.m_float <= float (std::numeric_limits<long long>::max ()) && m_var.m_float >= float (std::numeric_limits<long long>::min ());
#if defined(HAVE_64BIT_COORD)
@ -1271,6 +1307,7 @@ Variant::can_convert_to_longlong () const
case t_qbytearray:
#endif
case t_stdstring:
case t_bytearray:
{
tl::Extractor ex (to_string ());
try {
@ -1290,9 +1327,9 @@ Variant::can_convert_to_ulong () const
{
switch (m_type) {
case t_double:
return m_var.m_double <= std::numeric_limits<unsigned long>::max () && m_var.m_double >= std::numeric_limits<unsigned long>::min ();
return m_var.m_double <= double (std::numeric_limits<unsigned long>::max ()) && m_var.m_double >= double (std::numeric_limits<unsigned long>::min ());
case t_float:
return m_var.m_float <= std::numeric_limits<unsigned long>::max () && m_var.m_float >= std::numeric_limits<unsigned long>::min ();
return m_var.m_float <= float (std::numeric_limits<unsigned long>::max ()) && m_var.m_float >= float (std::numeric_limits<unsigned long>::min ());
#if defined(HAVE_64BIT_COORD)
case t_int128:
return m_var.m_int128 <= __int128 (std::numeric_limits<unsigned long long>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<unsigned long long>::min ());
@ -1324,6 +1361,7 @@ Variant::can_convert_to_ulong () const
case t_qbytearray:
#endif
case t_stdstring:
case t_bytearray:
{
tl::Extractor ex (to_string ());
try {
@ -1343,7 +1381,7 @@ Variant::can_convert_to_long () const
{
switch (m_type) {
case t_double:
return m_var.m_double <= std::numeric_limits<long>::max () && m_var.m_double >= std::numeric_limits<long>::min ();
return m_var.m_double <= double (std::numeric_limits<long>::max ()) && m_var.m_double >= double (std::numeric_limits<long>::min ());
case t_float:
return m_var.m_float <= float (std::numeric_limits<long>::max ()) && m_var.m_float >= float (std::numeric_limits<long>::min ());
#if defined(HAVE_64BIT_COORD)
@ -1373,6 +1411,7 @@ Variant::can_convert_to_long () const
case t_qbytearray:
#endif
case t_stdstring:
case t_bytearray:
{
tl::Extractor ex (to_string ());
try {
@ -1392,9 +1431,9 @@ Variant::can_convert_to_int () const
{
switch (m_type) {
case t_double:
return m_var.m_double <= std::numeric_limits<int>::max () && m_var.m_double >= std::numeric_limits<int>::min ();
return m_var.m_double <= double (std::numeric_limits<int>::max ()) && m_var.m_double >= double (std::numeric_limits<int>::min ());
case t_float:
return m_var.m_float <= std::numeric_limits<int>::max () && m_var.m_float >= std::numeric_limits<int>::min ();
return m_var.m_float <= float (std::numeric_limits<int>::max ()) && m_var.m_float >= float (std::numeric_limits<int>::min ());
#if defined(HAVE_64BIT_COORD)
case t_int128:
return m_var.m_int128 <= __int128 (std::numeric_limits<int>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<int>::min ());
@ -1424,6 +1463,7 @@ Variant::can_convert_to_int () const
case t_qbytearray:
#endif
case t_stdstring:
case t_bytearray:
{
tl::Extractor ex (to_string ());
try {
@ -1443,9 +1483,9 @@ Variant::can_convert_to_uint () const
{
switch (m_type) {
case t_double:
return m_var.m_double <= std::numeric_limits<unsigned int>::max () && m_var.m_double >= std::numeric_limits<unsigned int>::min ();
return m_var.m_double <= double (std::numeric_limits<unsigned int>::max ()) && m_var.m_double >= double (std::numeric_limits<unsigned int>::min ());
case t_float:
return m_var.m_float <= std::numeric_limits<unsigned int>::max () && m_var.m_float >= std::numeric_limits<unsigned int>::min ();
return m_var.m_float <= float (std::numeric_limits<unsigned int>::max ()) && m_var.m_float >= float (std::numeric_limits<unsigned int>::min ());
#if defined(HAVE_64BIT_COORD)
case t_int128:
return m_var.m_int128 <= __int128 (std::numeric_limits<unsigned int>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<unsigned int>::min ());
@ -1475,6 +1515,7 @@ Variant::can_convert_to_uint () const
case t_qbytearray:
#endif
case t_stdstring:
case t_bytearray:
{
tl::Extractor ex (to_string ());
try {
@ -1526,6 +1567,8 @@ Variant::to_qbytearray () const
{
if (m_type == t_qbytearray) {
return *m_var.m_qbytearray;
} else if (m_type == t_bytearray) {
return QByteArray (&m_var.m_bytearray->front (), m_var.m_bytearray->size ());
} else if (m_type == t_qstring) {
return m_var.m_qstring->toUtf8 ();
} else if (m_type == t_stdstring) {
@ -1544,6 +1587,8 @@ Variant::to_qstring () const
return *m_var.m_qstring;
} else if (m_type == t_qbytearray) {
return QString::fromUtf8 (*m_var.m_qbytearray);
} else if (m_type == t_bytearray) {
return QString::fromUtf8 (&m_var.m_bytearray->front ());
} else {
return tl::to_qstring (to_string ());
}
@ -1551,11 +1596,32 @@ Variant::to_qstring () const
#endif
std::vector<char>
Variant::to_bytearray () const
{
if (m_type == t_qbytearray) {
return std::vector<char> (m_var.m_qbytearray->constBegin (), m_var.m_qbytearray->constEnd ());
} else if (m_type == t_bytearray) {
return *m_var.m_bytearray;
} else if (m_type == t_qstring) {
QByteArray ba = m_var.m_qstring->toUtf8 ();
return std::vector<char> (ba.constBegin (), ba.constEnd ());
} else if (m_type == t_stdstring) {
return std::vector<char> (m_var.m_stdstring->begin (), m_var.m_stdstring->end ());
} else {
// TODO: maybe some other conversion makes sense? I.e. byte representation of int?
std::string s = to_string ();
return std::vector<char> (s.begin (), s.end ());
}
}
std::string
Variant::to_stdstring () const
{
if (m_type == t_stdstring) {
return *m_var.m_stdstring;
} else if (m_type == t_bytearray) {
return std::string (m_var.m_bytearray->begin (), m_var.m_bytearray->end ());
#if defined(HAVE_QT)
} else if (m_type == t_qstring) {
return tl::to_string (*m_var.m_qstring);
@ -1574,11 +1640,31 @@ Variant::to_string () const
return m_var.m_stdstring->c_str ();
} else if (m_type == t_bytearray) {
// need to add a terminating 0 for safety
if (! m_string) {
size_t n = m_var.m_bytearray->size ();
m_string = new char [n + 1];
strncpy (m_string, &m_var.m_bytearray->front (), n);
m_string[n] = 0;
}
return m_string;
#if defined(HAVE_QT)
} else if (m_type == t_qbytearray) {
// TODO: content may be longer - const char * terminates at first 0 character
return m_var.m_qbytearray->constData ();
// need to add a terminating 0 for safety
if (! m_string) {
size_t n = m_var.m_qbytearray->size ();
m_string = new char [n + 1];
strncpy (m_string, m_var.m_qbytearray->constData (), n);
m_string[n] = 0;
}
return m_string;
#endif
// conversion needed
@ -1623,8 +1709,6 @@ Variant::to_string () const
#if defined(HAVE_QT)
} else if (m_type == t_qstring) {
r = tl::to_string (*m_var.m_qstring);
} else if (m_type == t_qbytearray) {
r = std::string (m_var.m_qbytearray->constData (), m_var.m_qbytearray->size ());
#endif
} else if (m_type == t_list) {
for (std::vector<tl::Variant>::const_iterator v = m_var.m_list->begin (); v != m_var.m_list->end (); ++v) {
@ -1709,8 +1793,8 @@ Variant::to_int128 () const
} else if (m_type == t_bool) {
return m_var.m_bool;
#if defined(HAVE_QT)
} else if (m_type == t_qbytearray) {
tl::Extractor ex (m_var.m_qbytearray->constData ());
} else if (m_type == t_qbytearray || m_type == t_bytearray) {
tl::Extractor ex (to_string ());
__int128 l = 0;
ex.read (l);
return l;
@ -1780,9 +1864,9 @@ Variant::to_ulonglong () const
tl::from_string (*m_var.m_stdstring, l);
return l;
#if defined(HAVE_QT)
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray || m_type == t_bytearray) {
#else
} else if (m_type == t_string) {
} else if (m_type == t_string || m_type == t_bytearray) {
#endif
unsigned long long l = 0;
tl::from_string (to_string (), l);
@ -1834,9 +1918,9 @@ Variant::to_longlong () const
tl::from_string (*m_var.m_stdstring, l);
return l;
#if defined(HAVE_QT)
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray || m_type == t_bytearray) {
#else
} else if (m_type == t_string) {
} else if (m_type == t_string || m_type == t_bytearray) {
#endif
long long l = 0;
tl::from_string (to_string (), l);
@ -1888,9 +1972,9 @@ Variant::to_ulong () const
tl::from_string (*m_var.m_stdstring, l);
return l;
#if defined(HAVE_QT)
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray || m_type == t_bytearray) {
#else
} else if (m_type == t_string) {
} else if (m_type == t_string || m_type == t_bytearray) {
#endif
unsigned long l = 0;
tl::from_string (to_string (), l);
@ -1942,9 +2026,9 @@ Variant::to_long () const
tl::from_string (*m_var.m_stdstring, l);
return l;
#if defined(HAVE_QT)
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray || m_type == t_bytearray) {
#else
} else if (m_type == t_string) {
} else if (m_type == t_string || m_type == t_bytearray) {
#endif
long l = 0;
tl::from_string (to_string (), l);
@ -2048,9 +2132,9 @@ Variant::to_double () const
tl::from_string (*m_var.m_stdstring, d);
return d;
#if defined(HAVE_QT)
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray || m_type == t_bytearray) {
#else
} else if (m_type == t_string) {
} else if (m_type == t_string || m_type == t_bytearray) {
#endif
double d = 0;
tl::from_string (to_string (), d);
@ -2114,6 +2198,8 @@ Variant::native_ptr () const
case t_qbytearray:
return m_var.m_qbytearray;
#endif
case t_bytearray:
return m_var.m_bytearray;
case t_stdstring:
return m_var.m_stdstring;
case t_array:
@ -2198,9 +2284,9 @@ Variant::to_parsable_string () const
} else if (is_stdstring ()) {
return tl::to_quoted_string (*m_var.m_stdstring);
#if defined(HAVE_QT)
} else if (is_cstring () || is_qstring () || is_qbytearray ()) {
} else if (is_cstring () || is_qstring () || is_qbytearray () || is_bytearray ()) {
#else
} else if (is_cstring ()) {
} else if (is_cstring () || is_bytearray ()) {
#endif
return tl::to_quoted_string (to_string ());
} else if (is_list ()) {
@ -2314,6 +2400,8 @@ QVariant Variant::to_qvariant () const
case t_qbytearray:
return QVariant (*m_var.m_qbytearray);
#endif
case t_bytearray:
return QVariant (to_qbytearray ());
case t_list:
{
QList<QVariant> l;

View File

@ -164,6 +164,7 @@ public:
t_double,
t_string,
t_stdstring,
t_bytearray,
#if defined(HAVE_QT)
t_qstring,
t_qbytearray,
@ -190,6 +191,11 @@ public:
*/
Variant (const tl::Variant &d);
/**
* @brief Initialize the Variant with a std::vector<char>
*/
Variant (const std::vector<char> &s);
#if defined(HAVE_QT)
/**
* @brief Initialize the Variant with a QByteArray
@ -447,6 +453,11 @@ public:
*/
Variant &operator= (const std::string &v);
/**
* @brief Assignment of a STL byte array
*/
Variant &operator= (const std::vector<char> &v);
/**
* @brief Assignment of a double
*/
@ -625,6 +636,14 @@ public:
QString to_qstring () const;
#endif
/**
* @brief Conversion to a STL byte array
*
* This performs the conversion to a std::vector<char> as far as possible.
* No conversion is provided to user types currently.
*/
std::vector<char> to_bytearray () const;
/**
* @brief Conversion to a std::string
*
@ -1326,6 +1345,14 @@ public:
return m_type == t_id;
}
/**
* @brief Test, if it is a std::vector<char> byte array
*/
bool is_bytearray () const
{
return m_type == t_bytearray;
}
#if defined(HAVE_QT)
/**
@ -1368,12 +1395,24 @@ public:
bool is_a_string () const
{
#if defined(HAVE_QT)
return m_type == t_string || m_type == t_stdstring || m_type == t_qstring || m_type == t_qbytearray;
return m_type == t_string || m_type == t_stdstring || m_type == t_qstring;
#else
return m_type == t_string || m_type == t_stdstring;
#endif
}
/**
* @brief Test, if it is a byte array
*/
bool is_a_bytearray () const
{
#if defined(HAVE_QT)
return m_type == t_bytearray || m_type == t_qbytearray;
#else
return m_type == t_bytearray;
#endif
}
/**
* @brief Returns true if the variant is of the given type internally
*
@ -1525,6 +1564,7 @@ private:
QString *m_qstring;
QByteArray *m_qbytearray;
#endif
std::vector<char> *m_bytearray;
std::string *m_stdstring;
} m_var;
@ -1553,6 +1593,7 @@ template<> inline __int128 Variant::to<__int128> () const
template<> inline double Variant::to<double> () const { return to_double (); }
template<> inline float Variant::to<float> () const { return to_float (); }
template<> inline std::string Variant::to<std::string> () const { return to_stdstring (); }
template<> inline std::vector<char> Variant::to<std::vector<char> > () const { return to_bytearray (); }
#if defined(HAVE_QT)
template<> inline QString Variant::to<QString> () const { return to_qstring (); }
template<> inline QByteArray Variant::to<QByteArray> () const { return to_qbytearray (); }
@ -1578,6 +1619,7 @@ template<> inline bool Variant::is<__int128> () const { return m_typ
template<> inline bool Variant::is<double> () const { return m_type == t_double; }
template<> inline bool Variant::is<float> () const { return m_type == t_float; }
template<> inline bool Variant::is<std::string> () const { return m_type == t_stdstring; }
template<> inline bool Variant::is<std::vector<char> > () const { return m_type == t_bytearray; }
#if defined(HAVE_QT)
template<> inline bool Variant::is<QString> () const { return m_type == t_qstring; }
template<> inline bool Variant::is<QByteArray> () const { return m_type == t_qbytearray; }
@ -1603,6 +1645,7 @@ template<> inline bool Variant::can_convert_to<__int128> () const {
template<> inline bool Variant::can_convert_to<double> () const { return can_convert_to_double (); }
template<> inline bool Variant::can_convert_to<float> () const { return can_convert_to_float (); }
template<> inline bool Variant::can_convert_to<std::string> () const { return true; }
template<> inline bool Variant::can_convert_to<std::vector<char> > () const { return true; }
#if defined(HAVE_QT)
template<> inline bool Variant::can_convert_to<QString> () const { return true; }
template<> inline bool Variant::can_convert_to<QByteArray> () const { return true; }

View File

@ -2809,6 +2809,30 @@ class BasicTest(unittest.TestCase):
self.assertEqual(sc.got_s0a, 0)
self.assertEqual(sc.got_s0b, 0)
def test_74(self):
# binary strings
qba = pya.A.ia_cref_to_qba([ 17, 42, 0, 8 ])
self.assertEqual(repr(qba), "b'\\x11*\\x00\\x08'")
self.assertEqual(pya.A.qba_to_ia(qba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.qba_cref_to_ia(qba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.qba_cptr_to_ia(qba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.qba_ref_to_ia(qba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.qba_ptr_to_ia(qba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.qba_to_ia(b'\x00\x01\x02'), [ 0, 1, 2 ])
ba = pya.A.ia_cref_to_ba([ 17, 42, 0, 8 ])
self.assertEqual(repr(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 ])
self.assertEqual(pya.A.ba_ref_to_ia(ba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.ba_ptr_to_ia(ba), [ 17, 42, 0, 8 ])
self.assertEqual(pya.A.ba_to_ia(b'\x00\x01\x02'), [ 0, 1, 2 ])
# Custom factory implemented in Python
def test_80(self):
gc = pya.GObject.g_inst_count()

View File

@ -2731,6 +2731,32 @@ class Basic_TestClass < TestBase
end
def test_74
# binary strings
qba = RBA::A::ia_cref_to_qba([ 17, 42, 0, 8 ])
assert_equal(qba.inspect, "\"\\x11*\\x00\\b\"")
assert_equal(RBA::A::qba_to_ia(qba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::qba_cref_to_ia(qba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::qba_cptr_to_ia(qba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::qba_ref_to_ia(qba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::qba_ptr_to_ia(qba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::qba_to_ia("\x00\x01\x02"), [ 0, 1, 2 ])
ba = RBA::A::ia_cref_to_ba([ 17, 42, 0, 8 ])
assert_equal(ba.inspect, "\"\\x11*\\x00\\b\"")
assert_equal(RBA::A::ba_to_ia(ba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::ba_cref_to_ia(ba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::ba_cptr_to_ia(ba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::ba_ref_to_ia(ba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::ba_ptr_to_ia(ba), [ 17, 42, 0, 8 ])
assert_equal(RBA::A::ba_to_ia("\x00\x01\x02"), [ 0, 1, 2 ])
end
# Custom factory implemented in Ruby
def test_80