// // Copyright (c) ZeroC, Inc. All rights reserved. // namespace Ice { using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using Protocol = IceInternal.Protocol; /// /// Interface for output streams used to write Slice types to a sequence /// of bytes. /// public class OutputStream { /// /// 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(). /// public OutputStream() { _buf = new IceInternal.Buffer(); _instance = null; _closure = null; _encoding = Util.currentEncoding; _format = FormatType.CompactFormat; } /// /// This constructor uses the communicator's default encoding version. /// /// The communicator to use when initializing the stream. public OutputStream(Communicator communicator) { Debug.Assert(communicator != null); IceInternal.Instance instance = IceInternal.Util.getInstance(communicator); initialize(instance, instance.defaultsAndOverrides().defaultEncoding); } /// /// This constructor uses the given communicator and encoding version. /// /// The communicator to use when initializing the stream. /// The desired encoding version. 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); } /// /// Initializes the stream to use the communicator's default encoding version and class /// encoding format. /// /// The communicator to use when initializing the stream. public void initialize(Communicator communicator) { Debug.Assert(communicator != null); IceInternal.Instance instance = IceInternal.Util.getInstance(communicator); initialize(instance, instance.defaultsAndOverrides().defaultEncoding); } /// /// Initializes the stream to use the given encoding version and the communicator's /// default class encoding format. /// /// The communicator to use when initializing the stream. /// The desired encoding version. 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; } /// /// Resets this output stream. This method allows the stream to be reused, to avoid creating /// unnecessary garbage. /// public void reset() { _buf.reset(); clear(); } /// /// Releases any data retained by encapsulations. The reset() method internally calls clear(). /// 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; } /// /// Sets the encoding format for class and exception instances. /// /// The encoding format. public void setFormat(FormatType fmt) { _format = fmt; } /// /// Retrieves the closure object associated with this stream. /// /// The closure object. public object getClosure() { return _closure; } /// /// Associates a closure object with this stream. /// /// The new closure object. /// The previous closure object, or null. public object setClosure(object p) { object prev = _closure; _closure = p; return prev; } /// /// Indicates that the marshaling of a request or reply is finished. /// /// The byte sequence containing the encoded request or reply. public byte[] finished() { IceInternal.Buffer buf = prepareWrite(); byte[] result = new byte[buf.b.limit()]; buf.b.get(result); return result; } /// /// Swaps the contents of one stream with another. /// /// The other stream. 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; } /// /// Resizes the stream to a new size. /// /// The new size. public void resize(int sz) { _buf.resize(sz, false); _buf.b.position(sz); } /// /// Prepares the internal data buffer to be written to a socket. /// public IceInternal.Buffer prepareWrite() { _buf.b.limit(_buf.size()); _buf.b.position(0); return _buf; } /// /// Retrieves the internal data buffer. /// /// The buffer. public IceInternal.Buffer getBuffer() { return _buf; } /// /// Marks the start of a class instance. /// /// Preserved slices for this instance, or null. public void startValue(SlicedData data) { Debug.Assert(_encapsStack != null && _encapsStack.encoder != null); _encapsStack.encoder.startInstance(SliceType.ValueSlice, data); } /// /// Marks the end of a class instance. /// public void endValue() { Debug.Assert(_encapsStack != null && _encapsStack.encoder != null); _encapsStack.encoder.endInstance(); } /// /// Marks the start of a user exception. /// /// Preserved slices for this exception, or null. public void startException(SlicedData data) { Debug.Assert(_encapsStack != null && _encapsStack.encoder != null); _encapsStack.encoder.startInstance(SliceType.ExceptionSlice, data); } /// /// Marks the end of a user exception. /// public void endException() { Debug.Assert(_encapsStack != null && _encapsStack.encoder != null); _encapsStack.encoder.endInstance(); } /// /// Writes the start of an encapsulation to the stream. /// 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, FormatType.DefaultFormat); } } /// /// Writes the start of an encapsulation to the stream. /// /// The encoding version of the encapsulation. /// Specify the compact or sliced format. public void startEncapsulation(EncodingVersion encoding, 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.ice_writeMembers(this); } /// /// Ends the previous encapsulation. /// 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(); } /// /// Writes an empty encapsulation using the given encoding version. /// /// The encoding version of the encapsulation. public void writeEmptyEncapsulation(EncodingVersion encoding) { Protocol.checkSupportedEncoding(encoding); writeInt(6); // Size encoding.ice_writeMembers(this); } /// /// Writes a pre-encoded encapsulation. /// /// The encapsulation data. public void writeEncapsulation(byte[] v) { if(v.Length < 6) { throw new EncapsulationException(); } expand(v.Length); _buf.b.put(v); } /// /// Determines the current encoding version. /// /// The encoding version. public EncodingVersion getEncoding() { return _encapsStack != null ? _encapsStack.encoding : _encoding; } /// /// Marks the start of a new slice for a class instance or user exception. /// /// The Slice type ID corresponding to this slice. /// The Slice compact type ID corresponding to this slice or -1 if no compact ID /// is defined for the type ID. /// True if this is the last slice, false otherwise. public void startSlice(string typeId, int compactId, bool last) { Debug.Assert(_encapsStack != null && _encapsStack.encoder != null); _encapsStack.encoder.startSlice(typeId, compactId, last); } /// /// Marks the end of a slice for a class instance or user exception. /// public void endSlice() { Debug.Assert(_encapsStack != null && _encapsStack.encoder != null); _encapsStack.encoder.endSlice(); } /// /// Writes the state of Slice classes whose index was previously written with writeValue() to the stream. /// public void writePendingValues() { if(_encapsStack != null && _encapsStack.encoder != null) { _encapsStack.encoder.writePendingValues(); } else if(_encapsStack != null ? _encapsStack.encoding_1_0 : _encoding.Equals(Util.Encoding_1_0)) { // // If using the 1.0 encoding and no instances were written, we // still write an empty sequence for pending instances if // requested (i.e.: if this is called). // // This is required by the 1.0 encoding, even if no instances // are written we do marshal an empty sequence if marshaled // data types use classes. // writeSize(0); } } /// /// Writes a size to the stream. /// /// The size to write. public void writeSize(int v) { if(v > 254) { expand(5); _buf.b.put(255); _buf.b.putInt(v); } else { expand(1); _buf.b.put((byte)v); } } /// /// Returns the current position and allocates four bytes for a fixed-length (32-bit) size value. /// public int startSize() { int pos = _buf.b.position(); writeInt(0); // Placeholder for 32-bit size return pos; } /// /// Computes the amount of data written since the previous call to startSize and writes that value /// at the saved position. /// /// The saved position. public void endSize(int pos) { Debug.Assert(pos >= 0); rewriteInt(_buf.b.position() - pos - 4, pos); } /// /// Writes a blob of bytes to the stream. /// /// The byte array to be written. All of the bytes in the array are written. public void writeBlob(byte[] v) { if(v == null) { return; } expand(v.Length); _buf.b.put(v); } /// /// Writes a blob of bytes to the stream. /// /// The byte array to be written. All of the bytes in the array are written. /// The offset into the byte array from which to copy. /// The number of bytes from the byte array to copy. public void writeBlob(byte[] v, int off, int len) { if(v == null) { return; } expand(len); _buf.b.put(v, off, len); } /// /// Write the header information for an optional value. /// /// The numeric tag associated with the value. /// The optional format of the value. public bool writeOptional(int tag, OptionalFormat format) { Debug.Assert(_encapsStack != null); if(_encapsStack.encoder != null) { return _encapsStack.encoder.writeOptional(tag, format); } else { return writeOptionalImpl(tag, format); } } /// /// Writes a byte to the stream. /// /// The byte to write to the stream. public void writeByte(byte v) { expand(1); _buf.b.put(v); } /// /// Writes an optional byte to the stream. /// /// The optional tag. /// The optional byte to write to the stream. public void writeByte(int tag, Optional v) { if(v.HasValue) { writeByte(tag, v.Value); } } /// /// Writes an optional byte to the stream. /// /// The optional tag. /// The byte to write to the stream. public void writeByte(int tag, byte v) { if(writeOptional(tag, OptionalFormat.F1)) { writeByte(v); } } /// /// Writes a byte to the stream at the given position. The current position of the stream is not modified. /// /// The byte to write to the stream. /// The position at which to store the byte in the buffer. public void rewriteByte(byte v, int dest) { _buf.b.put(dest, v); } /// /// Writes a byte sequence to the stream. /// /// The byte sequence to write to the stream. /// Passing null causes an empty sequence to be written to the stream. public void writeByteSeq(byte[] v) { if(v == null) { writeSize(0); } else { writeSize(v.Length); expand(v.Length); _buf.b.put(v); } } /// /// Writes a byte sequence to the stream. /// /// The number of elements in the sequence. /// An enumerator for the container holding the sequence. public void writeByteSeq(int count, IEnumerable v) { if(count == 0) { writeSize(0); return; } { List value = v as List; if(value != null) { writeByteSeq(value.ToArray()); return; } } { LinkedList value = v as LinkedList; if(value != null) { writeSize(count); expand(count); IEnumerator i = v.GetEnumerator(); while(i.MoveNext()) { _buf.b.put(i.Current); } return; } } { Queue value = v as Queue; if(value != null) { writeByteSeq(value.ToArray()); return; } } { Stack value = v as Stack; if(value != null) { writeByteSeq(value.ToArray()); return; } } writeSize(count); expand(count); foreach(byte b in v) { _buf.b.put(b); } } /// /// Writes an optional byte sequence to the stream. /// /// The optional tag. /// The optional byte sequence to write to the stream. public void writeByteSeq(int tag, Optional v) { if(v.HasValue) { writeByteSeq(tag, v.Value); } } /// /// Writes an optional byte sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the optional byte sequence. public void writeByteSeq(int tag, int count, Optional v) where T : IEnumerable { if(v.HasValue && writeOptional(tag, OptionalFormat.VSize)) { writeByteSeq(count, v.Value); } } /// /// Writes an optional byte sequence to the stream. /// /// The optional tag. /// The byte sequence to write to the stream. public void writeByteSeq(int tag, byte[] v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeByteSeq(v); } } /// /// Writes an optional byte sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the byte sequence. public void writeByteSeq(int tag, int count, IEnumerable v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeByteSeq(count, v); } } /// /// Writes a serializable object to the stream. /// /// The serializable object to write. public void writeSerializable(object o) { if(o == null) { writeSize(0); return; } try { IceInternal.OutputStreamWrapper w = new IceInternal.OutputStreamWrapper(this); IFormatter f = new BinaryFormatter(); #pragma warning disable SYSLIB0011 // Type or member is obsolete f.Serialize(w, o); #pragma warning restore SYSLIB0011 // Type or member is obsolete w.Close(); } catch(System.Exception ex) { throw new MarshalException("cannot serialize object:", ex); } } /// /// Writes a boolean to the stream. /// /// The boolean to write to the stream. public void writeBool(bool v) { expand(1); _buf.b.put(v ? (byte)1 : (byte)0); } /// /// Writes an optional boolean to the stream. /// /// The optional tag. /// The optional boolean to write to the stream. public void writeBool(int tag, Optional v) { if(v.HasValue) { writeBool(tag, v.Value); } } /// /// Writes an optional boolean to the stream. /// /// The optional tag. /// The boolean to write to the stream. public void writeBool(int tag, bool v) { if(writeOptional(tag, OptionalFormat.F1)) { writeBool(v); } } /// /// Writes a boolean to the stream at the given position. The current position of the stream is not modified. /// /// The boolean to write to the stream. /// The position at which to store the boolean in the buffer. public void rewriteBool(bool v, int dest) { _buf.b.put(dest, v ? (byte)1 : (byte)0); } /// /// Writes a boolean sequence to the stream. /// /// The boolean sequence to write to the stream. /// Passing null causes an empty sequence to be written to the stream. public void writeBoolSeq(bool[] v) { if(v == null) { writeSize(0); } else { writeSize(v.Length); expand(v.Length); _buf.b.putBoolSeq(v); } } /// /// Writes a boolean sequence to the stream. /// /// The number of elements in the sequence. /// An enumerator for the container holding the sequence. public void writeBoolSeq(int count, IEnumerable v) { if(count == 0) { writeSize(0); return; } { List value = v as List; if(value != null) { writeBoolSeq(value.ToArray()); return; } } { LinkedList value = v as LinkedList; if(value != null) { writeSize(count); expand(count); IEnumerator i = v.GetEnumerator(); while(i.MoveNext()) { _buf.b.putBool(i.Current); } return; } } { Queue value = v as Queue; if(value != null) { writeBoolSeq(value.ToArray()); return; } } { Stack value = v as Stack; if(value != null) { writeBoolSeq(value.ToArray()); return; } } writeSize(count); expand(count); foreach(bool b in v) { _buf.b.putBool(b); } } /// /// Writes an optional boolean sequence to the stream. /// /// The optional tag. /// The optional boolean sequence to write to the stream. public void writeBoolSeq(int tag, Optional v) { if(v.HasValue) { writeBoolSeq(tag, v.Value); } } /// /// Writes an optional boolean sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the optional boolean sequence. public void writeBoolSeq(int tag, int count, Optional v) where T : IEnumerable { if(v.HasValue && writeOptional(tag, OptionalFormat.VSize)) { writeBoolSeq(count, v.Value); } } /// /// Writes an optional boolean sequence to the stream. /// /// The optional tag. /// The boolean sequence to write to the stream. public void writeBoolSeq(int tag, bool[] v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeBoolSeq(v); } } /// /// Writes an optional boolean sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the boolean sequence. public void writeBoolSeq(int tag, int count, IEnumerable v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeBoolSeq(count, v); } } /// /// Writes a short to the stream. /// /// The short to write to the stream. public void writeShort(short v) { expand(2); _buf.b.putShort(v); } /// /// Writes an optional short to the stream. /// /// The optional tag. /// The optional short to write to the stream. public void writeShort(int tag, Optional v) { if(v.HasValue) { writeShort(tag, v.Value); } } /// /// Writes an optional short to the stream. /// /// The optional tag. /// The short to write to the stream. public void writeShort(int tag, short v) { if(writeOptional(tag, OptionalFormat.F2)) { writeShort(v); } } /// /// Writes a short sequence to the stream. /// /// The short sequence to write to the stream. /// Passing null causes an empty sequence to be written to the stream. public void writeShortSeq(short[] v) { if(v == null) { writeSize(0); } else { writeSize(v.Length); expand(v.Length * 2); _buf.b.putShortSeq(v); } } /// /// Writes a short sequence to the stream. /// /// The number of elements in the sequence. /// An enumerator for the container holding the sequence. public void writeShortSeq(int count, IEnumerable v) { if(count == 0) { writeSize(0); return; } { List value = v as List; if(value != null) { writeShortSeq(value.ToArray()); return; } } { LinkedList value = v as LinkedList; if(value != null) { writeSize(count); expand(count * 2); IEnumerator i = v.GetEnumerator(); while(i.MoveNext()) { _buf.b.putShort(i.Current); } return; } } { Queue value = v as Queue; if(value != null) { writeShortSeq(value.ToArray()); return; } } { Stack value = v as Stack; if(value != null) { writeShortSeq(value.ToArray()); return; } } writeSize(count); expand(count * 2); foreach(short s in v) { _buf.b.putShort(s); } } /// /// Writes an optional short sequence to the stream. /// /// The optional tag. /// The optional short sequence to write to the stream. public void writeShortSeq(int tag, Optional v) { if(v.HasValue) { writeShortSeq(tag, v.Value); } } /// /// Writes an optional short sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the optional short sequence. public void writeShortSeq(int tag, int count, Optional v) where T : IEnumerable { if(v.HasValue && writeOptional(tag, OptionalFormat.VSize)) { writeSize(count == 0 ? 1 : count * 2 + (count > 254 ? 5 : 1)); writeShortSeq(count, v.Value); } } /// /// Writes an optional short sequence to the stream. /// /// The optional tag. /// The short sequence to write to the stream. public void writeShortSeq(int tag, short[] v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || v.Length == 0 ? 1 : v.Length * 2 + (v.Length > 254 ? 5 : 1)); writeShortSeq(v); } } /// /// Writes an optional short sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the short sequence. public void writeShortSeq(int tag, int count, IEnumerable v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || count == 0 ? 1 : count * 2 + (count > 254 ? 5 : 1)); writeShortSeq(count, v); } } /// /// Writes an int to the stream. /// /// The int to write to the stream. public void writeInt(int v) { expand(4); _buf.b.putInt(v); } /// /// Writes an optional int to the stream. /// /// The optional tag. /// The optional int to write to the stream. public void writeInt(int tag, Optional v) { if(v.HasValue) { writeInt(tag, v.Value); } } /// /// Writes an optional int to the stream. /// /// The optional tag. /// The int to write to the stream. public void writeInt(int tag, int v) { if(writeOptional(tag, OptionalFormat.F4)) { writeInt(v); } } /// /// Writes an int to the stream at the given position. The current position of the stream is not modified. /// /// The int to write to the stream. /// The position at which to store the int in the buffer. public void rewriteInt(int v, int dest) { _buf.b.putInt(dest, v); } /// /// Writes an int sequence to the stream. /// /// The int sequence to write to the stream. /// Passing null causes an empty sequence to be written to the stream. public void writeIntSeq(int[] v) { if(v == null) { writeSize(0); } else { writeSize(v.Length); expand(v.Length * 4); _buf.b.putIntSeq(v); } } /// /// Writes an int sequence to the stream. /// /// The number of elements in the sequence. /// An enumerator for the container holding the sequence. public void writeIntSeq(int count, IEnumerable v) { if(count == 0) { writeSize(0); return; } { List value = v as List; if(value != null) { writeIntSeq(value.ToArray()); return; } } { LinkedList value = v as LinkedList; if(value != null) { writeSize(count); expand(count * 4); IEnumerator i = v.GetEnumerator(); while(i.MoveNext()) { _buf.b.putInt(i.Current); } return; } } { Queue value = v as Queue; if(value != null) { writeIntSeq(value.ToArray()); return; } } { Stack value = v as Stack; if(value != null) { writeIntSeq(value.ToArray()); return; } } writeSize(count); expand(count * 4); foreach(int i in v) { _buf.b.putInt(i); } } /// /// Writes an optional int sequence to the stream. /// /// The optional tag. /// The optional int sequence to write to the stream. public void writeIntSeq(int tag, Optional v) { if(v.HasValue) { writeIntSeq(tag, v.Value); } } /// /// Writes an optional int sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the optional byte sequence. public void writeIntSeq(int tag, int count, Optional v) where T : IEnumerable { if(v.HasValue && writeOptional(tag, OptionalFormat.VSize)) { writeSize(count == 0 ? 1 : count * 4 + (count > 254 ? 5 : 1)); writeIntSeq(count, v.Value); } } /// /// Writes an optional int sequence to the stream. /// /// The optional tag. /// The int sequence to write to the stream. public void writeIntSeq(int tag, int[] v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || v.Length == 0 ? 1 : v.Length * 4 + (v.Length > 254 ? 5 : 1)); writeIntSeq(v); } } /// /// Writes an optional int sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the int sequence. public void writeIntSeq(int tag, int count, IEnumerable v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || count == 0 ? 1 : count * 4 + (count > 254 ? 5 : 1)); writeIntSeq(count, v); } } /// /// Writes a long to the stream. /// /// The long to write to the stream. public void writeLong(long v) { expand(8); _buf.b.putLong(v); } /// /// Writes an optional long to the stream. /// /// The optional tag. /// The optional long to write to the stream. public void writeLong(int tag, Optional v) { if(v.HasValue) { writeLong(tag, v.Value); } } /// /// Writes an optional long to the stream. /// /// The optional tag. /// The long to write to the stream. public void writeLong(int tag, long v) { if(writeOptional(tag, OptionalFormat.F8)) { writeLong(v); } } /// /// Writes a long sequence to the stream. /// /// The long sequence to write to the stream. /// Passing null causes an empty sequence to be written to the stream. public void writeLongSeq(long[] v) { if(v == null) { writeSize(0); } else { writeSize(v.Length); expand(v.Length * 8); _buf.b.putLongSeq(v); } } /// /// Writes a long sequence to the stream. /// /// The number of elements in the sequence. /// An enumerator for the container holding the sequence. public void writeLongSeq(int count, IEnumerable v) { if(count == 0) { writeSize(0); return; } { List value = v as List; if(value != null) { writeLongSeq(value.ToArray()); return; } } { LinkedList value = v as LinkedList; if(value != null) { writeSize(count); expand(count * 8); IEnumerator i = v.GetEnumerator(); while(i.MoveNext()) { _buf.b.putLong(i.Current); } return; } } { Queue value = v as Queue; if(value != null) { writeLongSeq(value.ToArray()); return; } } { Stack value = v as Stack; if(value != null) { writeLongSeq(value.ToArray()); return; } } writeSize(count); expand(count * 8); foreach(long l in v) { _buf.b.putLong(l); } } /// /// Writes an optional long sequence to the stream. /// /// The optional tag. /// The optional long sequence to write to the stream. public void writeLongSeq(int tag, Optional v) { if(v.HasValue) { writeLongSeq(tag, v.Value); } } /// /// Writes an optional long sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the optional long sequence. public void writeLongSeq(int tag, int count, Optional v) where T : IEnumerable { if(v.HasValue && writeOptional(tag, OptionalFormat.VSize)) { writeSize(count == 0 ? 1 : count * 8 + (count > 254 ? 5 : 1)); writeLongSeq(count, v.Value); } } /// /// Writes an optional long sequence to the stream. /// /// The optional tag. /// The long sequence to write to the stream. public void writeLongSeq(int tag, long[] v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || v.Length == 0 ? 1 : v.Length * 8 + (v.Length > 254 ? 5 : 1)); writeLongSeq(v); } } /// /// Writes an optional long sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the long sequence. public void writeLongSeq(int tag, int count, IEnumerable v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || count == 0 ? 1 : count * 8 + (count > 254 ? 5 : 1)); writeLongSeq(count, v); } } /// /// Writes a float to the stream. /// /// The float to write to the stream. public void writeFloat(float v) { expand(4); _buf.b.putFloat(v); } /// /// Writes an optional float to the stream. /// /// The optional tag. /// The optional float to write to the stream. public void writeFloat(int tag, Optional v) { if(v.HasValue) { writeFloat(tag, v.Value); } } /// /// Writes an optional float to the stream. /// /// The optional tag. /// The float to write to the stream. public void writeFloat(int tag, float v) { if(writeOptional(tag, OptionalFormat.F4)) { writeFloat(v); } } /// /// Writes a float sequence to the stream. /// /// The float sequence to write to the stream. /// Passing null causes an empty sequence to be written to the stream. public void writeFloatSeq(float[] v) { if(v == null) { writeSize(0); } else { writeSize(v.Length); expand(v.Length * 4); _buf.b.putFloatSeq(v); } } /// /// Writes a float sequence to the stream. /// /// The number of elements in the sequence. /// An enumerator for the container holding the sequence. public void writeFloatSeq(int count, IEnumerable v) { if(count == 0) { writeSize(0); return; } { List value = v as List; if(value != null) { writeFloatSeq(value.ToArray()); return; } } { LinkedList value = v as LinkedList; if(value != null) { writeSize(count); expand(count * 4); IEnumerator i = v.GetEnumerator(); while(i.MoveNext()) { _buf.b.putFloat(i.Current); } return; } } { Queue value = v as Queue; if(value != null) { writeFloatSeq(value.ToArray()); return; } } { Stack value = v as Stack; if(value != null) { writeFloatSeq(value.ToArray()); return; } } writeSize(count); expand(count * 4); foreach(float f in v) { _buf.b.putFloat(f); } } /// /// Writes an optional float sequence to the stream. /// /// The optional tag. /// The optional float sequence to write to the stream. public void writeFloatSeq(int tag, Optional v) { if(v.HasValue) { writeFloatSeq(tag, v.Value); } } /// /// Writes an optional float sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the optional float sequence. public void writeFloatSeq(int tag, int count, Optional v) where T : IEnumerable { if(v.HasValue && writeOptional(tag, OptionalFormat.VSize)) { writeSize(count == 0 ? 1 : count * 4 + (count > 254 ? 5 : 1)); writeFloatSeq(count, v.Value); } } /// /// Writes an optional float sequence to the stream. /// /// The optional tag. /// The float sequence to write to the stream. public void writeFloatSeq(int tag, float[] v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || v.Length == 0 ? 1 : v.Length * 4 + (v.Length > 254 ? 5 : 1)); writeFloatSeq(v); } } /// /// Writes an optional float sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the float sequence. public void writeFloatSeq(int tag, int count, IEnumerable v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || count == 0 ? 1 : count * 4 + (count > 254 ? 5 : 1)); writeFloatSeq(count, v); } } /// /// Writes a double to the stream. /// /// The double to write to the stream. public void writeDouble(double v) { expand(8); _buf.b.putDouble(v); } /// /// Writes an optional double to the stream. /// /// The optional tag. /// The optional double to write to the stream. public void writeDouble(int tag, Optional v) { if(v.HasValue) { writeDouble(tag, v.Value); } } /// /// Writes an optional double to the stream. /// /// The optional tag. /// The double to write to the stream. public void writeDouble(int tag, double v) { if(writeOptional(tag, OptionalFormat.F8)) { writeDouble(v); } } /// /// Writes a double sequence to the stream. /// /// The double sequence to write to the stream. /// Passing null causes an empty sequence to be written to the stream. public void writeDoubleSeq(double[] v) { if(v == null) { writeSize(0); } else { writeSize(v.Length); expand(v.Length * 8); _buf.b.putDoubleSeq(v); } } /// /// Writes a double sequence to the stream. /// /// The number of elements in the sequence. /// An enumerator for the container holding the sequence. public void writeDoubleSeq(int count, IEnumerable v) { if(count == 0) { writeSize(0); return; } { List value = v as List; if(value != null) { writeDoubleSeq(value.ToArray()); return; } } { LinkedList value = v as LinkedList; if(value != null) { writeSize(count); expand(count * 8); IEnumerator i = v.GetEnumerator(); while(i.MoveNext()) { _buf.b.putDouble(i.Current); } return; } } { Queue value = v as Queue; if(value != null) { writeDoubleSeq(value.ToArray()); return; } } { Stack value = v as Stack; if (value != null) { writeDoubleSeq(value.ToArray()); return; } } writeSize(count); expand(count * 8); foreach(double d in v) { _buf.b.putDouble(d); } } /// /// Writes an optional double sequence to the stream. /// /// The optional tag. /// The optional double sequence to write to the stream. public void writeDoubleSeq(int tag, Optional v) { if(v.HasValue) { writeDoubleSeq(tag, v.Value); } } /// /// Writes an optional double sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the optional double sequence. public void writeDoubleSeq(int tag, int count, Optional v) where T : IEnumerable { if(v.HasValue && writeOptional(tag, OptionalFormat.VSize)) { writeSize(count == 0 ? 1 : count * 8 + (count > 254 ? 5 : 1)); writeDoubleSeq(count, v.Value); } } /// /// Writes an optional double sequence to the stream. /// /// The optional tag. /// The double sequence to write to the stream. public void writeDoubleSeq(int tag, double[] v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeSize(v == null || v.Length == 0 ? 1 : v.Length * 8 + (v.Length > 254 ? 5 : 1)); writeDoubleSeq(v); } } /// /// Writes an optional double sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the double sequence. public void writeDoubleSeq(int tag, int count, IEnumerable v) { if(writeOptional(tag, 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); /// /// Writes a string to the stream. /// /// The string to write to the stream. Passing null causes /// an empty string to be written to the stream. 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); } /// /// Writes an optional string to the stream. /// /// The optional tag. /// The optional string to write to the stream. public void writeString(int tag, Optional v) { if(v.HasValue) { writeString(tag, v.Value); } } /// /// Writes an optional string to the stream. /// /// The optional tag. /// The string to write to the stream. public void writeString(int tag, string v) { if(writeOptional(tag, OptionalFormat.VSize)) { writeString(v); } } /// /// Writes a string sequence to the stream. /// /// The string sequence to write to the stream. /// Passing null causes an empty sequence to be written to the stream. 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]); } } } /// /// Writes a string sequence to the stream. /// /// The number of elements in the sequence. /// An enumerator for the container holding the sequence. public void writeStringSeq(int count, IEnumerable v) { writeSize(count); if(count != 0) { foreach(string s in v) { writeString(s); } } } /// /// Writes an optional string sequence to the stream. /// /// The optional tag. /// The optional string sequence to write to the stream. public void writeStringSeq(int tag, Optional v) { if(v.HasValue) { writeStringSeq(tag, v.Value); } } /// /// Writes an optional string sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the optional string sequence. public void writeStringSeq(int tag, int count, Optional v) where T : IEnumerable { if(v.HasValue && writeOptional(tag, OptionalFormat.FSize)) { int pos = startSize(); writeStringSeq(count, v.Value); endSize(pos); } } /// /// Writes an optional string sequence to the stream. /// /// The optional tag. /// The string sequence to write to the stream. public void writeStringSeq(int tag, string[] v) { if(writeOptional(tag, OptionalFormat.FSize)) { int pos = startSize(); writeStringSeq(v); endSize(pos); } } /// /// Writes an optional string sequence to the stream. /// /// The optional tag. /// The number of elements in the sequence. /// An enumerator for the string sequence. public void writeStringSeq(int tag, int count, IEnumerable v) { if(writeOptional(tag, OptionalFormat.FSize)) { int pos = startSize(); writeStringSeq(count, v); endSize(pos); } } /// /// Writes a proxy to the stream. /// /// The proxy to write. public void writeProxy(ObjectPrx v) { if(v != null) { v.iceWrite(this); } else { Identity ident = new Identity(); ident.ice_writeMembers(this); } } /// /// Writes an optional proxy to the stream. /// /// The optional tag. /// The optional proxy to write. public void writeProxy(int tag, Optional v) { if(v.HasValue) { writeProxy(tag, v.Value); } } /// /// Writes an optional proxy to the stream. /// /// The optional tag. /// The proxy to write. public void writeProxy(int tag, ObjectPrx v) { if(writeOptional(tag, OptionalFormat.FSize)) { int pos = startSize(); writeProxy(v); endSize(pos); } } /// /// Writes an enumerated value. /// /// The enumerator. /// The maximum enumerator value in the definition. 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); } } /// /// Writes an optional enumerator to the stream. /// /// The optional tag. /// The enumerator. /// The maximum enumerator value in the definition. public void writeEnum(int tag, int v, int maxValue) { if(writeOptional(tag, OptionalFormat.Size)) { writeEnum(v, maxValue); } } /// /// Writes a class instance to the stream. /// /// The value to write. This method writes the index of an instance; the state of the value is /// written once writePendingValues() is called. public void writeValue(Value v) { initEncaps(); _encapsStack.encoder.writeValue(v); } /// /// Writes an optional class instance to the stream. /// /// The optional tag. /// The optional value to write. public void writeValue(int tag, Optional v) where T : Value { if(v.HasValue) { writeValue(tag, v.Value); } } /// /// Writes an optional class instance to the stream. /// /// The optional tag. /// The value to write. public void writeValue(int tag, Value v) { if(writeOptional(tag, OptionalFormat.Class)) { writeValue(v); } } /// /// Writes a user exception to the stream. /// /// The user exception to write. public void writeException(UserException v) { initEncaps(); _encapsStack.encoder.writeException(v); } private bool writeOptionalImpl(int tag, 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; } /// /// Determines the current position in the stream. /// /// The current position. public int pos() { return _buf.b.position(); } /// /// Sets the current position in the stream. /// /// The new position. public void pos(int n) { _buf.b.position(n); } /// /// Determines the current size of the stream. /// /// The current size. public int size() { return _buf.size(); } /// /// Determines whether the stream is empty. /// /// True if no data has been written yet, false otherwise. public bool isEmpty() { return _buf.empty(); } /// /// Expand the stream to accept more data. /// /// The number of bytes to accommodate in the stream. 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, ValueSlice, ExceptionSlice } abstract private class EncapsEncoder { protected EncapsEncoder(OutputStream stream, Encaps encaps) { _stream = stream; _encaps = encaps; _typeIdIndex = 0; _marshaledMap = new Dictionary(); } internal abstract void writeValue(Value v); internal abstract void writeException(UserException v); internal abstract void startInstance(SliceType type, 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, OptionalFormat format) { return false; } internal virtual void writePendingValues() { } protected int registerTypeId(string typeId) { if(_typeIdMap == null) { _typeIdMap = new Dictionary(); } 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 instance marshaling. protected readonly Dictionary _marshaledMap; // Encapsulation attributes for instance marshaling. private Dictionary _typeIdMap; private int _typeIdIndex; } private sealed class EncapsEncoder10 : EncapsEncoder { internal EncapsEncoder10(OutputStream stream, Encaps encaps) : base(stream, encaps) { _sliceType = SliceType.NoSlice; _valueIdIndex = 0; _toBeMarshaledMap = new Dictionary(); } internal override void writeValue(Value v) { // // Object references are encoded as a negative integer in 1.0. // if(v != null) { _stream.writeInt(-registerValue(v)); } else { _stream.writeInt(0); } } internal override void writeException(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 instances even if some part of // the exception was sliced. // bool usesClasses = v.iceUsesClasses(); _stream.writeBool(usesClasses); v.iceWrite(_stream); if(usesClasses) { writePendingValues(); } } internal override void startInstance(SliceType sliceType, SlicedData sliceData) { _sliceType = sliceType; } internal override void endInstance() { if(_sliceType == SliceType.ValueSlice) { // // Write the Object slice. // startSlice(Value.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 instance 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.ValueSlice) { 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 writePendingValues() { while(_toBeMarshaledMap.Count > 0) { // // Consider the to be marshalled instances as marshalled now, // this is necessary to avoid adding again the "to be // marshalled instances" into _toBeMarshaledMap while writing // instances. // foreach(var e in _toBeMarshaledMap) { _marshaledMap.Add(e.Key, e.Value); } var savedMap = _toBeMarshaledMap; _toBeMarshaledMap = new Dictionary(); _stream.writeSize(savedMap.Count); foreach(var 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.iceWrite(_stream); } } _stream.writeSize(0); // Zero marker indicates end of sequence of sequences of instances. } private int registerValue(Value 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, ++_valueIdIndex); return _valueIdIndex; } // Instance attributes private SliceType _sliceType; // Slice attributes private int _writeSlice; // Position of the slice data members // Encapsulation attributes for instance marshaling. private int _valueIdIndex; private Dictionary _toBeMarshaledMap; } private sealed class EncapsEncoder11 : EncapsEncoder { internal EncapsEncoder11(OutputStream stream, Encaps encaps) : base(stream, encaps) { _current = null; _valueIdIndex = 1; } internal override void writeValue(Value v) { if(v == null) { _stream.writeSize(0); } else if(_current != null && _encaps.format == FormatType.SlicedFormat) { if(_current.indirectionTable == null) { _current.indirectionTable = new List(); _current.indirectionMap = new Dictionary(); } // // If writing an instance within a slice and using the sliced // format, write an index from the instance 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(UserException v) { v.iceWrite(_stream); } internal override void startInstance(SliceType sliceType, 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 = 0; if(_encaps.format == 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(0); // Placeholder for the slice flags // // For instance 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.ValueSlice) { // // Encode the type ID (only in the first slice for the compact // encoding). // if(_encaps.format == 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(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 == FormatType.SlicedFormat); _current.sliceFlags |= Protocol.FLAG_HAS_INDIRECTION_TABLE; // // Write the indirect instance table. // _stream.writeSize(_current.indirectionTable.Count); foreach(var 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, 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(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 instance into the most-derived type // known by the sender. // if(_encaps.format != FormatType.SlicedFormat) { return; } foreach(var 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 instance indirection table. // if(info.instances != null && info.instances.Length > 0) { if(_current.indirectionTable == null) { _current.indirectionTable = new List(); _current.indirectionMap = new Dictionary(); } foreach(var o in info.instances) { _current.indirectionTable.Add(o); } } endSlice(); } } private void writeInstance(Value 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, ++_valueIdIndex); 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.iceWrite(_stream); } private sealed class InstanceData { internal InstanceData(InstanceData previous) { if(previous != null) { previous.next = this; } this.previous = previous; 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 indirectionTable; internal Dictionary indirectionMap; internal InstanceData previous; internal InstanceData next; } private InstanceData _current; private int _valueIdIndex; // The ID of the next instance to marhsal } private sealed class Encaps { internal void reset() { encoder = null; } internal void setEncoding(EncodingVersion encoding) { this.encoding = encoding; encoding_1_0 = encoding.Equals(Util.Encoding_1_0); } internal int start; internal EncodingVersion encoding; internal bool encoding_1_0; internal FormatType format = 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(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 == FormatType.DefaultFormat) { _encapsStack.format = _format; } if(_encapsStack.encoder == null) // Lazy initialization. { if(_encapsStack.encoding_1_0) { _encapsStack.encoder = new EncapsEncoder10(this, _encapsStack); } else { _encapsStack.encoder = new EncapsEncoder11(this, _encapsStack); } } } } /// /// Base class for writing class instances to an output stream. /// public abstract class ValueWriter : Value { /// /// Writes the state of this Slice class instance to an output stream. /// /// The stream to write to. public abstract void write(OutputStream outStream); public override void iceWrite(OutputStream os) { write(os); } public override void iceRead(InputStream istr) { Debug.Assert(false); } } }