//
// openmapi.org - CompactTeaSharp - XdrEncodingStream.cs
//
// C# port Copyright 2008 by Topalis AG
//
// Author (C# port): mazurin, Johannes Roith
//
// This library is based on the RemoteTea java library:
//
// Author: Harald Albrecht
//
// Copyright (c) 1999, 2000
// Lehrstuhl fuer Prozessleittechnik (PLT), RWTH Aachen
// D-52064 Aachen, Germany. All rights reserved.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this program (see the file COPYING.LIB for more
// details); if not, write to the Free Software Foundation, Inc.,
// 675 Mass Ave, Cambridge, MA 02139, USA.
//
using System;
using System.Net;
using System.Text;
namespace CompactTeaSharp
{
///
/// Defines the abstract base class for all encoding XDR streams. An encoding
/// XDR stream receives data in the form of Java data types and writes it to
/// a data sink (for instance, network or memory buffer) in the
/// platform-independent XDR format.
///
public abstract class XdrEncodingStream
{
private string characterEncoding = null;
///
/// The character encoding for serializing strings.
///
/// The encoding to use for serializing strings.
/// if null, the system's default encoding is to be used.
public string CharacterEncoding {
get { return characterEncoding; }
set { this.characterEncoding = value; }
}
///
/// Begins encoding a new XDR record. This typically involves resetting this
/// encoding XDR stream back into a known state.
///
/// Indicates the receiver of the XDR data. This can
/// be null for XDR streams connected permanently to a
/// receiver (like in case of TCP/IP based XDR streams).
////
/// The int value to be encoded.
public abstract void XdrEncodeInt (int value);
///
/// Encodes a XDR opaque value, which is represented
/// by a vector of byte values, and starts at offset with a
/// length of length. Only the opaque value is encoded, but
/// no length indication is preceeding the opaque value, so the receiver
/// has to know how long the opaque value will be. The encoded data is
/// always padded to be a multiple of four. If the given length is not a
/// multiple of four, zero bytes will be used for padding.
/// Derived classes must ensure that the proper semantic is maintained.
///
/// The opaque value to be encoded in the form of a series of bytes
/// Start offset in the data.
/// The number of bytes to encode.
public abstract void XdrEncodeOpaque (byte [] value, int offset, int length);
///
/// Encodes a XDR opaque value, which is represented
/// by a vector of byte values. The length of the opaque value is written
/// to the XDR stream, so the receiver does not need to know
/// the exact length in advance. The encoded data is always padded to be
/// a multiple of four to maintain XDR alignment.
///
//// The opaque value to be encoded in the form of a series of bytes.
public void XdrEncodeDynamicOpaque (byte [] value)
{
XdrEncodeInt (value.Length);
XdrEncodeOpaque (value);
}
///
/// Encodes a XDR opaque value, which is represented
/// by a vector of byte values. Only the opaque value is encoded, but
/// no length indication is preceeding the opaque value, so the receiver
/// has to know how long the opaque value will be. The encoded data is
/// always padded to be a multiple of four. If the length of the given byte
/// vector is not a multiple of four, zero bytes will be used for padding.
///
/// The opaque value to be encoded in the form
/// of a series of bytes.
public void XdrEncodeOpaque (byte [] value)
{
XdrEncodeOpaque(value, 0, value.Length);
}
///
/// Encodes a XDR opaque value, which is represented
/// by a vector of byte values. Only the opaque value is encoded, but
/// no length indication is preceeding the opaque value, so the receiver
/// has to know how long the opaque value will be. The encoded data is
/// always padded to be a multiple of four. If the length of the given byte
/// vector is not a multiple of four, zero bytes will be used for padding.
///
/// The opaque value to be encoded in the form of a series of
/// bytes.
/// Length of vector to write.
/// This parameter is used as a sanity check.
/// throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeOpaque (byte [] value, int length)
{
if (value.Length != length)
throw new ArgumentException ("array size does not match protocol specification");
XdrEncodeOpaque (value, 0, value.Length);
}
///
/// Encodes a vector of bytes, which is nothing more
/// than a series of octets (or 8 bits wide bytes), each packed into its
/// very own 4 bytes (XDR int). Byte vectors are encoded together with a
/// preceeding length value. This way the receiver doesn't need to know
/// the length of the vector in advance.
///
public void XdrEncodeByteVector (byte [] value)
{
XdrEncodeInt (value.Length);
if (value.Length != 0) {
//
// For speed reasons, we do sign extension here, but the higher bits
// will be removed again when deserializing.
//
for (int i = 0; i < value.Length; i++)
XdrEncodeInt ((int) value [i]);
}
}
///
/// Encodes a vector of bytes, which is nothing more
/// than a series of octets (or 8 bits wide bytes), each packed into its
/// very own 4 bytes (XDR int).
///
/// throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeByteFixedVector (byte [] value, int length)
{
if (value.Length != length)
throw new ArgumentException ("array size does not match protocol specification");
if (length != 0) {
//
// For speed reasons, we do sign extension here, but the higher bits
// will be removed again when deserializing.
//
for (int i = 0; i < length; ++i )
XdrEncodeInt ((int) value[i]);
}
}
///
/// Encodes a byte and write it down this XDR stream.
///
public void XdrEncodeByte (byte value)
{
//
// For speed reasons, we do sign extension here, but the higher bits
// will be removed again when deserializing.
//
XdrEncodeInt ((int) value);
}
///
/// Encodes a short (which is a 16 bits wide quantity) and write it down this XDR stream.
///
public void XdrEncodeShort (short value)
{
XdrEncodeInt ((int) value);
}
///
/// Encodes a long (which is called a "hyper" in XDR
/// babble and is 64 bits wide) and write it down this XDR stream.
///
public void XdrEncodeLong (long value)
{
//
// Just encode the long (which is called a "hyper" in XDR babble) as
// two ints in network order, that is: big endian with the high int
// comming first.
//
XdrEncodeInt ((int)(value >> 32));
XdrEncodeInt ((int)(value & 0xFFFFFFFFL));
}
///
/// Encodes a float (which is a 32 bits wide floating
/// point quantity) and write it down this XDR stream.
///
public void XdrEncodeFloat (Single value)
{
XdrEncodeInt (BitConverter.ToInt32(BitConverter.GetBytes(value), 0));
}
///
/// Encodes a double (which is a 64 bits wide floating
/// point quantity) and write it down this XDR stream.
///
/// Double value to encode.
public void XdrEncodeDouble (double value)
{
XdrEncodeLong (BitConverter.DoubleToInt64Bits(value));
}
///
/// Encodes a boolean and writes it down this XDR stream.
///
public void XdrEncodeBoolean (bool value)
{
XdrEncodeInt (value ? 1 : 0);
}
///
/// Encodes a string and writes it down this XDR stream.
///
public void XdrEncodeString (string value)
{
Encoding ascii = (characterEncoding != null) ?
Encoding.GetEncoding (characterEncoding) : Encoding.GetEncoding (0);
XdrEncodeDynamicOpaque (ascii.GetBytes(value));
}
private void EncodeFixedArray (Action encoderCall, T[] vector, int length)
{
if (vector.Length != length)
throw new ArgumentException ("array size does not match " +
"protocol specification");
foreach (var current in vector)
encoderCall (current);
}
private void EncodeArray (Action encoderCall, T[] vector)
{
XdrEncodeInt (vector.Length);
foreach (var current in vector)
encoderCall (current);
}
public void XdrEncodeShortVector (short [] vectorToEncode)
{
EncodeArray (XdrEncodeShort, vectorToEncode);
}
/// @throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeShortFixedVector (short [] vectorToEncode, int length)
{
EncodeFixedArray (XdrEncodeShort, vectorToEncode, length);
}
public void XdrEncodeIntVector (int [] vectorToEncode)
{
EncodeArray (XdrEncodeInt, vectorToEncode);
}
/// @throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeIntFixedVector (int [] vectorToEncode, int length)
{
EncodeFixedArray (XdrEncodeInt, vectorToEncode, length);
}
public void XdrEncodeLongVector (long [] vectorToEncode)
{
EncodeArray (XdrEncodeLong, vectorToEncode);
}
/// @throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeLongFixedVector (long [] vectorToEncode, int length)
{
EncodeFixedArray (XdrEncodeLong, vectorToEncode, length);
}
public void XdrEncodeFloatVector (float [] vectorToEncode)
{
EncodeArray (XdrEncodeFloat, vectorToEncode);
}
/// @throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeFloatFixedVector (float [] vectorToEncode, int length)
{
EncodeFixedArray (XdrEncodeFloat, vectorToEncode, length);
}
public void XdrEncodeDoubleVector (double [] vectorToEncode)
{
EncodeArray (XdrEncodeDouble, vectorToEncode);
}
/// @throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeDoubleFixedVector (double [] vectorToEncode, int length)
{
EncodeFixedArray (XdrEncodeDouble, vectorToEncode, length);
}
public void XdrEncodeBooleanVector (bool [] vectorToEncode)
{
EncodeArray (XdrEncodeBoolean, vectorToEncode);
}
/// @throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeBooleanFixedVector (bool [] vectorToEncode, int length)
{
EncodeFixedArray (XdrEncodeBoolean, vectorToEncode, length);
}
public void XdrEncodeStringVector (string [] vectorToEncode)
{
EncodeArray (XdrEncodeString, vectorToEncode);
}
/// @throws IllegalArgumentException if the length of the vector does not
/// match the specified length.
public void XdrEncodeStringFixedVector (string [] vectorToEncode, int length)
{
EncodeFixedArray (XdrEncodeString, vectorToEncode, length);
}
public void EncodeWithBoolGate (IXdrAble obj)
{
EncodeWithBoolGate2 (obj);
}
public void EncodeWithBoolGate (IXdrEncodeable obj)
{
EncodeWithBoolGate2 (obj);
}
public void EncodeWithBoolGate2 (IXdrEncodeable obj)
{
if (obj != null) {
XdrEncodeBoolean (true);
obj.XdrEncode (this);
} else
XdrEncodeBoolean (false);
}
public void EncodeCountedSizeArray (T[] obj) where T : IXdrEncodeable
{
int length = obj.Length;
XdrEncodeInt (length);
foreach (var current in obj)
current.XdrEncode (this);
}
}
}