using Island.StandardLib.Exceptions;
using System;
using System.Collections.Generic;
using System.Text;
namespace Island.StandardLib.Storage
{
///
/// 表示一个提供读写操作的序列化数据容器
///
public class DataStorage
{
List Data;
public int Position { get; private set; }
public DataStorage()
{
Data = new List();
}
public DataStorage(byte[] data)
{
Data = new List(data);
}
public byte[] Bytes => Data.ToArray();
public int Size => Data.Count;
public bool IsReachedEnd => Position >= Size;
public void ReadInternal(byte[] data, int size)
{
for (int i = 0; i < size; i++)
data[i] = Data[i + Position];
Position += size;
}
public void WriteInternal(byte[] data)
{
for (int i = 0; i < data.Length; i++)
Data.Add(data[i]);
}
void WriteInternal(List data)
{
for (int i = 0; i < data.Count; i++)
Data.Add(data[i]);
}
public byte[] Read()
{
byte[] buf_size = new byte[4];
ReadInternal(buf_size, 4);
int size = BitConverter.ToInt32(buf_size, 0);
byte[] buff = new byte[size];
ReadInternal(buff, size);
return buff;
}
public void Write(T value)
where T : IStorable
{
DataStorage typeInstance = new DataStorage();
value.WriteToData(typeInstance);
int size = typeInstance.Size;
WriteInternal(BitConverter.GetBytes(size));
WriteInternal(typeInstance.Data);
}
public void Write(byte[] bytes)
{
WriteInternal(BitConverter.GetBytes(bytes.Length));
WriteInternal(bytes);
}
public void Write(int value)
{
WriteInternal(new byte[4] { 4, 0, 0, 0 });
WriteInternal(BitConverter.GetBytes(value));
}
public void Write(uint value)
{
WriteInternal(new byte[4] { 4, 0, 0, 0 });
WriteInternal(BitConverter.GetBytes(value));
}
public void Write(long value)
{
WriteInternal(new byte[4] { 8, 0, 0, 0 });
WriteInternal(BitConverter.GetBytes(value));
}
public void Write(char value)
{
WriteInternal(new byte[4] { 2, 0, 0, 0 });
WriteInternal(BitConverter.GetBytes(value));
}
public void Write(bool value)
{
WriteInternal(new byte[4] { 1, 0, 0, 0 });
WriteInternal(BitConverter.GetBytes(value));
}
public void Write(float value)
{
WriteInternal(new byte[4] { 4, 0, 0, 0 });
WriteInternal(BitConverter.GetBytes(value));
}
public void Write(double value)
{
WriteInternal(new byte[4] { 8, 0, 0, 0 });
WriteInternal(BitConverter.GetBytes(value));
}
public void Write(string value)
{
if (value == null)
value = "";
byte[] data = Encoding.UTF8.GetBytes(value);
WriteInternal(BitConverter.GetBytes(data.Length));
WriteInternal(data);
}
public void WriteNullable(T value) where T : class, IStorable, new()
{
WriteUncheck(value != null);
if (value != null) Write(value);
}
public void ReadNullable(out T value) where T : class, IStorable, new()
{
ReadUncheck(out bool hasValue);
if (hasValue) Read(out value);
else value = null;
}
public void WriteUncheck(byte value)
{
Data.Add(value);
}
public void WriteUncheck(int value)
{
WriteInternal(BitConverter.GetBytes(value));
}
public void WriteUncheck(uint value)
{
WriteInternal(BitConverter.GetBytes(value));
}
public void WriteUncheck(long value)
{
WriteInternal(BitConverter.GetBytes(value));
}
public void WriteUncheck(ulong value)
{
WriteInternal(BitConverter.GetBytes(value));
}
public void WriteUncheck(char value)
{
WriteInternal(BitConverter.GetBytes(value));
}
public void WriteUncheck(bool value)
{
WriteInternal(BitConverter.GetBytes(value));
}
public void WriteUncheck(float value)
{
WriteInternal(BitConverter.GetBytes(value));
}
public void WriteUncheck(double value)
{
WriteInternal(BitConverter.GetBytes(value));
}
public void WriteAuto(object value)
{
if (value is IStorable)
Write((IStorable)value);
else if (value is int)
Write((int)value);
else if (value is uint)
Write((uint)value);
else if (value is long)
Write((long)value);
else if (value is char)
Write((char)value);
else if (value is bool)
Write((bool)value);
else if (value is float)
Write((float)value);
else if (value is string)
Write((string)value);
else throw new DataStorageAutoException(DataStorageAutoException.Operation.WriteAuto, value);
}
public T Read() where T : IStorable, new()
{
byte[] data = Read();
DataStorage stor = new DataStorage(data);
T t = new T();
t.ReadFromData(stor);
return t;
}
public void Read(out T value) where T : IStorable, new()
{
value = Read();
}
public void Read(out int value)
{
byte[] data = Read();
if (data.Length != 4)
throw new DataStorageReadException(4, data);
value = BitConverter.ToInt32(data, 0);
}
public void Read(out uint value)
{
byte[] data = Read();
if (data.Length != 4)
throw new DataStorageReadException(4, data);
value = BitConverter.ToUInt32(data, 0);
}
public void Read(out long value)
{
byte[] data = Read();
if (data.Length != 8)
throw new DataStorageReadException(8, data);
value = BitConverter.ToInt64(data, 0);
}
public void Read(out char value)
{
byte[] data = Read();
if (data.Length != 2)
throw new DataStorageReadException(2, data);
value = BitConverter.ToChar(data, 0);
}
public void Read(out bool value)
{
byte[] data = Read();
if (data.Length != 1)
throw new DataStorageReadException(1, data);
value = BitConverter.ToBoolean(data, 0);
}
public void Read(out float value)
{
byte[] data = Read();
if (data.Length != 4)
throw new DataStorageReadException(4, data);
value = BitConverter.ToSingle(data, 0);
}
public void Read(out double value)
{
byte[] data = Read();
if (data.Length != 8)
throw new DataStorageReadException(8, data);
value = BitConverter.ToDouble(data, 0);
}
public void Read(out string value)
{
byte[] data = Read();
value = Encoding.UTF8.GetString(data);
}
public void ReadUncheck(out int value)
{
byte[] data = new byte[4];
ReadInternal(data, 4);
value = BitConverter.ToInt32(data, 0);
}
public void ReadUncheck(out byte value)
{
value = Data[Position++];
}
public void ReadUncheck(out uint value)
{
byte[] data = new byte[4];
ReadInternal(data, 4);
value = BitConverter.ToUInt32(data, 0);
}
public void ReadUncheck(out long value)
{
byte[] data = new byte[8];
ReadInternal(data, 8);
value = BitConverter.ToInt64(data, 0);
}
public void ReadUncheck(out ulong value)
{
byte[] data = new byte[8];
ReadInternal(data, 8);
value = BitConverter.ToUInt64(data, 0);
}
public void ReadUncheck(out char value)
{
byte[] data = new byte[2];
ReadInternal(data, 2);
value = BitConverter.ToChar(data, 0);
}
public void ReadUncheck(out bool value)
{
byte[] data = new byte[1];
ReadInternal(data, 1);
value = BitConverter.ToBoolean(data, 0);
}
public void ReadUncheck(out float value)
{
byte[] data = new byte[4];
ReadInternal(data, 4);
value = BitConverter.ToSingle(data, 0);
}
public void ReadUncheck(out double value)
{
byte[] data = new byte[8];
ReadInternal(data, 8);
value = BitConverter.ToDouble(data, 0);
}
}
}