summaryrefslogtreecommitdiff
path: root/csharp/src/Ice/OutputStream.cs
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2016-02-18 12:18:46 -0800
committerMark Spruiell <mes@zeroc.com>2016-02-18 12:18:46 -0800
commit0da776d5f307fc007c0ef3340d16387096d9c1c2 (patch)
tree12f56c9eb624010b0a9c04871175a543adf84667 /csharp/src/Ice/OutputStream.cs
parentFixed AMI bug where exception wasn't called if response callback was null, ad... (diff)
downloadice-0da776d5f307fc007c0ef3340d16387096d9c1c2.tar.bz2
ice-0da776d5f307fc007c0ef3340d16387096d9c1c2.tar.xz
ice-0da776d5f307fc007c0ef3340d16387096d9c1c2.zip
ICE-6861 - C# stream changes
Diffstat (limited to 'csharp/src/Ice/OutputStream.cs')
-rw-r--r--csharp/src/Ice/OutputStream.cs2844
1 files changed, 2844 insertions, 0 deletions
diff --git a/csharp/src/Ice/OutputStream.cs b/csharp/src/Ice/OutputStream.cs
new file mode 100644
index 00000000000..54ab4972379
--- /dev/null
+++ b/csharp/src/Ice/OutputStream.cs
@@ -0,0 +1,2844 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2015 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.
+//
+// **********************************************************************
+
+namespace Ice
+{
+
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Reflection;
+#if !COMPACT && !SILVERLIGHT
+ using System.Runtime.Serialization;
+ using System.Runtime.Serialization.Formatters.Binary;
+#endif
+ using System.Threading;
+ using Protocol = IceInternal.Protocol;
+
+ /// <summary>
+ /// Interface for output streams used to write Slice types to a sequence
+ /// of bytes.
+ /// </summary>
+ public class OutputStream
+ {
+
+ /// <summary>
+ /// Constructing an OutputStream without providing a communicator means the stream will
+ /// use the default encoding version and the default format for class encoding.
+ /// You can supply a communicator later by calling initialize().
+ /// </summary>
+ public OutputStream()
+ {
+ _buf = new IceInternal.Buffer();
+ instance_ = null;
+ _closure = null;
+ _encoding = Util.currentEncoding;
+ _format = FormatType.CompactFormat;
+ }
+
+ /// <summary>
+ /// This constructor uses the communicator's default encoding version.
+ /// </summary>
+ /// <param name="communicator">The communicator to use when initializing the stream.</param>
+ public OutputStream(Communicator communicator)
+ {
+ Debug.Assert(communicator != null);
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, instance.defaultsAndOverrides().defaultEncoding);
+ }
+
+ /// <summary>
+ /// This constructor uses the given communicator and encoding version.
+ /// </summary>
+ /// <param name="communicator">The communicator to use when initializing the stream.</param>
+ /// <param name="encoding">The desired encoding version.</param>
+ public OutputStream(Communicator communicator, EncodingVersion encoding)
+ {
+ Debug.Assert(communicator != null);
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, encoding);
+ }
+
+ public OutputStream(IceInternal.Instance instance, EncodingVersion encoding)
+ {
+ initialize(instance, encoding);
+ }
+
+ public OutputStream(IceInternal.Instance instance, EncodingVersion encoding, IceInternal.Buffer buf, bool adopt)
+ {
+ initialize(instance, encoding, new IceInternal.Buffer(buf, adopt));
+ }
+
+ public OutputStream(IceInternal.Instance instance, EncodingVersion encoding, byte[] data)
+ {
+ initialize(instance, encoding);
+ _buf = new IceInternal.Buffer(data);
+ }
+
+ /// <summary>
+ /// Initializes the stream to use the communicator's default encoding version and class
+ /// encoding format.
+ /// </summary>
+ /// <param name="communicator">The communicator to use when initializing the stream.</param>
+ public void initialize(Communicator communicator)
+ {
+ Debug.Assert(communicator != null);
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, instance.defaultsAndOverrides().defaultEncoding);
+ }
+
+ /// <summary>
+ /// Initializes the stream to use the given encoding version and the communicator's
+ /// default class encoding format.
+ /// </summary>
+ /// <param name="communicator">The communicator to use when initializing the stream.</param>
+ /// <param name="encoding">The desired encoding version.</param>
+ public void initialize(Communicator communicator, EncodingVersion encoding)
+ {
+ Debug.Assert(communicator != null);
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, encoding);
+ }
+
+ private void initialize(IceInternal.Instance instance, EncodingVersion encoding)
+ {
+ initialize(instance, encoding, new IceInternal.Buffer());
+ }
+
+ private void initialize(IceInternal.Instance instance, EncodingVersion encoding, IceInternal.Buffer buf)
+ {
+ Debug.Assert(instance != null);
+
+ instance_ = instance;
+ _buf = buf;
+ _closure = null;
+ _encoding = encoding;
+
+ _format = instance_.defaultsAndOverrides().defaultFormat;
+
+ _encapsStack = null;
+ _encapsCache = null;
+ }
+
+ /// <summary>
+ /// Resets this output stream. This method allows the stream to be reused, to avoid creating
+ /// unnecessary garbage.
+ /// </summary>
+ public void reset()
+ {
+ _buf.reset();
+ clear();
+ }
+
+ /// <summary>
+ /// Releases any data retained by encapsulations. The reset() method internally calls clear().
+ /// </summary>
+ public void clear()
+ {
+ if(_encapsStack != null)
+ {
+ Debug.Assert(_encapsStack.next == null);
+ _encapsStack.next = _encapsCache;
+ _encapsCache = _encapsStack;
+ _encapsStack = null;
+ _encapsCache.reset();
+ }
+ }
+
+ public IceInternal.Instance instance()
+ {
+ return instance_;
+ }
+
+ /// <summary>
+ /// Sets the encoding format for class and exception instances.
+ /// </summary>
+ /// <param name="fmt">The encoding format.</param>
+ public void setFormat(FormatType fmt)
+ {
+ _format = fmt;
+ }
+
+ /// <summary>
+ /// Retrieves the closure object associated with this stream.
+ /// </summary>
+ /// <returns>The closure object.</returns>
+ public object getClosure()
+ {
+ return _closure;
+ }
+
+ /// <summary>
+ /// Associates a closure object with this stream.
+ /// </summary>
+ /// <param name="p">The new closure object.</param>
+ /// <returns>The previous closure object, or null.</returns>
+ public object setClosure(object p)
+ {
+ object prev = _closure;
+ _closure = p;
+ return prev;
+ }
+
+ /// <summary>
+ /// Indicates that the marshaling of a request or reply is finished.
+ /// </summary>
+ /// <returns>The byte sequence containing the encoded request or reply.</returns>
+ public byte[] finished()
+ {
+ IceInternal.Buffer buf = prepareWrite();
+ byte[] result = new byte[buf.b.limit()];
+ buf.b.get(result);
+ return result;
+ }
+
+ /// <summary>
+ /// Swaps the contents of one stream with another.
+ /// </summary>
+ /// <param name="other">The other stream.</param>
+ public void swap(OutputStream other)
+ {
+ Debug.Assert(instance_ == other.instance_);
+
+ IceInternal.Buffer tmpBuf = other._buf;
+ other._buf = _buf;
+ _buf = tmpBuf;
+
+ EncodingVersion tmpEncoding = other._encoding;
+ other._encoding = _encoding;
+ _encoding = tmpEncoding;
+
+ object tmpClosure = other._closure;
+ other._closure = _closure;
+ _closure = tmpClosure;
+
+ //
+ // Swap is never called for streams that have encapsulations being written. However,
+ // encapsulations might still be set in case marshalling failed. We just
+ // reset the encapsulations if there are still some set.
+ //
+ resetEncapsulation();
+ other.resetEncapsulation();
+ }
+
+ private void resetEncapsulation()
+ {
+ _encapsStack = null;
+ }
+
+ /// <summary>
+ /// Resizes the stream to a new size.
+ /// </summary>
+ /// <param name="sz">The new size.</param>
+ public void resize(int sz)
+ {
+ _buf.resize(sz, false);
+ _buf.b.position(sz);
+ }
+
+ /// <summary>
+ /// Prepares the internal data buffer to be written to a socket.
+ /// </summary>
+ public IceInternal.Buffer prepareWrite()
+ {
+ _buf.b.limit(_buf.size());
+ _buf.b.position(0);
+ return _buf;
+ }
+
+ /// <summary>
+ /// Retrieves the internal data buffer.
+ /// </summary>
+ /// <returns>The buffer.</returns>
+ public IceInternal.Buffer getBuffer()
+ {
+ return _buf;
+ }
+
+ /// <summary>
+ /// Marks the start of an Ice object.
+ /// </summary>
+ /// <param name="data">Preserved slices for this object, or null.</param>
+ public void startObject(Ice.SlicedData data)
+ {
+ Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.startInstance(SliceType.ObjectSlice, data);
+ }
+
+ /// <summary>
+ /// Marks the end of an Ice object.
+ /// </summary>
+ public void endObject()
+ {
+ Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.endInstance();
+ }
+
+ /// <summary>
+ /// Marks the start of a user exception.
+ /// </summary>
+ /// <param name="data">Preserved slices for this exception, or null.</param>
+ public void startException(Ice.SlicedData data)
+ {
+ Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.startInstance(SliceType.ExceptionSlice, data);
+ }
+
+ /// <summary>
+ /// Marks the end of a user exception.
+ /// </summary>
+ public void endException()
+ {
+ Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.endInstance();
+ }
+
+ /// <summary>
+ /// Writes the start of an encapsulation to the stream.
+ /// </summary>
+ public void startEncapsulation()
+ {
+ //
+ // If no encoding version is specified, use the current write
+ // encapsulation encoding version if there's a current write
+ // encapsulation, otherwise, use the stream encoding version.
+ //
+
+ if(_encapsStack != null)
+ {
+ startEncapsulation(_encapsStack.encoding, _encapsStack.format);
+ }
+ else
+ {
+ startEncapsulation(_encoding, Ice.FormatType.DefaultFormat);
+ }
+ }
+
+ /// <summary>
+ /// Writes the start of an encapsulation to the stream.
+ /// </summary>
+ /// <param name="encoding">The encoding version of the encapsulation.</param>
+ /// <param name="format">Specify the compact or sliced format.</param>
+ public void startEncapsulation(EncodingVersion encoding, Ice.FormatType format)
+ {
+ Protocol.checkSupportedEncoding(encoding);
+
+ Encaps curr = _encapsCache;
+ if(curr != null)
+ {
+ curr.reset();
+ _encapsCache = _encapsCache.next;
+ }
+ else
+ {
+ curr = new Encaps();
+ }
+ curr.next = _encapsStack;
+ _encapsStack = curr;
+
+ _encapsStack.format = format;
+ _encapsStack.setEncoding(encoding);
+ _encapsStack.start = _buf.b.position();
+
+ writeInt(0); // Placeholder for the encapsulation length.
+ _encapsStack.encoding.write__(this);
+ }
+
+ /// <summary>
+ /// Ends the previous encapsulation.
+ /// </summary>
+ public void endEncapsulation()
+ {
+ Debug.Assert(_encapsStack != null);
+
+ // Size includes size and version.
+ int start = _encapsStack.start;
+ int sz = _buf.size() - start;
+ _buf.b.putInt(start, sz);
+
+ Encaps curr = _encapsStack;
+ _encapsStack = curr.next;
+ curr.next = _encapsCache;
+ _encapsCache = curr;
+ _encapsCache.reset();
+ }
+
+ /// <summary>
+ /// Writes an empty encapsulation using the given encoding version.
+ /// </summary>
+ /// <param name="encoding">The encoding version of the encapsulation.</param>
+ public void writeEmptyEncapsulation(EncodingVersion encoding)
+ {
+ Protocol.checkSupportedEncoding(encoding);
+ writeInt(6); // Size
+ encoding.write__(this);
+ }
+
+ /// <summary>
+ /// Writes a pre-encoded encapsulation.
+ /// </summary>
+ /// <param name="v">The encapsulation data.</param>
+ public void writeEncapsulation(byte[] v)
+ {
+ if(v.Length < 6)
+ {
+ throw new EncapsulationException();
+ }
+ expand(v.Length);
+ _buf.b.put(v);
+ }
+
+ /// <summary>
+ /// Determines the current encoding version.
+ /// </summary>
+ /// <returns>The encoding version.</returns>
+ public EncodingVersion getEncoding()
+ {
+ return _encapsStack != null ? _encapsStack.encoding : _encoding;
+ }
+
+ /// <summary>
+ /// Marks the start of a new slice for an Ice object or user exception.
+ /// </summary>
+ /// <param name="typeId">The Slice type ID corresponding to this slice.</param>
+ /// <param name="compactId">The Slice compact type ID corresponding to this slice or -1 if no compact ID
+ /// is defined for the type ID.</param>
+ /// <param name="last">True if this is the last slice, false otherwise.</param>
+ public void startSlice(string typeId, int compactId, bool last)
+ {
+ Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.startSlice(typeId, compactId, last);
+ }
+
+ /// <summary>
+ /// Marks the end of a slice for an Ice object or user exception.
+ /// </summary>
+ public void endSlice()
+ {
+ Debug.Assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.endSlice();
+ }
+
+ /// <summary>
+ /// Writes the state of Slice classes whose index was previously written with writeObject() to the stream.
+ /// </summary>
+ public void writePendingObjects()
+ {
+ if(_encapsStack != null && _encapsStack.encoder != null)
+ {
+ _encapsStack.encoder.writePendingObjects();
+ }
+ else if(_encapsStack != null ?
+ _encapsStack.encoding_1_0 : _encoding.Equals(Ice.Util.Encoding_1_0))
+ {
+ //
+ // If using the 1.0 encoding and no objects were written, we
+ // still write an empty sequence for pending objects if
+ // requested (i.e.: if this is called).
+ //
+ // This is required by the 1.0 encoding, even if no objects
+ // are written we do marshal an empty sequence if marshaled
+ // data types use classes.
+ //
+ writeSize(0);
+ }
+ }
+
+ /// <summary>
+ /// Writes a size to the stream.
+ /// </summary>
+ /// <param name="v">The size to write.</param>
+ public void writeSize(int v)
+ {
+ if(v > 254)
+ {
+ expand(5);
+ _buf.b.put((byte)255);
+ _buf.b.putInt(v);
+ }
+ else
+ {
+ expand(1);
+ _buf.b.put((byte)v);
+ }
+ }
+
+ /// <summary>
+ /// Returns the current position and allocates four bytes for a fixed-length (32-bit) size value.
+ /// </summary>
+ public int startSize()
+ {
+ int pos = _buf.b.position();
+ writeInt(0); // Placeholder for 32-bit size
+ return pos;
+ }
+
+ /// <summary>
+ /// Computes the amount of data written since the previous call to startSize and writes that value
+ /// at the saved position.
+ /// </summary>
+ /// <param name="pos">The saved position.</param>
+ public void endSize(int pos)
+ {
+ Debug.Assert(pos >= 0);
+ rewriteInt(_buf.b.position() - pos - 4, pos);
+ }
+
+ /// <summary>
+ /// Writes a blob of bytes to the stream.
+ /// </summary>
+ /// <param name="v">The byte array to be written. All of the bytes in the array are written.</param>
+ public void writeBlob(byte[] v)
+ {
+ if(v == null)
+ {
+ return;
+ }
+ expand(v.Length);
+ _buf.b.put(v);
+ }
+
+ /// <summary>
+ /// Writes a blob of bytes to the stream.
+ /// </summary>
+ /// <param name="v">The byte array to be written. All of the bytes in the array are written.</param>
+ /// <param name="off">The offset into the byte array from which to copy.</param>
+ /// <param name="len">The number of bytes from the byte array to copy.</param>
+ public void writeBlob(byte[] v, int off, int len)
+ {
+ if(v == null)
+ {
+ return;
+ }
+ expand(len);
+ _buf.b.put(v, off, len);
+ }
+
+ /// <summary>
+ /// Write the header information for an optional value.
+ /// </summary>
+ /// <param name="tag">The numeric tag associated with the value.</param>
+ /// <param name="format">The optional format of the value.</param>
+ public bool writeOptional(int tag, Ice.OptionalFormat format)
+ {
+ Debug.Assert(_encapsStack != null);
+ if(_encapsStack.encoder != null)
+ {
+ return _encapsStack.encoder.writeOptional(tag, format);
+ }
+ else
+ {
+ return writeOptionalImpl(tag, format);
+ }
+ }
+
+ /// <summary>
+ /// Writes a byte to the stream.
+ /// </summary>
+ /// <param name="v">The byte to write to the stream.</param>
+ public void writeByte(byte v)
+ {
+ expand(1);
+ _buf.b.put(v);
+ }
+
+ /// <summary>
+ /// Writes an optional byte to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional byte to write to the stream.</param>
+ public void writeByte(int tag, Ice.Optional<byte> v)
+ {
+ if(v.HasValue)
+ {
+ writeByte(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional byte to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The byte to write to the stream.</param>
+ public void writeByte(int tag, byte v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.F1))
+ {
+ writeByte(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a byte to the stream at the given position. The current position of the stream is not modified.
+ /// </summary>
+ /// <param name="v">The byte to write to the stream.</param>
+ /// <param name="dest">The position at which to store the byte in the buffer.</param>
+ public void rewriteByte(byte v, int dest)
+ {
+ _buf.b.put(dest, v);
+ }
+
+ /// <summary>
+ /// Writes a byte sequence to the stream.
+ /// </summary>
+ /// <param name="v">The byte sequence to write to the stream.
+ /// Passing null causes an empty sequence to be written to the stream.</param>
+ public void writeByteSeq(byte[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.Length);
+ expand(v.Length);
+ _buf.b.put(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a byte sequence to the stream.
+ /// </summary>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the container holding the sequence.</param>
+ public void writeByteSeq(int count, IEnumerable<byte> v)
+ {
+ if(count == 0)
+ {
+ writeSize(0);
+ return;
+ }
+
+ {
+ List<byte> value = v as List<byte>;
+ if(value != null)
+ {
+ writeByteSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ LinkedList<byte> value = v as LinkedList<byte>;
+ if(value != null)
+ {
+ writeSize(count);
+ expand(count);
+ IEnumerator<byte> i = v.GetEnumerator();
+ while(i.MoveNext())
+ {
+ _buf.b.put(i.Current);
+ }
+ return;
+ }
+ }
+
+ {
+ Queue<byte> value = v as Queue<byte>;
+ if(value != null)
+ {
+ writeByteSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ Stack<byte> value = v as Stack<byte>;
+ if(value != null)
+ {
+ writeByteSeq(value.ToArray());
+ return;
+ }
+ }
+
+ writeSize(count);
+ expand(count);
+ foreach(byte b in v)
+ {
+ _buf.b.put(b);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional byte sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional byte sequence to write to the stream.</param>
+ public void writeByteSeq(int tag, Ice.Optional<byte[]> v)
+ {
+ if(v.HasValue)
+ {
+ writeByteSeq(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional byte sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the optional byte sequence.</param>
+ public void writeByteSeq<T>(int tag, int count, Ice.Optional<T> v)
+ where T : IEnumerable<byte>
+ {
+ if(v.HasValue && writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeByteSeq(count, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional byte sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The byte sequence to write to the stream.</param>
+ public void writeByteSeq(int tag, byte[] v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeByteSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional byte sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the byte sequence.</param>
+ public void writeByteSeq(int tag, int count, IEnumerable<byte> v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeByteSeq(count, v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a serializable object to the stream.
+ /// </summary>
+ /// <param name="o">The serializable object to write.</param>
+ public void writeSerializable(object o)
+ {
+#if !COMPACT && !SILVERLIGHT
+ if(o == null)
+ {
+ writeSize(0);
+ return;
+ }
+ try
+ {
+ IceInternal.OutputStreamWrapper w = new IceInternal.OutputStreamWrapper(this);
+ IFormatter f = new BinaryFormatter();
+ f.Serialize(w, o);
+ w.Close();
+ }
+ catch(System.Exception ex)
+ {
+ throw new Ice.MarshalException("cannot serialize object:", ex);
+ }
+#else
+ throw new Ice.MarshalException("serialization not supported");
+#endif
+ }
+
+ /// <summary>
+ /// Writes a boolean to the stream.
+ /// </summary>
+ /// <param name="v">The boolean to write to the stream.</param>
+ public void writeBool(bool v)
+ {
+ expand(1);
+ _buf.b.put(v ? (byte)1 : (byte)0);
+ }
+
+ /// <summary>
+ /// Writes an optional boolean to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional boolean to write to the stream.</param>
+ public void writeBool(int tag, Ice.Optional<bool> v)
+ {
+ if(v.HasValue)
+ {
+ writeBool(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional boolean to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The boolean to write to the stream.</param>
+ public void writeBool(int tag, bool v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.F1))
+ {
+ writeBool(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a boolean to the stream at the given position. The current position of the stream is not modified.
+ /// </summary>
+ /// <param name="v">The boolean to write to the stream.</param>
+ /// <param name="dest">The position at which to store the boolean in the buffer.</param>
+ public void rewriteBool(bool v, int dest)
+ {
+ _buf.b.put(dest, v ? (byte)1 : (byte)0);
+ }
+
+ /// <summary>
+ /// Writes a boolean sequence to the stream.
+ /// </summary>
+ /// <param name="v">The boolean sequence to write to the stream.
+ /// Passing null causes an empty sequence to be written to the stream.</param>
+ public void writeBoolSeq(bool[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.Length);
+ expand(v.Length);
+ _buf.b.putBoolSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a boolean sequence to the stream.
+ /// </summary>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the container holding the sequence.</param>
+ public void writeBoolSeq(int count, IEnumerable<bool> v)
+ {
+ if(count == 0)
+ {
+ writeSize(0);
+ return;
+ }
+
+ {
+ List<bool> value = v as List<bool>;
+ if(value != null)
+ {
+ writeBoolSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ LinkedList<bool> value = v as LinkedList<bool>;
+ if(value != null)
+ {
+ writeSize(count);
+ expand(count);
+ IEnumerator<bool> i = v.GetEnumerator();
+ while(i.MoveNext())
+ {
+ _buf.b.putBool(i.Current);
+ }
+ return;
+ }
+ }
+
+ {
+ Queue<bool> value = v as Queue<bool>;
+ if(value != null)
+ {
+ writeBoolSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ Stack<bool> value = v as Stack<bool>;
+ if(value != null)
+ {
+ writeBoolSeq(value.ToArray());
+ return;
+ }
+ }
+
+ writeSize(count);
+ expand(count);
+ foreach(bool b in v)
+ {
+ _buf.b.putBool(b);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional boolean sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional boolean sequence to write to the stream.</param>
+ public void writeBoolSeq(int tag, Ice.Optional<bool[]> v)
+ {
+ if(v.HasValue)
+ {
+ writeBoolSeq(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional boolean sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the optional boolean sequence.</param>
+ public void writeBoolSeq<T>(int tag, int count, Ice.Optional<T> v)
+ where T : IEnumerable<bool>
+ {
+ if(v.HasValue && writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeBoolSeq(count, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional boolean sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The boolean sequence to write to the stream.</param>
+ public void writeBoolSeq(int tag, bool[] v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeBoolSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional boolean sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the boolean sequence.</param>
+ public void writeBoolSeq(int tag, int count, IEnumerable<bool> v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeBoolSeq(count, v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a short to the stream.
+ /// </summary>
+ /// <param name="v">The short to write to the stream.</param>
+ public void writeShort(short v)
+ {
+ expand(2);
+ _buf.b.putShort(v);
+ }
+
+ /// <summary>
+ /// Writes an optional short to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional short to write to the stream.</param>
+ public void writeShort(int tag, Ice.Optional<short> v)
+ {
+ if(v.HasValue)
+ {
+ writeShort(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional short to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The short to write to the stream.</param>
+ public void writeShort(int tag, short v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.F2))
+ {
+ writeShort(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a short sequence to the stream.
+ /// </summary>
+ /// <param name="v">The short sequence to write to the stream.
+ /// Passing null causes an empty sequence to be written to the stream.</param>
+ public void writeShortSeq(short[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.Length);
+ expand(v.Length * 2);
+ _buf.b.putShortSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a short sequence to the stream.
+ /// </summary>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the container holding the sequence.</param>
+ public void writeShortSeq(int count, IEnumerable<short> v)
+ {
+ if(count == 0)
+ {
+ writeSize(0);
+ return;
+ }
+
+ {
+ List<short> value = v as List<short>;
+ if(value != null)
+ {
+ writeShortSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ LinkedList<short> value = v as LinkedList<short>;
+ if(value != null)
+ {
+ writeSize(count);
+ expand(count * 2);
+ IEnumerator<short> i = v.GetEnumerator();
+ while(i.MoveNext())
+ {
+ _buf.b.putShort(i.Current);
+ }
+ return;
+ }
+ }
+
+ {
+ Queue<short> value = v as Queue<short>;
+ if(value != null)
+ {
+ writeShortSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ Stack<short> value = v as Stack<short>;
+ if(value != null)
+ {
+ writeShortSeq(value.ToArray());
+ return;
+ }
+ }
+
+ writeSize(count);
+ expand(count * 2);
+ foreach(short s in v)
+ {
+ _buf.b.putShort(s);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional short sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional short sequence to write to the stream.</param>
+ public void writeShortSeq(int tag, Ice.Optional<short[]> v)
+ {
+ if(v.HasValue)
+ {
+ writeShortSeq(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional short sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the optional short sequence.</param>
+ public void writeShortSeq<T>(int tag, int count, Ice.Optional<T> v)
+ where T : IEnumerable<short>
+ {
+ if(v.HasValue && writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(count == 0 ? 1 : count * 2 + (count > 254 ? 5 : 1));
+ writeShortSeq(count, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional short sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The short sequence to write to the stream.</param>
+ public void writeShortSeq(int tag, short[] v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.Length == 0 ? 1 : v.Length * 2 + (v.Length > 254 ? 5 : 1));
+ writeShortSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional short sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the short sequence.</param>
+ public void writeShortSeq(int tag, int count, IEnumerable<short> v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || count == 0 ? 1 : count * 2 + (count > 254 ? 5 : 1));
+ writeShortSeq(count, v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an int to the stream.
+ /// </summary>
+ /// <param name="v">The int to write to the stream.</param>
+ public void writeInt(int v)
+ {
+ expand(4);
+ _buf.b.putInt(v);
+ }
+
+ /// <summary>
+ /// Writes an optional int to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional int to write to the stream.</param>
+ public void writeInt(int tag, Ice.Optional<int> v)
+ {
+ if(v.HasValue)
+ {
+ writeInt(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional int to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The int to write to the stream.</param>
+ public void writeInt(int tag, int v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.F4))
+ {
+ writeInt(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an int to the stream at the given position. The current position of the stream is not modified.
+ /// </summary>
+ /// <param name="v">The int to write to the stream.</param>
+ /// <param name="dest">The position at which to store the int in the buffer.</param>
+ public void rewriteInt(int v, int dest)
+ {
+ _buf.b.putInt(dest, v);
+ }
+
+ /// <summary>
+ /// Writes an int sequence to the stream.
+ /// </summary>
+ /// <param name="v">The int sequence to write to the stream.
+ /// Passing null causes an empty sequence to be written to the stream.</param>
+ public void writeIntSeq(int[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.Length);
+ expand(v.Length * 4);
+ _buf.b.putIntSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an int sequence to the stream.
+ /// </summary>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the container holding the sequence.</param>
+ public void writeIntSeq(int count, IEnumerable<int> v)
+ {
+ if(count == 0)
+ {
+ writeSize(0);
+ return;
+ }
+
+ {
+ List<int> value = v as List<int>;
+ if(value != null)
+ {
+ writeIntSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ LinkedList<int> value = v as LinkedList<int>;
+ if(value != null)
+ {
+ writeSize(count);
+ expand(count * 4);
+ IEnumerator<int> i = v.GetEnumerator();
+ while(i.MoveNext())
+ {
+ _buf.b.putInt(i.Current);
+ }
+ return;
+ }
+ }
+
+ {
+ Queue<int> value = v as Queue<int>;
+ if(value != null)
+ {
+ writeIntSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ Stack<int> value = v as Stack<int>;
+ if(value != null)
+ {
+ writeIntSeq(value.ToArray());
+ return;
+ }
+ }
+
+ writeSize(count);
+ expand(count * 4);
+ foreach(int i in v)
+ {
+ _buf.b.putInt(i);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional int sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional int sequence to write to the stream.</param>
+ public void writeIntSeq(int tag, Ice.Optional<int[]> v)
+ {
+ if(v.HasValue)
+ {
+ writeIntSeq(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional int sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the optional byte sequence.</param>
+ public void writeIntSeq<T>(int tag, int count, Ice.Optional<T> v)
+ where T : IEnumerable<int>
+ {
+ if(v.HasValue && writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(count == 0 ? 1 : count * 4 + (count > 254 ? 5 : 1));
+ writeIntSeq(count, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional int sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The int sequence to write to the stream.</param>
+ public void writeIntSeq(int tag, int[] v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.Length == 0 ? 1 : v.Length * 4 + (v.Length > 254 ? 5 : 1));
+ writeIntSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional int sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the int sequence.</param>
+ public void writeIntSeq(int tag, int count, IEnumerable<int> v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || count == 0 ? 1 : count * 4 + (count > 254 ? 5 : 1));
+ writeIntSeq(count, v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a long to the stream.
+ /// </summary>
+ /// <param name="v">The long to write to the stream.</param>
+ public void writeLong(long v)
+ {
+ expand(8);
+ _buf.b.putLong(v);
+ }
+
+ /// <summary>
+ /// Writes an optional long to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional long to write to the stream.</param>
+ public void writeLong(int tag, Ice.Optional<long> v)
+ {
+ if(v.HasValue)
+ {
+ writeLong(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional long to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The long to write to the stream.</param>
+ public void writeLong(int tag, long v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.F8))
+ {
+ writeLong(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a long sequence to the stream.
+ /// </summary>
+ /// <param name="v">The long sequence to write to the stream.
+ /// Passing null causes an empty sequence to be written to the stream.</param>
+ public void writeLongSeq(long[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.Length);
+ expand(v.Length * 8);
+ _buf.b.putLongSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a long sequence to the stream.
+ /// </summary>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the container holding the sequence.</param>
+ public void writeLongSeq(int count, IEnumerable<long> v)
+ {
+ if(count == 0)
+ {
+ writeSize(0);
+ return;
+ }
+
+ {
+ List<long> value = v as List<long>;
+ if(value != null)
+ {
+ writeLongSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ LinkedList<long> value = v as LinkedList<long>;
+ if(value != null)
+ {
+ writeSize(count);
+ expand(count * 8);
+ IEnumerator<long> i = v.GetEnumerator();
+ while(i.MoveNext())
+ {
+ _buf.b.putLong(i.Current);
+ }
+ return;
+ }
+ }
+
+ {
+ Queue<long> value = v as Queue<long>;
+ if(value != null)
+ {
+ writeLongSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ Stack<long> value = v as Stack<long>;
+ if(value != null)
+ {
+ writeLongSeq(value.ToArray());
+ return;
+ }
+ }
+
+ writeSize(count);
+ expand(count * 8);
+ foreach(long l in v)
+ {
+ _buf.b.putLong(l);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional long sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional long sequence to write to the stream.</param>
+ public void writeLongSeq(int tag, Ice.Optional<long[]> v)
+ {
+ if(v.HasValue)
+ {
+ writeLongSeq(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional long sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the optional long sequence.</param>
+ public void writeLongSeq<T>(int tag, int count, Ice.Optional<T> v)
+ where T : IEnumerable<long>
+ {
+ if(v.HasValue && writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(count == 0 ? 1 : count * 8 + (count > 254 ? 5 : 1));
+ writeLongSeq(count, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional long sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The long sequence to write to the stream.</param>
+ public void writeLongSeq(int tag, long[] v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.Length == 0 ? 1 : v.Length * 8 + (v.Length > 254 ? 5 : 1));
+ writeLongSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional long sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the long sequence.</param>
+ public void writeLongSeq(int tag, int count, IEnumerable<long> v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || count == 0 ? 1 : count * 8 + (count > 254 ? 5 : 1));
+ writeLongSeq(count, v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a float to the stream.
+ /// </summary>
+ /// <param name="v">The float to write to the stream.</param>
+ public void writeFloat(float v)
+ {
+ expand(4);
+ _buf.b.putFloat(v);
+ }
+
+ /// <summary>
+ /// Writes an optional float to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional float to write to the stream.</param>
+ public void writeFloat(int tag, Ice.Optional<float> v)
+ {
+ if(v.HasValue)
+ {
+ writeFloat(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional float to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The float to write to the stream.</param>
+ public void writeFloat(int tag, float v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.F4))
+ {
+ writeFloat(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a float sequence to the stream.
+ /// </summary>
+ /// <param name="v">The float sequence to write to the stream.
+ /// Passing null causes an empty sequence to be written to the stream.</param>
+ public void writeFloatSeq(float[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.Length);
+ expand(v.Length * 4);
+ _buf.b.putFloatSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a float sequence to the stream.
+ /// </summary>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the container holding the sequence.</param>
+ public void writeFloatSeq(int count, IEnumerable<float> v)
+ {
+ if(count == 0)
+ {
+ writeSize(0);
+ return;
+ }
+
+ {
+ List<float> value = v as List<float>;
+ if(value != null)
+ {
+ writeFloatSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ LinkedList<float> value = v as LinkedList<float>;
+ if(value != null)
+ {
+ writeSize(count);
+ expand(count * 4);
+ IEnumerator<float> i = v.GetEnumerator();
+ while(i.MoveNext())
+ {
+ _buf.b.putFloat(i.Current);
+ }
+ return;
+ }
+ }
+
+ {
+ Queue<float> value = v as Queue<float>;
+ if(value != null)
+ {
+ writeFloatSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ Stack<float> value = v as Stack<float>;
+ if(value != null)
+ {
+ writeFloatSeq(value.ToArray());
+ return;
+ }
+ }
+
+ writeSize(count);
+ expand(count * 4);
+ foreach(float f in v)
+ {
+ _buf.b.putFloat(f);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional float sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional float sequence to write to the stream.</param>
+ public void writeFloatSeq(int tag, Ice.Optional<float[]> v)
+ {
+ if(v.HasValue)
+ {
+ writeFloatSeq(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional float sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the optional float sequence.</param>
+ public void writeFloatSeq<T>(int tag, int count, Ice.Optional<T> v)
+ where T : IEnumerable<float>
+ {
+ if(v.HasValue && writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(count == 0 ? 1 : count * 4 + (count > 254 ? 5 : 1));
+ writeFloatSeq(count, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional float sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The float sequence to write to the stream.</param>
+ public void writeFloatSeq(int tag, float[] v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.Length == 0 ? 1 : v.Length * 4 + (v.Length > 254 ? 5 : 1));
+ writeFloatSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional float sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the float sequence.</param>
+ public void writeFloatSeq(int tag, int count, IEnumerable<float> v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || count == 0 ? 1 : count * 4 + (count > 254 ? 5 : 1));
+ writeFloatSeq(count, v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a double to the stream.
+ /// </summary>
+ /// <param name="v">The double to write to the stream.</param>
+ public void writeDouble(double v)
+ {
+ expand(8);
+ _buf.b.putDouble(v);
+ }
+
+ /// <summary>
+ /// Writes an optional double to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional double to write to the stream.</param>
+ public void writeDouble(int tag, Ice.Optional<double> v)
+ {
+ if(v.HasValue)
+ {
+ writeDouble(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional double to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The double to write to the stream.</param>
+ public void writeDouble(int tag, double v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.F8))
+ {
+ writeDouble(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a double sequence to the stream.
+ /// </summary>
+ /// <param name="v">The double sequence to write to the stream.
+ /// Passing null causes an empty sequence to be written to the stream.</param>
+ public void writeDoubleSeq(double[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.Length);
+ expand(v.Length * 8);
+ _buf.b.putDoubleSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a double sequence to the stream.
+ /// </summary>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the container holding the sequence.</param>
+ public void writeDoubleSeq(int count, IEnumerable<double> v)
+ {
+ if(count == 0)
+ {
+ writeSize(0);
+ return;
+ }
+
+ {
+ List<double> value = v as List<double>;
+ if(value != null)
+ {
+ writeDoubleSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ LinkedList<double> value = v as LinkedList<double>;
+ if(value != null)
+ {
+ writeSize(count);
+ expand(count * 8);
+ IEnumerator<double> i = v.GetEnumerator();
+ while(i.MoveNext())
+ {
+ _buf.b.putDouble(i.Current);
+ }
+ return;
+ }
+ }
+
+ {
+ Queue<double> value = v as Queue<double>;
+ if(value != null)
+ {
+ writeDoubleSeq(value.ToArray());
+ return;
+ }
+ }
+
+ {
+ Stack<double> value = v as Stack<double>;
+ if (value != null)
+ {
+ writeDoubleSeq(value.ToArray());
+ return;
+ }
+ }
+
+ writeSize(count);
+ expand(count * 8);
+ foreach(double d in v)
+ {
+ _buf.b.putDouble(d);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional double sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional double sequence to write to the stream.</param>
+ public void writeDoubleSeq(int tag, Ice.Optional<double[]> v)
+ {
+ if(v.HasValue)
+ {
+ writeDoubleSeq(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional double sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the optional double sequence.</param>
+ public void writeDoubleSeq<T>(int tag, int count, Ice.Optional<T> v)
+ where T : IEnumerable<double>
+ {
+ if(v.HasValue && writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(count == 0 ? 1 : count * 8 + (count > 254 ? 5 : 1));
+ writeDoubleSeq(count, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional double sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The double sequence to write to the stream.</param>
+ public void writeDoubleSeq(int tag, double[] v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.Length == 0 ? 1 : v.Length * 8 + (v.Length > 254 ? 5 : 1));
+ writeDoubleSeq(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional double sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the double sequence.</param>
+ public void writeDoubleSeq(int tag, int count, IEnumerable<double> v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeSize(v == null || count == 0 ? 1 : count * 8 + (count > 254 ? 5 : 1));
+ writeDoubleSeq(count, v);
+ }
+ }
+
+ private static System.Text.UTF8Encoding utf8 = new System.Text.UTF8Encoding(false, true);
+
+ /// <summary>
+ /// Writes a string to the stream.
+ /// </summary>
+ /// <param name="v">The string to write to the stream. Passing null causes
+ /// an empty string to be written to the stream.</param>
+ public void writeString(string v)
+ {
+ if(v == null || v.Length == 0)
+ {
+ writeSize(0);
+ return;
+ }
+ byte[] arr = utf8.GetBytes(v);
+ writeSize(arr.Length);
+ expand(arr.Length);
+ _buf.b.put(arr);
+ }
+
+ /// <summary>
+ /// Writes an optional string to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional string to write to the stream.</param>
+ public void writeString(int tag, Ice.Optional<string> v)
+ {
+ if(v.HasValue)
+ {
+ writeString(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional string to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The string to write to the stream.</param>
+ public void writeString(int tag, string v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.VSize))
+ {
+ writeString(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a string sequence to the stream.
+ /// </summary>
+ /// <param name="v">The string sequence to write to the stream.
+ /// Passing null causes an empty sequence to be written to the stream.</param>
+ public void writeStringSeq(string[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.Length);
+ for(int i = 0; i < v.Length; i++)
+ {
+ writeString(v[i]);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Writes a string sequence to the stream.
+ /// </summary>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the container holding the sequence.</param>
+ public void writeStringSeq(int count, IEnumerable<string> v)
+ {
+ writeSize(count);
+ if(count != 0)
+ {
+ foreach(string s in v)
+ {
+ writeString(s);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional string sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional string sequence to write to the stream.</param>
+ public void writeStringSeq(int tag, Ice.Optional<String[]> v)
+ {
+ if(v.HasValue)
+ {
+ writeStringSeq(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional string sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the optional string sequence.</param>
+ public void writeStringSeq<T>(int tag, int count, Ice.Optional<T> v)
+ where T : IEnumerable<string>
+ {
+ if(v.HasValue && writeOptional(tag, Ice.OptionalFormat.FSize))
+ {
+ int pos = startSize();
+ writeStringSeq(count, v.Value);
+ endSize(pos);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional string sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The string sequence to write to the stream.</param>
+ public void writeStringSeq(int tag, string[] v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.FSize))
+ {
+ int pos = startSize();
+ writeStringSeq(v);
+ endSize(pos);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional string sequence to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="count">The number of elements in the sequence.</param>
+ /// <param name="v">An enumerator for the string sequence.</param>
+ public void writeStringSeq(int tag, int count, IEnumerable<string> v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.FSize))
+ {
+ int pos = startSize();
+ writeStringSeq(count, v);
+ endSize(pos);
+ }
+ }
+
+ /// <summary>
+ /// Writes a proxy to the stream.
+ /// </summary>
+ /// <param name="v">The proxy to write.</param>
+ public void writeProxy(Ice.ObjectPrx v)
+ {
+ if(v != null)
+ {
+ v.write__(this);
+ }
+ else
+ {
+ Identity ident = new Identity();
+ ident.write__(this);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional proxy to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional proxy to write.</param>
+ public void writeProxy(int tag, Ice.Optional<Ice.ObjectPrx> v)
+ {
+ if(v.HasValue)
+ {
+ writeProxy(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional proxy to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The proxy to write.</param>
+ public void writeProxy(int tag, Ice.ObjectPrx v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.FSize))
+ {
+ int pos = startSize();
+ writeProxy(v);
+ endSize(pos);
+ }
+ }
+
+ /// <summary>
+ /// Writes an enumerated value.
+ /// </summary>
+ /// <param name="v">The enumerator.</param>
+ /// <param name="maxValue">The maximum enumerator value in the definition.</param>
+ public void writeEnum(int v, int maxValue)
+ {
+ if(isEncoding_1_0())
+ {
+ if(maxValue < 127)
+ {
+ writeByte((byte)v);
+ }
+ else if(maxValue < 32767)
+ {
+ writeShort((short)v);
+ }
+ else
+ {
+ writeInt(v);
+ }
+ }
+ else
+ {
+ writeSize(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional enumerator to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The enumerator.</param>
+ /// <param name="maxValue">The maximum enumerator value in the definition.</param>
+ public void writeEnum(int tag, int v, int maxValue)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.Size))
+ {
+ writeEnum(v, maxValue);
+ }
+ }
+
+ /// <summary>
+ /// Writes a Slice value to the stream.
+ /// </summary>
+ /// <param name="v">The value to write. This method writes the index of an instance; the state of the value is
+ /// written once writePendingObjects() is called.</param>
+ public void writeObject(Ice.Object v)
+ {
+ initEncaps();
+ _encapsStack.encoder.writeObject(v);
+ }
+
+ /// <summary>
+ /// Writes an optional value to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The optional value to write.</param>
+ public void writeObject<T>(int tag, Ice.Optional<T> v)
+ where T : Ice.Object
+ {
+ if(v.HasValue)
+ {
+ writeObject(tag, v.Value);
+ }
+ }
+
+ /// <summary>
+ /// Writes an optional value to the stream.
+ /// </summary>
+ /// <param name="tag">The optional tag.</param>
+ /// <param name="v">The value to write.</param>
+ public void writeObject(int tag, Ice.Object v)
+ {
+ if(writeOptional(tag, Ice.OptionalFormat.Class))
+ {
+ writeObject(v);
+ }
+ }
+
+ /// <summary>
+ /// Writes a user exception to the stream.
+ /// </summary>
+ /// <param name="v">The user exception to write.</param>
+ public void writeException(Ice.UserException v)
+ {
+ initEncaps();
+ _encapsStack.encoder.writeException(v);
+ }
+
+ private bool writeOptionalImpl(int tag, Ice.OptionalFormat format)
+ {
+ if(isEncoding_1_0())
+ {
+ return false; // Optional members aren't supported with the 1.0 encoding.
+ }
+
+ int v = (int)format;
+ if(tag < 30)
+ {
+ v |= tag << 3;
+ writeByte((byte)v);
+ }
+ else
+ {
+ v |= 0x0F0; // tag = 30
+ writeByte((byte)v);
+ writeSize(tag);
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Determines the current position in the stream.
+ /// </summary>
+ /// <returns>The current position.</returns>
+ public int pos()
+ {
+ return _buf.b.position();
+ }
+
+ /// <summary>
+ /// Sets the current position in the stream.
+ /// </summary>
+ /// <param name="n">The new position.</param>
+ public void pos(int n)
+ {
+ _buf.b.position(n);
+ }
+
+ /// <summary>
+ /// Determines the current size of the stream.
+ /// </summary>
+ /// <returns>The current size.</returns>
+ public int size()
+ {
+ return _buf.size();
+ }
+
+ /// <summary>
+ /// Determines whether the stream is empty.
+ /// </summary>
+ /// <returns>True if no data has been written yet, false otherwise.</returns>
+ public bool isEmpty()
+ {
+ return _buf.empty();
+ }
+
+ /// <summary>
+ /// Expand the stream to accept more data.
+ /// </summary>
+ /// <param name="n">The number of bytes to accommodate in the stream.</param>
+ public void expand(int n)
+ {
+ _buf.expand(n);
+ }
+
+ private IceInternal.Instance instance_;
+ private IceInternal.Buffer _buf;
+ private object _closure;
+ private FormatType _format;
+
+ private enum SliceType { NoSlice, ObjectSlice, ExceptionSlice }
+
+ abstract private class EncapsEncoder
+ {
+ protected EncapsEncoder(OutputStream stream, Encaps encaps)
+ {
+ _stream = stream;
+ _encaps = encaps;
+ _typeIdIndex = 0;
+ _marshaledMap = new Dictionary<Ice.Object, int>();
+ }
+
+ internal abstract void writeObject(Ice.Object v);
+ internal abstract void writeException(Ice.UserException v);
+
+ internal abstract void startInstance(SliceType type, Ice.SlicedData data);
+ internal abstract void endInstance();
+ internal abstract void startSlice(string typeId, int compactId, bool last);
+ internal abstract void endSlice();
+
+ internal virtual bool writeOptional(int tag, Ice.OptionalFormat format)
+ {
+ return false;
+ }
+
+ internal virtual void writePendingObjects()
+ {
+ }
+
+ protected int registerTypeId(string typeId)
+ {
+ if(_typeIdMap == null)
+ {
+ _typeIdMap = new Dictionary<string, int>();
+ }
+
+ int p;
+ if(_typeIdMap.TryGetValue(typeId, out p))
+ {
+ return p;
+ }
+ else
+ {
+ _typeIdMap.Add(typeId, ++_typeIdIndex);
+ return -1;
+ }
+ }
+
+ protected readonly OutputStream _stream;
+ protected readonly Encaps _encaps;
+
+ // Encapsulation attributes for object marshalling.
+ protected readonly Dictionary<Ice.Object, int> _marshaledMap;
+
+ // Encapsulation attributes for object marshalling.
+ private Dictionary<string, int> _typeIdMap;
+ private int _typeIdIndex;
+ }
+
+ private sealed class EncapsEncoder10 : EncapsEncoder
+ {
+ internal EncapsEncoder10(OutputStream stream, Encaps encaps) : base(stream, encaps)
+ {
+ _sliceType = SliceType.NoSlice;
+ _objectIdIndex = 0;
+ _toBeMarshaledMap = new Dictionary<Ice.Object, int>();
+ }
+
+ internal override void writeObject(Ice.Object v)
+ {
+ //
+ // Object references are encoded as a negative integer in 1.0.
+ //
+ if(v != null)
+ {
+ _stream.writeInt(-registerObject(v));
+ }
+ else
+ {
+ _stream.writeInt(0);
+ }
+ }
+
+ internal override void writeException(Ice.UserException v)
+ {
+ //
+ // User exception with the 1.0 encoding start with a bool
+ // flag that indicates whether or not the exception uses
+ // classes.
+ //
+ // This allows reading the pending objects even if some part of
+ // the exception was sliced.
+ //
+ bool usesClasses = v.usesClasses__();
+ _stream.writeBool(usesClasses);
+ v.write__(_stream);
+ if(usesClasses)
+ {
+ writePendingObjects();
+ }
+ }
+
+ internal override void startInstance(SliceType sliceType, Ice.SlicedData sliceData)
+ {
+ _sliceType = sliceType;
+ }
+
+ internal override void endInstance()
+ {
+ if(_sliceType == SliceType.ObjectSlice)
+ {
+ //
+ // Write the Object slice.
+ //
+ startSlice(Ice.ObjectImpl.ice_staticId(), -1, true);
+ _stream.writeSize(0); // For compatibility with the old AFM.
+ endSlice();
+ }
+ _sliceType = SliceType.NoSlice;
+ }
+
+ internal override void startSlice(string typeId, int compactId, bool last)
+ {
+ //
+ // For object slices, encode a bool to indicate how the type ID
+ // is encoded and the type ID either as a string or index. For
+ // exception slices, always encode the type ID as a string.
+ //
+ if(_sliceType == SliceType.ObjectSlice)
+ {
+ int index = registerTypeId(typeId);
+ if(index < 0)
+ {
+ _stream.writeBool(false);
+ _stream.writeString(typeId);
+ }
+ else
+ {
+ _stream.writeBool(true);
+ _stream.writeSize(index);
+ }
+ }
+ else
+ {
+ _stream.writeString(typeId);
+ }
+
+ _stream.writeInt(0); // Placeholder for the slice length.
+
+ _writeSlice = _stream.pos();
+ }
+
+ internal override void endSlice()
+ {
+ //
+ // Write the slice length.
+ //
+ int sz = _stream.pos() - _writeSlice + 4;
+ _stream.rewriteInt(sz, _writeSlice - 4);
+ }
+
+ internal override void writePendingObjects()
+ {
+ while(_toBeMarshaledMap.Count > 0)
+ {
+ //
+ // Consider the to be marshalled objects as marshalled now,
+ // this is necessary to avoid adding again the "to be
+ // marshalled objects" into _toBeMarshaledMap while writing
+ // objects.
+ //
+ foreach(KeyValuePair<Ice.Object, int> e in _toBeMarshaledMap)
+ {
+ _marshaledMap.Add(e.Key, e.Value);
+ }
+
+ Dictionary<Ice.Object, int> savedMap = _toBeMarshaledMap;
+ _toBeMarshaledMap = new Dictionary<Ice.Object, int>();
+ _stream.writeSize(savedMap.Count);
+ foreach(KeyValuePair<Ice.Object, int> p in savedMap)
+ {
+ //
+ // Ask the instance to marshal itself. Any new class
+ // instances that are triggered by the classes marshaled
+ // are added to toBeMarshaledMap.
+ //
+ _stream.writeInt(p.Value);
+
+ try
+ {
+ p.Key.ice_preMarshal();
+ }
+ catch(System.Exception ex)
+ {
+ string s = "exception raised by ice_preMarshal:\n" + ex;
+ _stream.instance().initializationData().logger.warning(s);
+ }
+
+ p.Key.write__(_stream);
+ }
+ }
+ _stream.writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
+ }
+
+ private int registerObject(Ice.Object v)
+ {
+ Debug.Assert(v != null);
+
+ //
+ // Look for this instance in the to-be-marshaled map.
+ //
+ int p;
+ if(_toBeMarshaledMap.TryGetValue(v, out p))
+ {
+ return p;
+ }
+
+ //
+ // Didn't find it, try the marshaled map next.
+ //
+ if(_marshaledMap.TryGetValue(v, out p))
+ {
+ return p;
+ }
+
+ //
+ // We haven't seen this instance previously, create a new
+ // index, and insert it into the to-be-marshaled map.
+ //
+ _toBeMarshaledMap.Add(v, ++_objectIdIndex);
+ return _objectIdIndex;
+ }
+
+ // Instance attributes
+ private SliceType _sliceType;
+
+ // Slice attributes
+ private int _writeSlice; // Position of the slice data members
+
+ // Encapsulation attributes for object marshalling.
+ private int _objectIdIndex;
+ private Dictionary<Ice.Object, int> _toBeMarshaledMap;
+ }
+
+ private sealed class EncapsEncoder11 : EncapsEncoder
+ {
+ internal EncapsEncoder11(OutputStream stream, Encaps encaps) : base(stream, encaps)
+ {
+ _current = null;
+ _objectIdIndex = 1;
+ }
+
+ internal override void writeObject(Ice.Object v)
+ {
+ if(v == null)
+ {
+ _stream.writeSize(0);
+ }
+ else if(_current != null && _encaps.format == Ice.FormatType.SlicedFormat)
+ {
+ if(_current.indirectionTable == null)
+ {
+ _current.indirectionTable = new List<Ice.Object>();
+ _current.indirectionMap = new Dictionary<Ice.Object, int>();
+ }
+
+ //
+ // If writing an object within a slice and using the sliced
+ // format, write an index from the object indirection table.
+ //
+ int index;
+ if(!_current.indirectionMap.TryGetValue(v, out index))
+ {
+ _current.indirectionTable.Add(v);
+ int idx = _current.indirectionTable.Count; // Position + 1 (0 is reserved for nil)
+ _current.indirectionMap.Add(v, idx);
+ _stream.writeSize(idx);
+ }
+ else
+ {
+ _stream.writeSize(index);
+ }
+ }
+ else
+ {
+ writeInstance(v); // Write the instance or a reference if already marshaled.
+ }
+ }
+
+ internal override void writeException(Ice.UserException v)
+ {
+ v.write__(_stream);
+ }
+
+ internal override void startInstance(SliceType sliceType, Ice.SlicedData data)
+ {
+ if(_current == null)
+ {
+ _current = new InstanceData(null);
+ }
+ else
+ {
+ _current = _current.next == null ? new InstanceData(_current) : _current.next;
+ }
+ _current.sliceType = sliceType;
+ _current.firstSlice = true;
+
+ if(data != null)
+ {
+ writeSlicedData(data);
+ }
+ }
+
+ internal override void endInstance()
+ {
+ _current = _current.previous;
+ }
+
+ internal override void startSlice(string typeId, int compactId, bool last)
+ {
+ Debug.Assert((_current.indirectionTable == null || _current.indirectionTable.Count == 0) &&
+ (_current.indirectionMap == null || _current.indirectionMap.Count == 0));
+
+ _current.sliceFlagsPos = _stream.pos();
+
+ _current.sliceFlags = (byte)0;
+ if(_encaps.format == Ice.FormatType.SlicedFormat)
+ {
+ //
+ // Encode the slice size if using the sliced format.
+ //
+ _current.sliceFlags |= Protocol.FLAG_HAS_SLICE_SIZE;
+ }
+ if(last)
+ {
+ _current.sliceFlags |= Protocol.FLAG_IS_LAST_SLICE; // This is the last slice.
+ }
+
+ _stream.writeByte((byte)0); // Placeholder for the slice flags
+
+ //
+ // For object slices, encode the flag and the type ID either as a
+ // string or index. For exception slices, always encode the type
+ // ID a string.
+ //
+ if(_current.sliceType == SliceType.ObjectSlice)
+ {
+ //
+ // Encode the type ID (only in the first slice for the compact
+ // encoding).
+ //
+ if(_encaps.format == Ice.FormatType.SlicedFormat || _current.firstSlice)
+ {
+ if(compactId >= 0)
+ {
+ _current.sliceFlags |= Protocol.FLAG_HAS_TYPE_ID_COMPACT;
+ _stream.writeSize(compactId);
+ }
+ else
+ {
+ int index = registerTypeId(typeId);
+ if(index < 0)
+ {
+ _current.sliceFlags |= Protocol.FLAG_HAS_TYPE_ID_STRING;
+ _stream.writeString(typeId);
+ }
+ else
+ {
+ _current.sliceFlags |= Protocol.FLAG_HAS_TYPE_ID_INDEX;
+ _stream.writeSize(index);
+ }
+ }
+ }
+ }
+ else
+ {
+ _stream.writeString(typeId);
+ }
+
+ if((_current.sliceFlags & Protocol.FLAG_HAS_SLICE_SIZE) != 0)
+ {
+ _stream.writeInt(0); // Placeholder for the slice length.
+ }
+
+ _current.writeSlice = _stream.pos();
+ _current.firstSlice = false;
+ }
+
+ internal override void endSlice()
+ {
+ //
+ // Write the optional member end marker if some optional members
+ // were encoded. Note that the optional members are encoded before
+ // the indirection table and are included in the slice size.
+ //
+ if((_current.sliceFlags & Protocol.FLAG_HAS_OPTIONAL_MEMBERS) != 0)
+ {
+ _stream.writeByte((byte)Protocol.OPTIONAL_END_MARKER);
+ }
+
+ //
+ // Write the slice length if necessary.
+ //
+ if((_current.sliceFlags & Protocol.FLAG_HAS_SLICE_SIZE) != 0)
+ {
+ int sz = _stream.pos() - _current.writeSlice + 4;
+ _stream.rewriteInt(sz, _current.writeSlice - 4);
+ }
+
+ //
+ // Only write the indirection table if it contains entries.
+ //
+ if(_current.indirectionTable != null && _current.indirectionTable.Count > 0)
+ {
+ Debug.Assert(_encaps.format == Ice.FormatType.SlicedFormat);
+ _current.sliceFlags |= Protocol.FLAG_HAS_INDIRECTION_TABLE;
+
+ //
+ // Write the indirection object table.
+ //
+ _stream.writeSize(_current.indirectionTable.Count);
+ foreach(Ice.Object v in _current.indirectionTable)
+ {
+ writeInstance(v);
+ }
+ _current.indirectionTable.Clear();
+ _current.indirectionMap.Clear();
+ }
+
+ //
+ // Finally, update the slice flags.
+ //
+ _stream.rewriteByte(_current.sliceFlags, _current.sliceFlagsPos);
+ }
+
+ internal override bool writeOptional(int tag, Ice.OptionalFormat format)
+ {
+ if(_current == null)
+ {
+ return _stream.writeOptionalImpl(tag, format);
+ }
+ else
+ {
+ if(_stream.writeOptionalImpl(tag, format))
+ {
+ _current.sliceFlags |= Protocol.FLAG_HAS_OPTIONAL_MEMBERS;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ private void writeSlicedData(Ice.SlicedData slicedData)
+ {
+ Debug.Assert(slicedData != null);
+
+ //
+ // We only remarshal preserved slices if we are using the sliced
+ // format. Otherwise, we ignore the preserved slices, which
+ // essentially "slices" the object into the most-derived type
+ // known by the sender.
+ //
+ if(_encaps.format != Ice.FormatType.SlicedFormat)
+ {
+ return;
+ }
+
+ foreach(Ice.SliceInfo info in slicedData.slices)
+ {
+ startSlice(info.typeId, info.compactId, info.isLastSlice);
+
+ //
+ // Write the bytes associated with this slice.
+ //
+ _stream.writeBlob(info.bytes);
+
+ if(info.hasOptionalMembers)
+ {
+ _current.sliceFlags |= Protocol.FLAG_HAS_OPTIONAL_MEMBERS;
+ }
+
+ //
+ // Make sure to also re-write the object indirection table.
+ //
+ if(info.objects != null && info.objects.Length > 0)
+ {
+ if(_current.indirectionTable == null)
+ {
+ _current.indirectionTable = new List<Ice.Object>();
+ _current.indirectionMap = new Dictionary<Ice.Object, int>();
+ }
+ foreach(Ice.Object o in info.objects)
+ {
+ _current.indirectionTable.Add(o);
+ }
+ }
+
+ endSlice();
+ }
+ }
+
+ private void writeInstance(Ice.Object v)
+ {
+ Debug.Assert(v != null);
+
+ //
+ // If the instance was already marshaled, just write it's ID.
+ //
+ int p;
+ if(_marshaledMap.TryGetValue(v, out p))
+ {
+ _stream.writeSize(p);
+ return;
+ }
+
+ //
+ // We haven't seen this instance previously, create a new ID,
+ // insert it into the marshaled map, and write the instance.
+ //
+ _marshaledMap.Add(v, ++_objectIdIndex);
+
+ try
+ {
+ v.ice_preMarshal();
+ }
+ catch(System.Exception ex)
+ {
+ string s = "exception raised by ice_preMarshal:\n" + ex;
+ _stream.instance().initializationData().logger.warning(s);
+ }
+
+ _stream.writeSize(1); // Object instance marker.
+ v.write__(_stream);
+ }
+
+ private sealed class InstanceData
+ {
+ internal InstanceData(InstanceData previous)
+ {
+ if(previous != null)
+ {
+ previous.next = this;
+ }
+ this.previous = previous;
+ this.next = null;
+ }
+
+ // Instance attributes
+ internal SliceType sliceType;
+ internal bool firstSlice;
+
+ // Slice attributes
+ internal byte sliceFlags;
+ internal int writeSlice; // Position of the slice data members
+ internal int sliceFlagsPos; // Position of the slice flags
+ internal List<Ice.Object> indirectionTable;
+ internal Dictionary<Ice.Object, int> indirectionMap;
+
+ internal InstanceData previous;
+ internal InstanceData next;
+ }
+
+ private InstanceData _current;
+
+ private int _objectIdIndex; // The ID of the next object to marhsal
+ }
+
+ private sealed class Encaps
+ {
+ internal void reset()
+ {
+ encoder = null;
+ }
+
+ internal void setEncoding(EncodingVersion encoding)
+ {
+ this.encoding = encoding;
+ encoding_1_0 = encoding.Equals(Ice.Util.Encoding_1_0);
+ }
+
+ internal int start;
+ internal EncodingVersion encoding;
+ internal bool encoding_1_0;
+ internal Ice.FormatType format = Ice.FormatType.DefaultFormat;
+
+ internal EncapsEncoder encoder;
+
+ internal Encaps next;
+ }
+
+ //
+ // The encoding version to use when there's no encapsulation to
+ // read from or write to. This is for example used to read message
+ // headers or when the user is using the streaming API with no
+ // encapsulation.
+ //
+ private EncodingVersion _encoding;
+
+ private bool isEncoding_1_0()
+ {
+ return _encapsStack != null ? _encapsStack.encoding_1_0 : _encoding.Equals(Ice.Util.Encoding_1_0);
+ }
+
+ private Encaps _encapsStack;
+ private Encaps _encapsCache;
+
+ private void initEncaps()
+ {
+ if(_encapsStack == null) // Lazy initialization
+ {
+ _encapsStack = _encapsCache;
+ if(_encapsStack != null)
+ {
+ _encapsCache = _encapsCache.next;
+ }
+ else
+ {
+ _encapsStack = new Encaps();
+ }
+ _encapsStack.setEncoding(_encoding);
+ }
+
+ if(_encapsStack.format == Ice.FormatType.DefaultFormat)
+ {
+ _encapsStack.format = instance_.defaultsAndOverrides().defaultFormat;
+ }
+
+ if(_encapsStack.encoder == null) // Lazy initialization.
+ {
+ if(_encapsStack.encoding_1_0)
+ {
+ _encapsStack.encoder = new EncapsEncoder10(this, _encapsStack);
+ }
+ else
+ {
+ _encapsStack.encoder = new EncapsEncoder11(this, _encapsStack);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Base class for writing objects to an output stream.
+ /// </summary>
+ public abstract class ObjectWriter : ObjectImpl
+ {
+ /// <summary>
+ /// Writes the state of this Slice class to an output stream.
+ /// </summary>
+ /// <param name="outStream">The stream to write to.</param>
+ public abstract void write(OutputStream outStream);
+
+ public override void write__(OutputStream os)
+ {
+ write(os);
+ }
+
+ public override void read__(InputStream istr)
+ {
+ Debug.Assert(false);
+ }
+ }
+
+}