#region Disclaimer / License
// Copyright (C) 2009, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System;
using System.IO;
namespace OSGeo.MapGuide.MaestroAPI.Serialization
{
///
/// A utility for deserializing data in the internal MapGuide format.
///
public class MgBinarySerializer
{
private Stream m_stream;
private Version m_siteVersion;
///
///
///
public static int UInt16Len = BitConverter.GetBytes((UInt16)0).Length;
///
///
///
public static int UInt32Len = BitConverter.GetBytes((UInt32)0).Length;
///
///
///
public static int UInt64Len = BitConverter.GetBytes((UInt64)0).Length;
///
///
///
public static int FloatLen = BitConverter.GetBytes((float)0).Length;
///
///
///
public static int DoubleLen = BitConverter.GetBytes((double)0).Length;
///
///
///
public static int UInt8Len = 1; //a byte...
///
/// Gets the site version.
///
/// The site version.
public Version SiteVersion { get { return m_siteVersion; } }
///
/// Initializes a new instance of the class.
///
/// The stream.
/// The siteversion.
public MgBinarySerializer(Stream stream, Version siteversion)
{
m_stream = stream;
m_siteVersion = siteversion;
}
///
/// Writes the coordinates.
///
/// The coordinates.
/// The dimensions.
public void WriteCoordinates(double[] coordinates, int dimensions)
{
int ndim = dimensions;
if (ndim == 0)
ndim = 2;
else if (ndim > 4)
throw new Exception("Coordinate count reported: " + dimensions.ToString() + ", for a single coordinate");
if ((coordinates.Length % ndim) != 0)
throw new Exception("Invalid amount of coordinates...");
if (m_siteVersion <= SiteVersions.GetVersion(KnownSiteVersions.MapGuideEP1_1))
WriteClassId(18000);
else
WriteClassId(20000);
Write(coordinates.Length / ndim);
Write(dimensions);
for(int i = 0;i < coordinates.Length; i++)
Write(coordinates[i]);
}
///
/// Writes the resource identifier.
///
/// The resource ID.
public void WriteResourceIdentifier(string resourceID)
{
if (m_siteVersion <= SiteVersions.GetVersion(KnownSiteVersions.MapGuideEP1_1))
WriteClassId(12003);
else
WriteClassId(11500);
if (m_siteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2))
WriteStringInternal(resourceID);
else
Write(resourceID);
}
///
/// Writes the specified value.
///
/// The value.
public void Write(string value)
{
if (m_siteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2))
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.String, null, (ulong)value.Length + 1));
WriteStringInternal(value);
}
else
{
byte[] buf = System.Text.Encoding.UTF8.GetBytes(value + "\0");
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.String, null, (ulong)buf.Length));
WriteRaw(buf);
}
}
///
/// Writes the string internal.
///
/// The value.
public void WriteStringInternal(string value)
{
if (value == null)
value = "";
byte[] buf = System.Text.Encoding.Unicode.GetBytes(value + "\0");
int charWidth = System.Text.Encoding.Unicode.GetByteCount(" ");
m_stream.WriteByte((byte)charWidth);
m_stream.Write(BitConverter.GetBytes((UInt32)value.Length + 1), 0, UInt32Len);
m_stream.Write(buf, 0, buf.Length);
}
///
/// Writes the specified value.
///
/// The value.
public void Write(short value)
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.INT16, null, (ulong)UInt16Len));
m_stream.Write(BitConverter.GetBytes(value), 0, UInt16Len);
}
///
/// Writes the specified value.
///
/// The value.
public void Write(int value)
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.INT32, null, (ulong)UInt32Len));
m_stream.Write(BitConverter.GetBytes(value), 0, UInt32Len);
}
///
/// Writes the specified value.
///
/// The value.
public void Write(long value)
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.INT64, null, (ulong)UInt64Len));
m_stream.Write(BitConverter.GetBytes(value), 0, UInt64Len);
}
/*
private void Write(float value)
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.Float, null, (ulong)FloatLen));
m_stream.Write(BitConverter.GetBytes(value), 0, FloatLen);
}*/
///
/// Writes the specified value.
///
/// The value.
public void Write(double value)
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.Double, null, (ulong)DoubleLen));
m_stream.Write(BitConverter.GetBytes(value), 0, DoubleLen);
}
///
/// Writes the specified value.
///
/// if set to true [value].
public void Write(bool value)
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.INT8, null, (ulong)UInt8Len));
m_stream.WriteByte((byte)(value ? 1 : 0));
}
///
/// Writes the specified value.
///
/// The value.
public void Write(byte value)
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.INT8, null, (ulong)UInt8Len));
m_stream.WriteByte(value);
}
///
/// Writes the class id.
///
/// The value.
public void WriteClassId(int value)
{
Write(new MgArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.ClassId, null, (ulong)UInt32Len));
m_stream.Write(BitConverter.GetBytes(value), 0, UInt32Len);
}
///
/// Writes the stream end.
///
public void WriteStreamEnd()
{
m_stream.Write(BitConverter.GetBytes((UInt32)MgStreamHeaderValues.StreamEnd), 0, UInt32Len);
m_stream.Flush();
}
///
/// Writes the specified value.
///
/// The value.
public void Write(IBinarySerializable value)
{
if (value == null)
WriteClassId(0);
else
value.Serialize(this);
}
///
/// Writes the specified value.
///
/// The value.
private void Write(MgBinaryStreamArgumentPacket value)
{
m_stream.Write(BitConverter.GetBytes((UInt32)value.PacketHeader), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.ArgumentType), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.Version), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt64)value.Length), 0, UInt64Len);
}
///
/// Writes the specified stream.
///
/// The stream.
public void Write(Stream stream)
{
Write(new MgBinaryStreamArgumentPacket(MgPacketHeader.ArgumentSimple, MgArgumentType.INT8, null, (ulong)(stream == null ? 0 : stream.Length), MgBinaryStreamArgumentPacket.MG_STREAM_VERSION ));
Write(stream == null);
if (stream != null)
{
byte[] buf = new byte[8192];
int r = stream.Read(buf, 0, buf.Length);
while (r > 0)
{
m_stream.Write(BitConverter.GetBytes((UInt32)r), 0, UInt32Len);
r = stream.Read(buf, 0, buf.Length);
}
m_stream.Write(BitConverter.GetBytes((UInt32)0), 0, UInt32Len);
}
}
///
/// Writes the specified value.
///
/// The value.
private void Write(MgArgumentPacket value)
{
m_stream.Write(BitConverter.GetBytes((UInt32)value.PacketHeader), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.ArgumentType), 0, UInt32Len);
if (value.ArgumentType == MgArgumentType.String)
m_stream.Write(BitConverter.GetBytes((UInt32)value.Length), 0, UInt32Len);
}
/*
///
/// Writes the specified value.
///
/// The value.
private void Write(MgStreamHeader value)
{
m_stream.Write(BitConverter.GetBytes((UInt32)value.StreamStart), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.StreamVersion), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.StreamDataHdr), 0, UInt32Len);
}
///
/// Writes the specified value.
///
/// The value.
private void Write(MgOperationPacket value)
{
throw new NotImplementedException();
}
///
/// Writes the specified value.
///
/// The value.
private void Write(MgOperationResponsePacket value)
{
m_stream.Write(BitConverter.GetBytes((UInt32)value.PacketHeader), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.PacketVersion), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.ECode), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.NumReturnValues), 0, UInt32Len);
}
///
/// Writes the specified e code.
///
/// The e code.
/// The no of ret values.
private void Write(MgECode eCode, UInt32 noOfRetValues)
{
Write(new MgStreamHeader(MgStreamHeaderValues.StreamStart, MgStreamHeader.CurrentStreamVersion, MgStreamHeaderValues.StreamData));
Write(new MgOperationResponsePacket(MgPacketHeader.OperationResponse, 1, eCode, noOfRetValues));
}
///
/// Writes the specified value.
///
/// The value.
private void Write(MgControlPacket value)
{
Write(new MgStreamHeader(MgStreamHeaderValues.StreamStart, MgStreamHeader.CurrentStreamVersion, MgStreamHeaderValues.StreamData));
m_stream.Write(BitConverter.GetBytes((UInt32)value.PacketHeader), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.PacketVersion), 0, UInt32Len);
m_stream.Write(BitConverter.GetBytes((UInt32)value.ControlID), 0, UInt32Len);
WriteStreamEnd();
}
*/
///
/// Writes the raw.
///
/// The buf.
public void WriteRaw(byte[] buf)
{
m_stream.Write(buf, 0, buf.Length);
}
}
}