The InputStream Interface in C-Sharp

On this page:

Initializing an InputStream in C#

The InputStream class provides a number of overloaded constructors:

C#
namespace Ice
{
    public class InputStream
    {

        public InputStream();
        public InputStream(byte[] data);
        public InputStream(Communicator communicator);
        public InputStream(Communicator communicator, byte[] data);
        public InputStream(EncodingVersion encoding);
        public InputStream(EncodingVersion encoding, byte[] data);
        public InputStream(Communicator communicator, EncodingVersion encoding);
        public InputStream(Communicator communicator, EncodingVersion encoding, byte[] data);
        ...
    }
} 

The constructors accept three types of arguments:

  • A communicator instance
  • An encoding version
  • A byte array containing the encoded data that you intend to decode

You'll normally supply the encoded data argument. The stream does not make a copy of this data; rather, it uses the data as supplied and assumes it remains unmodified for the lifetime of the stream object.

We recommend supplying a communicator instance, otherwise you will not be able to decode proxy objects. The stream also inspects the communicator's settings to configure several of its own default settings, but you can optionally configure these settings manually using methods that we'll describe later.

If you omit an encoding version, the stream uses the default encoding version of the communicator (if provided) or the most recent encoding version.

If a communicator instance is not available at the time you construct the stream, you can optionally supply it later using one of the overloaded initialize methods:

C#
namespace Ice
{
    public class InputStream
    {
       public void initialize(Communicator communicator);
       public void initialize(Communicator communicator, EncodingVersion encoding);
       ...
    }
}

Invoking initialize causes the stream to re-initialize its settings based on the configuration of the given communicator.

Use the following methods to manually configure the stream:

C#
namespace Ice
{
    public class InputStream
    {
        public void setValueFactoryManager(ValueFactoryManager vfm);
        public void setLogger(Logger logger);
        public void setCompactIdResolver(System.Func<int, string> r);
        public void setClassResolver(System.Func<string, Type> r);
        public void setSliceValues(bool);
        public void setTraceSlicing(bool);

        ...
    }
}

The settings include:

  • Logger
    The stream uses a logger to record warning and trace messages.
  • Compact ID resolver
    A compact ID resolver for translating numeric values into Slice type IDs. The stream invokes the resolver by passing it the numeric compact ID. The resolver is expected to return the Slice type ID associated with that numeric ID or an empty string if the numeric ID is unknown. The application must supply a System.Func<int, string> delegate. 

  • Class resolver
    Translates Slice type IDs into C# classes. The resolver is expected to return the class corresponding to the Slice type ID or null if the ID is unknown. The application must supply a System.Func<string, Type> delegate. If you initialized the stream with a communicator, the stream uses the communicator's class resolver by default.

  • Slice values
    The flag indicates whether to slice instances of Slice classes to a known Slice type when a more derived type is unknown. An instance is "sliced" when no static information is available for a Slice type ID and no factory can be found for that type, resulting in the creation of an instance of a less-derived type. If slicing is disabled in this situation, the stream raises the exception NoValueFactoryException. The default behavior is to allow slicing.
  • Trace slicing
    The flag indicates whether to log messages when instances of Slice classes are sliced. If the stream is initialized with a communicator, this setting defaults to the value of the Ice.Trace.Slicing property, otherwise the setting defaults to false.

Extracting from an InputStream in C#

InputStream provides a number of read methods that allow you to extract Slice types from the stream.

For example, you can extract a boolean and a sequence of strings from a stream as follows:

C#
byte[] data = ...
Ice.InputStream in = new Ice.InputStream(communicator, data);
bool b = in.readBool();
string[] seq = in.readStringSeq();

Here are the methods for extracting data from a stream:

C#
namespace Ice
{
    public class InputStream
    {

