227 lines
6.3 KiB
C#
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();
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|