21#ifndef KROSS_RUBYVARIANT_H
22#define KROSS_RUBYVARIANT_H
24#define HAVE_STRLCAT_PROTO 1
25#define HAVE_STRLCPY_PROTO 1
34#define STR2CSTR(x) StringValuePtr(x)
38#include "rubyconfig.h"
41#include <tqstringlist.h>
47#include <tqdatetime.h>
104 template<
typename VARIANTTYPE,
typename RBTYPE = VALUE>
118 static VALUE toVALUE(
const TQVariant& v);
119 static TQVariant toVariant(VALUE value);
126 inline static VALUE toVALUE(
int i) {
129 inline static int toVariant(VALUE value) {
130 switch( TYPE(value) ) {
132 return FIX2INT(value);
134 return rb_big2int(value);
137 return (
int)(RFLOAT_VALUE(value));
139 return (
int)(RFLOAT(value)->value);
144 rb_raise(rb_eTypeError,
"Integer must be a fixed number");
151 struct RubyType<uint>
153 inline static VALUE toVALUE(uint i) {
156 inline static uint toVariant(VALUE value) {
157 switch( TYPE(value) ) {
159 return FIX2UINT(value);
161 return rb_big2uint(value);
164 return (uint)(RFLOAT_VALUE(value));
166 return (uint)(RFLOAT(value)->value);
171 rb_raise(rb_eTypeError,
"Unsigned integer must be a fixed number");
178 struct RubyType<double>
180 inline static VALUE toVALUE(
double d) {
181 return rb_float_new(d);
183 inline static double toVariant(VALUE value) {
184 return NUM2DBL(value);
190 struct RubyType<bool>
192 inline static VALUE toVALUE(
bool b) {
193 return b ? TRUE : FALSE;
195 inline static bool toVariant(VALUE value) {
196 switch( TYPE(value) ) {
202 rb_raise(rb_eTypeError,
"Boolean value expected");
211 struct RubyType<TQ_LLONG>
213 inline static VALUE toVALUE(TQ_LLONG l) {
214 return LONG2NUM((
long)l);
216 inline static TQ_LLONG toVariant(VALUE value) {
217 return NUM2LONG(value);
223 struct RubyType<TQ_ULLONG>
225 inline static VALUE toVALUE(TQ_ULLONG l) {
226 return UINT2NUM((
unsigned long)l);
228 inline static TQ_ULLONG toVariant(VALUE value) {
229 return NUM2UINT(value);
235 struct RubyType<TQByteArray>
237 inline static VALUE toVALUE(
const TQByteArray& ba) {
238 return rb_str_new(ba.data(), ba.size());
240 inline static TQByteArray toVariant(VALUE value) {
241 if( TYPE(value) != T_STRING ) {
242 rb_raise(rb_eTypeError,
"TQByteArray must be a string");
244 return TQCString(
"");
247 long length = LONG2NUM( RSTRING_LEN(value) );
249 long length = LONG2NUM( RSTRING(value)->len );
252 return TQCString(
"");
254 return TQCString(RSTRING_PTR(value), RSTRING_LEN(value));
256 char* ca = rb_str2cstr(value, &length);
257 return TQCString(ca, length);
264 struct RubyType<TQString>
266 inline static VALUE toVALUE(
const TQString& s) {
267 return s.isNull() ? rb_str_new2(
"") : rb_str_new2(s.latin1());
269 inline static TQString toVariant(VALUE value) {
270 if( TYPE(value) != T_STRING ) {
271 rb_raise(rb_eTypeError,
"TQString must be a string");
274 return STR2CSTR(value);
280 struct RubyType<TQSize>
282 inline static VALUE toVALUE(
const TQSize& s) {
283 VALUE l = rb_ary_new();
284 rb_ary_push(l, RubyType<int>::toVALUE(s.width()));
285 rb_ary_push(l, RubyType<int>::toVALUE(s.height()));
288 inline static TQSize toVariant(VALUE value) {
290 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
292 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
294 rb_raise(rb_eTypeError,
"TQSize must be an array with 2 elements");
297 return TQSize( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ) );
304 struct RubyType<TQSizeF>
306 inline static VALUE toVALUE(
const TQSizeF& s) {
307 VALUE l = rb_ary_new();
308 rb_ary_push(l, RubyType<double>::toVALUE(s.width()));
309 rb_ary_push(l, RubyType<double>::toVALUE(s.height()));
312 inline static TQSizeF toVariant(VALUE value) {
314 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
316 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
318 rb_raise(rb_eTypeError,
"TQSizeF must be an array with 2 elements");
321 return TQSizeF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ) );
329 struct RubyType<TQPoint>
331 inline static VALUE toVALUE(
const TQPoint& s) {
332 VALUE l = rb_ary_new();
333 rb_ary_push(l, RubyType<int>::toVALUE(s.x()));
334 rb_ary_push(l, RubyType<int>::toVALUE(s.y()));
337 inline static TQPoint toVariant(VALUE value) {
339 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
341 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
343 rb_raise(rb_eTypeError,
"TQPoint must be an array with 2 elements");
346 return TQPoint( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ) );
353 struct RubyType<TQPointF>
355 inline static VALUE toVALUE(
const TQPointF& s) {
356 VALUE l = rb_ary_new();
357 rb_ary_push(l, RubyType<double>::toVALUE(s.x()));
358 rb_ary_push(l, RubyType<double>::toVALUE(s.y()));
361 inline static TQPointF toVariant(VALUE value) {
363 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
365 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
367 rb_raise(rb_eTypeError,
"TQPointF must be an array with 2 elements");
370 return TQPointF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ) );
377 struct RubyType<TQRect>
379 inline static VALUE toVALUE(
const TQRect& s) {
380 VALUE l = rb_ary_new();
381 rb_ary_push(l, RubyType<int>::toVALUE(s.x()));
382 rb_ary_push(l, RubyType<int>::toVALUE(s.y()));
383 rb_ary_push(l, RubyType<int>::toVALUE(s.width()));
384 rb_ary_push(l, RubyType<int>::toVALUE(s.height()));
387 inline static TQRect toVariant(VALUE value) {
389 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 4 ) {
391 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 4 ) {
393 rb_raise(rb_eTypeError,
"TQRect must be an array with 4 elements");
396 return TQRect( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ),
397 RubyType<int>::toVariant( rb_ary_entry(value,2) ), RubyType<int>::toVariant( rb_ary_entry(value,3) ) );
404 struct RubyType<TQRectF>
406 inline static VALUE toVALUE(
const TQRectF& s) {
407 VALUE l = rb_ary_new();
408 rb_ary_push(l, RubyType<double>::toVALUE(s.x()));
409 rb_ary_push(l, RubyType<double>::toVALUE(s.y()));
410 rb_ary_push(l, RubyType<double>::toVALUE(s.width()));
411 rb_ary_push(l, RubyType<double>::toVALUE(s.height()));
414 inline static TQRectF toVariant(VALUE value) {
416 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 4 ) {
418 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 4 ) {
420 rb_raise(rb_eTypeError,
"TQRectF must be an array with 4 elements");
423 return TQRectF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ),
424 RubyType<double>::toVariant( rb_ary_entry(value,2) ), RubyType<double>::toVariant( rb_ary_entry(value,3) ) );
431 struct RubyType<TQUrl>
433 inline static VALUE toVALUE(
const TQUrl& url) {
434 return RubyType<TQString>::toVALUE( url.toString() );
436 inline static TQUrl toVariant(VALUE value) {
437 return TQUrl( RubyType<TQString>::toVariant(value) );
443 struct RubyType<TQStringList>
445 inline static VALUE toVALUE(
const TQStringList& list) {
446 VALUE l = rb_ary_new();
447 for (TQStringList::const_iterator it = list.begin(); it != list.end(); ++it) {
448 rb_ary_push(l, RubyType<TQString>::toVALUE(*it));
452 inline static TQStringList toVariant(VALUE value) {
453 if( TYPE(value) != T_ARRAY ) {
454 rb_raise(rb_eTypeError,
"TQStringList must be an array");
455 return TQStringList();
459 for(
int i = 0; i < RARRAY_LEN(value); i++)
461 for(
int i = 0; i < RARRAY(value)->len; i++)
463 l.append( RubyType<TQString>::toVariant( rb_ary_entry(value, i) ) );
471 struct RubyType<TQVariantList>
473 inline static VALUE toVALUE(
const TQVariantList& list) {
474 VALUE l = rb_ary_new();
475 foreach(TQVariant v, list)
476 rb_ary_push(l, RubyType<TQVariant>::toVALUE(v));
479 inline static TQVariantList toVariant(VALUE value) {
480 if( TYPE(value) != T_ARRAY ) {
481 rb_raise(rb_eTypeError,
"TQVariantList must be an array");
482 return TQVariantList();
486 for(
int i = 0; i < RARRAY_LEN(value); i++)
488 for(
int i = 0; i < RARRAY(value)->len; i++)
490 l.append( RubyType<TQVariant>::toVariant( rb_ary_entry(value, i) ) );
499 struct RubyType<TQStringVariantMap>
501 inline static VALUE toVALUE(
const TQStringVariantMap& map) {
502 VALUE h = rb_hash_new();
503 TQStringVariantMap::ConstIterator it(map.constBegin()), end(map.end());
504 for(; it != end; ++it)
505 rb_hash_aset(h, RubyType<TQString>::toVALUE(it.key()), RubyType<TQVariant>::toVALUE(it.value()) );
508 inline static int convertHash(VALUE key, VALUE value, VALUE vmap) {
509 TQStringVariantMap* map;
510 Data_Get_Struct(vmap, TQStringVariantMap, map);
512 map->insert(STR2CSTR(key), RubyType<TQVariant>::toVariant(value));
515 inline static TQStringVariantMap toVariant(VALUE value) {
516 if( TYPE(value) != T_HASH ) {
517 rb_raise(rb_eTypeError,
"TQStringVariantMap must be a hash");
518 return TQStringVariantMap();
520 TQStringVariantMap map;
521 VALUE vmap = Data_Wrap_Struct(rb_cObject, 0,0, &map);
522 rb_hash_foreach(value, (
int (*)(...))convertHash, vmap);
534 class RubyMetaTypeFactory
537 static MetaType*
create(
int typeId,
int metaTypeId, VALUE valueect = TQnil);
541 template<
typename VARIANTTYPE>
542 class RubyMetaTypeVariant :
public MetaTypeVariant<VARIANTTYPE>
545 RubyMetaTypeVariant(VALUE value)
546 : MetaTypeVariant<VARIANTTYPE>(
547 (TYPE(value) == T_NIL)
548 ? TQVariant().value<VARIANTTYPE>()
549 : RubyType<VARIANTTYPE>::toVariant(value)
552 virtual ~RubyMetaTypeVariant() {}
TDEAction * create(StdAction id, const char *name, const TQObject *recvr, const char *slot, TDEActionCollection *parent)
The Kross scripting bridge to embed scripting functionality into an application.
The RubyType helper classes used to cast between TQVariant and VALUE values.