        public byte readByte();
        public Ice.Optional<byte> readByte(int tag);
        public void readByte(int tag, out bool isset, out byte v);
        public byte[] readByteSeq();
        public void readByteSeq(out List<byte> l);
        public void readByteSeq(out LinkedList<byte> l);
        public void readByteSeq(out Queue<byte> l);
        public void readByteSeq(out Stack<byte> l);
        public Ice.Optional<byte[]> readByteSeq(int tag);
        public void readByteSeq(int tag, out bool isset, out byte[] v);

        public bool readBool();
        public Ice.Optional<bool> readBool(int tag);
        public void readBool(int tag, out bool isset, out bool v);
        public bool[] readBoolSeq();
        public void readBoolSeq(out List<bool> l);
        public void readBoolSeq(out LinkedList<bool> l);
        public void readBoolSeq(out Queue<bool> l);
        public void readBoolSeq(out Stack<bool> l);
        public Ice.Optional<bool[]> readBoolSeq(int tag);
        public void readBoolSeq(int tag, out bool isset, out bool[] v);

        public short readShort();
        public Ice.Optional<short> readShort(int tag);
        public void readShort(int tag, out bool isset, out short v);
        public short[] readShortSeq();
        public void readShortSeq(out List<short> l);
        public void readShortSeq(out LinkedList<short> l);
        public void readShortSeq(out Queue<short> l);
        public void readShortSeq(out Stack<short> l);
        public Ice.Optional<short[]> readShortSeq(int tag);
        public void readShortSeq(int tag, out bool isset, out short[] v);

        public int readInt();
        public Ice.Optional<int> readInt(int tag);
        public void readInt(int tag, out bool isset, out int v);
        public int[] readIntSeq();
        public void readIntSeq(out List<int> l);
        public void readIntSeq(out LinkedList<int> l);
        public void readIntSeq(out Queue<int> l);
        public void readIntSeq(out Stack<int> l);
        public Ice.Optional<int[]> readIntSeq(int tag);
        public void readIntSeq(int tag, out bool isset, out int[] v);

        public long readLong();
        public Ice.Optional<long> readLong(int tag);
        public void readLong(int tag, out bool isset, out long v);
        public long[] readLongSeq();
        public void readLongSeq(out List<long> l);
        public void readLongSeq(out LinkedList<long> l);
        public void readLongSeq(out Queue<long> l);
        public void readLongSeq(out Stack<long> l);
        public Ice.Optional<long[]> readLongSeq(int tag);
        public void readLongSeq(int tag, out bool isset, out long[] v);

        public float readFloat();
        public Ice.Optional<float> readFloat(int tag);
        public void readFloat(int tag, out bool isset, out float v);
        public float[] readFloatSeq();
        public void readFloatSeq(out List<float> l);
        public void readFloatSeq(out LinkedList<float> l);
        public void readFloatSeq(out Queue<float> l);
        public void readFloatSeq(out Stack<float> l);
        public Ice.Optional<float[]> readFloatSeq(int tag);
        public void readFloatSeq(int tag, out bool isset, out float[] v);

        public double readDouble();
        public Ice.Optional<double> readDouble(int tag);
        public void readDouble(int tag, out bool isset, out double v);
        public double[] readDoubleSeq();
        public void readDoubleSeq(out List<double> l);
        public void readDoubleSeq(out LinkedList<double> l);
        public void readDoubleSeq(out Queue<double> l);
        public void readDoubleSeq(out Stack<double> l);
        public Ice.Optional<double[]> readDoubleSeq(int tag);
        public void readDoubleSeq(int tag, out bool isset, out double[] v);

        public string readString();
        public Ice.Optional<string> readString(int tag);
        public void readString(int tag, out bool isset, out string v);
        public string[] readStringSeq();
        public void readStringSeq(out List<string> l);
        public void readStringSeq(out LinkedList<string> l);
        public void readStringSeq(out Queue<string> l);
        public void readStringSeq(out Stack<string> l);
        public Ice.Optional<string[]> readStringSeq(int tag);
        public void readStringSeq(int tag, out bool isset, out string[] v);

