summaryrefslogtreecommitdiff
path: root/rb/src
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2012-05-16 16:05:50 -0700
committerMark Spruiell <mes@zeroc.com>2012-05-16 16:05:50 -0700
commit3b6fbd2cb1ab0e9f6dbdfd4cbda02eb16fd85569 (patch)
treeedfa533e67fb4ee003d1afbb2e1ba8a9b03ef3f3 /rb/src
parentporting ami test changes to python (diff)
downloadice-3b6fbd2cb1ab0e9f6dbdfd4cbda02eb16fd85569.tar.bz2
ice-3b6fbd2cb1ab0e9f6dbdfd4cbda02eb16fd85569.tar.xz
ice-3b6fbd2cb1ab0e9f6dbdfd4cbda02eb16fd85569.zip
* Ruby port of sliced/compact/preserved
* Python clean up * More changes to exceptions test
Diffstat (limited to 'rb/src')
-rw-r--r--rb/src/IceRuby/Endpoint.cpp37
-rw-r--r--rb/src/IceRuby/Operation.cpp168
-rw-r--r--rb/src/IceRuby/Proxy.cpp47
-rw-r--r--rb/src/IceRuby/Types.cpp383
-rw-r--r--rb/src/IceRuby/Types.h68
-rw-r--r--rb/src/IceRuby/Util.cpp274
-rw-r--r--rb/src/IceRuby/Util.h15
7 files changed, 804 insertions, 188 deletions
diff --git a/rb/src/IceRuby/Endpoint.cpp b/rb/src/IceRuby/Endpoint.cpp
index 31dc8f473cb..c5ea7cb5ba3 100644
--- a/rb/src/IceRuby/Endpoint.cpp
+++ b/rb/src/IceRuby/Endpoint.cpp
@@ -143,10 +143,6 @@ IceRuby::createEndpointInfo(const Ice::EndpointInfoPtr& p)
Ice::UDPEndpointInfoPtr udp = Ice::UDPEndpointInfoPtr::dynamicCast(p);
rb_ivar_set(info, rb_intern("@host"), createString(udp->host));
rb_ivar_set(info, rb_intern("@port"), INT2FIX(udp->port));
- rb_ivar_set(info, rb_intern("@protocolMajor"), CHR2FIX(udp->protocolMajor));
- rb_ivar_set(info, rb_intern("@protocolMinor"), CHR2FIX(udp->protocolMinor));
- rb_ivar_set(info, rb_intern("@encodingMajor"), CHR2FIX(udp->encodingMajor));
- rb_ivar_set(info, rb_intern("@encodingMinor"), CHR2FIX(udp->encodingMinor));
rb_ivar_set(info, rb_intern("@mcastInterface"), createString(udp->mcastInterface));
rb_ivar_set(info, rb_intern("@mcastTtl"), INT2FIX(udp->mcastTtl));
}
@@ -158,6 +154,7 @@ IceRuby::createEndpointInfo(const Ice::EndpointInfoPtr& p)
Ice::ByteSeq b = opaque->rawBytes;
VALUE v = callRuby(rb_str_new, reinterpret_cast<const char*>(&b[0]), static_cast<long>(b.size()));
rb_ivar_set(info, rb_intern("@rawBytes"), v);
+ rb_ivar_set(info, rb_intern("@rawEncoding"), createEncodingVersion(opaque->rawEncoding));
}
else if(Ice::IPEndpointInfoPtr::dynamicCast(p))
{
@@ -171,6 +168,8 @@ IceRuby::createEndpointInfo(const Ice::EndpointInfoPtr& p)
{
info = Data_Wrap_Struct(_endpointInfoClass, 0, IceRuby_EndpointInfo_free, new Ice::EndpointInfoPtr(p));
}
+ rb_ivar_set(info, rb_intern("@protocol"), createProtocolVersion(p->protocol));
+ rb_ivar_set(info, rb_intern("@encoding"), createEncodingVersion(p->encoding));
rb_ivar_set(info, rb_intern("@timeout"), INT2FIX(p->timeout));
rb_ivar_set(info, rb_intern("@compress"), p->compress ? Qtrue : Qfalse);
return info;
@@ -256,10 +255,12 @@ IceRuby::initEndpoint(VALUE iceModule)
rb_define_method(_endpointInfoClass, "secure", CAST_METHOD(IceRuby_EndpointInfo_secure), 0);
//
- // Instance members.
+ // Instance members.
//
- rb_define_attr(_endpointInfoClass, "timeout", 1, 0);
- rb_define_attr(_endpointInfoClass, "compress", 1, 0);
+ rb_define_attr(_endpointInfoClass, "protocol", 1, 0);
+ rb_define_attr(_endpointInfoClass, "encoding", 1, 0);
+ rb_define_attr(_endpointInfoClass, "timeout", 1, 0);
+ rb_define_attr(_endpointInfoClass, "compress", 1, 0);
//
// IPEndpointInfo
@@ -267,10 +268,10 @@ IceRuby::initEndpoint(VALUE iceModule)
_ipEndpointInfoClass = rb_define_class_under(iceModule, "IPEndpointInfo", _endpointInfoClass);
//
- // Instance members.
+ // Instance members.
//
- rb_define_attr(_ipEndpointInfoClass, "host", 1, 0);
- rb_define_attr(_ipEndpointInfoClass, "port", 1, 0);
+ rb_define_attr(_ipEndpointInfoClass, "host", 1, 0);
+ rb_define_attr(_ipEndpointInfoClass, "port", 1, 0);
//
// TCPEndpointInfo
@@ -283,14 +284,10 @@ IceRuby::initEndpoint(VALUE iceModule)
_udpEndpointInfoClass = rb_define_class_under(iceModule, "UDPEndpointInfo", _ipEndpointInfoClass);
//
- // Instance members.
+ // Instance members.
//
- rb_define_attr(_udpEndpointInfoClass, "protocolMajor", 1, 0);
- rb_define_attr(_udpEndpointInfoClass, "protocolMinor", 1, 0);
- rb_define_attr(_udpEndpointInfoClass, "encodingMajor", 1, 0);
- rb_define_attr(_udpEndpointInfoClass, "encodingMinor", 1, 0);
- rb_define_attr(_udpEndpointInfoClass, "mcastInterface", 1, 0);
- rb_define_attr(_udpEndpointInfoClass, "mcastTtl", 1, 0);
+ rb_define_attr(_udpEndpointInfoClass, "mcastInterface", 1, 0);
+ rb_define_attr(_udpEndpointInfoClass, "mcastTtl", 1, 0);
//
// OpaqueEndpointInfo
@@ -298,9 +295,10 @@ IceRuby::initEndpoint(VALUE iceModule)
_opaqueEndpointInfoClass = rb_define_class_under(iceModule, "OpaqueEndpointInfo", _endpointInfoClass);
//
- // Instance members.
+ // Instance members.
//
- rb_define_attr(_opaqueEndpointInfoClass, "rawBytes", 1, 0);
+ rb_define_attr(_opaqueEndpointInfoClass, "rawBytes", 1, 0);
+ rb_define_attr(_opaqueEndpointInfoClass, "rawEncoding", 1, 0);
}
bool
@@ -308,4 +306,3 @@ IceRuby::checkEndpoint(VALUE v)
{
return callRuby(rb_obj_is_kind_of, v, _endpointClass) == Qtrue;
}
-
diff --git a/rb/src/IceRuby/Operation.cpp b/rb/src/IceRuby/Operation.cpp
index bdee38a11b7..a8743a3145e 100644
--- a/rb/src/IceRuby/Operation.cpp
+++ b/rb/src/IceRuby/Operation.cpp
@@ -43,7 +43,7 @@ class OperationI : public Operation
{
public:
- OperationI(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+ OperationI(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
virtual VALUE invoke(const Ice::ObjectPrx&, VALUE, VALUE);
virtual void deprecate(const string&);
@@ -54,6 +54,7 @@ private:
Ice::OperationMode _mode;
Ice::OperationMode _sendMode;
bool _amd;
+ Ice::FormatType _format;
ParamInfoList _inParams;
ParamInfoList _outParams;
ParamInfoPtr _returnType;
@@ -63,7 +64,7 @@ private:
bool _returnsClasses;
string _deprecateMessage;
- void prepareRequest(const Ice::CommunicatorPtr&, VALUE, bool, vector<Ice::Byte>&);
+ void prepareRequest(const Ice::ObjectPrx&, VALUE, bool, vector<Ice::Byte>&);
VALUE unmarshalResults(const vector<Ice::Byte>&, const Ice::CommunicatorPtr&);
VALUE unmarshalException(const vector<Ice::Byte>&, const Ice::CommunicatorPtr&);
bool validateException(VALUE) const;
@@ -71,6 +72,29 @@ private:
};
typedef IceUtil::Handle<OperationI> OperationIPtr;
+class UserExceptionReaderFactoryI : public Ice::UserExceptionReaderFactory
+{
+public:
+
+ UserExceptionReaderFactoryI(const Ice::CommunicatorPtr& communicator) :
+ _communicator(communicator)
+ {
+ }
+
+ virtual void createAndThrow(const string& id) const
+ {
+ ExceptionInfoPtr info = lookupExceptionInfo(id);
+ if(info)
+ {
+ throw ExceptionReader(_communicator, info);
+ }
+ }
+
+private:
+
+ const Ice::CommunicatorPtr _communicator;
+};
+
}
extern "C"
@@ -82,12 +106,13 @@ IceRuby_Operation_free(OperationPtr* p)
extern "C"
VALUE
-IceRuby_defineOperation(VALUE /*self*/, VALUE name, VALUE mode, VALUE sendMode, VALUE amd, VALUE inParams,
+IceRuby_defineOperation(VALUE /*self*/, VALUE name, VALUE mode, VALUE sendMode, VALUE amd, VALUE format, VALUE inParams,
VALUE outParams, VALUE returnType, VALUE exceptions)
{
ICE_RUBY_TRY
{
- OperationIPtr op = new OperationI(name, mode, sendMode, amd, inParams, outParams, returnType, exceptions);
+ OperationIPtr op = new OperationI(name, mode, sendMode, amd, format, inParams, outParams, returnType,
+ exceptions);
return Data_Wrap_Struct(_operationClass, 0, IceRuby_Operation_free, new OperationPtr(op));
}
ICE_RUBY_CATCH
@@ -145,8 +170,8 @@ IceRuby::ParamInfo::unmarshaled(VALUE val, VALUE target, void* closure)
//
// OperationI implementation.
//
-IceRuby::OperationI::OperationI(VALUE name, VALUE mode, VALUE sendMode, VALUE amd, VALUE inParams, VALUE outParams,
- VALUE returnType, VALUE exceptions)
+IceRuby::OperationI::OperationI(VALUE name, VALUE mode, VALUE sendMode, VALUE amd, VALUE format, VALUE inParams,
+ VALUE outParams, VALUE returnType, VALUE exceptions)
{
_name = getString(name);
_amd = amd == Qtrue;
@@ -173,6 +198,20 @@ IceRuby::OperationI::OperationI(VALUE name, VALUE mode, VALUE sendMode, VALUE am
assert(TYPE(sendModeValue) == T_FIXNUM);
_sendMode = static_cast<Ice::OperationMode>(FIX2LONG(sendModeValue));
+ //
+ // format
+ //
+ if(format == Qnil)
+ {
+ _format = Ice::DefaultFormat;
+ }
+ else
+ {
+ volatile VALUE formatValue = callRuby(rb_funcall, format, rb_intern("to_i"), 0);
+ assert(TYPE(formatValue) == T_FIXNUM);
+ _format = static_cast<Ice::FormatType>(FIX2LONG(formatValue));
+ }
+
long i;
//
@@ -236,7 +275,7 @@ IceRuby::OperationI::invoke(const Ice::ObjectPrx& proxy, VALUE args, VALUE hctx)
// Marshal the input parameters to a byte sequence.
//
Ice::ByteSeq params;
- prepareRequest(communicator, args, false, params);
+ prepareRequest(proxy, args, false, params);
if(!_deprecateMessage.empty())
{
@@ -316,8 +355,7 @@ IceRuby::OperationI::deprecate(const string& msg)
}
void
-IceRuby::OperationI::prepareRequest(const Ice::CommunicatorPtr& communicator, VALUE args, bool async,
- vector<Ice::Byte>& bytes)
+IceRuby::OperationI::prepareRequest(const Ice::ObjectPrx& proxy, VALUE args, bool async, vector<Ice::Byte>& bytes)
{
//
// Validate the number of arguments.
@@ -335,7 +373,13 @@ IceRuby::OperationI::prepareRequest(const Ice::CommunicatorPtr& communicator, VA
//
// Marshal the in parameters.
//
- Ice::OutputStreamPtr os = Ice::createOutputStream(communicator);
+ Ice::OutputStreamPtr os = Ice::createOutputStream(proxy->ice_getCommunicator());
+ os->startEncapsulation(proxy->ice_getEncodingVersion());
+
+ if(_sendsClasses && _format != Ice::DefaultFormat)
+ {
+ os->format(_format);
+ }
ObjectMap objectMap;
long i = 0;
@@ -364,6 +408,7 @@ IceRuby::OperationI::prepareRequest(const Ice::CommunicatorPtr& communicator, VA
os->writePendingObjects();
}
+ os->endEncapsulation();
os->finished(bytes);
}
}
@@ -382,6 +427,17 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice:
// in a tuple of the form (result, outParam1, ...). Otherwise just return the value.
//
Ice::InputStreamPtr is = Ice::createInputStream(communicator, bytes);
+
+ //
+ // Store a pointer to a local SlicedDataUtil object as the stream's closure.
+ // This is necessary to support object unmarshaling (see ObjectReader).
+ //
+ SlicedDataUtil util;
+ assert(!is->closure());
+ is->closure(&util);
+
+ is->startEncapsulation();
+
for(ParamInfoList::iterator p = _outParams.begin(); p != _outParams.end(); ++p, ++i)
{
void* closure = reinterpret_cast<void*>(i);
@@ -398,85 +454,55 @@ IceRuby::OperationI::unmarshalResults(const vector<Ice::Byte>& bytes, const Ice:
is->readPendingObjects();
}
+ util.update();
+
+ is->endEncapsulation();
+
return results;
}
VALUE
IceRuby::OperationI::unmarshalException(const vector<Ice::Byte>& bytes, const Ice::CommunicatorPtr& communicator)
{
- int traceSlicing = -1;
-
Ice::InputStreamPtr is = Ice::createInputStream(communicator, bytes);
- bool usesClasses;
- is->read(usesClasses);
+ //
+ // Store a pointer to a local SlicedDataUtil object as the stream's closure.
+ // This is necessary to support object unmarshaling (see ObjectReader).
+ //
+ SlicedDataUtil util;
+ assert(!is->closure());
+ is->closure(&util);
- string id;
- is->read(id);
- const string origId = id;
+ is->startEncapsulation();
- while(!id.empty())
+ try
{
- ExceptionInfoPtr info = lookupExceptionInfo(id);
- if(info)
+ Ice::UserExceptionReaderFactoryPtr factory = new UserExceptionReaderFactoryI(communicator);
+ is->throwException(factory);
+ }
+ catch(const ExceptionReader& r)
+ {
+ volatile VALUE ex = r.getException();
+
+ if(validateException(ex))
{
- volatile VALUE ex = info->unmarshal(is);
- if(info->usesClasses)
- {
- is->readPendingObjects();
- }
+ util.update();
- if(validateException(ex))
- {
- return ex;
- }
- else
- {
- volatile VALUE cls = CLASS_OF(ex);
- volatile VALUE path = callRuby(rb_class_path, cls);
- assert(TYPE(path) == T_STRING);
- Ice::UnknownUserException e(__FILE__, __LINE__);
- e.unknown = RSTRING_PTR(path);
- throw e;
- }
+ return ex;
}
else
{
- if(traceSlicing == -1)
- {
- traceSlicing = communicator->getProperties()->getPropertyAsInt("Ice.Trace.Slicing") > 0;
- }
-
- if(traceSlicing > 0)
- {
- communicator->getLogger()->trace("Slicing", "unknown exception type `" + id + "'");
- }
-
- is->skipSlice(); // Slice off what we don't understand.
-
- try
- {
- is->read(id); // Read type id for next slice.
- }
- catch(Ice::UnmarshalOutOfBoundsException& ex)
- {
- //
- // When readString raises this exception it means we've seen the last slice,
- // so we set the reason member to a more helpful message.
- //
- ex.reason = "unknown exception type `" + origId + "'";
- throw;
- }
+ volatile VALUE cls = CLASS_OF(ex);
+ volatile VALUE path = callRuby(rb_class_path, cls);
+ assert(TYPE(path) == T_STRING);
+ Ice::UnknownUserException e(__FILE__, __LINE__);
+ e.unknown = RSTRING_PTR(path);
+ throw e;
}
}
- //
- // Getting here should be impossible: we can get here only if the
- // sender has marshaled a sequence of type IDs, none of which we
- // have a factory for. This means that sender and receiver disagree
- // about the Slice definitions they use.
- //
- throw Ice::UnknownUserException(__FILE__, __LINE__, "unknown exception type `" + origId + "'");
+ throw Ice::UnknownUserException(__FILE__, __LINE__, "unknown exception");
}
bool
@@ -507,7 +533,7 @@ IceRuby::OperationI::checkTwowayOnly(const Ice::ObjectPrx& proxy) const
bool
IceRuby::initOperation(VALUE iceModule)
{
- rb_define_module_function(iceModule, "__defineOperation", CAST_METHOD(IceRuby_defineOperation), 8);
+ rb_define_module_function(iceModule, "__defineOperation", CAST_METHOD(IceRuby_defineOperation), 9);
//
// Define a class to represent an operation.
diff --git a/rb/src/IceRuby/Proxy.cpp b/rb/src/IceRuby/Proxy.cpp
index 45027d02e80..96821876a6e 100644
--- a/rb/src/IceRuby/Proxy.cpp
+++ b/rb/src/IceRuby/Proxy.cpp
@@ -547,6 +547,37 @@ IceRuby_ObjectPrx_ice_secure(VALUE self, VALUE b)
extern "C"
VALUE
+IceRuby_ObjectPrx_ice_getEncodingVersion(VALUE self)
+{
+ ICE_RUBY_TRY
+ {
+ Ice::ObjectPrx p = getProxy(self);
+ return createEncodingVersion(p->ice_getEncodingVersion());
+ }
+ ICE_RUBY_CATCH
+ return Qnil;
+}
+
+extern "C"
+VALUE
+IceRuby_ObjectPrx_ice_encodingVersion(VALUE self, VALUE v)
+{
+ Ice::EncodingVersion val;
+ if(getEncodingVersion(v, val))
+ {
+ ICE_RUBY_TRY
+ {
+ Ice::ObjectPrx p = getProxy(self);
+ return createProxy(p->ice_encodingVersion(val), rb_class_of(self));
+ }
+ ICE_RUBY_CATCH
+ }
+
+ return Qnil;
+}
+
+extern "C"
+VALUE
IceRuby_ObjectPrx_ice_isPreferSecure(VALUE self)
{
ICE_RUBY_TRY
@@ -861,6 +892,19 @@ IceRuby_ObjectPrx_ice_getCachedConnection(VALUE self)
extern "C"
VALUE
+IceRuby_ObjectPrx_ice_flushBatchRequests(VALUE self)
+{
+ ICE_RUBY_TRY
+ {
+ Ice::ObjectPrx p = getProxy(self);
+ p->ice_flushBatchRequests();
+ }
+ ICE_RUBY_CATCH
+ return Qnil;
+}
+
+extern "C"
+VALUE
IceRuby_ObjectPrx_cmp(VALUE self, VALUE other)
{
ICE_RUBY_TRY
@@ -1180,6 +1224,8 @@ IceRuby::initProxy(VALUE iceModule)
rb_define_method(_proxyClass, "ice_endpointSelection", CAST_METHOD(IceRuby_ObjectPrx_ice_endpointSelection), 1);
rb_define_method(_proxyClass, "ice_isSecure", CAST_METHOD(IceRuby_ObjectPrx_ice_isSecure), 0);
rb_define_method(_proxyClass, "ice_secure", CAST_METHOD(IceRuby_ObjectPrx_ice_secure), 1);
+ rb_define_method(_proxyClass, "ice_getEncodingVersion", CAST_METHOD(IceRuby_ObjectPrx_ice_getEncodingVersion), 0);
+ rb_define_method(_proxyClass, "ice_encodingVersion", CAST_METHOD(IceRuby_ObjectPrx_ice_encodingVersion), 1);
rb_define_method(_proxyClass, "ice_isPreferSecure", CAST_METHOD(IceRuby_ObjectPrx_ice_isPreferSecure), 0);
rb_define_method(_proxyClass, "ice_preferSecure", CAST_METHOD(IceRuby_ObjectPrx_ice_preferSecure), 1);
rb_define_method(_proxyClass, "ice_getRouter", CAST_METHOD(IceRuby_ObjectPrx_ice_getRouter), 0);
@@ -1201,6 +1247,7 @@ IceRuby::initProxy(VALUE iceModule)
rb_define_method(_proxyClass, "ice_connectionId", CAST_METHOD(IceRuby_ObjectPrx_ice_connectionId), 1);
rb_define_method(_proxyClass, "ice_getConnection", CAST_METHOD(IceRuby_ObjectPrx_ice_getConnection), 0);
rb_define_method(_proxyClass, "ice_getCachedConnection", CAST_METHOD(IceRuby_ObjectPrx_ice_getCachedConnection), 0);
+ rb_define_method(_proxyClass, "ice_flushBatchRequests", CAST_METHOD(IceRuby_ObjectPrx_ice_flushBatchRequests), 0);
rb_define_method(_proxyClass, "hash", CAST_METHOD(IceRuby_ObjectPrx_hash), 0);
rb_define_method(_proxyClass, "to_s", CAST_METHOD(IceRuby_ObjectPrx_ice_toString), 0);
diff --git a/rb/src/IceRuby/Types.cpp b/rb/src/IceRuby/Types.cpp
index f9648123349..5c29dd817b1 100644
--- a/rb/src/IceRuby/Types.cpp
+++ b/rb/src/IceRuby/Types.cpp
@@ -14,6 +14,7 @@
#include <IceUtil/OutputUtil.h>
#include <IceUtil/ScopedArray.h>
#include <Ice/LocalException.h>
+#include <Ice/SlicedData.h>
//
// Required for RHASH_SIZE to work properly with Ruby 1.8.x.
@@ -175,6 +176,193 @@ addExceptionInfo(const string& id, const ExceptionInfoPtr& info)
}
//
+// SlicedDataUtil implementation
+//
+VALUE IceRuby::SlicedDataUtil::_slicedDataType = Qnil;
+VALUE IceRuby::SlicedDataUtil::_sliceInfoType = Qnil;
+
+IceRuby::SlicedDataUtil::SlicedDataUtil()
+{
+}
+
+IceRuby::SlicedDataUtil::~SlicedDataUtil()
+{
+ //
+ // Make sure we break any cycles among the objects in preserved slices.
+ //
+ for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p)
+ {
+ (*p)->getSlicedData()->clearObjects();
+ }
+}
+
+void
+IceRuby::SlicedDataUtil::add(const ObjectReaderPtr& reader)
+{
+ assert(reader->getSlicedData());
+ _readers.insert(reader);
+}
+
+void
+IceRuby::SlicedDataUtil::update()
+{
+ for(set<ObjectReaderPtr>::iterator p = _readers.begin(); p != _readers.end(); ++p)
+ {
+ setMember((*p)->getObject(), (*p)->getSlicedData());
+ }
+}
+
+void
+IceRuby::SlicedDataUtil::setMember(VALUE obj, const Ice::SlicedDataPtr& slicedData)
+{
+ //
+ // Create a Ruby equivalent of the SlicedData object.
+ //
+
+ assert(slicedData);
+
+ if(_slicedDataType == Qnil)
+ {
+ _slicedDataType = callRuby(rb_path2class, "Ice::SlicedData");
+ assert(!NIL_P(_slicedDataType));
+ }
+ if(_sliceInfoType == Qnil)
+ {
+ _sliceInfoType = callRuby(rb_path2class, "Ice::SliceInfo");
+ assert(!NIL_P(_sliceInfoType));
+ }
+
+ volatile VALUE sd = callRuby(rb_class_new_instance, 0, static_cast<VALUE*>(0), _slicedDataType);
+
+ Ice::Int sz = slicedData->slices.size();
+ volatile VALUE slices = createArray(sz);
+
+ callRuby(rb_iv_set, sd, "@slices", slices);
+
+ //
+ // Translate each SliceInfo object into its Ruby equivalent.
+ //
+ int i = 0;
+ for(vector<Ice::SliceInfoPtr>::const_iterator p = slicedData->slices.begin(); p != slicedData->slices.end(); ++p)
+ {
+ volatile VALUE slice = callRuby(rb_class_new_instance, 0, static_cast<VALUE*>(0), _sliceInfoType);
+
+ RARRAY_PTR(slices)[i++] = slice;
+
+ //
+ // typeId
+ //
+ volatile VALUE typeId = createString((*p)->typeId);
+ callRuby(rb_iv_set, slice, "@typeId", typeId);
+
+ //
+ // bytes
+ //
+ volatile VALUE bytes = callRuby(rb_str_new, reinterpret_cast<const char*>(&(*p)->bytes[0]), (*p)->bytes.size());
+ callRuby(rb_iv_set, slice, "@bytes", bytes);
+
+ //
+ // objects
+ //
+ volatile VALUE objects = createArray((*p)->objects.size());
+ callRuby(rb_iv_set, slice, "@objects", objects);
+
+ int j = 0;
+ for(vector<Ice::ObjectPtr>::iterator q = (*p)->objects.begin(); q != (*p)->objects.end(); ++q)
+ {
+ //
+ // Each element in the objects list is an instance of ObjectReader that wraps a Python object.
+ //
+ assert(*q);
+ ObjectReaderPtr r = ObjectReaderPtr::dynamicCast(*q);
+ assert(r);
+ VALUE o = r->getObject();
+ assert(o != Qnil); // Should be non-nil.
+ RARRAY_PTR(objects)[j++] = o;
+ }
+ }
+
+ callRuby(rb_iv_set, obj, "@_ice_slicedData", sd);
+}
+
+//
+// Instances of preserved class and exception types may have a data member
+// named _ice_slicedData which is an instance of the Ruby class Ice::SlicedData.
+//
+Ice::SlicedDataPtr
+IceRuby::SlicedDataUtil::getMember(VALUE obj, ObjectMap* objectMap)
+{
+ Ice::SlicedDataPtr slicedData;
+
+ if(callRuby(rb_ivar_defined, obj, rb_intern("@_ice_slicedData")) == Qtrue)
+ {
+ volatile VALUE sd = callRuby(rb_iv_get, obj, "@_ice_slicedData");
+
+ if(sd != Qnil)
+ {
+ //
+ // The "slices" member is an array of Ice::SliceInfo objects.
+ //
+ volatile VALUE sl = callRuby(rb_iv_get, sd, "@slices");
+ assert(TYPE(sl) == T_ARRAY);
+
+ Ice::SliceInfoSeq slices;
+
+ long sz = RARRAY_LEN(sl);
+ for(long i = 0; i < sz; ++i)
+ {
+ volatile VALUE s = RARRAY_PTR(sl)[i];
+
+ Ice::SliceInfoPtr info = new Ice::SliceInfo;
+
+ volatile VALUE typeId = callRuby(rb_iv_get, s, "@typeId");
+ info->typeId = getString(typeId);
+
+ volatile VALUE bytes = callRuby(rb_iv_get, s, "@bytes");
+ assert(TYPE(bytes) == T_STRING);
+ const char* str = RSTRING_PTR(bytes);
+ const long len = RSTRING_LEN(bytes);
+ if(str != 0 && len != 0)
+ {
+ vector<Ice::Byte> vtmp(reinterpret_cast<const Ice::Byte*>(str),
+ reinterpret_cast<const Ice::Byte*>(str + len));
+ info->bytes.swap(vtmp);
+ }
+
+ volatile VALUE objects = callRuby(rb_iv_get, s, "@objects");
+ assert(TYPE(objects) == T_ARRAY);
+ long osz = RARRAY_LEN(objects);
+ for(long j = 0; j < osz; ++j)
+ {
+ VALUE o = RARRAY_PTR(objects)[j];
+
+ Ice::ObjectPtr writer;
+
+ ObjectMap::iterator i = objectMap->find(o);
+ if(i == objectMap->end())
+ {
+ writer = new ObjectWriter(o, objectMap);
+ objectMap->insert(ObjectMap::value_type(o, writer));
+ }
+ else
+ {
+ writer = i->second;
+ }
+
+ info->objects.push_back(writer);
+ }
+
+ slices.push_back(info);
+ }
+
+ slicedData = new Ice::SlicedData(slices);
+ }
+ }
+
+ return slicedData;
+}
+
+//
// UnmarshalCallback implementation.
//
IceRuby::UnmarshalCallback::~UnmarshalCallback()
@@ -1397,12 +1585,7 @@ IceRuby::ClassInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap*
ObjectMap::iterator q = objectMap->find(p);
if(q == objectMap->end())
{
- volatile VALUE cls = CLASS_OF(p);
- volatile VALUE type = callRuby(rb_const_get, cls, rb_intern("ICE_TYPE"));
- assert(!NIL_P(type)); // Should have been caught by validate().
- ClassInfoPtr info = ClassInfoPtr::dynamicCast(getType(type));
- assert(info);
- writer = new ObjectWriter(info, p, objectMap);
+ writer = new ObjectWriter(p, objectMap);
objectMap->insert(ObjectMap::value_type(p, writer));
}
else
@@ -1457,7 +1640,6 @@ IceRuby::ClassInfo::print(VALUE value, IceUtilInternal::Output& out, PrintObject
{
type = callRuby(rb_const_get, cls, rb_intern("ICE_TYPE"));
info = ClassInfoPtr::dynamicCast(getType(type));
- assert(info);
}
catch(const RubyException& ex)
{
@@ -1659,9 +1841,14 @@ IceRuby::ProxyInfo::destroy()
//
// ObjectWriter implementation.
//
-IceRuby::ObjectWriter::ObjectWriter(const ClassInfoPtr& info, VALUE object, ObjectMap* objectMap) :
- _info(info), _object(object), _map(objectMap)
+IceRuby::ObjectWriter::ObjectWriter(VALUE object, ObjectMap* objectMap) :
+ _object(object), _map(objectMap)
{
+ volatile VALUE cls = CLASS_OF(object);
+ volatile VALUE type = callRuby(rb_const_get, cls, rb_intern("ICE_TYPE"));
+ assert(!NIL_P(type));
+ _info = ClassInfoPtr::dynamicCast(getType(type));
+ assert(_info);
}
void
@@ -1677,12 +1864,22 @@ IceRuby::ObjectWriter::ice_preMarshal()
void
IceRuby::ObjectWriter::write(const Ice::OutputStreamPtr& os) const
{
+ Ice::SlicedDataPtr slicedData;
+
+ if(_info->preserve)
+ {
+ //
+ // Retrieve the SlicedData object that we stored as a hidden member of the Python object.
+ //
+ slicedData = SlicedDataUtil::getMember(_object, const_cast<ObjectMap*>(_map));
+ }
+
+ os->startObject(slicedData);
+
ClassInfoPtr info = _info;
while(info)
{
- os->writeTypeId(info->id);
-
- os->startSlice();
+ os->startSlice(info->id, !info->base);
for(DataMemberList::iterator q = info->members.begin(); q != info->members.end(); ++q)
{
DataMemberPtr member = *q;
@@ -1700,13 +1897,7 @@ IceRuby::ObjectWriter::write(const Ice::OutputStreamPtr& os) const
info = info->base;
}
- //
- // Marshal the Ice::Object slice.
- //
- os->writeTypeId(Ice::Object::ice_staticId());
- os->startSlice();
- os->writeSize(0); // For compatibility with the old AFM.
- os->endSlice();
+ os->endObject();
}
//
@@ -1728,8 +1919,10 @@ IceRuby::ObjectReader::ice_postUnmarshal()
}
void
-IceRuby::ObjectReader::read(const Ice::InputStreamPtr& is, bool rid)
+IceRuby::ObjectReader::read(const Ice::InputStreamPtr& is)
{
+ is->startObject();
+
//
// Unmarshal the slices of a user-defined class.
//
@@ -1738,11 +1931,6 @@ IceRuby::ObjectReader::read(const Ice::InputStreamPtr& is, bool rid)
ClassInfoPtr info = _info;
while(info)
{
- if(rid)
- {
- is->readTypeId();
- }
-
is->startSlice();
for(DataMemberList::iterator p = info->members.begin(); p != info->members.end(); ++p)
{
@@ -1751,28 +1939,18 @@ IceRuby::ObjectReader::read(const Ice::InputStreamPtr& is, bool rid)
}
is->endSlice();
- rid = true;
-
info = info->base;
}
}
- //
- // Unmarshal the Ice::Object slice.
- //
- if(rid)
- {
- is->readTypeId();
- }
+ _slicedData = is->endObject(_info->preserve);
- is->startSlice();
- // For compatibility with the old AFM.
- Ice::Int sz = is->readSize();
- if(sz != 0)
+ if(_slicedData)
{
- throw Ice::MarshalException(__FILE__, __LINE__);
+ SlicedDataUtil* util = reinterpret_cast<SlicedDataUtil*>(is->closure());
+ assert(util);
+ util->add(this);
}
- is->endSlice();
}
ClassInfoPtr
@@ -1787,6 +1965,12 @@ IceRuby::ObjectReader::getObject() const
return _object;
}
+Ice::SlicedDataPtr
+IceRuby::ObjectReader::getSlicedData() const
+{
+ return _slicedData;
+}
+
//
// InfoMapDestroyer implementation.
//
@@ -1848,48 +2032,11 @@ IceRuby::ReadObjectCallback::invoke(const Ice::ObjectPtr& p)
//
// ExceptionInfo implementation.
//
-void
-IceRuby::ExceptionInfo::marshal(VALUE p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap)
-{
- if(callRuby(rb_obj_is_kind_of, p, rubyClass) == Qfalse)
- {
- throw RubyException(rb_eTypeError, "expected exception %s", id.c_str());
- }
-
- os->write(usesClasses);
-
- ExceptionInfoPtr info = this;
- while(info)
- {
- os->write(info->id);
-
- os->startSlice();
- for(DataMemberList::iterator q = info->members.begin(); q != info->members.end(); ++q)
- {
- DataMemberPtr member = *q;
- volatile VALUE val = callRuby(rb_ivar_get, p, member->rubyID);
- if(!member->type->validate(val))
- {
- throw RubyException(rb_eTypeError, "invalid value for %s member `%s'", id.c_str(),
- member->name.c_str());
- }
-
- member->type->marshal(val, os, objectMap);
- }
- os->endSlice();
-
- info = info->base;
- }
-}
-
VALUE
IceRuby::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is)
{
volatile VALUE obj = callRuby(rb_class_new_instance, 0, static_cast<VALUE*>(0), rubyClass);
- //
- // NOTE: The type id for the first slice has already been read.
- //
ExceptionInfoPtr info = this;
while(info)
{
@@ -1902,11 +2049,6 @@ IceRuby::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is)
is->endSlice();
info = info->base;
- if(info)
- {
- string id;
- is->read(id); // Read the ID of the next slice.
- }
}
return obj;
@@ -1954,6 +2096,71 @@ IceRuby::ExceptionInfo::printMembers(VALUE value, IceUtilInternal::Output& out,
}
}
+//
+// ExceptionReader implementation.
+//
+IceRuby::ExceptionReader::ExceptionReader(const Ice::CommunicatorPtr& communicator, const ExceptionInfoPtr& info) :
+ Ice::UserExceptionReader(communicator), _info(info)
+{
+}
+
+IceRuby::ExceptionReader::~ExceptionReader()
+ throw()
+{
+}
+
+void
+IceRuby::ExceptionReader::read(const Ice::InputStreamPtr& is) const
+{
+ is->startException();
+
+ const_cast<VALUE&>(_ex) = _info->unmarshal(is);
+
+ is->endException(false);
+}
+
+bool
+IceRuby::ExceptionReader::usesClasses() const
+{
+ return _info->usesClasses;
+}
+
+void
+IceRuby::ExceptionReader::usesClasses(bool)
+{
+}
+
+string
+IceRuby::ExceptionReader::ice_name() const
+{
+ return _info->id;
+}
+
+Ice::Exception*
+IceRuby::ExceptionReader::ice_clone() const
+{
+ assert(false);
+ return 0;
+}
+
+void
+IceRuby::ExceptionReader::ice_throw() const
+{
+ throw *this;
+}
+
+VALUE
+IceRuby::ExceptionReader::getException() const
+{
+ return _ex;
+}
+
+Ice::SlicedDataPtr
+IceRuby::ExceptionReader::getSlicedData() const
+{
+ return 0;
+}
+
extern "C"
VALUE
IceRuby_defineEnum(VALUE /*self*/, VALUE id, VALUE type, VALUE enumerators)
@@ -2078,8 +2285,10 @@ IceRuby_declareClass(VALUE /*self*/, VALUE id)
{
info = new ClassInfo;
info->id = idstr;
- info->isBase = idstr == "::Ice::Object";
+ info->isBase = idstr == Ice::Object::ice_staticId();
info->isLocal = false;
+ info->isAbstract = false;
+ info->preserve = false;
info->rubyClass = Qnil;
info->typeObj = createType(info);
info->defined = false;
@@ -2106,6 +2315,8 @@ IceRuby_declareLocalClass(VALUE /*self*/, VALUE id)
info->id = idstr;
info->isBase = idstr == "::Ice::LocalObject";
info->isLocal = true;
+ info->isAbstract = false;
+ info->preserve = false;
info->rubyClass = Qnil;
info->typeObj = createType(info);
info->defined = false;
@@ -2183,7 +2394,8 @@ IceRuby_TypeInfo_defineProxy(VALUE self, VALUE type, VALUE classInfo)
extern "C"
VALUE
-IceRuby_TypeInfo_defineClass(VALUE self, VALUE type, VALUE isAbstract, VALUE base, VALUE interfaces, VALUE members)
+IceRuby_TypeInfo_defineClass(VALUE self, VALUE type, VALUE isAbstract, VALUE preserve, VALUE base, VALUE interfaces,
+ VALUE members)
{
ICE_RUBY_TRY
{
@@ -2191,6 +2403,7 @@ IceRuby_TypeInfo_defineClass(VALUE self, VALUE type, VALUE isAbstract, VALUE bas
assert(info);
info->isAbstract = isAbstract == Qtrue;
+ info->preserve = preserve == Qtrue;
if(!NIL_P(base))
{
@@ -2329,7 +2542,7 @@ IceRuby::initTypes(VALUE iceModule)
rb_define_module_function(iceModule, "__declareLocalClass", CAST_METHOD(IceRuby_declareLocalClass), 1);
rb_define_module_function(iceModule, "__defineException", CAST_METHOD(IceRuby_defineException), 4);
- rb_define_method(_typeInfoClass, "defineClass", CAST_METHOD(IceRuby_TypeInfo_defineClass), 5);
+ rb_define_method(_typeInfoClass, "defineClass", CAST_METHOD(IceRuby_TypeInfo_defineClass), 6);
rb_define_method(_typeInfoClass, "defineProxy", CAST_METHOD(IceRuby_TypeInfo_defineProxy), 2);
rb_define_module_function(iceModule, "__stringify", CAST_METHOD(IceRuby_stringify), 2);
diff --git a/rb/src/IceRuby/Types.h b/rb/src/IceRuby/Types.h
index a42840a568d..954272f8f02 100644
--- a/rb/src/IceRuby/Types.h
+++ b/rb/src/IceRuby/Types.h
@@ -37,6 +37,34 @@ class AbortMarshaling
typedef std::map<VALUE, Ice::ObjectPtr> ObjectMap;
+class ObjectReader;
+typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr;
+
+//
+// This class keeps track of Ruby objects (instances of Slice classes
+// and exceptions) that have preserved slices.
+//
+class SlicedDataUtil
+{
+public:
+
+ SlicedDataUtil();
+ ~SlicedDataUtil();
+
+ void add(const ObjectReaderPtr&);
+
+ void update();
+
+ static void setMember(VALUE, const Ice::SlicedDataPtr&);
+ static Ice::SlicedDataPtr getMember(VALUE, ObjectMap*);
+
+private:
+
+ std::set<ObjectReaderPtr> _readers;
+ static VALUE _slicedDataType;
+ static VALUE _sliceInfoType;
+};
+
struct PrintObjectHistory
{
int index;
@@ -298,6 +326,7 @@ public:
bool isBase; // Is this the ClassInfo for Ice::Object or Ice::LocalObject?
bool isLocal;
bool isAbstract;
+ bool preserve;
ClassInfoPtr base;
ClassInfoList interfaces;
DataMemberList members;
@@ -338,7 +367,6 @@ class ExceptionInfo : public IceUtil::Shared
{
public:
- void marshal(VALUE, const Ice::OutputStreamPtr&, ObjectMap*);
VALUE unmarshal(const Ice::InputStreamPtr&);
void print(VALUE, IceUtilInternal::Output&);
@@ -358,7 +386,7 @@ class ObjectWriter : public Ice::ObjectWriter
{
public:
- ObjectWriter(const ClassInfoPtr&, VALUE, ObjectMap*);
+ ObjectWriter(VALUE, ObjectMap*);
virtual void ice_preMarshal();
@@ -366,9 +394,9 @@ public:
private:
- ClassInfoPtr _info;
VALUE _object;
ObjectMap* _map;
+ ClassInfoPtr _info;
};
//
@@ -382,19 +410,51 @@ public:
virtual void ice_postUnmarshal();
- virtual void read(const Ice::InputStreamPtr&, bool);
+ virtual void read(const Ice::InputStreamPtr&);
virtual ClassInfoPtr getInfo() const;
VALUE getObject() const; // Borrowed reference.
+ Ice::SlicedDataPtr getSlicedData() const;
+
private:
VALUE _object;
ClassInfoPtr _info;
+ Ice::SlicedDataPtr _slicedData;
};
typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr;
+//
+// ExceptionReader creates a Ruby user exception and unmarshals it.
+//
+class ExceptionReader : public Ice::UserExceptionReader
+{
+public:
+
+ ExceptionReader(const Ice::CommunicatorPtr&, const ExceptionInfoPtr&);
+ ~ExceptionReader() throw();
+
+ virtual void read(const Ice::InputStreamPtr&) const;
+ virtual bool usesClasses() const;
+ virtual void usesClasses(bool);
+
+ virtual std::string ice_name() const;
+ virtual Ice::Exception* ice_clone() const;
+ virtual void ice_throw() const;
+
+ VALUE getException() const;
+
+ Ice::SlicedDataPtr getSlicedData() const;
+
+private:
+
+ ExceptionInfoPtr _info;
+ VALUE _ex;
+ Ice::SlicedDataPtr _slicedData;
+};
+
ClassInfoPtr lookupClassInfo(const std::string&);
ExceptionInfoPtr lookupExceptionInfo(const std::string&);
diff --git a/rb/src/IceRuby/Util.cpp b/rb/src/IceRuby/Util.cpp
index 0674c80f352..b5333cbcbd1 100644
--- a/rb/src/IceRuby/Util.cpp
+++ b/rb/src/IceRuby/Util.cpp
@@ -14,6 +14,123 @@
using namespace std;
using namespace IceRuby;
+namespace
+{
+
+bool
+checkIsInstance(VALUE p, const char* type)
+{
+ volatile VALUE rbType = callRuby(rb_path2class, type);
+ assert(!NIL_P(rbType));
+ return callRuby(rb_obj_is_instance_of, p, rbType) == Qtrue;
+}
+
+template<typename T, const char* PT>
+bool
+setVersion(VALUE p, const T& version)
+{
+ assert(checkIsInstance(p, PT));
+
+ VALUE major = callRuby(rb_int2inum, version.major);
+ VALUE minor = callRuby(rb_int2inum, version.minor);
+ rb_ivar_set(p, rb_intern("@major"), major);
+ rb_ivar_set(p, rb_intern("@minor"), minor);
+
+ return true;
+}
+
+template<typename T, const char* PT>
+bool
+getVersion(VALUE p, T& v)
+{
+ assert(checkIsInstance(p, PT));
+ volatile VALUE major = callRuby(rb_ivar_get, p, rb_intern("@major"));
+ volatile VALUE minor = callRuby(rb_ivar_get, p, rb_intern("@minor"));
+
+ long m;
+
+ m = getInteger(major);
+ if(m < 0 || m > 255)
+ {
+ throw RubyException(rb_eTypeError, "version major must be a value between 0 and 255");
+ return false;
+ }
+ v.major = m;
+
+ m = getInteger(minor);
+ if(m < 0 || m > 255)
+ {
+ throw RubyException(rb_eTypeError, "version minor must be a value between 0 and 255");
+ return false;
+ }
+ v.minor = m;
+
+ return true;
+}
+
+template<typename T, const char* PT>
+VALUE
+createVersion(const T& version)
+{
+ volatile VALUE rbType = callRuby(rb_path2class, PT);
+ assert(!NIL_P(rbType));
+
+ volatile VALUE obj = callRuby(rb_class_new_instance, 0, static_cast<VALUE*>(0), rbType);
+
+ if(!setVersion<T, PT>(obj, version))
+ {
+ return Qnil;
+ }
+
+ return obj;
+}
+
+template<typename T, const char* PT>
+VALUE
+versionToString(VALUE p)
+{
+ volatile VALUE rbType = callRuby(rb_path2class, PT);
+ assert(!NIL_P(rbType));
+ if(callRuby(rb_obj_is_instance_of, p, rbType) != Qtrue)
+ {
+ throw RubyException(rb_eTypeError, "argument is not an instance of %s", PT);
+ }
+
+ T v;
+ if(!getVersion<T, PT>(p, v))
+ {
+ return NULL;
+ }
+
+ ICE_RUBY_TRY
+ {
+ string s = IceInternal::versionToString<T>(v);
+ return createString(s);
+ }
+ ICE_RUBY_CATCH
+ return Qnil;
+}
+
+template<typename T, const char* PT>
+VALUE
+stringToVersion(VALUE p)
+{
+ string str = getString(p);
+
+ ICE_RUBY_TRY
+ {
+ T v = IceInternal::stringToVersion<T>(str);
+ return createVersion<T, PT>(v);
+ }
+ ICE_RUBY_CATCH
+ return Qnil;
+}
+
+char Ice_ProtocolVersion[] = "Ice::ProtocolVersion";
+char Ice_EncodingVersion[] = "Ice::EncodingVersion";
+
+}
+
extern "C"
VALUE
IceRuby_stringVersion(int /*argc*/, VALUE* /*argv*/, VALUE /*self*/)
@@ -39,11 +156,82 @@ IceRuby_intVersion(int /*argc*/, VALUE* /*argv*/, VALUE /*self*/)
return Qnil;
}
+extern "C"
+VALUE
+IceRuby_currentProtocol(int /*argc*/, VALUE* /*argv*/, VALUE /*self*/)
+{
+ ICE_RUBY_TRY
+ {
+ return createProtocolVersion(Ice::currentProtocol);
+ }
+ ICE_RUBY_CATCH
+ return Qnil;
+}
+
+extern "C"
+VALUE
+IceRuby_currentProtocolEncoding(int /*argc*/, VALUE* /*argv*/, VALUE /*self*/)
+{
+ ICE_RUBY_TRY
+ {
+ return createEncodingVersion(Ice::currentProtocolEncoding);
+ }
+ ICE_RUBY_CATCH
+ return Qnil;
+}
+
+extern "C"
+VALUE
+IceRuby_currentEncoding(int /*argc*/, VALUE* /*argv*/, VALUE /*self*/)
+{
+ ICE_RUBY_TRY
+ {
+ return createEncodingVersion(Ice::currentEncoding);
+ }
+ ICE_RUBY_CATCH
+ return Qnil;
+}
+
+extern "C"
+VALUE
+IceRuby_protocolVersionToString(VALUE /*self*/, VALUE v)
+{
+ return versionToString<Ice::ProtocolVersion, Ice_ProtocolVersion>(v);
+}
+
+extern "C"
+VALUE
+IceRuby_stringToProtocolVersion(VALUE /*self*/, VALUE v)
+{
+ return stringToVersion<Ice::ProtocolVersion, Ice_ProtocolVersion>(v);
+}
+
+extern "C"
+VALUE
+IceRuby_encodingVersionToString(VALUE /*self*/, VALUE v)
+{
+ return versionToString<Ice::EncodingVersion, Ice_EncodingVersion>(v);
+}
+
+extern "C"
+VALUE
+IceRuby_stringToEncodingVersion(VALUE /*self*/, VALUE v)
+{
+ return stringToVersion<Ice::EncodingVersion, Ice_EncodingVersion>(v);
+}
+
void
IceRuby::initUtil(VALUE iceModule)
{
rb_define_module_function(iceModule, "stringVersion", CAST_METHOD(IceRuby_stringVersion), -1);
rb_define_module_function(iceModule, "intVersion", CAST_METHOD(IceRuby_intVersion), -1);
+ rb_define_module_function(iceModule, "currentProtocol", CAST_METHOD(IceRuby_currentProtocol), -1);
+ rb_define_module_function(iceModule, "currentProtocolEncoding", CAST_METHOD(IceRuby_currentProtocolEncoding), -1);
+ rb_define_module_function(iceModule, "currentEncoding", CAST_METHOD(IceRuby_currentEncoding), -1);
+ rb_define_module_function(iceModule, "protocolVersionToString", CAST_METHOD(IceRuby_protocolVersionToString), 1);
+ rb_define_module_function(iceModule, "stringToProtocolVersion", CAST_METHOD(IceRuby_stringToProtocolVersion), 1);
+ rb_define_module_function(iceModule, "encodingVersionToString", CAST_METHOD(IceRuby_encodingVersionToString), 1);
+ rb_define_module_function(iceModule, "stringToEncodingVersion", CAST_METHOD(IceRuby_stringToEncodingVersion), 1);
}
IceRuby::RubyException::RubyException()
@@ -340,6 +528,74 @@ IceRuby::createIdentity(const Ice::Identity& id)
}
VALUE
+IceRuby::createProtocolVersion(const Ice::ProtocolVersion& v)
+{
+ return createVersion<Ice::ProtocolVersion, Ice_ProtocolVersion>(v);
+}
+
+VALUE
+IceRuby::createEncodingVersion(const Ice::EncodingVersion& v)
+{
+ return createVersion<Ice::EncodingVersion, Ice_EncodingVersion>(v);
+}
+
+bool
+IceRuby::getEncodingVersion(VALUE p, Ice::EncodingVersion& v)
+{
+ volatile VALUE cls = callRuby(rb_path2class, Ice_EncodingVersion);
+ assert(!NIL_P(cls));
+
+ if(callRuby(rb_obj_is_kind_of, p, cls) == Qfalse)
+ {
+ throw RubyException(rb_eTypeError, "value is not an Ice::EncodingVersion");
+ }
+
+ if(!getVersion<Ice::EncodingVersion, Ice_EncodingVersion>(p, v))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+#if 0
+VALUE
+IceRuby::currentProtocol(VALUE)
+{
+}
+
+VALUE
+IceRuby::currentProtocolEncoding(VALUE)
+{
+}
+
+VALUE
+IceRuby::currentEncoding(VALUE)
+{
+}
+
+VALUE
+IceRuby::protocolVersionToString(VALUE, VALUE)
+{
+}
+
+VALUE
+IceRuby::stringToProtocolVersion(VALUE, VALUE)
+{
+}
+
+VALUE
+IceRuby::encodingVersionToString(VALUE, VALUE)
+{
+}
+
+VALUE
+IceRuby::stringToEncodingVersion(VALUE, VALUE)
+{
+}
+#endif
+
+VALUE
IceRuby::callProtected(RubyFunction func, VALUE arg)
{
int error = 0;
@@ -464,17 +720,19 @@ setExceptionMembers(const Ice::LocalException& ex, VALUE p)
}
catch(const Ice::UnsupportedProtocolException& e)
{
- callRuby(rb_iv_set, p, "@badMajor", INT2FIX(e.badMajor));
- callRuby(rb_iv_set, p, "@badMinor", INT2FIX(e.badMinor));
- callRuby(rb_iv_set, p, "@major", INT2FIX(e.major));
- callRuby(rb_iv_set, p, "@minor", INT2FIX(e.minor));
+ VALUE m;
+ m = createProtocolVersion(e.bad);
+ callRuby(rb_iv_set, p, "@bad", m);
+ m = createProtocolVersion(e.supported);
+ callRuby(rb_iv_set, p, "@supported", m);
}
catch(const Ice::UnsupportedEncodingException& e)
{
- callRuby(rb_iv_set, p, "@badMajor", INT2FIX(e.badMajor));
- callRuby(rb_iv_set, p, "@badMinor", INT2FIX(e.badMinor));
- callRuby(rb_iv_set, p, "@major", INT2FIX(e.major));
- callRuby(rb_iv_set, p, "@minor", INT2FIX(e.minor));
+ VALUE m;
+ m = createEncodingVersion(e.bad);
+ callRuby(rb_iv_set, p, "@bad", m);
+ m = createEncodingVersion(e.supported);
+ callRuby(rb_iv_set, p, "@supported", m);
}
catch(const Ice::NoObjectFactoryException& e)
{
diff --git a/rb/src/IceRuby/Util.h b/rb/src/IceRuby/Util.h
index a58416800dd..236b18c029e 100644
--- a/rb/src/IceRuby/Util.h
+++ b/rb/src/IceRuby/Util.h
@@ -131,6 +131,21 @@ Ice::Identity getIdentity(VALUE);
VALUE createIdentity(const Ice::Identity&);
//
+// Create a Ruby instance of Ice.ProtocolVersion.
+//
+VALUE createProtocolVersion(const Ice::ProtocolVersion&);
+
+//
+// Create a Ruby instance of Ice.EncodingVersion.
+//
+VALUE createEncodingVersion(const Ice::EncodingVersion&);
+
+//
+// Extracts the members of an encoding version.
+//
+bool getEncodingVersion(VALUE, Ice::EncodingVersion&);
+
+//
// The callRuby functions are used to invoke Ruby C API functions
// while translating any Ruby exception into RubyException so that
// C++ objects are cleaned up properly. Overloadings are provided