You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/Serialization/MemoryStreamReader.cs

568 lines
16 KiB

6 years ago
using System;
using System.Collections.Concurrent;
6 years ago
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
6 years ago
using ZeroLevel.Services.Extensions;
6 years ago
namespace ZeroLevel.Services.Serialization
{
/// <summary>
6 years ago
/// A wrapper over a MemoryStream for reading, with a check for overflow
6 years ago
/// </summary>
public sealed class MemoryStreamReader
: IBinaryReader
{
private readonly Stream _stream;
private bool _reverseByteOrder = false;
public void ReverseByteOrder(bool use_reverse_byte_order)
{
_reverseByteOrder = use_reverse_byte_order;
}
6 years ago
6 years ago
public MemoryStreamReader(byte[] data)
{
if (data == null)
throw new ArgumentNullException(nameof(data));
_stream = new MemoryStream(data);
}
public MemoryStreamReader(Stream stream)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
_stream = stream;
}
6 years ago
/// <summary>
6 years ago
/// Flag reading
6 years ago
/// </summary>
public bool ReadBoolean()
{
if (CheckOutOfRange(_stream, 1))
throw new OutOfMemoryException("Array index out of bounds");
return BitConverter.ToBoolean(new byte[1] { ReadByte() }, 0);
}
6 years ago
/// <summary>
6 years ago
/// Reading byte
6 years ago
/// </summary>
public byte ReadByte()
{
if (CheckOutOfRange(_stream, 1))
throw new OutOfMemoryException("Array index out of bounds");
return (byte)_stream.ReadByte();
}
5 years ago
public char ReadChar()
{
if (CheckOutOfRange(_stream, 2))
throw new OutOfMemoryException("Array index out of bounds");
var buffer = ReadBuffer(2);
return BitConverter.ToChar(buffer, 0);
}
6 years ago
/// <summary>
6 years ago
/// Reading bytes
6 years ago
/// </summary>
/// <returns></returns>
public byte[] ReadBytes()
{
var length = BitConverter.ToInt32(ReadBuffer(4), 0);
if (length == 0) return new byte[0];
return ReadBuffer(length);
}
public short ReadShort()
{
var buffer = ReadBuffer(2);
return BitConverter.ToInt16(buffer, 0);
}
public ushort ReadUShort()
{
var buffer = ReadBuffer(2);
return BitConverter.ToUInt16(buffer, 0);
}
6 years ago
/// <summary>
6 years ago
/// Read 32-bit integer (4 bytes)
6 years ago
/// </summary>
public Int32 ReadInt32()
{
var buffer = ReadBuffer(4);
return BitConverter.ToInt32(buffer, 0);
}
public UInt32 ReadUInt32()
{
var buffer = ReadBuffer(4);
return BitConverter.ToUInt32(buffer, 0);
}
6 years ago
public decimal ReadDecimal()
{
6 years ago
var p1 = ReadInt32();
var p2 = ReadInt32();
var p3 = ReadInt32();
var p4 = ReadInt32();
return BitConverterExt.ToDecimal(new int[] { p1, p2, p3, p4 });
6 years ago
}
6 years ago
/// <summary>
6 years ago
/// Read integer 64-bit number (8 bytes)
6 years ago
/// </summary>
public Int64 ReadLong()
{
var buffer = ReadBuffer(8);
return BitConverter.ToInt64(buffer, 0);
}
public UInt64 ReadULong()
{
var buffer = ReadBuffer(8);
return BitConverter.ToUInt64(buffer, 0);
}
6 years ago
public TimeSpan ReadTimeSpan()
{
return new TimeSpan(ReadLong());
}
6 years ago
public float ReadFloat()
{
var buffer = ReadBuffer(4);
return BitConverter.ToSingle(buffer, 0);
}
6 years ago
public double ReadDouble()
{
var buffer = ReadBuffer(8);
return BitConverter.ToDouble(buffer, 0);
}
/// <summary>
6 years ago
/// Read string (4 bytes per length + Length bytes)
6 years ago
/// </summary>
public string ReadString()
{
var length = BitConverter.ToInt32(ReadBuffer(4), 0);
if (length == 0) return null;
var buffer = ReadBuffer(length);
return Encoding.UTF8.GetString(buffer);
}
6 years ago
/// <summary>
6 years ago
/// Read GUID (16 bytes)
6 years ago
/// </summary>
public Guid ReadGuid()
{
var buffer = ReadBuffer(16);
return new Guid(buffer);
}
6 years ago
/// <summary>
6 years ago
/// Reading byte-package (read the size of the specified number of bytes, and then the packet itself read size)
6 years ago
/// </summary>
public byte[] ReadBuffer(int count)
{
if (count == 0) return null;
if (CheckOutOfRange(_stream, count))
throw new OutOfMemoryException("Array index out of bounds");
var buffer = new byte[count];
var readedCount = _stream.Read(buffer, 0, count);
if (count != readedCount)
6 years ago
throw new InvalidOperationException($"The stream returned less data ({count} bytes) than expected ({readedCount} bytes)");
if (_reverseByteOrder && count > 1)
{
byte b;
for (int i = 0; i < (count >> 1); i++)
{
b = buffer[i];
buffer[i] = buffer[count - i - 1];
buffer[count - i - 1] = b;
}
}
6 years ago
return buffer;
}
6 years ago
/// <summary>
6 years ago
/// Reading the datetime
6 years ago
/// </summary>
/// <returns></returns>
public DateTime? ReadDateTime()
{
var is_null = ReadByte();
if (is_null == 0) return null;
var buffer = ReadBuffer(8);
long deserialized = BitConverter.ToInt64(buffer, 0);
return DateTime.FromBinary(deserialized);
}
public IPAddress ReadIP()
{
6 years ago
var addr = ReadBytes();
6 years ago
return new IPAddress(addr);
}
public IPEndPoint ReadIPEndpoint()
{
6 years ago
var addr = ReadIP();
6 years ago
var port = ReadInt32();
return new IPEndPoint(addr, port);
}
/// <summary>
6 years ago
/// Check if data reading is outside the stream
6 years ago
/// </summary>
private bool CheckOutOfRange(Stream stream, int offset)
6 years ago
{
return (stream.Position + offset) > stream.Length;
}
#region Extensions
6 years ago
public List<T> ReadCollection<T>()
where T : IBinarySerializable, new()
{
int count = ReadInt32();
var collection = new List<T>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var item = new T();
item.Deserialize(this);
collection.Add(item);
}
}
return collection;
}
public Dictionary<TKey, TValue> ReadDictionary<TKey, TValue>()
{
int count = ReadInt32();
5 years ago
var collection = new Dictionary<TKey, TValue>(count);
if (count > 0)
{
TKey key;
TValue value;
for (int i = 0; i < count; i++)
{
key = ReadCompatible<TKey>();
value = ReadCompatible<TValue>();
collection.Add(key, value);
}
}
return collection;
}
public ConcurrentDictionary<TKey, TValue> ReadDictionaryAsConcurrent<TKey, TValue>()
{
int count = ReadInt32();
var collection = new ConcurrentDictionary<TKey, TValue>();
if (count > 0)
{
TKey key;
TValue value;
for (int i = 0; i < count; i++)
{
key = ReadCompatible<TKey>();
value = ReadCompatible<TValue>();
collection.TryAdd(key, value);
}
}
return collection;
}
6 years ago
public T ReadCompatible<T>()
{
return MessageSerializer.DeserializeCompatible<T>(this);
}
public T Read<T>() where T : IBinarySerializable
{
byte type = ReadByte();
if (type == 0) return default(T);
var item = (T)Activator.CreateInstance<T>();
item.Deserialize(this);
return item;
}
public List<string> ReadStringCollection()
{
int count = ReadInt32();
var collection = new List<string>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadString());
}
}
return collection;
}
public List<IPAddress> ReadIPCollection()
{
int count = ReadInt32();
var collection = new List<IPAddress>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadIP());
}
}
return collection;
}
public List<IPEndPoint> ReadIPEndPointCollection()
{
int count = ReadInt32();
var collection = new List<IPEndPoint>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadIPEndpoint());
}
}
return collection;
}
public List<Guid> ReadGuidCollection()
{
int count = ReadInt32();
var collection = new List<Guid>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadGuid());
}
}
return collection;
}
public List<DateTime> ReadDateTimeCollection()
{
int count = ReadInt32();
var collection = new List<DateTime>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadDateTime() ?? DateTime.MinValue);
}
}
return collection;
}
6 years ago
public List<Int64> ReadInt64Collection()
{
int count = ReadInt32();
var collection = new List<Int64>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadLong());
}
}
return collection;
}
6 years ago
public List<Int32> ReadInt32Collection()
{
int count = ReadInt32();
var collection = new List<Int32>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadInt32());
}
}
return collection;
}
public List<UInt64> ReadUInt64Collection()
{
int count = ReadInt32();
var collection = new List<UInt64>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadULong());
}
}
return collection;
}
public List<UInt32> ReadUInt32Collection()
{
int count = ReadInt32();
var collection = new List<UInt32>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadUInt32());
}
}
return collection;
}
public List<char> ReadCharCollection()
{
int count = ReadInt32();
var collection = new List<char>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadChar());
}
}
return collection;
}
public List<short> ReadShortCollection()
{
int count = ReadInt32();
var collection = new List<short>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadShort());
}
}
return collection;
}
public List<ushort> ReadUShortCollection()
{
int count = ReadInt32();
var collection = new List<ushort>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadUShort());
}
}
return collection;
}
6 years ago
public List<float> ReadFloatCollection()
{
int count = ReadInt32();
var collection = new List<float>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadFloat());
}
}
return collection;
}
6 years ago
public List<Double> ReadDoubleCollection()
{
int count = ReadInt32();
var collection = new List<Double>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadDouble());
}
}
return collection;
}
6 years ago
public List<bool> ReadBooleanCollection()
{
int count = ReadInt32();
var collection = new List<bool>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadBoolean());
}
}
return collection;
}
6 years ago
public List<byte> ReadByteCollection()
{
int count = ReadInt32();
var collection = new List<byte>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadByte());
}
}
return collection;
}
6 years ago
public List<byte[]> ReadByteArrayCollection()
{
int count = ReadInt32();
var collection = new List<byte[]>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadBytes());
}
}
return collection;
}
6 years ago
public List<decimal> ReadDecimalCollection()
{
int count = ReadInt32();
var collection = new List<decimal>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadDecimal());
}
}
return collection;
}
public List<TimeSpan> ReadTimeSpanCollection()
{
int count = ReadInt32();
var collection = new List<TimeSpan>(count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
collection.Add(ReadTimeSpan());
}
}
return collection;
}
#endregion Extensions
6 years ago
public void Dispose()
{
_stream.Dispose();
}
5 years ago
public Stream Stream => _stream;
6 years ago
}
}

Powered by TurnKey Linux.