diff options
author | Mark Spruiell <mes@zeroc.com> | 2012-05-16 16:05:50 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2012-05-16 16:05:50 -0700 |
commit | 3b6fbd2cb1ab0e9f6dbdfd4cbda02eb16fd85569 (patch) | |
tree | edfa533e67fb4ee003d1afbb2e1ba8a9b03ef3f3 /rb/src | |
parent | porting ami test changes to python (diff) | |
download | ice-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.cpp | 37 | ||||
-rw-r--r-- | rb/src/IceRuby/Operation.cpp | 168 | ||||
-rw-r--r-- | rb/src/IceRuby/Proxy.cpp | 47 | ||||
-rw-r--r-- | rb/src/IceRuby/Types.cpp | 383 | ||||
-rw-r--r-- | rb/src/IceRuby/Types.h | 68 | ||||
-rw-r--r-- | rb/src/IceRuby/Util.cpp | 274 | ||||
-rw-r--r-- | rb/src/IceRuby/Util.h | 15 |
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 |