parent
1e3ae08606
commit
b0b8e4ed0b
@ -0,0 +1,559 @@
|
||||
/***************************************************************************
|
||||
* rubyvariant.h
|
||||
* This file is part of the KDE project
|
||||
* copyright (C)2005 by Cyrille Berger (cberger@cberger.net)
|
||||
* copyright (C)2006 by Sebastian Sauer (mail@dipe.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
* You should have received a copy of the GNU Library General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef KROSS_RUBYVARIANT_H
|
||||
#define KROSS_RUBYVARIANT_H
|
||||
|
||||
#define HAVE_STRLCAT_PROTO 1
|
||||
#define HAVE_STRLCPY_PROTO 1
|
||||
#include "config.h"
|
||||
|
||||
#include <ruby.h>
|
||||
|
||||
#ifndef HAVE_RUBY_1_9
|
||||
#include <st.h>
|
||||
#else // HAVE_RUBY_1_9
|
||||
#include <ruby/st.h>
|
||||
#endif // HAVE_RUBY_1_9
|
||||
//#include <typeinfo>
|
||||
|
||||
#include "rubyconfig.h"
|
||||
|
||||
#include <tqstring.h>
|
||||
#include <tqstringlist.h>
|
||||
#include <tqvariant.h>
|
||||
#include <tqsize.h>
|
||||
#include <tqpoint.h>
|
||||
#include <tqrect.h>
|
||||
#include <tqurl.h>
|
||||
#include <tqdatetime.h>
|
||||
|
||||
namespace Kross {
|
||||
|
||||
/**
|
||||
* The RubyType helper classes used to cast between TQVariant
|
||||
* and VALUE values.
|
||||
*
|
||||
* Following TQVariant::Type's are implemented;
|
||||
* \li TQVariant::Invalid
|
||||
* \li TQVariant::Int
|
||||
* \li TQVariant::UInt
|
||||
* \li TQVariant::Double
|
||||
* \li TQVariant::Bool
|
||||
* \li TQVariant::LongLong
|
||||
* \li TQVariant::ULongLong
|
||||
* \li TQVariant::ByteArray
|
||||
* \li TQVariant::String
|
||||
* \li TQVariant::StringList
|
||||
* \li TQVariant::Size
|
||||
* \li TQVariant::SizeF
|
||||
* \li TQVariant::Point
|
||||
* \li TQVariant::PointF
|
||||
* \li TQVariant::Rect
|
||||
* \li TQVariant::RectF
|
||||
* \li TQVariant::Url
|
||||
* \li TQVariant::List
|
||||
* \li TQVariant::Map
|
||||
*
|
||||
* Following TQVariant::Type's are unimplemented yet (do we need them anyways?);
|
||||
* \li TQVariant::BitArray
|
||||
* \li TQVariant::Date
|
||||
* \li TQVariant::Time
|
||||
* \li TQVariant::DateTime
|
||||
* \li TQVariant::Bitmap
|
||||
* \li TQVariant::Brush
|
||||
* \li TQVariant::Char
|
||||
* \li TQVariant::Color
|
||||
* \li TQVariant::Cursor
|
||||
* \li TQVariant::Font
|
||||
* \li TQVariant::Icon
|
||||
* \li TQVariant::Image
|
||||
* \li TQVariant::KeySequence
|
||||
* \li TQVariant::Line
|
||||
* \li TQVariant::LineF
|
||||
* \li TQVariant::Locale
|
||||
* \li TQVariant::Palette
|
||||
* \li TQVariant::Pen
|
||||
* \li TQVariant::Pixmap
|
||||
* \li TQVariant::PointArray
|
||||
* \li TQVariant::Polygon
|
||||
* \li TQVariant::RegExp
|
||||
* \li TQVariant::Region
|
||||
* \li TQVariant::SizePolicy
|
||||
* \li TQVariant::TextFormat
|
||||
* \li TQVariant::TextLength
|
||||
*/
|
||||
template<typename VARIANTTYPE, typename RBTYPE = VALUE>
|
||||
struct RubyType
|
||||
{
|
||||
// template-specialisations need to implement following both static
|
||||
// functions to translate between TQVariant and Ruby's VALUE values.
|
||||
|
||||
//inline static RBTYPE toVALUE(const VARIANTTYPE&) { return Py::None(); }
|
||||
//inline static TQVARIANTTYPE toVariant(const VARIANTTYPE&) { return TQVariant(); }
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQVariant>
|
||||
{
|
||||
static VALUE toVALUE(const TQVariant& v);
|
||||
static TQVariant toVariant(VALUE value);
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<int>
|
||||
{
|
||||
inline static VALUE toVALUE(int i) {
|
||||
return INT2FIX(i);
|
||||
}
|
||||
inline static int toVariant(VALUE value) {
|
||||
switch( TYPE(value) ) {
|
||||
case T_FIXNUM:
|
||||
return FIX2INT(value);
|
||||
case T_BIGNUM:
|
||||
return rb_big2int(value);
|
||||
case T_FLOAT:
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
return (int)(RFLOAT_VALUE(value));
|
||||
#else
|
||||
return (int)(RFLOAT(value)->value);
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rb_raise(rb_eTypeError, "Integer must be a fixed number");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<uint>
|
||||
{
|
||||
inline static VALUE toVALUE(uint i) {
|
||||
return UINT2NUM(i);
|
||||
}
|
||||
inline static uint toVariant(VALUE value) {
|
||||
switch( TYPE(value) ) {
|
||||
case T_FIXNUM:
|
||||
return FIX2UINT(value);
|
||||
case T_BIGNUM:
|
||||
return rb_big2uint(value);
|
||||
case T_FLOAT:
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
return (uint)(RFLOAT_VALUE(value));
|
||||
#else
|
||||
return (uint)(RFLOAT(value)->value);
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rb_raise(rb_eTypeError, "Unsigned integer must be a fixed number");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<double>
|
||||
{
|
||||
inline static VALUE toVALUE(double d) {
|
||||
return rb_float_new(d);
|
||||
}
|
||||
inline static double toVariant(VALUE value) {
|
||||
return NUM2DBL(value);
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<bool>
|
||||
{
|
||||
inline static VALUE toVALUE(bool b) {
|
||||
return b ? TRUE : FALSE;
|
||||
}
|
||||
inline static bool toVariant(VALUE value) {
|
||||
switch( TYPE(value) ) {
|
||||
case T_TRUE:
|
||||
return true;
|
||||
case T_FALSE:
|
||||
return false;
|
||||
default: {
|
||||
rb_raise(rb_eTypeError, "Boolean value expected");
|
||||
return false;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQ_LLONG>
|
||||
{
|
||||
inline static VALUE toVALUE(TQ_LLONG l) {
|
||||
return /*INT2NUM*/ LONG2NUM((long)l);
|
||||
}
|
||||
inline static TQ_LLONG toVariant(VALUE value) {
|
||||
return NUM2LONG(value);
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQ_ULLONG>
|
||||
{
|
||||
inline static VALUE toVALUE(TQ_ULLONG l) {
|
||||
return UINT2NUM((unsigned long)l);
|
||||
}
|
||||
inline static TQ_ULLONG toVariant(VALUE value) {
|
||||
return NUM2UINT(value);
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQByteArray>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQByteArray& ba) {
|
||||
return rb_str_new(ba.data(), ba.size());
|
||||
}
|
||||
inline static TQByteArray toVariant(VALUE value) {
|
||||
if( TYPE(value) != T_STRING ) {
|
||||
rb_raise(rb_eTypeError, "TQByteArray must be a string");
|
||||
//return STR2CSTR( rb_inspect(value) );
|
||||
return TQCString("");
|
||||
}
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
long length = LONG2NUM( RSTRING_LEN(value) );
|
||||
#else
|
||||
long length = LONG2NUM( RSTRING(value)->len );
|
||||
#endif
|
||||
if( length < 0 )
|
||||
return TQCString("");
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
return TQCString(RSTRING_PTR(value), RSTRING_LEN(value));
|
||||
#else // HAVE_RUBY_1_9
|
||||
char* ca = rb_str2cstr(value, &length);
|
||||
return TQCString(ca, length);
|
||||
#endif // HAVE_RUBY_1_9
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQString>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQString& s) {
|
||||
return s.isNull() ? rb_str_new2("") : rb_str_new2(s.latin1());
|
||||
}
|
||||
inline static TQString toVariant(VALUE value) {
|
||||
if( TYPE(value) != T_STRING ) {
|
||||
rb_raise(rb_eTypeError, "TQString must be a string");
|
||||
return TQString();
|
||||
}
|
||||
return STR2CSTR(value);
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQSize>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQSize& s) {
|
||||
VALUE l = rb_ary_new();
|
||||
rb_ary_push(l, RubyType<int>::toVALUE(s.width()));
|
||||
rb_ary_push(l, RubyType<int>::toVALUE(s.height()));
|
||||
return l;
|
||||
}
|
||||
inline static TQSize toVariant(VALUE value) {
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
|
||||
#else
|
||||
if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
|
||||
#endif
|
||||
rb_raise(rb_eTypeError, "TQSize must be an array with 2 elements");
|
||||
return TQSize();
|
||||
}
|
||||
return TQSize( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ) );
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQSizeF>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQSizeF& s) {
|
||||
VALUE l = rb_ary_new();
|
||||
rb_ary_push(l, RubyType<double>::toVALUE(s.width()));
|
||||
rb_ary_push(l, RubyType<double>::toVALUE(s.height()));
|
||||
return l;
|
||||
}
|
||||
inline static TQSizeF toVariant(VALUE value) {
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
|
||||
#else
|
||||
if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
|
||||
#endif
|
||||
rb_raise(rb_eTypeError, "TQSizeF must be an array with 2 elements");
|
||||
return TQSizeF();
|
||||
}
|
||||
return TQSizeF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ) );
|
||||
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQPoint>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQPoint& s) {
|
||||
VALUE l = rb_ary_new();
|
||||
rb_ary_push(l, RubyType<int>::toVALUE(s.x()));
|
||||
rb_ary_push(l, RubyType<int>::toVALUE(s.y()));
|
||||
return l;
|
||||
}
|
||||
inline static TQPoint toVariant(VALUE value) {
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
|
||||
#else
|
||||
if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
|
||||
#endif
|
||||
rb_raise(rb_eTypeError, "TQPoint must be an array with 2 elements");
|
||||
return TQPoint();
|
||||
}
|
||||
return TQPoint( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ) );
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQPointF>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQPointF& s) {
|
||||
VALUE l = rb_ary_new();
|
||||
rb_ary_push(l, RubyType<double>::toVALUE(s.x()));
|
||||
rb_ary_push(l, RubyType<double>::toVALUE(s.y()));
|
||||
return l;
|
||||
}
|
||||
inline static TQPointF toVariant(VALUE value) {
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
|
||||
#else
|
||||
if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
|
||||
#endif
|
||||
rb_raise(rb_eTypeError, "TQPointF must be an array with 2 elements");
|
||||
return TQPointF();
|
||||
}
|
||||
return TQPointF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ) );
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQRect>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQRect& s) {
|
||||
VALUE l = rb_ary_new();
|
||||
rb_ary_push(l, RubyType<int>::toVALUE(s.x()));
|
||||
rb_ary_push(l, RubyType<int>::toVALUE(s.y()));
|
||||
rb_ary_push(l, RubyType<int>::toVALUE(s.width()));
|
||||
rb_ary_push(l, RubyType<int>::toVALUE(s.height()));
|
||||
return l;
|
||||
}
|
||||
inline static TQRect toVariant(VALUE value) {
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 4 ) {
|
||||
#else
|
||||
if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 4 ) {
|
||||
#endif
|
||||
rb_raise(rb_eTypeError, "TQRect must be an array with 4 elements");
|
||||
return TQRect();
|
||||
}
|
||||
return TQRect( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ),
|
||||
RubyType<int>::toVariant( rb_ary_entry(value,2) ), RubyType<int>::toVariant( rb_ary_entry(value,3) ) );
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQRectF>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQRectF& s) {
|
||||
VALUE l = rb_ary_new();
|
||||
rb_ary_push(l, RubyType<double>::toVALUE(s.x()));
|
||||
rb_ary_push(l, RubyType<double>::toVALUE(s.y()));
|
||||
rb_ary_push(l, RubyType<double>::toVALUE(s.width()));
|
||||
rb_ary_push(l, RubyType<double>::toVALUE(s.height()));
|
||||
return l;
|
||||
}
|
||||
inline static TQRectF toVariant(VALUE value) {
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 4 ) {
|
||||
#else
|
||||
if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 4 ) {
|
||||
#endif
|
||||
rb_raise(rb_eTypeError, "TQRectF must be an array with 4 elements");
|
||||
return TQRectF();
|
||||
}
|
||||
return TQRectF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ),
|
||||
RubyType<double>::toVariant( rb_ary_entry(value,2) ), RubyType<double>::toVariant( rb_ary_entry(value,3) ) );
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQUrl>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQUrl& url) {
|
||||
return RubyType<TQString>::toVALUE( url.toString() );
|
||||
}
|
||||
inline static TQUrl toVariant(VALUE value) {
|
||||
return TQUrl( RubyType<TQString>::toVariant(value) );
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQStringList>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQStringList& list) {
|
||||
VALUE l = rb_ary_new();
|
||||
for (TQStringList::const_iterator it = list.begin(); it != list.end(); ++it) {
|
||||
rb_ary_push(l, RubyType<TQString>::toVALUE(*it));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
inline static TQStringList toVariant(VALUE value) {
|
||||
if( TYPE(value) != T_ARRAY ) {
|
||||
rb_raise(rb_eTypeError, "TQStringList must be an array");
|
||||
return TQStringList();
|
||||
}
|
||||
TQStringList l;
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
for(int i = 0; i < RARRAY_LEN(value); i++)
|
||||
#else
|
||||
for(int i = 0; i < RARRAY(value)->len; i++)
|
||||
#endif
|
||||
l.append( RubyType<TQString>::toVariant( rb_ary_entry(value, i) ) );
|
||||
return l;
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQVariantList>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQVariantList& list) {
|
||||
VALUE l = rb_ary_new();
|
||||
foreach(TQVariant v, list)
|
||||
rb_ary_push(l, RubyType<TQVariant>::toVALUE(v));
|
||||
return l;
|
||||
}
|
||||
inline static TQVariantList toVariant(VALUE value) {
|
||||
if( TYPE(value) != T_ARRAY ) {
|
||||
rb_raise(rb_eTypeError, "TQVariantList must be an array");
|
||||
return TQVariantList();
|
||||
}
|
||||
TQVariantList l;
|
||||
#ifdef HAVE_RUBY_1_9
|
||||
for(int i = 0; i < RARRAY_LEN(value); i++)
|
||||
#else
|
||||
for(int i = 0; i < RARRAY(value)->len; i++)
|
||||
#endif
|
||||
l.append( RubyType<TQVariant>::toVariant( rb_ary_entry(value, i) ) );
|
||||
return l;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/// \internal
|
||||
template<>
|
||||
struct RubyType<TQVariantMap>
|
||||
{
|
||||
inline static VALUE toVALUE(const TQVariantMap& map) {
|
||||
VALUE h = rb_hash_new();
|
||||
TQMap<TQString, TQVariant>::ConstIterator it(map.constBegin()), end(map.end());
|
||||
for(; it != end; ++it)
|
||||
rb_hash_aset(h, RubyType<TQString>::toVALUE(it.key()), RubyType<TQVariant>::toVALUE(it.value()) );
|
||||
return h;
|
||||
}
|
||||
inline static int convertHash(VALUE key, VALUE value, VALUE vmap) {
|
||||
TQVariantMap* map;
|
||||
Data_Get_Struct(vmap, TQVariantMap, map);
|
||||
if (key != TQundef)
|
||||
map->insert(STR2CSTR(key), RubyType<TQVariant>::toVariant(value));
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
inline static TQVariantMap toVariant(VALUE value) {
|
||||
if( TYPE(value) != T_HASH ) {
|
||||
rb_raise(rb_eTypeError, "TQVariantMap must be a hash");
|
||||
return TQVariantMap();
|
||||
}
|
||||
TQVariantMap map;
|
||||
VALUE vmap = Data_Wrap_Struct(rb_cObject, 0,0, &map);
|
||||
rb_hash_foreach(value, (int (*)(...))convertHash, vmap);
|
||||
return map;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* The RubyMetaTypeFactory helper class us used as factory within
|
||||
* \a RubyExtension to translate an argument into a \a MetaType
|
||||
* needed for TQGenericArgument's data pointer.
|
||||
*/
|
||||
class RubyMetaTypeFactory
|
||||
{
|
||||
public:
|
||||
static MetaType* create(int typeId, int metaTypeId, VALUE valueect = TQnil);
|
||||
};
|
||||
|
||||
/// \internal
|
||||
template<typename VARIANTTYPE>
|
||||
class RubyMetaTypeVariant : public MetaTypeVariant<VARIANTTYPE>
|
||||
{
|
||||
public:
|
||||
RubyMetaTypeVariant(VALUE value)
|
||||
: MetaTypeVariant<VARIANTTYPE>(
|
||||
(TYPE(value) == T_NIL)
|
||||
? TQVariant().value<VARIANTTYPE>()
|
||||
: RubyType<VARIANTTYPE>::toVariant(value)
|
||||
) {}
|
||||
|
||||
virtual ~RubyMetaTypeVariant() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in new issue