1 // **********************************************************************
3 // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
8 // **********************************************************************
11 #include <Ice/LocalException.h>
15 using namespace IceRuby
;
19 IceRuby_stringVersion(int /*argc*/, VALUE
* /*argv*/, VALUE
/*self*/)
23 string s
= ICE_STRING_VERSION
;
24 return createString(s
);
32 IceRuby_intVersion(int /*argc*/, VALUE
* /*argv*/, VALUE
/*self*/)
36 return INT2FIX(ICE_INT_VERSION
);
43 IceRuby::initUtil(VALUE iceModule
)
45 rb_define_module_function(iceModule
, "stringVersion", CAST_METHOD(IceRuby_stringVersion
), -1);
46 rb_define_module_function(iceModule
, "intVersion", CAST_METHOD(IceRuby_intVersion
), -1);
49 IceRuby::RubyException::RubyException()
54 IceRuby::RubyException::RubyException(VALUE exv
) :
59 IceRuby::RubyException::RubyException(VALUE exClass
, const char* fmt
, ...)
65 vsnprintf(buf
, BUFSIZ
, fmt
, args
);
66 buf
[BUFSIZ
- 1] = '\0';
69 ex
= callRuby(rb_exc_new2
, exClass
, buf
);
73 IceRuby::RubyException::operator<<(ostream
& ostr
) const
75 volatile VALUE cls
= rb_class_path(CLASS_OF(ex
));
76 volatile VALUE msg
= rb_obj_as_string(ex
);
77 ostr
<< RSTRING_PTR(cls
) << ": " << RSTRING_PTR(msg
);
82 IceRuby::isString(VALUE val
)
84 return TYPE(val
) == T_STRING
|| callRuby(rb_respond_to
, val
, rb_intern("to_str")) != 0;
88 IceRuby::isArray(VALUE val
)
90 return TYPE(val
) == T_ARRAY
|| callRuby(rb_respond_to
, val
, rb_intern("to_arr")) != 0;
94 IceRuby::isHash(VALUE val
)
96 return TYPE(val
) == T_HASH
|| callRuby(rb_respond_to
, val
, rb_intern("to_hash")) != 0;
100 IceRuby::getString(VALUE val
)
102 volatile VALUE result
= callRuby(rb_string_value
, &val
);
103 return string(RSTRING_PTR(result
), RSTRING_LEN(result
));
107 IceRuby::createString(const string
& str
)
109 return callRuby(rb_str_new
, str
.c_str(), static_cast<long>(str
.size()));
113 IceRuby::getInteger(VALUE val
)
115 if(!FIXNUM_P(val
) && TYPE(val
) != T_BIGNUM
)
117 val
= callRuby(rb_Integer
, val
);
121 return FIX2LONG(val
);
123 else if(TYPE(val
) == T_BIGNUM
)
125 Ice::Long l
= getLong(val
);
126 if(l
>= static_cast<Ice::Long
>(INT_MIN
) && l
<= static_cast<Ice::Long
>(INT_MAX
))
128 return static_cast<long>(l
);
131 throw RubyException(rb_eTypeError
, "unable to convert value to an integer");
134 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
135 #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
138 IceRuby::getLong(VALUE val
)
141 // The rb_num2ll function raises exceptions, but we can't call it using callProtected
142 // because its return type is long long and not VALUE.
144 volatile VALUE v
= callRuby(rb_Integer
, val
);
147 throw RubyException(rb_eTypeError
, "unable to convert value to a long");
155 assert(TYPE(v
) == T_BIGNUM
);
156 long len
= RBIGNUM_LEN(v
);
157 if(len
> SIZEOF_LONG_LONG
/SIZEOF_BDIGITS
)
159 throw RubyException(rb_eRangeError
, "bignum too big to convert into long");
161 BDIGIT
*ds
= RBIGNUM_DIGITS(v
);
168 Ice::Long l
= static_cast<Ice::Long
>(num
);
169 if(l
< 0 && (RBIGNUM_SIGN(v
) || l
!= LLONG_MIN
))
171 throw RubyException(rb_eRangeError
, "bignum too big to convert into long");
173 if (!RBIGNUM_SIGN(v
))
182 IceRuby::arrayToStringSeq(VALUE val
, vector
<string
>& seq
)
184 volatile VALUE arr
= callRuby(rb_check_array_type
, val
);
189 for(long i
= 0; i
< RARRAY_LEN(arr
); ++i
)
191 string s
= getString(RARRAY_PTR(arr
)[i
]);
192 seq
.push_back(getString(RARRAY_PTR(arr
)[i
]));
198 IceRuby::stringSeqToArray(const vector
<string
>& seq
)
200 volatile VALUE result
= createArray(seq
.size());
204 for(vector
<string
>::const_iterator p
= seq
.begin(); p
!= seq
.end(); ++p
, ++i
)
206 RARRAY_PTR(result
)[i
] = createString(*p
);
215 struct HashToContextIterator
: public IceRuby::HashIterator
217 HashToContextIterator(Ice::Context
& c
) : ctx(c
)
221 virtual void element(VALUE key
, VALUE value
)
223 string kstr
= IceRuby::getString(key
);
224 string vstr
= IceRuby::getString(value
);
234 IceRuby::hashToContext(VALUE val
, Ice::Context
& ctx
)
236 if(TYPE(val
) != T_HASH
)
238 val
= callRuby(rb_convert_type
, val
, T_HASH
, "Hash", "to_hash");
244 HashToContextIterator
iter(ctx
);
245 hashIterate(val
, iter
);
250 IceRuby::contextToHash(const Ice::Context
& ctx
)
252 volatile VALUE result
= callRuby(rb_hash_new
);
253 for(Ice::Context::const_iterator p
= ctx
.begin(); p
!= ctx
.end(); ++p
)
255 volatile VALUE key
= callRuby(rb_str_new
, p
->first
.c_str(), static_cast<long>(p
->first
.size()));
256 volatile VALUE value
= callRuby(rb_str_new
, p
->second
.c_str(), static_cast<long>(p
->second
.size()));
257 callRuby(rb_hash_aset
, result
, key
, value
);
264 IceRuby_Util_hash_foreach_callback(VALUE val
, VALUE arg
)
266 VALUE key
= rb_ary_entry(val
, 0);
267 VALUE value
= rb_ary_entry(val
, 1);
270 // We can't allow any C++ exceptions to propagate out of this function.
274 IceRuby::HashIterator
* iter
= reinterpret_cast<IceRuby::HashIterator
*>(arg
);
275 iter
->element(key
, value
);
283 typedef VALUE (*ICE_RUBY_HASH_FOREACH_CALLBACK
)(...);
287 IceRuby::hashIterate(VALUE h
, HashIterator
& iter
)
289 assert(TYPE(h
) == T_HASH
);
290 callRuby(rb_iterate
, rb_each
, h
,
291 reinterpret_cast<ICE_RUBY_HASH_FOREACH_CALLBACK
>(IceRuby_Util_hash_foreach_callback
),
292 reinterpret_cast<VALUE
>(&iter
));
296 IceRuby::getIdentity(VALUE v
)
298 volatile VALUE cls
= callRuby(rb_path2class
, "Ice::Identity");
301 if(callRuby(rb_obj_is_kind_of
, v
, cls
) == Qfalse
)
303 throw RubyException(rb_eTypeError
, "value is not an Ice::Identity");
306 volatile VALUE name
= callRuby(rb_iv_get
, v
, "@name");
307 volatile VALUE category
= callRuby(rb_iv_get
, v
, "@category");
309 if(!NIL_P(category
) && !isString(category
))
311 throw RubyException(rb_eTypeError
, "identity category must be a string");
314 if(NIL_P(name
) || !isString(name
))
316 throw RubyException(rb_eTypeError
, "identity name must be a string");
319 Ice::Identity result
;
320 result
.name
= getString(name
);
323 result
.category
= getString(category
);
329 IceRuby::createIdentity(const Ice::Identity
& id
)
331 volatile VALUE cls
= callRuby(rb_path2class
, "Ice::Identity");
334 volatile VALUE result
= callRuby(rb_class_new_instance
, 0, reinterpret_cast<VALUE
*>(0), cls
);
335 volatile VALUE name
= callRuby(rb_str_new
, id
.name
.c_str(), static_cast<long>(id
.name
.size()));
336 volatile VALUE category
= callRuby(rb_str_new
, id
.category
.c_str(), static_cast<long>(id
.category
.size()));
337 callRuby(rb_iv_set
, result
, "@name", name
);
338 callRuby(rb_iv_set
, result
, "@category", category
);
343 IceRuby::callProtected(RubyFunction func
, VALUE arg
)
346 volatile VALUE result
= rb_protect(func
, arg
, &error
);
349 throw RubyException();
355 setExceptionMembers(const Ice::LocalException
& ex
, VALUE p
)
358 // Transfer data members from Ice exception to Ruby exception.
364 catch(const Ice::InitializationException
& e
)
366 volatile VALUE v
= createString(e
.reason
);
367 callRuby(rb_iv_set
, p
, "@reason", v
);
369 catch(const Ice::PluginInitializationException
& e
)
371 volatile VALUE v
= createString(e
.reason
);
372 callRuby(rb_iv_set
, p
, "@reason", v
);
374 catch(const Ice::AlreadyRegisteredException
& e
)
377 v
= createString(e
.kindOfObject
);
378 callRuby(rb_iv_set
, p
, "@kindOfObject", v
);
379 v
= createString(e
.id
);
380 callRuby(rb_iv_set
, p
, "@id", v
);
382 catch(const Ice::NotRegisteredException
& e
)
385 v
= createString(e
.kindOfObject
);
386 callRuby(rb_iv_set
, p
, "@kindOfObject", v
);
387 v
= createString(e
.id
);
388 callRuby(rb_iv_set
, p
, "@id", v
);
390 catch(const Ice::TwowayOnlyException
& e
)
392 volatile VALUE v
= createString(e
.operation
);
393 callRuby(rb_iv_set
, p
, "@operation", v
);
395 catch(const Ice::UnknownException
& e
)
397 volatile VALUE v
= createString(e
.unknown
);
398 callRuby(rb_iv_set
, p
, "@unknown", v
);
400 catch(const Ice::ObjectAdapterDeactivatedException
& e
)
402 volatile VALUE v
= createString(e
.name
);
403 callRuby(rb_iv_set
, p
, "@name", v
);
405 catch(const Ice::ObjectAdapterIdInUseException
& e
)
407 volatile VALUE v
= createString(e
.id
);
408 callRuby(rb_iv_set
, p
, "@id", v
);
410 catch(const Ice::NoEndpointException
& e
)
412 volatile VALUE v
= createString(e
.proxy
);
413 callRuby(rb_iv_set
, p
, "@proxy", v
);
415 catch(const Ice::EndpointParseException
& e
)
417 volatile VALUE v
= createString(e
.str
);
418 callRuby(rb_iv_set
, p
, "@str", v
);
420 catch(const Ice::IdentityParseException
& e
)
422 volatile VALUE v
= createString(e
.str
);
423 callRuby(rb_iv_set
, p
, "@str", v
);
425 catch(const Ice::ProxyParseException
& e
)
427 volatile VALUE v
= createString(e
.str
);
428 callRuby(rb_iv_set
, p
, "@str", v
);
430 catch(const Ice::IllegalIdentityException
& e
)
432 volatile VALUE v
= IceRuby::createIdentity(e
.id
);
433 callRuby(rb_iv_set
, p
, "@id", v
);
435 catch(const Ice::RequestFailedException
& e
)
438 v
= IceRuby::createIdentity(e
.id
);
439 callRuby(rb_iv_set
, p
, "@id", v
);
440 v
= createString(e
.facet
);
441 callRuby(rb_iv_set
, p
, "@facet", v
);
442 v
= createString(e
.operation
);
443 callRuby(rb_iv_set
, p
, "@operation", v
);
445 catch(const Ice::FileException
& e
)
447 volatile VALUE v
= INT2FIX(e
.error
);
448 callRuby(rb_iv_set
, p
, "@error", v
);
449 v
= createString(e
.path
);
450 callRuby(rb_iv_set
, p
, "@path", v
);
452 catch(const Ice::SyscallException
& e
) // This must appear after all subclasses of SyscallException.
454 volatile VALUE v
= INT2FIX(e
.error
);
455 callRuby(rb_iv_set
, p
, "@error", v
);
457 catch(const Ice::DNSException
& e
)
460 v
= INT2FIX(e
.error
);
461 callRuby(rb_iv_set
, p
, "@error", v
);
462 v
= createString(e
.host
);
463 callRuby(rb_iv_set
, p
, "@host", v
);
465 catch(const Ice::UnsupportedProtocolException
& e
)
467 callRuby(rb_iv_set
, p
, "@badMajor", INT2FIX(e
.badMajor
));
468 callRuby(rb_iv_set
, p
, "@badMinor", INT2FIX(e
.badMinor
));
469 callRuby(rb_iv_set
, p
, "@major", INT2FIX(e
.major
));
470 callRuby(rb_iv_set
, p
, "@minor", INT2FIX(e
.minor
));
472 catch(const Ice::UnsupportedEncodingException
& e
)
474 callRuby(rb_iv_set
, p
, "@badMajor", INT2FIX(e
.badMajor
));
475 callRuby(rb_iv_set
, p
, "@badMinor", INT2FIX(e
.badMinor
));
476 callRuby(rb_iv_set
, p
, "@major", INT2FIX(e
.major
));
477 callRuby(rb_iv_set
, p
, "@minor", INT2FIX(e
.minor
));
479 catch(const Ice::NoObjectFactoryException
& e
)
482 v
= createString(e
.reason
);
483 callRuby(rb_iv_set
, p
, "@reason", v
);
484 v
= createString(e
.type
);
485 callRuby(rb_iv_set
, p
, "@type", v
);
487 catch(const Ice::UnexpectedObjectException
& e
)
490 v
= createString(e
.reason
);
491 callRuby(rb_iv_set
, p
, "@reason", v
);
492 v
= createString(e
.type
);
493 callRuby(rb_iv_set
, p
, "@type", v
);
494 v
= createString(e
.expectedType
);
495 callRuby(rb_iv_set
, p
, "@expectedType", v
);
497 catch(const Ice::ProtocolException
& e
) // This must appear after all subclasses of ProtocolException.
499 volatile VALUE v
= createString(e
.reason
);
500 callRuby(rb_iv_set
, p
, "@reason", v
);
502 catch(const Ice::FeatureNotSupportedException
& e
)
504 volatile VALUE v
= createString(e
.unsupportedFeature
);
505 callRuby(rb_iv_set
, p
, "@unsupportedFeature", v
);
507 catch(const Ice::SecurityException
& e
)
509 volatile VALUE v
= createString(e
.reason
);
510 callRuby(rb_iv_set
, p
, "@reason", v
);
512 catch(const Ice::LocalException
&)
521 IceRuby::createArrayHelper(long sz
)
523 VALUE arr
= callRuby(rb_ary_new2
, sz
);
526 callRubyVoid(rb_ary_store
, arr
, sz
- 1, Qnil
);
532 IceRuby::convertLocalException(const Ice::LocalException
& ex
)
535 // We cannot throw a C++ exception or raise a Ruby exception. If an error
536 // occurs while we are converting the exception, we do our best to return
537 // an appropriate Ruby exception.
541 string name
= ex
.ice_name();
542 volatile VALUE cls
= callRuby(rb_path2class
, name
.c_str());
545 throw RubyException(rb_eRuntimeError
, "exception class `%s' not found", name
.c_str());
547 volatile VALUE result
= callRuby(rb_class_new_instance
, 0, reinterpret_cast<VALUE
*>(0), cls
);
548 setExceptionMembers(ex
, result
);
551 catch(const RubyException
& e
)
557 string msg
= "failure occurred while converting exception " + ex
.ice_name();
558 return rb_exc_new2(rb_eRuntimeError
, msg
.c_str());