summaryrefslogtreecommitdiff
path: root/php/src/IcePHP/Marshal.cpp
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2009-06-23 17:47:58 -0700
committerMark Spruiell <mes@zeroc.com>2009-06-23 17:47:58 -0700
commita2e794a1366fcd71f04496c206869ffa158547ac (patch)
tree4c9d6554f3dc658aeaa76892aeecfc3d7eb56b61 /php/src/IcePHP/Marshal.cpp
parentAdd x64 configurations to C++ projects (diff)
downloadice-a2e794a1366fcd71f04496c206869ffa158547ac.tar.bz2
ice-a2e794a1366fcd71f04496c206869ffa158547ac.tar.xz
ice-a2e794a1366fcd71f04496c206869ffa158547ac.zip
PHP changes:
- static translation - more traditional language mapping (multiple communicators, etc.) - support for registered (persistent) communicators - support for PHP namespaces (PHP 5.3 or later)
Diffstat (limited to 'php/src/IcePHP/Marshal.cpp')
-rw-r--r--php/src/IcePHP/Marshal.cpp2305
1 files changed, 0 insertions, 2305 deletions
diff --git a/php/src/IcePHP/Marshal.cpp b/php/src/IcePHP/Marshal.cpp
deleted file mode 100644
index fe802f345d1..00000000000
--- a/php/src/IcePHP/Marshal.cpp
+++ /dev/null
@@ -1,2305 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
-//
-// This copy of Ice is licensed to you under the terms described in the
-// ICE_LICENSE file included in this distribution.
-//
-// **********************************************************************
-
-#include <Marshal.h>
-#include <Profile.h>
-#include <Proxy.h>
-#include <Util.h>
-
-#include <IceUtil/InputUtil.h>
-#include <IceUtil/OutputUtil.h>
-#include <IceUtil/ScopedArray.h>
-
-using namespace std;
-using namespace IcePHP;
-
-ZEND_EXTERN_MODULE_GLOBALS(ice)
-
-//
-// The marshaling implementation is fairly straightforward. The factory methods in the
-// Marshaler base class examine the given Slice type and create a Marshaler subclass
-// that is responsible for marshaling that type. Some caching is done for complex types
-// such as struct and class; the cached Marshaler instance is stored as a member of the
-// ice_class_entry struct. (Cached instances are destroyed by Slice_destroyClasses.)
-//
-// The implementation of Ice object marshaling is more complex. In order to interface
-// with the Ice stream interface, we need to supply Ice::Object instances, and we must
-// be able to properly handle object graphs and cycles. The solution is to wrap each
-// PHP object with a temporary Ice::Object, and maintain a table that associates each PHP
-// object to its wrapper, so that graphs work correctly.
-//
-// The ObjectMarshaler class doesn't actually marshal object instances. Rather, it
-// represents the top-level marshaler for a particular formal type (i.e., the declared
-// type of a data member or operation parameter). During marshaling, the ObjectMarshaler
-// validates the type of the object to ensure it is compatible with the formal type,
-// and then obtains or creates an ObjectWriter instance for the object. Since each PHP
-// object is represented by an unsigned integer handle, looking up the wrapper is simple.
-//
-// Once the writer is obtained, the marshaler gives it to the stream. Eventually, the
-// stream will invoke write on the writer, at which point the data members are
-// marshaled. For efficiency, each "slice" of the object's state is marshaled by an
-// ObjectSliceMarshaler, which is cached for future reuse.
-//
-// Note that a graph of PHP objects does not result in an equivalent graph of writers.
-// Links between objects exist only in the PHP object representation. Furthermore, the
-// lifetime of the writers is bound to the operation, not to the PHP objects. Writers
-// exist only as a bridge to the C++ marshaling facility.
-//
-// Unmarshaling of Ice objects works in a similar fashion. A default object factory
-// is installed in the communicator that is capable of instantiating any concrete
-// class type for which a definition is present, including the type "::Ice::Object".
-// It returns an instance of ObjectReader, a subclass of Ice::Object that overrides
-// the read method to unmarshal object state. The setValue method is eventually
-// called on the ObjectReader in order to transfer its object handle to a different
-// zval value.
-//
-
-namespace IcePHP
-{
-
-//
-// Marshaler subclass definitions.
-//
-class PrimitiveMarshaler : public Marshaler
-{
-public:
- PrimitiveMarshaler(const Slice::BuiltinPtr&);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
- bool validate(zval* TSRMLS_DC);
-
-private:
- Slice::BuiltinPtr _type;
-};
-typedef IceUtil::Handle<PrimitiveMarshaler> PrimitiveMarshalerPtr;
-
-class SequenceMarshaler : public Marshaler
-{
-public:
- SequenceMarshaler(const Slice::SequencePtr& TSRMLS_DC);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- Slice::SequencePtr _type;
- Slice::BuiltinPtr _builtin;
- MarshalerPtr _elementMarshaler;
-};
-
-class ProxyMarshaler : public Marshaler
-{
-public:
- ProxyMarshaler(const Slice::ProxyPtr&);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- Slice::ProxyPtr _type;
-};
-
-class MemberMarshaler : public Marshaler
-{
-public:
- MemberMarshaler(const string&, const MarshalerPtr&);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- string _name;
- MarshalerPtr _marshaler;
-};
-
-class StructMarshaler : public Marshaler
-{
-public:
- StructMarshaler(const Slice::StructPtr& TSRMLS_DC);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- Slice::StructPtr _type;
- zend_class_entry* _class;
- vector<MarshalerPtr> _members;
-};
-
-class EnumMarshaler : public Marshaler
-{
-public:
- EnumMarshaler(const Slice::EnumPtr& TSRMLS_DC);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- zend_class_entry* _class;
- long _count;
-};
-
-class NativeDictionaryMarshaler : public Marshaler
-{
-public:
- NativeDictionaryMarshaler(const Slice::TypePtr&, const Slice::TypePtr& TSRMLS_DC);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- Slice::Builtin::Kind _keyKind;
- MarshalerPtr _keyMarshaler;
- MarshalerPtr _valueMarshaler;
-};
-
-class ExceptionMarshaler : public Marshaler
-{
-public:
- ExceptionMarshaler(const Slice::ExceptionPtr& TSRMLS_DC);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- Slice::ExceptionPtr _ex;
- zend_class_entry* _class;
-};
-
-//
-// Special marshaler just for the Ice::Object slice.
-//
-class IceObjectSliceMarshaler : public Marshaler
-{
-public:
- IceObjectSliceMarshaler(TSRMLS_D);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-};
-
-class ObjectSliceMarshaler : public Marshaler
-{
-public:
- ObjectSliceMarshaler(const string&, const Slice::DataMemberList& TSRMLS_DC);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- string _scoped;
- vector<MarshalerPtr> _members;
-};
-
-class ObjectWriter : public Ice::ObjectWriter
-{
-public:
- ObjectWriter(zval*, const Slice::SyntaxTreeBasePtr&, ObjectMap& TSRMLS_DC);
- ~ObjectWriter();
-
- virtual void ice_preMarshal();
-
- virtual void write(const Ice::OutputStreamPtr&) const;
-
-private:
- zval* _value;
- Slice::ClassDefPtr _type; // nil if type is ::Ice::Object
- ObjectMap& _map;
-#ifdef ZTS
- TSRMLS_D;
-#endif
-};
-
-class ReadObjectCallback : public Ice::ReadObjectCallback
-{
-public:
-
- virtual void invoke(const ::Ice::ObjectPtr&);
-
- zend_class_entry* ce; // The formal type
- string scoped;
- zval* zv; // The destination zval
-};
-typedef IceUtil::Handle<ReadObjectCallback> ReadObjectCallbackPtr;
-
-class ObjectReader : public Ice::ObjectReader
-{
-public:
- ObjectReader(zval*, const Slice::ClassDefPtr& TSRMLS_DC);
- ~ObjectReader();
-
- virtual void ice_postUnmarshal();
-
- virtual void read(const Ice::InputStreamPtr&, bool);
-
- void setValue(zend_class_entry*, const string&, zval*);
-
-private:
- zval* _value;
- Slice::ClassDefPtr _type; // nil if type is ::Ice::Object
-#ifdef ZTS
- TSRMLS_D;
-#endif
- zend_class_entry* _class;
-};
-typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr;
-
-class ObjectMarshaler : public Marshaler
-{
-public:
- ObjectMarshaler(const Slice::ClassDefPtr& TSRMLS_DC);
-
- virtual bool marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC);
- virtual bool unmarshal(zval*, const Ice::InputStreamPtr& TSRMLS_DC);
-
- virtual void destroy();
-
-private:
- Slice::ClassDefPtr _def;
- zend_class_entry* _class; // The static class type.
- string _scoped;
-};
-
-} // End of namespace IcePHP
-
-//
-// Marshaler implementation.
-//
-IcePHP::Marshaler::Marshaler()
-{
-}
-
-IcePHP::Marshaler::~Marshaler()
-{
-}
-
-MarshalerPtr
-IcePHP::Marshaler::createMarshaler(const Slice::TypePtr& type TSRMLS_DC)
-{
- Slice::BuiltinPtr builtin = Slice::BuiltinPtr::dynamicCast(type);
- if(builtin)
- {
- switch(builtin->kind())
- {
- case Slice::Builtin::KindByte:
- case Slice::Builtin::KindBool:
- case Slice::Builtin::KindShort:
- case Slice::Builtin::KindInt:
- case Slice::Builtin::KindLong:
- case Slice::Builtin::KindFloat:
- case Slice::Builtin::KindDouble:
- case Slice::Builtin::KindString:
- return new PrimitiveMarshaler(builtin);
-
- case Slice::Builtin::KindObject:
- return new ObjectMarshaler(0 TSRMLS_CC);
-
- case Slice::Builtin::KindObjectProxy:
- return new ProxyMarshaler(0);
-
- case Slice::Builtin::KindLocalObject:
- php_error_docref(0 TSRMLS_CC, E_ERROR, "unexpected local type");
- return 0;
- }
- }
-
- Slice::SequencePtr seq = Slice::SequencePtr::dynamicCast(type);
- if(seq)
- {
- return new SequenceMarshaler(seq TSRMLS_CC);
- }
-
- Slice::ProxyPtr proxy = Slice::ProxyPtr::dynamicCast(type);
- if(proxy)
- {
- return new ProxyMarshaler(proxy);
- }
-
- Slice::StructPtr st = Slice::StructPtr::dynamicCast(type);
- if(st)
- {
- //
- // Check to see if a marshaler for this type has already been created. If not, create
- // one and cache it in the marshaler map for future use.
- //
- string scoped = st->scoped();
- MarshalerMap* marshalerMap = static_cast<MarshalerMap*>(ICE_G(marshalerMap));
- MarshalerMap::iterator p = marshalerMap->find(scoped);
- if(p != marshalerMap->end())
- {
- return p->second;
- }
- else
- {
- MarshalerPtr result = new StructMarshaler(st TSRMLS_CC);
- marshalerMap->insert(pair<string, MarshalerPtr>(scoped, result));
- return result;
- }
- }
-
- Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type);
- if(en)
- {
- return new EnumMarshaler(en TSRMLS_CC);
- }
-
- Slice::DictionaryPtr dict = Slice::DictionaryPtr::dynamicCast(type);
- if(dict)
- {
- if(isNativeKey(dict->keyType()))
- {
- return new NativeDictionaryMarshaler(dict->keyType(), dict->valueType() TSRMLS_CC);
- }
- }
-
- Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(type);
- if(cl)
- {
- //
- // Don't cache ObjectMarshaler - we cache ObjectSliceMarshaler instead.
- //
- Slice::ClassDefPtr def = cl->definition();
- if(!def)
- {
- string scoped = cl->scoped();
- php_error_docref(0 TSRMLS_CC, E_ERROR, "cannot use Slice %s %s because it has not been defined",
- cl->isInterface() ? "interface" : "class", scoped.c_str());
- return 0;
- }
- return new ObjectMarshaler(def TSRMLS_CC);
- }
-
- return 0;
-}
-
-MarshalerPtr
-IcePHP::Marshaler::createMemberMarshaler(const string& name, const Slice::TypePtr& type TSRMLS_DC)
-{
- MarshalerPtr result;
- MarshalerPtr m = createMarshaler(type TSRMLS_CC);
- if(m)
- {
- result = new MemberMarshaler(name, m);
- }
- return result;
-}
-
-MarshalerPtr
-IcePHP::Marshaler::createExceptionMarshaler(const Slice::ExceptionPtr& ex TSRMLS_DC)
-{
- return new ExceptionMarshaler(ex TSRMLS_CC);
-}
-
-//
-// PrimitiveMarshaler implementation.
-//
-IcePHP::PrimitiveMarshaler::PrimitiveMarshaler(const Slice::BuiltinPtr& type) :
- _type(type)
-{
-}
-
-bool
-IcePHP::PrimitiveMarshaler::validate(zval* zv TSRMLS_DC)
-{
- switch(_type->kind())
- {
- case Slice::Builtin::KindBool:
- {
- if(Z_TYPE_P(zv) != IS_BOOL)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected boolean value but received %s", s.c_str());
- return false;
- }
- break;
- }
- case Slice::Builtin::KindByte:
- {
- if(Z_TYPE_P(zv) != IS_LONG)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected byte value but received %s", s.c_str());
- return false;
- }
- long val = Z_LVAL_P(zv);
- if(val < 0 || val > 255)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "value %ld is out of range for a byte", val);
- return false;
- }
- break;
- }
- case Slice::Builtin::KindShort:
- {
- if(Z_TYPE_P(zv) != IS_LONG)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected short value but received %s", s.c_str());
- return false;
- }
- long val = Z_LVAL_P(zv);
- if(val < SHRT_MIN || val > SHRT_MAX)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "value %ld is out of range for a short", val);
- return false;
- }
- break;
- }
- case Slice::Builtin::KindInt:
- {
- if(Z_TYPE_P(zv) != IS_LONG)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected int value but received %s", s.c_str());
- return false;
- }
- long val = Z_LVAL_P(zv);
- if(val < INT_MIN || val > INT_MAX)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "value %ld is out of range for an int", val);
- return false;
- }
- break;
- }
- case Slice::Builtin::KindLong:
- {
- //
- // The platform's 'long' type may not be 64 bits, so we also accept
- // a string argument for this type.
- //
- if(Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_STRING)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected long value but received %s", s.c_str());
- return false;
- }
- Ice::Long val;
- if(Z_TYPE_P(zv) == IS_LONG)
- {
- val = Z_LVAL_P(zv);
- }
- else
- {
- string sval(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
- if(!IceUtilInternal::stringToInt64(sval, val))
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "invalid long value `%s'", Z_STRVAL_P(zv));
- return false;
- }
- }
- break;
- }
- case Slice::Builtin::KindFloat:
- {
- if(Z_TYPE_P(zv) != IS_DOUBLE)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected float value but received %s", s.c_str());
- return false;
- }
- break;
- }
- case Slice::Builtin::KindDouble:
- {
- if(Z_TYPE_P(zv) != IS_DOUBLE)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected double value but received %s", s.c_str());
- return false;
- }
- break;
- }
- case Slice::Builtin::KindString:
- {
- if(Z_TYPE_P(zv) != IS_STRING && Z_TYPE_P(zv) != IS_NULL)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected string value but received %s", s.c_str());
- return false;
- }
- break;
- }
-
- case Slice::Builtin::KindObject:
- case Slice::Builtin::KindObjectProxy:
- case Slice::Builtin::KindLocalObject:
- assert(false);
- }
- return true;
-}
-
-bool
-IcePHP::PrimitiveMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& TSRMLS_DC)
-{
- if(!validate(zv TSRMLS_CC))
- {
- return false;
- }
-
- switch(_type->kind())
- {
- case Slice::Builtin::KindBool:
- {
- assert(Z_TYPE_P(zv) == IS_BOOL);
- os->writeBool(Z_BVAL_P(zv) ? true : false);
- break;
- }
- case Slice::Builtin::KindByte:
- {
- assert(Z_TYPE_P(zv) == IS_LONG);
- long val = Z_LVAL_P(zv);
- assert(val >= 0 && val <= 255);
- os->writeByte(static_cast<Ice::Byte>(val));
- break;
- }
- case Slice::Builtin::KindShort:
- {
- assert(Z_TYPE_P(zv) == IS_LONG);
- long val = Z_LVAL_P(zv);
- assert(val >= SHRT_MIN && val <= SHRT_MAX);
- os->writeShort(static_cast<Ice::Short>(val));
- break;
- }
- case Slice::Builtin::KindInt:
- {
- assert(Z_TYPE_P(zv) == IS_LONG);
- long val = Z_LVAL_P(zv);
- assert(val >= INT_MIN && val <= INT_MAX);
- os->writeInt(static_cast<Ice::Int>(val));
- break;
- }
- case Slice::Builtin::KindLong:
- {
- //
- // The platform's 'long' type may not be 64 bits, so we also accept
- // a string argument for this type.
- //
- assert(Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_STRING);
- Ice::Long val;
- if(Z_TYPE_P(zv) == IS_LONG)
- {
- val = Z_LVAL_P(zv);
- }
- else
- {
- string sval(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
- IceUtilInternal::stringToInt64(sval, val);
- }
- os->writeLong(val);
- break;
- }
- case Slice::Builtin::KindFloat:
- {
- assert(Z_TYPE_P(zv) == IS_DOUBLE);
- double val = Z_DVAL_P(zv);
- os->writeFloat(static_cast<Ice::Float>(val));
- break;
- }
- case Slice::Builtin::KindDouble:
- {
- assert(Z_TYPE_P(zv) == IS_DOUBLE);
- double val = Z_DVAL_P(zv);
- os->writeDouble(val);
- break;
- }
- case Slice::Builtin::KindString:
- {
- assert(Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_NULL);
- if(Z_TYPE_P(zv) == IS_STRING)
- {
- string val(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
- os->writeString(val);
- }
- else
- {
- os->writeString(string());
- }
- break;
- }
-
- case Slice::Builtin::KindObject:
- case Slice::Builtin::KindObjectProxy:
- case Slice::Builtin::KindLocalObject:
- assert(false);
- }
- return true;
-}
-
-bool
-IcePHP::PrimitiveMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- switch(_type->kind())
- {
- case Slice::Builtin::KindBool:
- {
- bool val = is->readBool();
- ZVAL_BOOL(zv, val ? 1 : 0);
- break;
- }
- case Slice::Builtin::KindByte:
- {
- Ice::Byte val = is->readByte();
- ZVAL_LONG(zv, val & 0xff);
- break;
- }
- case Slice::Builtin::KindShort:
- {
- Ice::Short val = is->readShort();
- ZVAL_LONG(zv, val);
- break;
- }
- case Slice::Builtin::KindInt:
- {
- Ice::Int val = is->readInt();
- ZVAL_LONG(zv, val);
- break;
- }
- case Slice::Builtin::KindLong:
- {
- Ice::Long val = is->readLong();
-
- //
- // The platform's 'long' type may not be 64 bits, so we store 64-bit
- // values as a string.
- //
- if(sizeof(Ice::Long) > sizeof(long) && (val < LONG_MIN || val > LONG_MAX))
- {
- string str = IceUtilInternal::int64ToString(val);
- ZVAL_STRINGL(zv, const_cast<char*>(str.c_str()), str.length(), 1);
- }
- else
- {
- ZVAL_LONG(zv, static_cast<long>(val));
- }
- break;
- }
- case Slice::Builtin::KindFloat:
- {
- Ice::Float val = is->readFloat();
- ZVAL_DOUBLE(zv, val);
- break;
- }
- case Slice::Builtin::KindDouble:
- {
- Ice::Double val = is->readDouble();
- ZVAL_DOUBLE(zv, val);
- break;
- }
- case Slice::Builtin::KindString:
- {
- string val = is->readString();
- ZVAL_STRINGL(zv, const_cast<char*>(val.c_str()), val.length(), 1);
- break;
- }
-
- case Slice::Builtin::KindObject:
- case Slice::Builtin::KindObjectProxy:
- case Slice::Builtin::KindLocalObject:
- assert(false);
- }
-
- return true;
-}
-
-void
-IcePHP::PrimitiveMarshaler::destroy()
-{
-}
-
-//
-// SequenceMarshaler implementation.
-//
-IcePHP::SequenceMarshaler::SequenceMarshaler(const Slice::SequencePtr& type TSRMLS_DC) :
- _type(type)
-{
- Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type);
- if(b && b->kind() != Slice::Builtin::KindObject && b->kind() != Slice::Builtin::KindObjectProxy)
- {
- _builtin = b;
- }
- _elementMarshaler = createMarshaler(type->type() TSRMLS_CC);
-}
-
-bool
-IcePHP::SequenceMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& m TSRMLS_DC)
-{
- if(Z_TYPE_P(zv) != IS_ARRAY && Z_TYPE_P(zv) != IS_NULL)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected array or null for sequence but received %s", s.c_str());
- return false;
- }
-
- if(Z_TYPE_P(zv) == IS_NULL)
- {
- os->writeSize(0);
- return true;
- }
-
- HashTable* arr = Z_ARRVAL_P(zv);
-
- HashPosition pos;
- zend_hash_internal_pointer_reset_ex(arr, &pos);
- Ice::Int sz = static_cast<Ice::Int>(zend_hash_num_elements(arr));
-
- if(_builtin)
- {
- PrimitiveMarshalerPtr pm = PrimitiveMarshalerPtr::dynamicCast(_elementMarshaler);
- assert(pm);
- switch(_builtin->kind())
- {
- case Slice::Builtin::KindBool:
- {
- Ice::BoolSeq seq(sz);
- Ice::Int i = 0;
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!pm->validate(*val TSRMLS_CC))
- {
- return false;
- }
- seq[i++] = Z_BVAL_P(*val) ? true : false;
- zend_hash_move_forward_ex(arr, &pos);
- }
- os->writeBoolSeq(seq);
- break;
- }
- case Slice::Builtin::KindByte:
- {
- Ice::ByteSeq seq(sz);
- Ice::Int i = 0;
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!pm->validate(*val TSRMLS_CC))
- {
- return false;
- }
- long l = Z_LVAL_P(*val);
- assert(l >= 0 && l <= 255);
- seq[i++] = static_cast<Ice::Byte>(l);
- zend_hash_move_forward_ex(arr, &pos);
- }
- os->writeByteSeq(seq);
- break;
- }
- case Slice::Builtin::KindShort:
- {
- Ice::ShortSeq seq(sz);
- Ice::Int i = 0;
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!pm->validate(*val TSRMLS_CC))
- {
- return false;
- }
- long l = Z_LVAL_P(*val);
- assert(l >= SHRT_MIN && l <= SHRT_MAX);
- seq[i++] = static_cast<Ice::Short>(l);
- zend_hash_move_forward_ex(arr, &pos);
- }
- os->writeShortSeq(seq);
- break;
- }
- case Slice::Builtin::KindInt:
- {
- Ice::IntSeq seq(sz);
- Ice::Int i = 0;
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!pm->validate(*val TSRMLS_CC))
- {
- return false;
- }
- long l = Z_LVAL_P(*val);
- assert(l >= INT_MIN && l <= INT_MAX);
- seq[i++] = static_cast<Ice::Int>(l);
- zend_hash_move_forward_ex(arr, &pos);
- }
- os->writeIntSeq(seq);
- break;
- }
- case Slice::Builtin::KindLong:
- {
- Ice::LongSeq seq(sz);
- Ice::Int i = 0;
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!pm->validate(*val TSRMLS_CC))
- {
- return false;
- }
- //
- // The platform's 'long' type may not be 64 bits, so we also accept
- // a string argument for this type.
- //
- assert(Z_TYPE_P(*val) == IS_LONG || Z_TYPE_P(*val) == IS_STRING);
- Ice::Long l;
- if(Z_TYPE_P(*val) == IS_LONG)
- {
- l = Z_LVAL_P(*val);
- }
- else
- {
- string sval(Z_STRVAL_P(*val), Z_STRLEN_P(*val));
- IceUtilInternal::stringToInt64(sval, l);
- }
- seq[i++] = l;
- zend_hash_move_forward_ex(arr, &pos);
- }
- os->writeLongSeq(seq);
- break;
- }
- case Slice::Builtin::KindFloat:
- {
- Ice::FloatSeq seq(sz);
- Ice::Int i = 0;
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!pm->validate(*val TSRMLS_CC))
- {
- return false;
- }
- double d = Z_DVAL_P(*val);
- seq[i++] = static_cast<Ice::Float>(d);
- zend_hash_move_forward_ex(arr, &pos);
- }
- os->writeFloatSeq(seq);
- break;
- }
- case Slice::Builtin::KindDouble:
- {
- Ice::DoubleSeq seq(sz);
- Ice::Int i = 0;
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!pm->validate(*val TSRMLS_CC))
- {
- return false;
- }
- double d = Z_DVAL_P(*val);
- seq[i++] = d;
- zend_hash_move_forward_ex(arr, &pos);
- }
- os->writeDoubleSeq(seq);
- break;
- }
- case Slice::Builtin::KindString:
- {
- Ice::StringSeq seq(sz);
- Ice::Int i = 0;
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!pm->validate(*val TSRMLS_CC))
- {
- return false;
- }
- string s;
- if(Z_TYPE_P(*val) == IS_STRING)
- {
- s = string(Z_STRVAL_P(*val), Z_STRLEN_P(*val));
- }
- else
- {
- assert(Z_TYPE_P(*val) == IS_NULL);
- }
- seq[i++] = s;
- zend_hash_move_forward_ex(arr, &pos);
- }
- os->writeStringSeq(seq);
- break;
- }
-
- case Slice::Builtin::KindObject:
- case Slice::Builtin::KindObjectProxy:
- case Slice::Builtin::KindLocalObject:
- assert(false);
- }
- }
- else
- {
- os->writeSize(sz);
-
- void* data;
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
- if(!_elementMarshaler->marshal(*val, os, m TSRMLS_CC))
- {
- return false;
- }
- zend_hash_move_forward_ex(arr, &pos);
- }
- }
-
- return true;
-}
-
-bool
-IcePHP::SequenceMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- array_init(zv);
-
- if(_builtin)
- {
- switch(_builtin->kind())
- {
- case Slice::Builtin::KindBool:
- {
- pair<const bool*, const bool*> pr;
- IceUtilInternal::ScopedArray<bool> arr(is->readBoolSeq(pr));
- Ice::Int i = 0;
- for(const bool* p = pr.first; p != pr.second; ++p, ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- ZVAL_BOOL(val, *p ? 1 : 0);
- add_index_zval(zv, i, val);
- }
- break;
- }
- case Slice::Builtin::KindByte:
- {
- pair<const Ice::Byte*, const Ice::Byte*> pr;
- is->readByteSeq(pr);
- Ice::Int i = 0;
- for(const Ice::Byte* p = pr.first; p != pr.second; ++p, ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- ZVAL_LONG(val, *p & 0xff);
- add_index_zval(zv, i, val);
- }
- break;
- }
- case Slice::Builtin::KindShort:
- {
- pair<const Ice::Short*, const Ice::Short*> pr;
- IceUtilInternal::ScopedArray<Ice::Short> arr(is->readShortSeq(pr));
- Ice::Int i = 0;
- for(const Ice::Short* p = pr.first; p != pr.second; ++p, ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- ZVAL_LONG(val, *p);
- add_index_zval(zv, i, val);
- }
- break;
- }
- case Slice::Builtin::KindInt:
- {
- pair<const Ice::Int*, const Ice::Int*> pr;
- IceUtilInternal::ScopedArray<Ice::Int> arr(is->readIntSeq(pr));
- Ice::Int i = 0;
- for(const Ice::Int* p = pr.first; p != pr.second; ++p, ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- ZVAL_LONG(val, *p);
- add_index_zval(zv, i, val);
- }
- break;
- }
- case Slice::Builtin::KindLong:
- {
- pair<const Ice::Long*, const Ice::Long*> pr;
- IceUtilInternal::ScopedArray<Ice::Long> arr(is->readLongSeq(pr));
- Ice::Int i = 0;
- for(const Ice::Long* p = pr.first; p != pr.second; ++p, ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- //
- // The platform's 'long' type may not be 64 bits, so we store 64-bit
- // values as a string.
- //
- if(sizeof(Ice::Long) > sizeof(long) && (*p < LONG_MIN || *p > LONG_MAX))
- {
- string str = IceUtilInternal::int64ToString(*p);
- ZVAL_STRINGL(val, const_cast<char*>(str.c_str()), str.length(), 1);
- }
- else
- {
- ZVAL_LONG(val, static_cast<long>(*p));
- }
- add_index_zval(zv, i, val);
- }
- break;
- }
- case Slice::Builtin::KindFloat:
- {
- pair<const Ice::Float*, const Ice::Float*> pr;
- IceUtilInternal::ScopedArray<Ice::Float> arr(is->readFloatSeq(pr));
- Ice::Int i = 0;
- for(const Ice::Float* p = pr.first; p != pr.second; ++p, ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- ZVAL_DOUBLE(zv, *p);
- add_index_zval(zv, i, val);
- }
- break;
- }
- case Slice::Builtin::KindDouble:
- {
- pair<const Ice::Double*, const Ice::Double*> pr;
- IceUtilInternal::ScopedArray<Ice::Double> arr(is->readDoubleSeq(pr));
- Ice::Int i = 0;
- for(const Ice::Double* p = pr.first; p != pr.second; ++p, ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- ZVAL_DOUBLE(zv, *p);
- add_index_zval(zv, i, val);
- }
- break;
- }
- case Slice::Builtin::KindString:
- {
- Ice::StringSeq seq = is->readStringSeq();
- Ice::Int i = 0;
- for(Ice::StringSeq::iterator p = seq.begin(); p != seq.end(); ++p, ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- ZVAL_STRINGL(val, const_cast<char*>(p->c_str()), p->length(), 1);
- add_index_zval(zv, i, val);
- }
- break;
- }
-
- case Slice::Builtin::KindObject:
- case Slice::Builtin::KindObjectProxy:
- case Slice::Builtin::KindLocalObject:
- assert(false);
- }
- }
- else
- {
- Ice::Int sz = is->readSize();
- for(Ice::Int i = 0; i < sz; ++i)
- {
- zval* val;
- MAKE_STD_ZVAL(val);
- if(!_elementMarshaler->unmarshal(val, is TSRMLS_CC))
- {
- return false;
- }
- add_index_zval(zv, i, val);
- }
- }
-
- return true;
-}
-
-void
-IcePHP::SequenceMarshaler::destroy()
-{
- _elementMarshaler->destroy();
- _elementMarshaler = 0;
-}
-
-//
-// ProxyMarshaler implementation.
-//
-IcePHP::ProxyMarshaler::ProxyMarshaler(const Slice::ProxyPtr& type) :
- _type(type)
-{
-}
-
-bool
-IcePHP::ProxyMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& TSRMLS_DC)
-{
- if(Z_TYPE_P(zv) != IS_OBJECT && Z_TYPE_P(zv) != IS_NULL)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected proxy value but received %s", s.c_str());
- return false;
- }
-
- Ice::ObjectPrx proxy;
- Slice::ClassDefPtr def;
- if(!ZVAL_IS_NULL(zv))
- {
- if(!fetchProxy(zv, proxy, def TSRMLS_CC))
- {
- return false;
- }
-
- if(_type)
- {
- string scoped = _type->_class()->scoped();
- if(def)
- {
- if(!def->isA(scoped))
- {
- string s = def->scoped();
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected a proxy of type %s but received %s",
- scoped.c_str(), s.c_str());
- return false;
- }
- }
- else
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected a proxy of type %s", scoped.c_str());
- return false;
- }
- }
- }
- os->writeProxy(proxy);
-
- return true;
-}
-
-bool
-IcePHP::ProxyMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- Ice::ObjectPrx proxy = is->readProxy();
-
- if(!proxy)
- {
- ZVAL_NULL(zv);
- return true;
- }
-
- //
- // If _type is not a primitive proxy (i.e., Builtin::KindObjectProxy), then we
- // want to associate our class with the proxy so that it is considered to be
- // "narrowed".
- //
- Slice::ClassDefPtr def;
- if(_type)
- {
- def = _type->_class()->definition();
- }
-
- if(!createProxy(zv, proxy, def TSRMLS_CC))
- {
- return false;
- }
-
- return true;
-}
-
-void
-IcePHP::ProxyMarshaler::destroy()
-{
-}
-
-//
-// MemberMarshaler implementation.
-//
-IcePHP::MemberMarshaler::MemberMarshaler(const string& name, const MarshalerPtr& marshaler) :
- _name(name), _marshaler(marshaler)
-{
-}
-
-bool
-IcePHP::MemberMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& m TSRMLS_DC)
-{
- void* data;
- if(zend_hash_find(Z_OBJPROP_P(zv), const_cast<char*>(_name.c_str()), _name.length() + 1, &data) == FAILURE)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "member `%s' is not defined", _name.c_str());
- return false;
- }
-
- zval** val = reinterpret_cast<zval**>(data);
- return _marshaler->marshal(*val, os, m TSRMLS_CC);;
-}
-
-bool
-IcePHP::MemberMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- zval* val;
- MAKE_STD_ZVAL(val);
-
- if(!_marshaler->unmarshal(val, is TSRMLS_CC))
- {
- return false;
- }
-
- //
- // The add_property_zval function fails if the data member has protected visibility.
- // As a workaround, before calling the function we change the current scope to be that
- // of the object.
- //
- zend_class_entry *oldScope = EG(scope);
- EG(scope) = Z_OBJCE_P(zv);
-
- int status = add_property_zval(zv, const_cast<char*>(_name.c_str()), val);
-
- EG(scope) = oldScope; // Restore the previous scope.
-
- if(status == FAILURE)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to set member `%s'", _name.c_str());
- return false;
- }
-
- zval_ptr_dtor(&val); // add_property_zval increments the refcount.
-
- return true;
-}
-
-void
-IcePHP::MemberMarshaler::destroy()
-{
- _marshaler->destroy();
- _marshaler = 0;
-}
-
-//
-// StructMarshaler implementation.
-//
-IcePHP::StructMarshaler::StructMarshaler(const Slice::StructPtr& type TSRMLS_DC) :
- _type(type)
-{
- _class = findClassScoped(type->scoped() TSRMLS_CC);
- assert(_class);
-
- Slice::DataMemberList members = type->dataMembers();
- for(Slice::DataMemberList::iterator q = members.begin(); q != members.end(); ++q)
- {
- MarshalerPtr marshaler = createMemberMarshaler((*q)->name(), (*q)->type() TSRMLS_CC);
- assert(marshaler);
- _members.push_back(marshaler);
- }
-}
-
-bool
-IcePHP::StructMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& m TSRMLS_DC)
-{
- if(Z_TYPE_P(zv) != IS_OBJECT)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected struct value of type %s but received %s", _class->name,
- s.c_str());
- return false;
- }
-
- //
- // Compare class entries.
- //
- zend_class_entry* ce = Z_OBJCE_P(zv);
- if(ce != _class)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected struct value of type %s but received %s", _class->name,
- ce->name);
- return false;
- }
-
- for(vector<MarshalerPtr>::iterator p = _members.begin(); p != _members.end(); ++p)
- {
- if(!(*p)->marshal(zv, os, m TSRMLS_CC))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool
-IcePHP::StructMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- if(object_init_ex(zv, _class) != SUCCESS)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to initialize object of type %s", _class->name);
- return false;
- }
-
- for(vector<MarshalerPtr>::iterator p = _members.begin(); p != _members.end(); ++p)
- {
- if(!(*p)->unmarshal(zv, is TSRMLS_CC))
- {
- return false;
- }
- }
-
- return true;
-}
-
-void
-IcePHP::StructMarshaler::destroy()
-{
- vector<MarshalerPtr> members = _members;
- _members.clear();
- for(vector<MarshalerPtr>::iterator p = members.begin(); p != members.end(); ++p)
- {
- (*p)->destroy();
- }
-}
-
-//
-// EnumMarshaler implementation.
-//
-IcePHP::EnumMarshaler::EnumMarshaler(const Slice::EnumPtr& type TSRMLS_DC)
-{
- _class = findClassScoped(type->scoped() TSRMLS_CC);
- assert(_class);
- _count = static_cast<long>(type->getEnumerators().size());
-}
-
-bool
-IcePHP::EnumMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& TSRMLS_DC)
-{
- if(Z_TYPE_P(zv) != IS_LONG)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected long value for enum %s but received %s", _class->name,
- s.c_str());
- return false;
- }
-
- //
- // Validate value.
- //
- long val = Z_LVAL_P(zv);
- if(val < 0 || val >= _count)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "value %ld is out of range for enum %s", val, _class->name);
- return false;
- }
-
- if(_count <= 127)
- {
- os->writeByte(static_cast<Ice::Byte>(val));
- }
- else if(_count <= 32767)
- {
- os->writeShort(static_cast<Ice::Short>(val));
- }
- else
- {
- os->writeInt(static_cast<Ice::Int>(val));
- }
-
- return true;
-}
-
-bool
-IcePHP::EnumMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- if(_count <= 127)
- {
- Ice::Byte val = is->readByte();
- ZVAL_LONG(zv, val);
- }
- else if(_count <= 32767)
- {
- Ice::Short val = is->readShort();
- ZVAL_LONG(zv, val);
- }
- else
- {
- Ice::Int val = is->readInt();
- ZVAL_LONG(zv, val);
- }
-
- return true;
-}
-
-void
-IcePHP::EnumMarshaler::destroy()
-{
-}
-
-//
-// NativeDictionaryMarshaler implementation.
-//
-IcePHP::NativeDictionaryMarshaler::NativeDictionaryMarshaler(const Slice::TypePtr& keyType,
- const Slice::TypePtr& valueType TSRMLS_DC)
-{
- Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(keyType);
- assert(b);
- _keyKind = b->kind();
- _keyMarshaler = createMarshaler(keyType TSRMLS_CC);
- _valueMarshaler = createMarshaler(valueType TSRMLS_CC);
-}
-
-bool
-IcePHP::NativeDictionaryMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& m TSRMLS_DC)
-{
- if(Z_TYPE_P(zv) != IS_ARRAY && Z_TYPE_P(zv) != IS_NULL)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected array or null for dictionary but received %s", s.c_str());
- return false;
- }
-
- if(Z_TYPE_P(zv) == IS_NULL)
- {
- os->writeSize(0);
- return true;
- }
-
- HashTable* arr = Z_ARRVAL_P(zv);
- HashPosition pos;
- void* data;
-
- os->writeSize(zend_hash_num_elements(arr));
-
- zend_hash_internal_pointer_reset_ex(arr, &pos);
- while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE)
- {
- zval** val = reinterpret_cast<zval**>(data);
-
- //
- // Get the key (which can be a long or a string).
- //
- char* keyStr;
- uint keyLen;
- ulong keyNum;
- int keyType = zend_hash_get_current_key_ex(arr, &keyStr, &keyLen, &keyNum, 0, &pos);
-
- //
- // Store the key in a zval, so that we can reuse the PrimitiveMarshaler logic.
- //
- zval zkey;
- if(keyType == HASH_KEY_IS_LONG)
- {
- ZVAL_LONG(&zkey, keyNum);
- }
- else
- {
- ZVAL_STRINGL(&zkey, keyStr, keyLen - 1, 1);
- }
-
- //
- // Convert the zval to the key type required by Slice, if necessary.
- //
- switch(_keyKind)
- {
- case Slice::Builtin::KindBool:
- {
- convert_to_boolean(&zkey);
- break;
- }
-
- case Slice::Builtin::KindByte:
- case Slice::Builtin::KindShort:
- case Slice::Builtin::KindInt:
- case Slice::Builtin::KindLong:
- {
- if(keyType == HASH_KEY_IS_STRING)
- {
- convert_to_long(&zkey);
- }
- break;
- }
-
- case Slice::Builtin::KindString:
- {
- if(keyType == HASH_KEY_IS_LONG)
- {
- convert_to_string(&zkey);
- }
- break;
- }
-
- case Slice::Builtin::KindFloat:
- case Slice::Builtin::KindDouble:
- case Slice::Builtin::KindObject:
- case Slice::Builtin::KindObjectProxy:
- case Slice::Builtin::KindLocalObject:
- assert(false);
- }
-
- //
- // Marshal the key.
- //
- if(!_keyMarshaler->marshal(&zkey, os, m TSRMLS_CC))
- {
- zval_dtor(&zkey);
- return false;
- }
-
- zval_dtor(&zkey);
-
- //
- // Marshal the value.
- //
- if(!_valueMarshaler->marshal(*val, os, m TSRMLS_CC))
- {
- return false;
- }
-
- zend_hash_move_forward_ex(arr, &pos);
- }
-
- return true;
-}
-
-bool
-IcePHP::NativeDictionaryMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- array_init(zv);
-
- Ice::Int sz = is->readSize();
-
- for(Ice::Int i = 0; i < sz; ++i)
- {
- zval key;
- zval* val;
- INIT_ZVAL(key);
- MAKE_STD_ZVAL(val);
-
- if(!_keyMarshaler->unmarshal(&key, is TSRMLS_CC))
- {
- return false;
- }
- if(!_valueMarshaler->unmarshal(val, is TSRMLS_CC))
- {
- return false;
- }
-
- switch(Z_TYPE(key))
- {
- case IS_LONG:
- add_index_zval(zv, Z_LVAL(key), val);
- break;
- case IS_BOOL:
- add_index_zval(zv, Z_BVAL(key) ? 1 : 0, val);
- break;
- case IS_STRING:
- add_assoc_zval_ex(zv, Z_STRVAL(key), Z_STRLEN(key) + 1, val);
- break;
- default:
- assert(false);
- return false;
- }
- zval_dtor(&key);
- }
-
- return true;
-}
-
-void
-IcePHP::NativeDictionaryMarshaler::destroy()
-{
- _keyMarshaler->destroy();
- _keyMarshaler = 0;
- _valueMarshaler->destroy();
- _valueMarshaler = 0;
-}
-
-//
-// ExceptionMarshaler implementation.
-//
-IcePHP::ExceptionMarshaler::ExceptionMarshaler(const Slice::ExceptionPtr& ex TSRMLS_DC) :
- _ex(ex)
-{
- _class = findClassScoped(ex->scoped() TSRMLS_CC);
- assert(_class);
-}
-
-bool
-IcePHP::ExceptionMarshaler::marshal(zval*, const Ice::OutputStreamPtr&, ObjectMap& TSRMLS_DC)
-{
- //
- // We never need to marshal an exception.
- //
- php_error_docref(0 TSRMLS_CC, E_ERROR, "exception marshaling is not supported");
- return false;
-}
-
-bool
-IcePHP::ExceptionMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- if(object_init_ex(zv, _class) != SUCCESS)
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "unable to initialize exception %s", _class->name);
- return false;
- }
-
- //
- // NOTE: The type id for the first slice has already been read.
- //
-
- Slice::ExceptionPtr ex = _ex;
- while(ex)
- {
- Slice::DataMemberList members = ex->dataMembers();
- is->startSlice();
- for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p)
- {
- MarshalerPtr member = createMemberMarshaler((*p)->name(), (*p)->type() TSRMLS_CC);
- if(!member->unmarshal(zv, is TSRMLS_CC))
- {
- return false;
- }
- }
- is->endSlice();
- ex = ex->base();
- if(ex)
- {
- is->readString(); // Skip id.
- }
- }
-
- return true;
-}
-
-void
-IcePHP::ExceptionMarshaler::destroy()
-{
-}
-
-//
-// IceObjectSliceMarshaler implementation.
-//
-IcePHP::IceObjectSliceMarshaler::IceObjectSliceMarshaler(TSRMLS_D)
-{
-}
-
-bool
-IcePHP::IceObjectSliceMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& TSRMLS_DC)
-{
- assert(Z_TYPE_P(zv) == IS_OBJECT);
-
- os->writeTypeId(Ice::Object::ice_staticId());
- os->startSlice();
- os->writeSize(0); // For compatibility with the old AFM.
- os->endSlice();
-
- return true;
-}
-
-bool
-IcePHP::IceObjectSliceMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- assert(Z_TYPE_P(zv) == IS_OBJECT);
-
- //
- // Do not read type id here - see ObjectReader::__read().
- //
- //is->readTypeId()
-
- is->startSlice();
-
- // For compatibility with the old AFM.
- Ice::Int sz = is->readSize();
- if(sz != 0)
- {
- throw Ice::MarshalException(__FILE__, __LINE__);
- }
-
- is->endSlice();
-
- return true;
-}
-
-void
-IcePHP::IceObjectSliceMarshaler::destroy()
-{
-}
-
-//
-// ObjectSliceMarshaler implementation.
-//
-IcePHP::ObjectSliceMarshaler::ObjectSliceMarshaler(const string& scoped,
- const Slice::DataMemberList& members TSRMLS_DC) :
- _scoped(scoped)
-{
- for(Slice::DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p)
- {
- MarshalerPtr marshaler = createMemberMarshaler((*p)->name(), (*p)->type() TSRMLS_CC);
- assert(marshaler);
- _members.push_back(marshaler);
- }
-}
-
-bool
-IcePHP::ObjectSliceMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& m TSRMLS_DC)
-{
- assert(Z_TYPE_P(zv) == IS_OBJECT);
-
- os->writeTypeId(_scoped);
- os->startSlice();
- for(vector<MarshalerPtr>::iterator p = _members.begin(); p != _members.end(); ++p)
- {
- if(!(*p)->marshal(zv, os, m TSRMLS_CC))
- {
- return false;
- }
- }
- os->endSlice();
-
- return true;
-}
-
-bool
-IcePHP::ObjectSliceMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- assert(Z_TYPE_P(zv) == IS_OBJECT);
-
- //
- // Do not read type id here - see ObjectReader::__read().
- //
- //is->readTypeId()
-
- is->startSlice();
- for(vector<MarshalerPtr>::iterator p = _members.begin(); p != _members.end(); ++p)
- {
- if(!(*p)->unmarshal(zv, is TSRMLS_CC))
- {
- return false;
- }
- }
- is->endSlice();
-
- return true;
-}
-
-void
-IcePHP::ObjectSliceMarshaler::destroy()
-{
- vector<MarshalerPtr> members = _members;
- _members.clear();
- for(vector<MarshalerPtr>::iterator p = members.begin(); p != members.end(); ++p)
- {
- (*p)->destroy();
- }
-}
-
-//
-// ObjectWriter implementation.
-//
-IcePHP::ObjectWriter::ObjectWriter(zval* value, const Slice::SyntaxTreeBasePtr& type, ObjectMap& m TSRMLS_DC) :
- _value(value), _map(m)
-{
-#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
-// Strange Sun C++ 5.3 bug.
- const IceUtil::HandleBase<Slice::SyntaxTreeBase>& hb = type;
- _type = Slice::ClassDefPtr::dynamicCast(hb);
-#else
- _type = Slice::ClassDefPtr::dynamicCast(type);
-#endif
-
-#ifdef ZTS
- this->TSRMLS_C = TSRMLS_C;
-#endif
-
- Z_OBJ_HT_P(_value)->add_ref(_value TSRMLS_CC);
-}
-
-IcePHP::ObjectWriter::~ObjectWriter()
-{
- Z_OBJ_HT_P(_value)->del_ref(_value TSRMLS_CC);
-}
-
-void
-IcePHP::ObjectWriter::ice_preMarshal()
-{
- zend_call_method_with_0_params(&_value, 0, 0, "ice_preMarshal", 0);
-}
-
-void
-IcePHP::ObjectWriter::write(const Ice::OutputStreamPtr& os) const
-{
- MarshalerMap* marshalerMap = static_cast<MarshalerMap*>(ICE_G(marshalerMap));
- ObjectMap& objectMap = const_cast<ObjectMap&>(_map);
- zval* value = const_cast<zval*>(_value);
-
- Slice::ClassDefPtr def = _type;
- while(true)
- {
- string scoped = def->scoped();
- MarshalerPtr slice;
- MarshalerMap::iterator p = marshalerMap->find(scoped);
- if(p != marshalerMap->end())
- {
- slice = p->second;
- }
- else
- {
- slice = new ObjectSliceMarshaler(scoped, def->dataMembers() TSRMLS_CC);
- marshalerMap->insert(pair<string, MarshalerPtr>(scoped, slice));
- }
-
- if(!slice->marshal(value, os, objectMap TSRMLS_CC))
- {
- Ice::MarshalException ex(__FILE__, __LINE__);
- ex.reason = "unable to marshal object slice of type " + scoped;
- throw ex;
- }
-
- Slice::ClassList bases = def->bases();
- if(!bases.empty() && !bases.front()->isInterface())
- {
- def = bases.front();
- }
- else
- {
- break;
- }
- }
-
- //
- // Marshal the Ice::Object slice.
- //
- MarshalerPtr slice;
- MarshalerMap::iterator p = marshalerMap->find(Ice::Object::ice_staticId());
- if(p != marshalerMap->end())
- {
- slice = p->second;
- }
- else
- {
- slice = new IceObjectSliceMarshaler(TSRMLS_C);
- marshalerMap->insert(pair<string, MarshalerPtr>(Ice::Object::ice_staticId(), slice));
- }
-
- if(!slice->marshal(value, os, objectMap TSRMLS_CC))
- {
- Ice::MarshalException ex(__FILE__, __LINE__);
- ex.reason = "unable to marshal object slice of type Ice::Object";
- throw ex;
- }
-}
-
-//
-// ReadObjectCallback implementation.
-//
-void
-IcePHP::ReadObjectCallback::invoke(const Ice::ObjectPtr& v)
-{
- ObjectReaderPtr p = ObjectReaderPtr::dynamicCast(v);
- if(p)
- {
- p->setValue(ce, scoped, zv);
- }
- else
- {
- ZVAL_NULL(zv);
- }
-}
-
-//
-// ObjectReader implementation.
-//
-IcePHP::ObjectReader::ObjectReader(zval* val, const Slice::ClassDefPtr& type TSRMLS_DC) :
- _value(val), _type(type)
-{
-#ifdef ZTS
- this->TSRMLS_C = TSRMLS_C;
-#endif
-
- ZVAL_ADDREF(_value);
-
- _class = Z_OBJCE_P(_value);
-}
-
-IcePHP::ObjectReader::~ObjectReader()
-{
- zval_ptr_dtor(&_value);
-}
-
-void
-IcePHP::ObjectReader::ice_postUnmarshal()
-{
- zend_call_method_with_0_params(&_value, 0, 0, "ice_postUnmarshal", 0);
-}
-
-void
-IcePHP::ObjectReader::read(const Ice::InputStreamPtr& is, bool rid)
-{
- MarshalerMap* marshalerMap = static_cast<MarshalerMap*>(ICE_G(marshalerMap));
-
- //
- // Unmarshal the slices of a user-defined class.
- //
- if(_type)
- {
- Slice::ClassDefPtr def = _type;
- while(true)
- {
- string scoped;
- if(rid)
- {
- scoped = is->readTypeId();
- }
- else
- {
- scoped = def->scoped();
- }
-
- MarshalerPtr slice;
- MarshalerMap::iterator p = marshalerMap->find(scoped);
- if(p != marshalerMap->end())
- {
- slice = p->second;
- }
- else
- {
- slice = new ObjectSliceMarshaler(scoped, def->dataMembers() TSRMLS_CC);
- marshalerMap->insert(pair<string, MarshalerPtr>(scoped, slice));
- }
-
- if(!slice->unmarshal(_value, is TSRMLS_CC))
- {
- Ice::MarshalException ex(__FILE__, __LINE__);
- ex.reason = "unable to unmarshal object slice of type " + scoped;
- throw ex;
- }
-
- rid = true;
-
- Slice::ClassList bases = def->bases();
- if(!bases.empty() && !bases.front()->isInterface())
- {
- def = bases.front();
- }
- else
- {
- break;
- }
- }
- }
-
- //
- // Unmarshal the Ice::Object slice.
- //
- if(rid)
- {
- is->readTypeId();
- }
-
- MarshalerPtr slice;
- MarshalerMap::iterator p = marshalerMap->find(Ice::Object::ice_staticId());
- if(p != marshalerMap->end())
- {
- slice = p->second;
- }
- else
- {
- slice = new IceObjectSliceMarshaler(TSRMLS_C);
- marshalerMap->insert(pair<string, MarshalerPtr>(Ice::Object::ice_staticId(), slice));
- }
-
- if(!slice->unmarshal(_value, is TSRMLS_CC))
- {
- Ice::MarshalException ex(__FILE__, __LINE__);
- ex.reason = "unable to unmarshal object slice of type Ice::Object";
- throw ex;
- }
-}
-
-void
-IcePHP::ObjectReader::setValue(zend_class_entry* ce, const string& scoped, zval* zv)
-{
- //
- // Compare the class entries. The argument "ce" represents the formal type.
- //
- if(!checkClass(_class, ce))
- {
- Ice::UnexpectedObjectException ex(__FILE__, __LINE__);
- ex.type = _type ? _type->scoped() : "::Ice::Object";
- ex.expectedType = scoped;
- throw ex;
- }
-
- //
- // Now both zvals have the same object handle (they point at the same object). We need to
- // increment the object's reference count accordingly.
- //
- Z_TYPE_P(zv) = IS_OBJECT;
- zv->value.obj = _value->value.obj;
- Z_OBJ_HT_P(_value)->add_ref(_value TSRMLS_CC);
-}
-
-//
-// ObjectMarshaler implementation.
-//
-IcePHP::ObjectMarshaler::ObjectMarshaler(const Slice::ClassDefPtr& def TSRMLS_DC) :
- _def(def)
-{
- //
- // Find the class entry for this type.
- //
- if(def)
- {
- _scoped = def->scoped();
- _class = findClassScoped(_scoped TSRMLS_CC);
- }
- else
- {
- _scoped = "::Ice::Object";
- _class = findClass("Ice_Object" TSRMLS_CC);
- }
-
- assert(_class);
-}
-
-bool
-IcePHP::ObjectMarshaler::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap& m TSRMLS_DC)
-{
- if(Z_TYPE_P(zv) == IS_NULL)
- {
- os->writeObject(0);
- return true;
- }
-
- if(Z_TYPE_P(zv) != IS_OBJECT)
- {
- string s = zendTypeToString(Z_TYPE_P(zv));
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected object value of type %s but received %s", _class->name,
- s.c_str());
- return false;
- }
-
- //
- // Verify that the given object is compatible with the formal type.
- //
- zend_class_entry* ce = Z_OBJCE_P(zv);
- if(!checkClass(ce, _class))
- {
- php_error_docref(0 TSRMLS_CC, E_ERROR, "expected object value of type %s but received %s", _class->name,
- ce->name);
- return false;
- }
-
- //
- // ObjectWriter is a subclass of Ice::Object that wraps a PHP object for marshaling. It is
- // possible that this PHP object has already been marshaled, therefore we first must check
- // the object map to see if this object is present. If so, we use the existing ObjectWriter,
- // otherwise we create a new one. The key of the map is the object's handle.
- //
- Ice::ObjectPtr writer;
-
- ObjectMap::iterator q = m.find(Z_OBJ_HANDLE_P(zv));
- if(q == m.end())
- {
- //
- // Determine the most-derived Slice type implemented by this object by scanning its
- // inheritance hierarchy until we find a class or interface that we recognize.
- //
- Profile* profile = static_cast<Profile*>(ICE_G(profile));
- assert(profile);
- zend_class_entry* cls = ce;
- const Profile::ClassMap& classes = profile->classes();
- Profile::ClassMap::const_iterator p = classes.find(cls->name);
- while(p == classes.end())
- {
- if(cls->parent)
- {
- p = classes.find(cls->parent->name);
- }
- for(zend_uint i = 0; i < cls->num_interfaces && p == classes.end(); ++i)
- {
- p = classes.find(cls->interfaces[i]->name);
- }
- cls = cls->parent;
- }
- assert(p != classes.end());
-
- writer = new ObjectWriter(zv, p->second, m TSRMLS_CC);
- m.insert(pair<unsigned int, Ice::ObjectPtr>(Z_OBJ_HANDLE_P(zv), writer));
- }
- else
- {
- writer = q->second;
- }
-
- //
- // Give the writer to the stream. The stream will eventually call write() on it.
- //
- os->writeObject(writer);
-
- return true;
-}
-
-bool
-IcePHP::ObjectMarshaler::unmarshal(zval* zv, const Ice::InputStreamPtr& is TSRMLS_DC)
-{
- ReadObjectCallbackPtr cb = new ReadObjectCallback;
- cb->ce = _class;
- cb->scoped = _scoped;
- cb->zv = zv;
-
- //
- // Invoke readObject(), passing our callback object. When the object is eventually unmarshaled,
- // our callback will be invoked and we will assign a value to zv.
- //
- is->readObject(cb);
-
- return true;
-}
-
-void
-IcePHP::ObjectMarshaler::destroy()
-{
-}
-
-//
-// PHPObjectFactory implementation.
-//
-IcePHP::PHPObjectFactory::PHPObjectFactory(TSRMLS_D)
-{
-#ifdef ZTS
- this->TSRMLS_C = TSRMLS_C;
-#endif
-}
-
-Ice::ObjectPtr
-IcePHP::PHPObjectFactory::create(const string& scoped)
-{
- Profile* profile = static_cast<Profile*>(ICE_G(profile));
- assert(profile);
-
- ObjectFactoryMap* ofm = static_cast<ObjectFactoryMap*>(ICE_G(objectFactoryMap));
- assert(ofm);
-
- //
- // We can only unmarshal an object if we have the definition of its Slice type.
- //
- const Profile::ClassMap& classes = profile->classes();
- Profile::ClassMap::const_iterator p = classes.find(flatten(scoped));
- Slice::ClassDefPtr def;
- if(p != classes.end())
- {
- def = p->second;
- }
- else
- {
- return 0;
- }
-
- //
- // First check our map for a factory registered for this type.
- //
- ObjectFactoryMap::iterator q = ofm->find(scoped);
- if(q == ofm->end())
- {
- //
- // Next, check for a default factory.
- //
- q = ofm->find("");
- }
-
- //
- // If we found a factory, invoke create() on the object.
- //
- if(q != ofm->end())
- {
- zval* id;
- MAKE_STD_ZVAL(id);
- ZVAL_STRINGL(id, const_cast<char*>(scoped.c_str()), scoped.length(), 1);
-
- zval* zresult = 0;
-
- zend_call_method_with_1_params(&q->second, 0, 0, "create", &zresult, id);
-
- zval_ptr_dtor(&id);
-
- AutoDestroy destroyResult(zresult);
-
- //
- // Bail out if an exception has already been thrown.
- //
- if(EG(exception))
- {
- throw AbortMarshaling();
- }
-
- if(zresult)
- {
- //
- // If the factory returned a non-null value, verify that it is an object, and that it
- // implements Ice_Object.
- //
- if(!ZVAL_IS_NULL(zresult))
- {
- if(Z_TYPE_P(zresult) != IS_OBJECT)
- {
- Ice::MarshalException ex(__FILE__, __LINE__);
- ex.reason = "object factory did not return an object for type " + scoped;
- throw ex;
- }
-
- zend_class_entry* ce = Z_OBJCE_P(zresult);
- zend_class_entry* base = findClass("Ice_Object" TSRMLS_CC);
- if(!checkClass(ce, base))
- {
- Ice::MarshalException ex(__FILE__, __LINE__);
- ex.reason = "object returned by factory does not implement Ice_Object";
- throw ex;
- }
-
- return new ObjectReader(zresult, def TSRMLS_CC);
- }
- }
- }
-
- //
- // Attempt to find a class entry for the given type id. If no class entry is
- // found, or the class is abstract, then we return nil and the stream will skip
- // the slice and try again.
- //
- zend_class_entry* cls = findClassScoped(scoped TSRMLS_CC);
-
- //
- // Instantiate the class if it's not abstract.
- //
- Ice::ObjectPtr result;
- const int abstractFlags = ZEND_ACC_INTERFACE | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
- if(cls && (cls->ce_flags & abstractFlags) == 0)
- {
- zval* obj;
- MAKE_STD_ZVAL(obj);
- object_init_ex(obj, cls);
- result = new ObjectReader(obj, def TSRMLS_CC);
- zval_ptr_dtor(&obj);
- }
-
- return result;
-}
-
-void
-IcePHP::PHPObjectFactory::destroy()
-{
-}