// /** // * 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(value); } List referencedObjects = new List(); 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() != 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(); } } } }