// /** // * File: ObjectReader.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.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using System.Runtime.InteropServices.WindowsRuntime; using System.Linq; namespace ln.types.serialize { public class ObjectReader : IDisposable { public Stream Stream { get; } public object[] ReferencedObjects { get => referencedObjects.ToArray(); set => referencedObjects = new List(value); } List referencedObjects = new List(); public ObjectReader(Stream stream) { Stream = stream; } public ObjectReader(String fileName) { Stream = new FileStream(fileName,FileMode.Open); } public virtual object QueryReferencedObject(object re) { return referencedObjects[(int)re]; } public object Read() { byte[] b; char ch = (char)Stream.ReadByte(); switch (ch) { case 'N': return null; case 'O': return ReadObject(); case 'o': return QueryReferencedObject(Read()); case 's': return ReadString(); case '8': return (byte)Stream.ReadByte(); case '2': b = new byte[2]; Stream.Read(b, 0, b.Length); return BitConverter.ToInt16(b, 0); case '4': b = new byte[4]; Stream.Read(b, 0, b.Length); return BitConverter.ToInt32(b, 0); case 'L': b = new byte[8]; Stream.Read(b, 0, b.Length); return BitConverter.ToInt64(b, 0); case '3': b = new byte[2]; Stream.Read(b, 0, b.Length); return BitConverter.ToUInt16(b, 0); case '5': b = new byte[4]; Stream.Read(b, 0, b.Length); return BitConverter.ToUInt32(b, 0); case 'l': b = new byte[8]; Stream.Read(b, 0, b.Length); return BitConverter.ToUInt64(b, 0); case 'f': b = new byte[4]; Stream.Read(b, 0, b.Length); return BitConverter.ToSingle(b, 0); case 'd': b = new byte[8]; Stream.Read(b, 0, b.Length); return BitConverter.ToDouble(b, 0); case 'B': return true; case 'b': return false; case 'S': return ReadStruct(); case 'A': return ReadArray(); default: throw new NotImplementedException(String.Format("Identifier {0} (0x{1:x8})",ch,(int)ch)); } } public Array ReadArray() { List items = new List(); string assemblyName = Read() as string; String typeName = Read() as string; int length = (int)Read(); Type eType = Assembly.Load(assemblyName).GetType(typeName); Array array = Array.CreateInstance(eType, length); for (int n = 0; n < length; n++) array.SetValue(Read(), n); return array; } public object ReadObject() { String assemblyName = Read() as string; String typeName = Read() as string; object o = Activator.CreateInstance(assemblyName, typeName).Unwrap(); Type type = o.GetType(); referencedObjects.Add(o); ReadFields(o); return o; } public void ReadThis(object o) { Stream.ReadByte(); String assemblyName = Read() as string; String typeName = Read() as string; ReadFields(o); } private void ReadFields(object o) { Type type = o.GetType(); int nFields = (int)Read(); for (int n = 0; n < nFields; n++) { string fieldName = Read() as string; object value = Read(); FieldInfo fieldInfo = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); fieldInfo.SetValue(o, value); } } public object ReadStruct() { String assemblyName = Read() as string; String typeName = Read() as string; int nFields = (int)Read(); object o = Activator.CreateInstance(assemblyName, typeName).Unwrap(); Type type = o.GetType(); for (int n = 0; n < nFields; n++) { string fieldName = Read() as string; object value = Read(); FieldInfo fieldInfo = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); fieldInfo.SetValue(o, value); } return o; } private string ReadString() { int length = (int)Read(); byte[] buffer = new byte[length]; Stream.Read(buffer, 0, length); return Encoding.UTF8.GetString(buffer); } public void Dispose() { Stream.Close(); Stream.Dispose(); } } }