]> icculus.org git repositories - duncan/yast2-ruby-bindings.git/blob - src/ruby/Y2RubyTypeConv.cc
5e1c17270828992ada11bf2c392e4ce33427cdc8
[duncan/yast2-ruby-bindings.git] / src / ruby / Y2RubyTypeConv.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                                                                      |
10 | ruby language support                              (C) Novell Inc.   |
11 \----------------------------------------------------------------------/
12
13 Author: Duncan Mac-Vicar <dmacvicar@suse.de>
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License
17 as published by the Free Software Foundation; either version
18 2 of the License, or (at your option) any later version.
19
20 */
21
22 #include <ycp/y2log.h>
23
24 #include <ycp/YCPValue.h>
25 #include <ycp/YCPBoolean.h>
26 #include <ycp/YCPList.h>
27 #include <ycp/YCPMap.h>
28 #include <ycp/YCPString.h>
29 #include <ycp/YCPInteger.h>
30 #include <ycp/YCPTerm.h>
31 #include <ycp/YCPFloat.h>
32 #include <ycp/YCPElement.h>
33 #include <ycp/YCPSymbol.h>
34 #include <ycp/YCPPath.h>
35 #include <ycp/YCPVoid.h>
36 #include <ycp/Import.h>
37
38 #include "Y2RubyTypePath.h"
39 #include "Y2RubyTypeTerm.h"
40
41 #include "Y2RubyTypeConv.h"
42
43 #define IS_A(obj,klass) ((rb_obj_is_kind_of((obj),(klass))==Qtrue)?1:0)
44
45 static YCPMap rbhash_2_ycpmap( VALUE value )
46 {
47   YCPMap map;
48   VALUE keys = rb_funcall(value, rb_intern("keys"), 0);
49   int n = NUM2LONG(rb_funcall(keys, rb_intern("size"), 0));
50   for ( int i=0; i<n; ++i)
51   {
52     VALUE rkey = rb_funcall(keys, rb_intern("at"), 1, i);
53     YCPValue ykey = rbvalue_2_ycpvalue(rkey);
54     YCPValue yvalue = rbvalue_2_ycpvalue( rb_funcall(value, rb_intern("[]"), 1, rkey) );
55     map.add(ykey, yvalue);
56   }
57   return map;
58 }
59
60 static YCPList rbarray_2_ycplist( VALUE value )
61 {
62   YCPList list;
63   int n = NUM2LONG(rb_funcall(value, rb_intern("size"), 0));
64   for ( int i=0; i<n; ++i)
65   {
66     VALUE element = rb_funcall(value, rb_intern("[]"), 1, i);
67     list.add( rbvalue_2_ycpvalue(element) );
68   }
69   return list;
70 }
71
72
73 /**
74  * Converts a YCPValue into a Ruby Value
75  * Supports neested lists using recursion.
76  */
77 extern "C" VALUE
78 ycpvalue_2_rbvalue( YCPValue ycpval )
79 {
80   // TODO
81   // YT_BYTEBLOCK YT_PATH YT_SYMBOL YT_LIST YT_TERM YT_MAP YT_CODE YT_RETURN YT_BREAK YT_ENTRY YT_ERROR  YT_REFERENCE YT_EXTERNA
82   if (ycpval->isVoid())
83   {
84     return Qnil;
85   }
86   else if (ycpval->isBoolean())
87   {
88     return ycpval->asBoolean()->value() ? Qtrue : Qfalse;
89   }
90   else if (ycpval->isString())
91   {
92     return rb_str_new2(ycpval->asString()->value().c_str());
93   }
94   else if (ycpval->isPath())
95   {
96     // FIXME implement a ruby class for YCPPath
97     return rb_str_new2(ycpval->asPath()->asString()->value().c_str());
98   }
99   else if (ycpval->isTerm())
100   {
101     return ryast_rterm_from_yterm(ycpval->asTerm());
102   }
103   else if (ycpval->isInteger())
104   {
105     return INT2NUM( ycpval->asInteger()->value() );
106   }
107   else if (ycpval->isFloat())
108   {
109     return rb_float_new(ycpval->asFloat()->value());
110   }
111   else if ( ycpval->isMap() )
112   {
113     VALUE rbhash;
114     rbhash = rb_hash_new();
115     YCPMap map = ycpval->asMap();
116     y2internal("map size %d\n", (int) map.size());
117
118     for ( YCPMapIterator it = map.begin(); it != map.end(); ++it )
119     {
120       YCPValue key = it.key();
121       YCPValue value = it.value();
122       rb_hash_aset(rbhash, ycpvalue_2_rbvalue(key), ycpvalue_2_rbvalue(value) );
123     }
124     return rbhash;
125   }
126   else if (ycpval->isList())
127   {
128     VALUE rblist;
129     rblist = rb_ary_new();
130     YCPList list = ycpval->asList();
131     y2internal("list size %d\n",list.size());
132     for (int i=0; i < list.size(); i++)
133     {
134       rb_ary_push( rblist, ycpvalue_2_rbvalue(list.value(i)));
135     }
136     return rblist;
137   }
138   else if (ycpval->isSymbol())
139   {
140     YCPSymbol symbol = ycpval->asSymbol();
141     return rb_intern(symbol->symbol_cstr());
142   }
143   rb_raise( rb_eTypeError, "Conversion of YCP type %s not supported", ycpval->toString().c_str() );
144   return Qnil;
145 }
146
147 // isEmpty size add remove (value n) toString
148 YCPValue
149 rbvalue_2_ycpvalue( VALUE value )
150 {
151   VALUE klass = rb_funcall( value, rb_intern("class"), 0);
152   //std::cout << RSTRING( rb_funcall( klass, rb_intern("to_s"), 0))->ptr << " | " << RSTRING(rb_funcall( value, rb_intern("inspect"), 0))->ptr << std::endl;
153   //y2internal("type: '%d'", TYPE(value));
154   // TODO conver integers, and add support for lists, ah, and boleans!
155   switch (TYPE(value))
156   {
157   case T_NIL:
158     return YCPVoid();
159   case T_STRING:
160     return YCPString(RSTRING (value)->ptr);
161     break;
162   case T_TRUE:
163     return YCPBoolean(true);
164     break;
165   case T_FALSE:
166     return YCPBoolean(false);
167     break;
168   case T_FIXNUM:
169     return YCPInteger(NUM2LONG(value));
170     break;
171   case T_FLOAT:
172     return YCPFloat(NUM2DBL(value));
173     break;
174   case T_ARRAY:
175     return rbarray_2_ycplist(value);
176     break;
177   case T_HASH:
178     return rbhash_2_ycpmap(value);
179     break;
180   case T_SYMBOL:
181     return YCPSymbol(rb_id2name(rb_to_id(value)));
182   //case T_DATA:
183   //  rb_raise( rb_eRuntimeError, "Object");
184     break;
185   default:
186     string class_name(RSTRING(rb_funcall(rb_funcall(value, rb_intern("class"), 0), rb_intern("to_s"), 0))->ptr);
187     /* get the Term class object */
188     if ( class_name == "YaST::Term" )
189     {
190       return ryast_yterm_from_rterm(value);
191     }
192     rb_raise( rb_eTypeError, "Conversion of Ruby type not supported");
193     return YCPValue();
194   }
195 }
196
197 YCPValue
198 rbvalue_2_ycppath( VALUE value )
199 {
200   VALUE stringrep = rb_funcall(value, rb_intern("to_s"), 0);
201   return  YCPPath(RSTRING(stringrep)->ptr);
202 }
203