        public int readSize();
        public int readAndCheckSeqSize(int minSizeWireSize);

        public ObjectPrx readProxy();
        public Ice.Optional<Ice.ObjectPrx> readProxy(int tag);
        public void readProxy(int tag, out bool isset, out Ice.ObjectPrx v);

        public void readValue<T>(System.Action<T> cb) where T : Ice.Value;
        public void readValue<T>(int tag, System.Action<T> cb) where T : Ice.Value;
        public void readValue(System.Action<Ice.Value> cb);
        public void readValue(int tag, System.Action<Ice.Value> cb);

        public int readEnum(int maxValue);
 
        public void throwException();
        public void throwException(UserExceptionFactory factory);
 
        public void startValue();
        public SlicedData endValue(bool preserve);
 
        public void startException();
        public SlicedData endException(bool preserve);

        public string startSlice();
        public void endSlice();
        public void skipSlice();

        public EncodingVersion startEncapsulation();
        public void endEncapsulation();
        public EncodingVersion skipEncapsulation();
        public EncodingVersion skipEmptyEncapsulation();
        public int getEncapsulationSize();

        public EncodingVersion getEncoding();
 
        public void readPendingValues();

        public object readSerializable();
        public void readBlob(byte[] v);
        public byte[] readBlob(int sz);

        public void skip(int sz);
        public void skipSize();
 
        public bool readOptional(int tag, OptionalFormat format);
 
        public int pos();
        public void pos(int n);

        ...
    }
}

