remove excessive logging
[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
117     for ( YCPMapIterator it = map.begin(); it != map.end(); ++it )
118     {
119       YCPValue key = it.key();
120       YCPValue value = it.value();
121       rb_hash_aset(rbhash, ycpvalue_2_rbvalue(key), ycpvalue_2_rbvalue(value) );
122     }
123     return rbhash;
124   }
125   else if (ycpval->isList())
126   {
127     VALUE rblist;
128     rblist = rb_ary_new();
129     YCPList list = ycpval->asList();
130     for (int i=0; i < list.size(); i++)
131     {
132       rb_ary_push( rblist, ycpvalue_2_rbvalue(list.value(i)));
133     }
134     return rblist;
135   }
136   else if (ycpval->isSymbol())
137   {
138     YCPSymbol symbol = ycpval->asSymbol();
139     return rb_intern(symbol->symbol_cstr());
140   }
141   rb_raise( rb_eTypeError, "conversion of YCP type %s not supported", ycpval->toString().c_str() );
142   return Qnil;
143 }
144
145 // isEmpty size add remove (value n) toString
146 YCPValue
147 rbvalue_2_ycpvalue( VALUE value )
148 {
149   VALUE klass = rb_funcall( value, rb_intern("class"), 0);
150   //std::cout << RSTRING( rb_funcall( klass, rb_intern("to_s"), 0))->ptr << " | " << RSTRING(rb_funcall( value, rb_intern("inspect"), 0))->ptr << std::endl;
151   //y2internal("type: '%d'", TYPE(value));
152   // TODO conver integers, and add support for lists, ah, and boleans!
153   switch (TYPE(value))
154   {
155   case T_NIL:
156     return YCPVoid();
157   case T_STRING:
158     return YCPString(RSTRING (value)->ptr);
159     break;
160   case T_TRUE:
161     return YCPBoolean(true);
162     break;
163   case T_FALSE:
164     return YCPBoolean(false);
165     break;
166   case T_FIXNUM:
167     return YCPInteger(NUM2LONG(value));
168     break;
169   case T_FLOAT:
170     return YCPFloat(NUM2DBL(value));
171     break;
172   case T_ARRAY:
173     return rbarray_2_ycplist(value);
174     break;
175   case T_HASH:
176     return rbhash_2_ycpmap(value);
177     break;
178   case T_SYMBOL:
179     return YCPSymbol(rb_id2name(rb_to_id(value)));
180   //case T_DATA:
181   //  rb_raise( rb_eRuntimeError, "Object");
182     break;
183   default:
184     string class_name(RSTRING(rb_funcall(rb_funcall(value, rb_intern("class"), 0), rb_intern("to_s"), 0))->ptr);
185     /* get the Term class object */
186     if ( class_name == "YaST::Term" )
187     {
188       return ryast_yterm_from_rterm(value);
189     }
190     rb_raise( rb_eTypeError, "conversion of Ruby type not supported");
191     return YCPValue();
192   }
193 }
194
195 YCPValue
196 rbvalue_2_ycppath( VALUE value )
197 {
198   VALUE stringrep = rb_funcall(value, rb_intern("to_s"), 0);
199   return  YCPPath(RSTRING(stringrep)->ptr);
200 }
201