rubyvariant.h
1/***************************************************************************
2 * rubyvariant.h
3 * This file is part of the KDE project
4 * copyright (C)2005 by Cyrille Berger (cberger@cberger.net)
5 * copyright (C)2006 by Sebastian Sauer (mail@dipe.org)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this program; see the file COPYING. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 ***************************************************************************/
20
21#ifndef KROSS_RUBYVARIANT_H
22#define KROSS_RUBYVARIANT_H
23
24#define HAVE_STRLCAT_PROTO 1
25#define HAVE_STRLCPY_PROTO 1
26#include "config.h"
27
28#include <ruby.h>
29
30#ifndef HAVE_RUBY_1_9
31#include <st.h>
32#else // HAVE_RUBY_1_9
33#include <ruby/st.h>
34#define STR2CSTR(x) StringValuePtr(x)
35#endif // HAVE_RUBY_1_9
36//#include <typeinfo>
37
38#include "rubyconfig.h"
39
40#include <tqstring.h>
41#include <tqstringlist.h>
42#include <tqvariant.h>
43#include <tqsize.h>
44#include <tqpoint.h>
45#include <tqrect.h>
46#include <tqurl.h>
47#include <tqdatetime.h>
48
49namespace Kross {
50
104 template<typename VARIANTTYPE, typename RBTYPE = VALUE>
105 struct RubyType
106 {
107 // template-specialisations need to implement following both static
108 // functions to translate between TQVariant and Ruby's VALUE values.
109
110 //inline static RBTYPE toVALUE(const VARIANTTYPE&) { return Py::None(); }
111 //inline static TQVARIANTTYPE toVariant(const VARIANTTYPE&) { return TQVariant(); }
112 };
113
115 template<>
116 struct RubyType<TQVariant>
117 {
118 static VALUE toVALUE(const TQVariant& v);
119 static TQVariant toVariant(VALUE value);
120 };
121
123 template<>
124 struct RubyType<int>
125 {
126 inline static VALUE toVALUE(int i) {
127 return INT2FIX(i);
128 }
129 inline static int toVariant(VALUE value) {
130 switch( TYPE(value) ) {
131 case T_FIXNUM:
132 return FIX2INT(value);
133 case T_BIGNUM:
134 return rb_big2int(value);
135 case T_FLOAT:
136#ifdef HAVE_RUBY_1_9
137 return (int)(RFLOAT_VALUE(value));
138#else
139 return (int)(RFLOAT(value)->value);
140#endif
141 default:
142 break;
143 }
144 rb_raise(rb_eTypeError, "Integer must be a fixed number");
145 return 0;
146 }
147 };
148
150 template<>
151 struct RubyType<uint>
152 {
153 inline static VALUE toVALUE(uint i) {
154 return UINT2NUM(i);
155 }
156 inline static uint toVariant(VALUE value) {
157 switch( TYPE(value) ) {
158 case T_FIXNUM:
159 return FIX2UINT(value);
160 case T_BIGNUM:
161 return rb_big2uint(value);
162 case T_FLOAT:
163#ifdef HAVE_RUBY_1_9
164 return (uint)(RFLOAT_VALUE(value));
165#else
166 return (uint)(RFLOAT(value)->value);
167#endif
168 default:
169 break;
170 }
171 rb_raise(rb_eTypeError, "Unsigned integer must be a fixed number");
172 return 0;
173 }
174 };
175
177 template<>
178 struct RubyType<double>
179 {
180 inline static VALUE toVALUE(double d) {
181 return rb_float_new(d);
182 }
183 inline static double toVariant(VALUE value) {
184 return NUM2DBL(value);
185 }
186 };
187
189 template<>
190 struct RubyType<bool>
191 {
192 inline static VALUE toVALUE(bool b) {
193 return b ? TRUE : FALSE;
194 }
195 inline static bool toVariant(VALUE value) {
196 switch( TYPE(value) ) {
197 case T_TRUE:
198 return true;
199 case T_FALSE:
200 return false;
201 default: {
202 rb_raise(rb_eTypeError, "Boolean value expected");
203 return false;
204 } break;
205 }
206 }
207 };
208
210 template<>
211 struct RubyType<TQ_LLONG>
212 {
213 inline static VALUE toVALUE(TQ_LLONG l) {
214 return /*INT2NUM*/ LONG2NUM((long)l);
215 }
216 inline static TQ_LLONG toVariant(VALUE value) {
217 return NUM2LONG(value);
218 }
219 };
220
222 template<>
223 struct RubyType<TQ_ULLONG>
224 {
225 inline static VALUE toVALUE(TQ_ULLONG l) {
226 return UINT2NUM((unsigned long)l);
227 }
228 inline static TQ_ULLONG toVariant(VALUE value) {
229 return NUM2UINT(value);
230 }
231 };
232
234 template<>
235 struct RubyType<TQByteArray>
236 {
237 inline static VALUE toVALUE(const TQByteArray& ba) {
238 return rb_str_new(ba.data(), ba.size());
239 }
240 inline static TQByteArray toVariant(VALUE value) {
241 if( TYPE(value) != T_STRING ) {
242 rb_raise(rb_eTypeError, "TQByteArray must be a string");
243 //return STR2CSTR( rb_inspect(value) );
244 return TQCString("");
245 }
246#ifdef HAVE_RUBY_1_9
247 long length = LONG2NUM( RSTRING_LEN(value) );
248#else
249 long length = LONG2NUM( RSTRING(value)->len );
250#endif
251 if( length < 0 )
252 return TQCString("");
253#ifdef HAVE_RUBY_1_9
254 return TQCString(RSTRING_PTR(value), RSTRING_LEN(value));
255#else // HAVE_RUBY_1_9
256 char* ca = rb_str2cstr(value, &length);
257 return TQCString(ca, length);
258#endif // HAVE_RUBY_1_9
259 }
260 };
261
263 template<>
264 struct RubyType<TQString>
265 {
266 inline static VALUE toVALUE(const TQString& s) {
267 return s.isNull() ? rb_str_new2("") : rb_str_new2(s.latin1());
268 }
269 inline static TQString toVariant(VALUE value) {
270 if( TYPE(value) != T_STRING ) {
271 rb_raise(rb_eTypeError, "TQString must be a string");
272 return TQString();
273 }
274 return STR2CSTR(value);
275 }
276 };
277
279 template<>
280 struct RubyType<TQSize>
281 {
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()));
286 return l;
287 }
288 inline static TQSize toVariant(VALUE value) {
289#ifdef HAVE_RUBY_1_9
290 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
291#else
292 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
293#endif
294 rb_raise(rb_eTypeError, "TQSize must be an array with 2 elements");
295 return TQSize();
296 }
297 return TQSize( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ) );
298 }
299 };
300
301#if 0
303 template<>
304 struct RubyType<TQSizeF>
305 {
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()));
310 return l;
311 }
312 inline static TQSizeF toVariant(VALUE value) {
313#ifdef HAVE_RUBY_1_9
314 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
315#else
316 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
317#endif
318 rb_raise(rb_eTypeError, "TQSizeF must be an array with 2 elements");
319 return TQSizeF();
320 }
321 return TQSizeF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ) );
322
323 }
324 };
325#endif
326
328 template<>
329 struct RubyType<TQPoint>
330 {
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()));
335 return l;
336 }
337 inline static TQPoint toVariant(VALUE value) {
338#ifdef HAVE_RUBY_1_9
339 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
340#else
341 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
342#endif
343 rb_raise(rb_eTypeError, "TQPoint must be an array with 2 elements");
344 return TQPoint();
345 }
346 return TQPoint( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ) );
347 }
348 };
349
350#if 0
352 template<>
353 struct RubyType<TQPointF>
354 {
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()));
359 return l;
360 }
361 inline static TQPointF toVariant(VALUE value) {
362#ifdef HAVE_RUBY_1_9
363 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2 ) {
364#else
365 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 2 ) {
366#endif
367 rb_raise(rb_eTypeError, "TQPointF must be an array with 2 elements");
368 return TQPointF();
369 }
370 return TQPointF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ) );
371 }
372 };
373#endif
374
376 template<>
377 struct RubyType<TQRect>
378 {
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()));
385 return l;
386 }
387 inline static TQRect toVariant(VALUE value) {
388#ifdef HAVE_RUBY_1_9
389 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 4 ) {
390#else
391 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 4 ) {
392#endif
393 rb_raise(rb_eTypeError, "TQRect must be an array with 4 elements");
394 return TQRect();
395 }
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) ) );
398 }
399 };
400
401#if 0
403 template<>
404 struct RubyType<TQRectF>
405 {
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()));
412 return l;
413 }
414 inline static TQRectF toVariant(VALUE value) {
415#ifdef HAVE_RUBY_1_9
416 if( TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 4 ) {
417#else
418 if( TYPE(value) != T_ARRAY || RARRAY(value)->len != 4 ) {
419#endif
420 rb_raise(rb_eTypeError, "TQRectF must be an array with 4 elements");
421 return TQRectF();
422 }
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) ) );
425 }
426 };
427#endif
428
430 template<>
431 struct RubyType<TQUrl>
432 {
433 inline static VALUE toVALUE(const TQUrl& url) {
434 return RubyType<TQString>::toVALUE( url.toString() );
435 }
436 inline static TQUrl toVariant(VALUE value) {
437 return TQUrl( RubyType<TQString>::toVariant(value) );
438 }
439 };
440
442 template<>
443 struct RubyType<TQStringList>
444 {
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));
449 }
450 return l;
451 }
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();
456 }
457 TQStringList l;
458#ifdef HAVE_RUBY_1_9
459 for(int i = 0; i < RARRAY_LEN(value); i++)
460#else
461 for(int i = 0; i < RARRAY(value)->len; i++)
462#endif
463 l.append( RubyType<TQString>::toVariant( rb_ary_entry(value, i) ) );
464 return l;
465 }
466 };
467
468#if 0
470 template<>
471 struct RubyType<TQVariantList>
472 {
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));
477 return l;
478 }
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();
483 }
484 TQVariantList l;
485#ifdef HAVE_RUBY_1_9
486 for(int i = 0; i < RARRAY_LEN(value); i++)
487#else
488 for(int i = 0; i < RARRAY(value)->len; i++)
489#endif
490 l.append( RubyType<TQVariant>::toVariant( rb_ary_entry(value, i) ) );
491 return l;
492 }
493 };
494#endif
495
496#if 0
498 template<>
499 struct RubyType<TQStringVariantMap>
500 {
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()) );
506 return h;
507 }
508 inline static int convertHash(VALUE key, VALUE value, VALUE vmap) {
509 TQStringVariantMap* map;
510 Data_Get_Struct(vmap, TQStringVariantMap, map);
511 if (key != TQundef)
512 map->insert(STR2CSTR(key), RubyType<TQVariant>::toVariant(value));
513 return ST_CONTINUE;
514 }
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();
519 }
520 TQStringVariantMap map;
521 VALUE vmap = Data_Wrap_Struct(rb_cObject, 0,0, &map);
522 rb_hash_foreach(value, (int (*)(...))convertHash, vmap);
523 return map;
524 }
525 };
526#endif
527
528#if 0
534 class RubyMetaTypeFactory
535 {
536 public:
537 static MetaType* create(int typeId, int metaTypeId, VALUE valueect = TQnil);
538 };
539
541 template<typename VARIANTTYPE>
542 class RubyMetaTypeVariant : public MetaTypeVariant<VARIANTTYPE>
543 {
544 public:
545 RubyMetaTypeVariant(VALUE value)
546 : MetaTypeVariant<VARIANTTYPE>(
547 (TYPE(value) == T_NIL)
548 ? TQVariant().value<VARIANTTYPE>()
549 : RubyType<VARIANTTYPE>::toVariant(value)
550 ) {}
551
552 virtual ~RubyMetaTypeVariant() {}
553 };
554
555#endif
556
557}
558
559#endif
560
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.
Definition callable.h:31
The RubyType helper classes used to cast between TQVariant and VALUE values.