Member functions are provided for extracting all of the primitive types, as well as sequences of primitive types; these are self-explanatory. The remaining member functions have the following semantics:

  • Ice.Optional<type> readType(int tag)
    void readType(int tag, out bool isset, out type v)
    Extracts an optional value. The first method returns an Optional object that the caller can query to determine whether the value has been set and then obtain its value. The second method sets isset to true if the value is present and provides the value in v; if the value is not present, v is initialized to a default value appropriate for its type.

  • Ice.Optional<byte[]> readByteSeq(int tag)
    void readByteSeq(int tag, out bool isset, out byte[] v)
    Extracts an optional sequence value. The first method returns an Optional object that the caller can query to determine whether the value has been set and then obtain its value. The second method sets isset to true if the value is present and provides the value in v; if the value is not present, v is initialized to null.

  • int readSize()
    The Ice encoding has a compact representation to indicate size. This function extracts a size and returns it as an integer.
  • int readAndCheckSeqSize(int minWireSize)
    Like readSize, this function reads a size and returns it, but also verifies that there is enough data remaining in the unmarshaling buffer to successfully unmarshal the elements of the sequence. The minWireSize parameter indicates the smallest possible on-the-wire representation of a single sequence element. If the unmarshaling buffer contains insufficient data to unmarshal the sequence, the function throws UnmarshalOutOfBoundsException.
  • Ice.ObjectPrx readProxy()
    This function returns an instance of the base proxy type, ObjectPrx. The Slice compiler optionally generates helper functions to extract proxies of user-defined types.
  • void readValue<T>(System.Action<T> cb) where T : Ice.Value
    The Ice encoding for class instances requires extraction to occur in stages. The readValue function accepts a delegate of type System.Action<T>. When the class instance is available, the delegate is called. The application must call readPendingValues on the stream to ensure that all instances are properly extracted.

  • int readEnum(int maxValue)
    Unmarshals the integer value of an enumerator. The maxValue argument represents the highest enumerator value in the enumeration. Consider the following definitions:

    Slice
    enum Color { red, green, blue }
    enum Fruit { Apple, Pear=3, Orange }
    

    The maximum value for Color is 2, and the maximum value for Fruit is 4.

  • void throwException()
    void throwException(UserExceptionFactory factory)
    These functions extract a user exception from the stream and throw it. If the stored exception is of an unknown type, the functions attempt to extract and throw a less-derived exception. If that also fails, an exception is thrown: for the 1.0 encoding, the exception is UnmarshalOutOfBoundsException, for the 1.1 encoding, the exception is UnknownUserException. You can optionally supply a UserExceptionFactory delegate:

    C#
    namespace Ice
    {
        public delegate void UserExceptionFactory(string id);
    }

    As the stream decodes each slice of a user exception, it will invoke the factory first to give it an opportunity to raise an exception corresponding to the given Slice type ID. If the factory does not recognize the type ID, it must return without throwing. In this case, the stream will make its own attempt to locate a class for the type ID; if that fails, the stream skips the slice and tries again for the next slice.

  • string startSlice()
    void endSlice()
    void skipSlice()
    Start, end, and skip a slice of member data, respectively. These functions are used when manually extracting the slices of a class instance or user exception. The startSlice method returns the type ID of the next slice, which may be an empty string depending on the format used to encode the instance or exception.
  • void startValue()
    SlicedData endValue(bool preserve)
    The startValue method must be called prior to reading the slices of a class instance. The endValue method must be called after all slices have been read. Pass true to endValue in order to preserve the slices of any unknown more-derived types, or false to discard the slices. If preserve is true and the stream actually preserved any slices, the return value of endValue is a non-nil SlicedData object that encapsulates the slice data. If the caller later wishes to forward the instance with any preserved slices intact, it must supply this SlicedData object to the output stream.
  • void startException()
    SlicedData endException(bool preserve)
    The startException method must be called prior to reading the slices of an exception. The endException method must be called after all slices have been read. Pass true to endException in order to preserve the slices of any unknown more-derived types, or false to discard the slices. If preserve is true and the stream actually preserved any slices, the return value of endException is a non-nil SlicedData object that encapsulates the slice data. If the caller later wishes to forward the exception with any preserved slices intact, it must supply this SlicedData object to the output stream.
  • EncodingVersion startEncapsulation()
    void endEncapsulation()
    EncodingVersion skipEncapsulation()
    Start, end, and skip an encapsulation, respectively. The startEncapsulation and skipEncapsulation methods return the encoding version used to encode the contents of the encapsulation.
  • EncodingVersion skipEmptyEncapsulation()
    Skips an encapsulation that is expected to be empty and returns its encoding version. The stream raises EncapsulationException if the encapsulation is not empty.
  • int getEncapsulationSize()
    Returns the size of the current encapsulation.
  • EncodingVersion getEncoding()
    Returns the encoding version currently in use by the stream.
  • void readPendingValues()
    An application must call this function after all other data has been extracted, but only if class instances were encoded. This function extracts the state of class instances and invokes their corresponding callback objects (see readValue). For backward compatibility with encoding version 1.0, this function must only be called when non-optional data members or parameters use class types.
  • byte[] readBlob(int sz)
    Extracts an array of sz bytes from the stream at its current position. The returned byte array contains undecoded data from the stream's internal buffer. The stream's position is advanced by sz.

  • void readBlob(byte[] v)
    Extracts an array of v.Length bytes from the stream at its current position. The byte array will contain undecoded data from the stream's internal buffer. The stream's position is advanced by v.Length.
  • void skip(int sz)
    Skips the given number of bytes.
  • void skipSize()
    Reads a size at the current position and skips that number of bytes.
  • bool readOptional(int tag, OptionalFormat fmt)
    Returns true if an optional value with the given tag and format is present, or false otherwise. If this method returns true, the data associated with that optional value must be read next. Optional values must be read in order by tag from least to greatest. The OptionalFormat enumeration is defined as follows:

    C#
    namespace Ice
    {
        public enum OptionalFormat
        {
            OptionalFormatF1, OptionalFormatF2, OptionalFormatF4, OptionalFormatF8,
            OptionalFormatSize, OptionalFormatVSize, OptionalFormatFSize,
            OptionalFormatEndMarker
        }
    } 

    Refer to the encoding discussion for more information on the meaning of these values.

  • int pos()
    void pos(int n)

    Returns or modifies the stream's current position, respectively.

See Also