com.zeroc.Ice.OutputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ice Show documentation
Show all versions of ice Show documentation
Ice is a comprehensive RPC framework that helps you build distributed applications with minimal effort using familiar object-oriented idioms
//
// Copyright (c) ZeroC, Inc. All rights reserved.
//
package com.zeroc.Ice;
/**
* Interface to marshal (write) Slice types into sequence of bytes encoded using the
* Ice encoding.
*
* @see InputStream
**/
public class OutputStream
{
/**
* Constructing an OutputStream without providing a communicator means the stream will
* use the default encoding version, the default format for class encoding, and a
* non-direct buffer. You can supply a communicator later by calling initialize().
**/
public OutputStream()
{
this(false);
}
/**
* 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().
*
* @param direct Indicates whether to use a direct buffer.
**/
public OutputStream(boolean direct)
{
_buf = new com.zeroc.IceInternal.Buffer(direct);
_instance = null;
_closure = null;
_encoding = com.zeroc.IceInternal.Protocol.currentEncoding;
_format = FormatType.CompactFormat;
}
/**
* This constructor uses the communicator's default encoding version.
*
* @param communicator The communicator to use when initializing the stream.
**/
public OutputStream(Communicator communicator)
{
assert(communicator != null);
final com.zeroc.IceInternal.Instance instance = com.zeroc.IceInternal.Util.getInstance(communicator);
initialize(instance, instance.defaultsAndOverrides().defaultEncoding, instance.cacheMessageBuffers() > 1);
}
/**
* This constructor uses the communicator's default encoding version.
*
* @param communicator The communicator to use when initializing the stream.
* @param direct Indicates whether to use a direct buffer.
**/
public OutputStream(Communicator communicator, boolean direct)
{
assert(communicator != null);
final com.zeroc.IceInternal.Instance instance = com.zeroc.IceInternal.Util.getInstance(communicator);
initialize(instance, instance.defaultsAndOverrides().defaultEncoding, direct);
}
/**
* This constructor uses the given communicator and encoding version.
*
* @param communicator The communicator to use when initializing the stream.
* @param encoding The desired Ice encoding version.
**/
public OutputStream(Communicator communicator, EncodingVersion encoding)
{
assert(communicator != null);
final com.zeroc.IceInternal.Instance instance = com.zeroc.IceInternal.Util.getInstance(communicator);
initialize(instance, encoding, instance.cacheMessageBuffers() > 1);
}
/**
* This constructor uses the given communicator and encoding version.
*
* @param communicator The communicator to use when initializing the stream.
* @param encoding The desired Ice encoding version.
* @param direct Indicates whether to use a direct buffer.
**/
public OutputStream(Communicator communicator, EncodingVersion encoding, boolean direct)
{
assert(communicator != null);
final com.zeroc.IceInternal.Instance instance = com.zeroc.IceInternal.Util.getInstance(communicator);
initialize(instance, encoding, direct);
}
public OutputStream(com.zeroc.IceInternal.Instance instance, EncodingVersion encoding)
{
initialize(instance, encoding, instance.cacheMessageBuffers() > 1);
}
public OutputStream(com.zeroc.IceInternal.Instance instance, EncodingVersion encoding, boolean direct)
{
initialize(instance, encoding, direct);
}
public OutputStream(com.zeroc.IceInternal.Instance instance, EncodingVersion encoding,
com.zeroc.IceInternal.Buffer buf, boolean adopt)
{
initialize(instance, encoding, new com.zeroc.IceInternal.Buffer(buf, adopt));
}
/**
* Initializes the stream to use the communicator's default encoding version and class
* encoding format.
*
* @param communicator The communicator to use when initializing the stream.
**/
public void initialize(Communicator communicator)
{
assert(communicator != null);
final com.zeroc.IceInternal.Instance instance = com.zeroc.IceInternal.Util.getInstance(communicator);
initialize(instance, instance.defaultsAndOverrides().defaultEncoding, instance.cacheMessageBuffers() > 1);
}
/**
* Initializes the stream to use the given encoding version and the communicator's
* default class encoding format.
*
* @param communicator The communicator to use when initializing the stream.
* @param encoding The desired Ice encoding version.
**/
public void initialize(Communicator communicator, EncodingVersion encoding)
{
assert(communicator != null);
final com.zeroc.IceInternal.Instance instance = com.zeroc.IceInternal.Util.getInstance(communicator);
initialize(instance, encoding, instance.cacheMessageBuffers() > 1);
}
private void initialize(com.zeroc.IceInternal.Instance instance, EncodingVersion encoding, boolean direct)
{
initialize(instance, encoding, new com.zeroc.IceInternal.Buffer(direct));
}
private void initialize(com.zeroc.IceInternal.Instance instance, EncodingVersion encoding,
com.zeroc.IceInternal.Buffer buf)
{
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 {@link #reset} method internally calls clear
.
**/
public void clear()
{
if(_encapsStack != null)
{
assert(_encapsStack.next == null);
_encapsStack.next = _encapsCache;
_encapsCache = _encapsStack;
_encapsCache.reset();
_encapsStack = null;
}
}
public com.zeroc.IceInternal.Instance instance()
{
return _instance;
}
/**
* Sets the encoding format for class and exception instances.
*
* @param fmt The encoding format.
**/
public void setFormat(FormatType fmt)
{
_format = fmt;
}
/**
* Retrieves the closure object associated with this stream.
*
* @return The closure object.
**/
public Object getClosure()
{
return _closure;
}
/**
* Associates a closure object with this stream.
*
* @param p The new closure object.
* @return The previous closure object, or null.
**/
public Object setClosure(Object p)
{
Object prev = _closure;
_closure = p;
return prev;
}
/**
* Indicates that marshaling is finished.
*
* @return The byte sequence containing the encoded data.
**/
public byte[] finished()
{
com.zeroc.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.
*
* @param other The other stream.
**/
public void swap(OutputStream other)
{
assert(_instance == other._instance);
com.zeroc.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.
*
* @param sz The new size.
**/
public void resize(int sz)
{
_buf.resize(sz, false);
_buf.position(sz);
}
/**
* Prepares the internal data buffer to be written to a socket.
* @return The internal buffer.
**/
public com.zeroc.IceInternal.Buffer prepareWrite()
{
_buf.limit(_buf.size());
_buf.position(0);
return _buf;
}
/**
* Retrieves the internal data buffer.
*
* @return The buffer.
**/
public com.zeroc.IceInternal.Buffer getBuffer()
{
return _buf;
}
/**
* Marks the start of a class instance.
*
* @param data Preserved slices for this instance, or null.
**/
public void startValue(SlicedData data)
{
assert(_encapsStack != null && _encapsStack.encoder != null);
_encapsStack.encoder.startInstance(SliceType.ValueSlice, data);
}
/**
* Marks the end of a class instance.
**/
public void endValue()
{
assert(_encapsStack != null && _encapsStack.encoder != null);
_encapsStack.encoder.endInstance();
}
/**
* Marks the start of a user exception.
*
* @param data Preserved slices for this exception, or null.
**/
public void startException(SlicedData data)
{
assert(_encapsStack != null && _encapsStack.encoder != null);
_encapsStack.encoder.startInstance(SliceType.ExceptionSlice, data);
}
/**
* Marks the end of a user exception.
**/
public void endException()
{
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.
*
* @param encoding The encoding version of the encapsulation.
*
* @param format Specify the compact or sliced format.
*
**/
public void startEncapsulation(EncodingVersion encoding, FormatType format)
{
com.zeroc.IceInternal.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.size();
writeInt(0); // Placeholder for the encapsulation length.
_encapsStack.encoding.ice_writeMembers(this);
}
/**
* Ends the previous encapsulation.
**/
public void endEncapsulation()
{
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.
*
* @param encoding The desired encoding version.
**/
public void writeEmptyEncapsulation(EncodingVersion encoding)
{
com.zeroc.IceInternal.Protocol.checkSupportedEncoding(encoding);
writeInt(6); // Size
encoding.ice_writeMembers(this);
}
/**
* Writes a pre-encoded encapsulation.
*
* @param v 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.
*
* @return 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.
*
* @param typeId The Slice type ID corresponding to this slice.
*
* @param compactId The Slice compact type ID corresponding to
* this slice or -1 if no compact ID is defined for the
* type ID.
*
* @param last True if this is the last slice, false otherwise.
**/
public void startSlice(String typeId, int compactId, boolean last)
{
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()
{
assert(_encapsStack != null && _encapsStack.encoder != null);
_encapsStack.encoder.endSlice();
}
/**
* Writes the state of Slice classes whose index was previously
* written with {@link #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.
*
* @param v The size to write.
**/
public void writeSize(int v)
{
if(v > 254)
{
expand(5);
_buf.b.put((byte)-1);
_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.
*
* @return The current position.
**/
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.
*
* @param pos The saved position.
**/
public void endSize(int pos)
{
assert(pos >= 0);
rewriteInt(_buf.b.position() - pos - 4, pos);
}
/**
* Writes a blob of bytes to the stream.
*
* @param v 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.
*
* @param v The byte array to be written.
* @param off The offset into the byte array from which to copy.
* @param len 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.
*
* @param tag The numeric tag associated with the value.
* @param format The optional format of the value.
* @return True if the current encoding supports optionals, false otherwise.
**/
public boolean writeOptional(int tag, OptionalFormat format)
{
assert(_encapsStack != null);
if(_encapsStack.encoder != null)
{
return _encapsStack.encoder.writeOptional(tag, format);
}
else
{
return writeOptionalImpl(tag, format);
}
}
/**
* Writes a byte to the stream.
*
* @param v 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.
*
* @param tag The optional tag.
* @param v The optional byte to write to the stream.
**/
public void writeByte(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeByte(tag, v.get());
}
}
/**
* Writes an optional byte to the stream.
*
* @param tag The optional tag.
* @param v 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.
*
* @param v The byte to write to the stream.
* @param dest 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.
*
* @param v 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 an optional byte sequence to the stream.
*
* @param tag The optional tag.
* @param v The optional byte sequence to write to the stream.
**/
public void writeByteSeq(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeByteSeq(tag, v.get());
}
}
/**
* Writes an optional byte sequence to the stream.
*
* @param tag The optional tag.
* @param v The byte sequence to write to the stream.
**/
public void writeByteSeq(int tag, byte[] v)
{
if(writeOptional(tag, OptionalFormat.VSize))
{
writeByteSeq(v);
}
}
/**
* Writes the remaining contents of the byte buffer as a byte sequence to the stream.
*
* @param v The byte buffer to write to the stream.
**/
public void writeByteBuffer(java.nio.ByteBuffer v)
{
if(v == null || v.remaining() == 0)
{
writeSize(0);
}
else
{
writeSize(v.remaining());
expand(v.remaining());
_buf.b.put(v);
}
}
/**
* Writes a serializable Java object to the stream.
*
* @param o The serializable object to write.
**/
public void writeSerializable(java.io.Serializable o)
{
if(o == null)
{
writeSize(0);
return;
}
try
{
com.zeroc.IceInternal.OutputStreamWrapper w = new com.zeroc.IceInternal.OutputStreamWrapper(this);
java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(w);
out.writeObject(o);
out.close();
w.close();
}
catch(java.lang.Exception ex)
{
throw new MarshalException("cannot serialize object: " + ex);
}
}
/**
* Writes an optional serializable Java object to the stream.
*
* @param The serializable class.
* @param tag The optional tag.
* @param v The optional serializable object to write.
**/
public void writeSerializable(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeSerializable(tag, v.get());
}
}
/**
* Writes an optional serializable Java object to the stream.
*
* @param tag The optional tag.
* @param v The serializable object to write.
**/
public void writeSerializable(int tag, java.io.Serializable v)
{
if(writeOptional(tag, OptionalFormat.VSize))
{
writeSerializable(v);
}
}
/**
* Writes a boolean to the stream.
*
* @param v The boolean to write to the stream.
**/
public void writeBool(boolean v)
{
expand(1);
_buf.b.put(v ? (byte)1 : (byte)0);
}
/**
* Writes an optional boolean to the stream.
*
* @param tag The optional tag.
* @param v The optional boolean to write to the stream.
**/
public void writeBool(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeBool(tag, v.get());
}
}
/**
* Writes an optional boolean to the stream.
*
* @param tag The optional tag.
* @param v The boolean to write to the stream.
**/
public void writeBool(int tag, boolean 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.
*
* @param v The boolean to write to the stream.
* @param dest The position at which to store the boolean in the buffer.
**/
public void rewriteBool(boolean v, int dest)
{
_buf.b.put(dest, v ? (byte)1 : (byte)0);
}
/**
* Writes a boolean sequence to the stream.
*
* @param v The boolean sequence to write to the stream.
* Passing null
causes an empty sequence to be written to the stream.
**/
public void writeBoolSeq(boolean[] v)
{
if(v == null)
{
writeSize(0);
}
else
{
writeSize(v.length);
expand(v.length);
for(boolean b : v)
{
_buf.b.put(b ? (byte)1 : (byte)0);
}
}
}
/**
* Writes an optional boolean sequence to the stream.
*
* @param tag The optional tag.
* @param v The optional boolean sequence to write to the stream.
**/
public void writeBoolSeq(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeBoolSeq(tag, v.get());
}
}
/**
* Writes an optional boolean sequence to the stream.
*
* @param tag The optional tag.
* @param v The boolean sequence to write to the stream.
**/
public void writeBoolSeq(int tag, boolean[] v)
{
if(writeOptional(tag, OptionalFormat.VSize))
{
writeBoolSeq(v);
}
}
/**
* Writes a short to the stream.
*
* @param v 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.
*
* @param tag The optional tag.
* @param v The optional short to write to the stream.
**/
public void writeShort(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeShort(tag, v.get());
}
}
/**
* Writes an optional short to the stream.
*
* @param tag The optional tag.
* @param v 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.
*
* @param v 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);
java.nio.ShortBuffer shortBuf = _buf.b.asShortBuffer();
shortBuf.put(v);
_buf.position(_buf.b.position() + v.length * 2);
}
}
/**
* Writes an optional short sequence to the stream.
*
* @param tag The optional tag.
* @param v The optional short sequence to write to the stream.
**/
public void writeShortSeq(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeShortSeq(tag, v.get());
}
}
/**
* Writes an optional short sequence to the stream.
*
* @param tag The optional tag.
* @param v 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 the remaining contents of the short buffer as a short sequence to the stream.
*
* @param v The short buffer to write to the stream.
**/
public void writeShortBuffer(java.nio.ShortBuffer v)
{
if(v == null || v.remaining() == 0)
{
writeSize(0);
}
else
{
int sz = v.remaining();
writeSize(sz);
expand(sz * 2);
java.nio.ShortBuffer shortBuf = _buf.b.asShortBuffer();
shortBuf.put(v);
_buf.position(_buf.b.position() + sz * 2);
}
}
/**
* Writes an int to the stream.
*
* @param v 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.
*
* @param tag The optional tag.
* @param v The optional int to write to the stream.
**/
public void writeInt(int tag, java.util.OptionalInt v)
{
if(v != null && v.isPresent())
{
writeInt(tag, v.getAsInt());
}
}
/**
* Writes an optional int to the stream.
*
* @param tag The optional tag.
* @param v 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.
*
* @param v The int to write to the stream.
* @param dest 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.
*
* @param v 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);
java.nio.IntBuffer intBuf = _buf.b.asIntBuffer();
intBuf.put(v);
_buf.position(_buf.b.position() + v.length * 4);
}
}
/**
* Writes an optional int sequence to the stream.
*
* @param tag The optional tag.
* @param v The optional int sequence to write to the stream.
**/
public void writeIntSeq(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeIntSeq(tag, v.get());
}
}
/**
* Writes an optional int sequence to the stream.
*
* @param tag The optional tag.
* @param v 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 the remaining contents of the int buffer as an int sequence to the stream.
*
* @param v The int buffer to write to the stream.
**/
public void writeIntBuffer(java.nio.IntBuffer v)
{
if(v == null || v.remaining() == 0)
{
writeSize(0);
}
else
{
int sz = v.remaining();
writeSize(sz);
expand(sz * 4);
java.nio.IntBuffer intBuf = _buf.b.asIntBuffer();
intBuf.put(v);
_buf.position(_buf.b.position() + sz * 4);
}
}
/**
* Writes a long to the stream.
*
* @param v 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.
*
* @param tag The optional tag.
* @param v The optional long to write to the stream.
**/
public void writeLong(int tag, java.util.OptionalLong v)
{
if(v != null && v.isPresent())
{
writeLong(tag, v.getAsLong());
}
}
/**
* Writes an optional long to the stream.
*
* @param tag The optional tag.
* @param v 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.
*
* @param v 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);
java.nio.LongBuffer longBuf = _buf.b.asLongBuffer();
longBuf.put(v);
_buf.position(_buf.b.position() + v.length * 8);
}
}
/**
* Writes an optional long sequence to the stream.
*
* @param tag The optional tag.
* @param v The optional long sequence to write to the stream.
**/
public void writeLongSeq(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeLongSeq(tag, v.get());
}
}
/**
* Writes an optional long sequence to the stream.
*
* @param tag The optional tag.
* @param v 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 the remaining contents of the long buffer as a long sequence to the stream.
*
* @param v The long buffer to write to the stream.
**/
public void writeLongBuffer(java.nio.LongBuffer v)
{
if(v == null || v.remaining() == 0)
{
writeSize(0);
}
else
{
int sz = v.remaining();
writeSize(sz);
expand(sz * 8);
java.nio.LongBuffer longBuf = _buf.b.asLongBuffer();
longBuf.put(v);
_buf.position(_buf.b.position() + sz * 8);
}
}
/**
* Writes a float to the stream.
*
* @param v 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.
*
* @param tag The optional tag.
* @param v The optional float to write to the stream.
**/
public void writeFloat(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeFloat(tag, v.get());
}
}
/**
* Writes an optional float to the stream.
*
* @param tag The optional tag.
* @param v 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.
*
* @param v 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);
java.nio.FloatBuffer floatBuf = _buf.b.asFloatBuffer();
floatBuf.put(v);
_buf.position(_buf.b.position() + v.length * 4);
}
}
/**
* Writes an optional float sequence to the stream.
*
* @param tag The optional tag.
* @param v The optional float sequence to write to the stream.
**/
public void writeFloatSeq(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeFloatSeq(tag, v.get());
}
}
/**
* Writes an optional float sequence to the stream.
*
* @param tag The optional tag.
* @param v 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 the remaining contents of the float buffer as a float sequence to the stream.
*
* @param v The float buffer to write to the stream.
**/
public void writeFloatBuffer(java.nio.FloatBuffer v)
{
if(v == null || v.remaining() == 0)
{
writeSize(0);
}
else
{
int sz = v.remaining();
writeSize(sz);
expand(sz * 4);
java.nio.FloatBuffer floatBuf = _buf.b.asFloatBuffer();
floatBuf.put(v);
_buf.position(_buf.b.position() + sz * 4);
}
}
/**
* Writes a double to the stream.
*
* @param v 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.
*
* @param tag The optional tag.
* @param v The optional double to write to the stream.
**/
public void writeDouble(int tag, java.util.OptionalDouble v)
{
if(v != null && v.isPresent())
{
writeDouble(tag, v.getAsDouble());
}
}
/**
* Writes an optional double to the stream.
*
* @param tag The optional tag.
* @param v 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.
*
* @param v 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);
java.nio.DoubleBuffer doubleBuf = _buf.b.asDoubleBuffer();
doubleBuf.put(v);
_buf.position(_buf.b.position() + v.length * 8);
}
}
/**
* Writes an optional double sequence to the stream.
*
* @param tag The optional tag.
* @param v The optional double sequence to write to the stream.
**/
public void writeDoubleSeq(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeDoubleSeq(tag, v.get());
}
}
/**
* Writes an optional double sequence to the stream.
*
* @param tag The optional tag.
* @param v 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 the remaining contents of the double buffer as a double sequence to the stream.
*
* @param v The double buffer to write to the stream.
**/
public void writeDoubleBuffer(java.nio.DoubleBuffer v)
{
if(v == null || v.remaining() == 0)
{
writeSize(0);
}
else
{
int sz = v.remaining();
writeSize(sz);
expand(sz * 8);
java.nio.DoubleBuffer doubleBuf = _buf.b.asDoubleBuffer();
doubleBuf.put(v);
_buf.position(_buf.b.position() + sz * 8);
}
}
final static java.nio.charset.Charset _utf8 = java.nio.charset.Charset.forName("UTF8");
private java.nio.charset.CharsetEncoder _charEncoder = null;
/**
* Writes a string to the stream.
*
* @param v 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)
{
writeSize(0);
}
else
{
final int len = v.length();
if(len > 0)
{
if(_stringBytes == null || len > _stringBytes.length)
{
_stringBytes = new byte[len];
}
if(_stringChars == null || len > _stringChars.length)
{
_stringChars = new char[len];
}
//
// If the string contains only 7-bit characters, it's more efficient
// to perform the conversion to UTF-8 manually.
//
v.getChars(0, len, _stringChars, 0);
for(int i = 0; i < len; ++i)
{
if(_stringChars[i] > (char)127)
{
//
// Found a multibyte character.
//
if(_charEncoder == null)
{
_charEncoder = _utf8.newEncoder();
}
java.nio.ByteBuffer b = null;
try
{
b = _charEncoder.encode(java.nio.CharBuffer.wrap(_stringChars, 0, len));
}
catch(java.nio.charset.CharacterCodingException ex)
{
throw new MarshalException(ex);
}
writeSize(b.limit());
expand(b.limit());
_buf.b.put(b);
return;
}
_stringBytes[i] = (byte)_stringChars[i];
}
writeSize(len);
expand(len);
_buf.b.put(_stringBytes, 0, len);
}
else
{
writeSize(0);
}
}
}
/**
* Writes an optional string to the stream.
*
* @param tag The optional tag.
* @param v The optional string to write to the stream.
**/
public void writeString(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeString(tag, v.get());
}
}
/**
* Writes an optional string to the stream.
*
* @param tag The optional tag.
* @param v 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.
*
* @param v 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(String e : v)
{
writeString(e);
}
}
}
/**
* Writes an optional string sequence to the stream.
*
* @param tag The optional tag.
* @param v The optional string sequence to write to the stream.
**/
public void writeStringSeq(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeStringSeq(tag, v.get());
}
}
/**
* Writes an optional string sequence to the stream.
*
* @param tag The optional tag.
* @param v 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 a proxy to the stream.
*
* @param v The proxy to write.
**/
public void writeProxy(ObjectPrx v)
{
if(v != null)
{
v._write(this);
}
else
{
Identity ident = new Identity();
ident.ice_writeMembers(this);
}
}
/**
* Writes an optional proxy to the stream.
*
* @param tag The optional tag.
* @param v The optional proxy to write to the stream.
**/
public void writeProxy(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeProxy(tag, v.get());
}
}
/**
* Writes an optional proxy to the stream.
*
* @param tag The optional tag.
* @param v The proxy to write to the stream.
**/
public void writeProxy(int tag, ObjectPrx v)
{
if(writeOptional(tag, OptionalFormat.FSize))
{
int pos = startSize();
writeProxy(v);
endSize(pos);
}
}
/**
* Write an enumerated value.
*
* @param v The enumerator.
* @param maxValue 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 a Slice value to the stream.
*
* @param v The value to write. This method writes the index of an instance; the state of the value is
* written once {@link #writePendingValues} is called.
**/
public void writeValue(Value v)
{
initEncaps();
_encapsStack.encoder.writeValue(v);
}
/**
* Writes an optional value to the stream.
*
* @param tag The optional tag.
* @param v The optional value to write to the stream.
* @param The type of the optional value.
**/
public void writeValue(int tag, java.util.Optional v)
{
if(v != null && v.isPresent())
{
writeValue(tag, v.get());
}
}
/**
* Writes an optional value to the stream.
*
* @param tag The optional tag.
* @param v The value to write to the stream.
**/
public void writeValue(int tag, Value v)
{
if(writeOptional(tag, OptionalFormat.Class))
{
writeValue(v);
}
}
/**
* Writes a user exception to the stream.
*
* @param v The user exception to write.
**/
public void writeException(UserException v)
{
initEncaps();
_encapsStack.encoder.writeException(v);
}
private boolean writeOptionalImpl(int tag, OptionalFormat format)
{
if(isEncoding_1_0())
{
return false; // Optional members aren't supported with the 1.0 encoding.
}
int v = format.value();
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.
*
* @return The current position.
**/
public int pos()
{
return _buf.b.position();
}
/**
* Sets the current position in the stream.
*
* @param n The new position.
**/
public void pos(int n)
{
_buf.position(n);
}
/**
* Determines the current size of the stream.
*
* @return The current size.
**/
public int size()
{
return _buf.size();
}
/**
* Determines whether the stream is empty.
*
* @return True if no data has been written yet, false otherwise.
**/
public boolean isEmpty()
{
return _buf.empty();
}
/**
* Expand the stream to accept more data.
*
* @param n The number of bytes to accommodate in the stream.
**/
public void expand(int n)
{
_buf.expand(n);
}
private com.zeroc.IceInternal.Instance _instance;
private com.zeroc.IceInternal.Buffer _buf;
private Object _closure;
private FormatType _format;
private byte[] _stringBytes; // Reusable array for string operations.
private char[] _stringChars; // Reusable array for string operations.
private enum SliceType { NoSlice, ValueSlice, ExceptionSlice }
abstract private static class EncapsEncoder
{
protected EncapsEncoder(OutputStream stream, Encaps encaps)
{
_stream = stream;
_encaps = encaps;
_typeIdIndex = 0;
_marshaledMap = new java.util.IdentityHashMap<>();
}
abstract void writeValue(Value v);
abstract void writeException(UserException v);
abstract void startInstance(SliceType type, SlicedData data);
abstract void endInstance();
abstract void startSlice(String typeId, int compactId, boolean last);
abstract void endSlice();
boolean writeOptional(int tag, OptionalFormat format)
{
return false;
}
void writePendingValues()
{
}
protected int registerTypeId(String typeId)
{
if(_typeIdMap == null) // Lazy initialization
{
_typeIdMap = new java.util.TreeMap<>();
}
Integer p = _typeIdMap.get(typeId);
if(p != null)
{
return p;
}
else
{
_typeIdMap.put(typeId, ++_typeIdIndex);
return -1;
}
}
final protected OutputStream _stream;
final protected Encaps _encaps;
// Encapsulation attributes for instance marshaling.
final protected java.util.IdentityHashMap _marshaledMap;
private java.util.TreeMap _typeIdMap;
private int _typeIdIndex;
}
private static final class EncapsEncoder10 extends EncapsEncoder
{
EncapsEncoder10(OutputStream stream, Encaps encaps)
{
super(stream, encaps);
_sliceType = SliceType.NoSlice;
_valueIdIndex = 0;
_toBeMarshaledMap = new java.util.IdentityHashMap<>();
}
@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);
}
}
@Override
void writeException(UserException v)
{
//
// User exception with the 1.0 encoding start with a boolean
// 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.
//
boolean usesClasses = v._usesClasses();
_stream.writeBool(usesClasses);
v._write(_stream);
if(usesClasses)
{
writePendingValues();
}
}
@Override
void startInstance(SliceType sliceType, SlicedData sliceData)
{
_sliceType = sliceType;
}
@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;
}
@Override
void startSlice(String typeId, int compactId, boolean last)
{
//
// For instance slices, encode a boolean 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();
}
@Override
void endSlice()
{
//
// Write the slice length.
//
final int sz = _stream.pos() - _writeSlice + 4;
_stream.rewriteInt(sz, _writeSlice - 4);
}
@Override
void writePendingValues()
{
while(_toBeMarshaledMap.size() > 0)
{
//
// Consider the to be marshalled instances as marshaled now,
// this is necessary to avoid adding again the "to be
// marshaled instances" into _toBeMarshaledMap while writing
// instances.
//
_marshaledMap.putAll(_toBeMarshaledMap);
java.util.IdentityHashMap savedMap = _toBeMarshaledMap;
_toBeMarshaledMap = new java.util.IdentityHashMap<>();
_stream.writeSize(savedMap.size());
for(java.util.Map.Entry p : savedMap.entrySet())
{
//
// Ask the instance to marshal itself. Any new class
// instances that are triggered by the classes marshaled
// are added to toBeMarshaledMap.
//
_stream.writeInt(p.getValue().intValue());
try
{
p.getKey().ice_preMarshal();
}
catch(java.lang.Exception ex)
{
String s = "exception raised by ice_preMarshal:\n" + com.zeroc.IceInternal.Ex.toString(ex);
_stream.instance().initializationData().logger.warning(s);
}
p.getKey()._iceWrite(_stream);
}
}
_stream.writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
}
private int registerValue(Value v)
{
assert(v != null);
//
// Look for this instance in the to-be-marshaled map.
//
Integer p = _toBeMarshaledMap.get(v);
if(p != null)
{
return p.intValue();
}
//
// Didn't find it, try the marshaled map next.
//
p = _marshaledMap.get(v);
if(p != null)
{
return p.intValue();
}
//
// We haven't seen this instance previously, create a new
// index, and insert it into the to-be-marshaled map.
//
_toBeMarshaledMap.put(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 java.util.IdentityHashMap _toBeMarshaledMap;
}
private static final class EncapsEncoder11 extends EncapsEncoder
{
EncapsEncoder11(OutputStream stream, Encaps encaps)
{
super(stream, encaps);
_current = null;
_valueIdIndex = 1;
}
@Override
void writeValue(Value v)
{
if(v == null)
{
_stream.writeSize(0);
}
else if(_current != null && _encaps.format == FormatType.SlicedFormat)
{
if(_current.indirectionTable == null) // Lazy initialization
{
_current.indirectionTable = new java.util.ArrayList<>();
_current.indirectionMap = new java.util.IdentityHashMap<>();
}
//
// If writing an instance within a slice and using the sliced
// format, write an index from the instance indirection
// table. The indirect instance table is encoded at the end of
// each slice and is always read (even if the Slice is
// unknown).
//
Integer index = _current.indirectionMap.get(v);
if(index == null)
{
_current.indirectionTable.add(v);
final int idx = _current.indirectionTable.size(); // Position + 1 (0 is reserved for nil)
_current.indirectionMap.put(v, idx);
_stream.writeSize(idx);
}
else
{
_stream.writeSize(index.intValue());
}
}
else
{
writeInstance(v); // Write the instance or a reference if already marshaled.
}
}
@Override
void writeException(UserException v)
{
v._write(_stream);
}
@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);
}
}
@Override
void endInstance()
{
_current = _current.previous;
}
@Override
void startSlice(String typeId, int compactId, boolean last)
{
assert((_current.indirectionTable == null || _current.indirectionTable.isEmpty()) &&
(_current.indirectionMap == null || _current.indirectionMap.isEmpty()));
_current.sliceFlagsPos = _stream.pos();
_current.sliceFlags = (byte)0;
if(_encaps.format == FormatType.SlicedFormat)
{
// Encode the slice size if using the sliced format.
_current.sliceFlags |= com.zeroc.IceInternal.Protocol.FLAG_HAS_SLICE_SIZE;
}
if(last)
{
_current.sliceFlags |= com.zeroc.IceInternal.Protocol.FLAG_IS_LAST_SLICE; // This is the last slice.
}
_stream.writeByte((byte)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 |= com.zeroc.IceInternal.Protocol.FLAG_HAS_TYPE_ID_COMPACT;
_stream.writeSize(compactId);
}
else
{
int index = registerTypeId(typeId);
if(index < 0)
{
_current.sliceFlags |= com.zeroc.IceInternal.Protocol.FLAG_HAS_TYPE_ID_STRING;
_stream.writeString(typeId);
}
else
{
_current.sliceFlags |= com.zeroc.IceInternal.Protocol.FLAG_HAS_TYPE_ID_INDEX;
_stream.writeSize(index);
}
}
}
}
else
{
_stream.writeString(typeId);
}
if((_current.sliceFlags & com.zeroc.IceInternal.Protocol.FLAG_HAS_SLICE_SIZE) != 0)
{
_stream.writeInt(0); // Placeholder for the slice length.
}
_current.writeSlice = _stream.pos();
_current.firstSlice = false;
}
@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 & com.zeroc.IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS) != 0)
{
_stream.writeByte((byte)com.zeroc.IceInternal.Protocol.OPTIONAL_END_MARKER);
}
//
// Write the slice length if necessary.
//
if((_current.sliceFlags & com.zeroc.IceInternal.Protocol.FLAG_HAS_SLICE_SIZE) != 0)
{
final 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.isEmpty())
{
assert(_encaps.format == FormatType.SlicedFormat);
_current.sliceFlags |= com.zeroc.IceInternal.Protocol.FLAG_HAS_INDIRECTION_TABLE;
//
// Write the indirection instance table.
//
_stream.writeSize(_current.indirectionTable.size());
for(Value v : _current.indirectionTable)
{
writeInstance(v);
}
_current.indirectionTable.clear();
_current.indirectionMap.clear();
}
//
// Finally, update the slice flags.
//
_stream.rewriteByte(_current.sliceFlags, _current.sliceFlagsPos);
}
@Override
boolean writeOptional(int tag, OptionalFormat format)
{
if(_current == null)
{
return _stream.writeOptionalImpl(tag, format);
}
else
{
if(_stream.writeOptionalImpl(tag, format))
{
_current.sliceFlags |= com.zeroc.IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS;
return true;
}
else
{
return false;
}
}
}
private void writeSlicedData(SlicedData slicedData)
{
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;
}
for(SliceInfo info : 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 |= com.zeroc.IceInternal.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) // Lazy initialization
{
_current.indirectionTable = new java.util.ArrayList<>();
_current.indirectionMap = new java.util.IdentityHashMap<>();
}
for(Value o : info.instances)
{
_current.indirectionTable.add(o);
}
}
endSlice();
}
}
private void writeInstance(Value v)
{
assert(v != null);
//
// If the instance was already marshaled, just write it's ID.
//
Integer p = _marshaledMap.get(v);
if(p != null)
{
_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.put(v, ++_valueIdIndex);
try
{
v.ice_preMarshal();
}
catch(java.lang.Exception ex)
{
String s = "exception raised by ice_preMarshal:\n" + com.zeroc.IceInternal.Ex.toString(ex);
_stream.instance().initializationData().logger.warning(s);
}
_stream.writeSize(1); // Class instance marker.
v._iceWrite(_stream);
}
private static final class InstanceData
{
InstanceData(InstanceData previous)
{
if(previous != null)
{
previous.next = this;
}
this.previous = previous;
this.next = null;
}
// Instance attributes
SliceType sliceType;
boolean firstSlice;
// Slice attributes
byte sliceFlags;
int writeSlice; // Position of the slice data members
int sliceFlagsPos; // Position of the slice flags
java.util.List indirectionTable;
java.util.IdentityHashMap indirectionMap;
final InstanceData previous;
InstanceData next;
}
private InstanceData _current;
private int _valueIdIndex; // The ID of the next instance to marhsal
}
private static final class Encaps
{
void reset()
{
encoder = null;
}
void setEncoding(EncodingVersion encoding)
{
this.encoding = encoding;
encoding_1_0 = encoding.equals(Util.Encoding_1_0);
}
int start;
FormatType format = FormatType.DefaultFormat;
EncodingVersion encoding;
boolean encoding_1_0;
EncapsEncoder encoder;
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 boolean 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);
}
}
}
/** @hidden */
@FunctionalInterface
static public interface Marshaler
{
void marshal(OutputStream ostr);
}
}