ln.types/serialize/ObjectWriter.cs

227 lines
6.3 KiB
C#

// /**
// * File: ObjectWriter.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.IO;
using System.Text;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using ln.types.sync;
namespace ln.types.serialize
{
/**
* Types
*
* N null
* b "false"
* B "true"
* 8 byte
* 2 short
* 4 int
* L long
* f float
* d double
* s string
* 3 ushort
* 5 uint
* l ulong
* S struct
* A Array
*
**/
public class ObjectWriter
{
public Stream Stream { get; }
public object[] ReferencedObjects
{
get => referencedObjects.ToArray();
set => referencedObjects = new List<object>(value);
}
List<object> referencedObjects = new List<object>();
public ObjectWriter(Stream stream)
{
Stream = stream;
}
private void WriteByte(char ch)
{
Stream.WriteByte((byte)ch);
}
public virtual object QueryReference(object o)
{
if (referencedObjects.Contains(o))
return referencedObjects.IndexOf(o);
referencedObjects.Add(o);
return o;
}
public void Write(object o)
{
if (o == null)
{
WriteByte('N');
}
else
{
Type type = o.GetType();
if (type.IsValueType || typeof(string).Equals(type))
{
WriteValue(o);
}
else if (type.IsArray)
{
WriteArray(o as Array);
}
else
{
WriteObject(o);
}
}
}
private void WriteArray(Array a)
{
int length = a.Length;
Type eType = a.GetType().GetElementType();
WriteByte('A');
WriteValue(eType.Assembly.FullName);
Write(eType.FullName);
WriteValue(length);
for (int n = 0; n < length; n++)
Write(a.GetValue(n));
}
private void WriteObject(object _o)
{
object o = QueryReference(_o);
if (o == _o)
{
Type type = o.GetType();
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where((x) => !x.IsNotSerialized).ToArray();
WriteByte('O');
WriteValue(type.Assembly.FullName);
WriteValue(type.FullName);
WriteValue((int)fieldInfos.Length);
foreach (FieldInfo fieldInfo in fieldInfos)
{
if (fieldInfo.GetCustomAttribute<Unsynced>() != null)
{
WriteValue(fieldInfo.Name);
WriteByte('N');
}
else
{
WriteValue(fieldInfo.Name);
Write(fieldInfo.GetValue(o));
}
}
}
else
{
WriteByte('o');
Write(o);
}
}
private void WriteValue(object value)
{
Type type = value.GetType();
if (typeof(String).Equals(type))
{
WriteByte('s');
byte[] buffer = Encoding.UTF8.GetBytes(value as string);
WriteValue(buffer.Length);
Stream.Write(buffer, 0, buffer.Length);
} else if (!type.IsPrimitive)
{
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where((x)=>!x.DeclaringType.Equals(typeof(object))).ToArray();
WriteByte('S');
WriteValue(type.Assembly.FullName);
WriteValue(type.FullName);
WriteValue(fieldInfos.Length);
foreach (FieldInfo fieldInfo in fieldInfos)
{
WriteValue(fieldInfo.Name);
Write(fieldInfo.GetValue(value));
}
}
else if (typeof(Boolean).Equals(type))
{
WriteByte((bool)value ? 'B' : 'b');
}
else if (typeof(byte).Equals(type))
{
WriteByte('8');
Stream.WriteByte((byte)value);
}
else if (typeof(short).Equals(type))
{
WriteByte('2');
Stream.Write(BitConverter.GetBytes((short)value),0,2);
}
else if (typeof(int).Equals(type))
{
WriteByte('4');
Stream.Write(BitConverter.GetBytes((int)value), 0, 4);
}
else if (typeof(long).Equals(type))
{
WriteByte('L');
Stream.Write(BitConverter.GetBytes((long)value), 0, 8);
}
else if (typeof(float).Equals(type))
{
WriteByte('f');
Stream.Write(BitConverter.GetBytes((float)value), 0, 4);
}
else if (typeof(double).Equals(type))
{
WriteByte('d');
Stream.Write(BitConverter.GetBytes((double)value), 0, 8);
}
else if (typeof(ushort).Equals(type))
{
WriteByte('3');
Stream.Write(BitConverter.GetBytes((ushort)value), 0, 2);
}
else if (typeof(uint).Equals(type))
{
WriteByte('5');
Stream.Write(BitConverter.GetBytes((uint)value), 0, 4);
}
else if (typeof(ulong).Equals(type))
{
WriteByte('l');
Stream.Write(BitConverter.GetBytes((ulong)value), 0, 8);
}
else
{
throw new NotImplementedException();
}
}
}
}