// /** // * 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; using ln.logging; using System.Collections; 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]; } private object QueryObjectReplacement(object replacement) { if (replacement is ListReplacement) { ListReplacement listReplacement = (ListReplacement)replacement; object list = Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { listReplacement.elementType }), new object[] { listReplacement.elements }); return list; } else if (replacement is DictionaryReplacement) { DictionaryReplacement dictionaryReplacement = (DictionaryReplacement)replacement; IDictionary dictionary = (IDictionary)Activator.CreateInstance(typeof(Dictionary<,>).MakeGenericType(new Type[] { dictionaryReplacement.keyType, dictionaryReplacement.valueType })); for (int n=0;n() { return (T)Read(); } public object Read() { byte[] b; int pos = (int)Stream.Position; char ch = (char)Stream.ReadByte(); Logging.Log(LogLevel.DEBUG, "Read: {0} @ 0x{1:x8}", ch, pos); switch (ch) { case 'N': return null; case 'O': return ReadObject(); case 'o': return QueryObjectReplacement(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(); case 'T': return ReadType(); default: throw new NotImplementedException(String.Format("Identifier {0} (0x{1:x8})",ch,(int)ch)); } } private Type ReadType() { Logging.Log(LogLevel.DEBUG, "readType()"); string assemblyName = Read() as string; String typeName = Read() as string; object nn = Read(); int nGenericArgs = (int)nn; Type[] genericArgs = new Type[nGenericArgs]; for (int n=0;n 0) { type = type.MakeGenericType(genericArgs); } return type; } public Array ReadArray() { List items = new List(); Type eType = Read(); int length = (int)Read(); Array array = Array.CreateInstance(eType, length); for (int n = 0; n < length; n++) array.SetValue(Read(), n); return array; } public object ReadObject() { Type type = Read(); object o = Activator.CreateInstance(type,true); referencedObjects.Add(o); ReadFields(o); return o; } public void ReadThis(object o) { Stream.ReadByte(); Read(); ReadFields(o); } private void ReadFields(object o) { Type type = o.GetType(); int nFields = Read(); for (int n = 0; n < nFields; n++) { string fieldName = Read(); object value = Read(); FieldInfo fieldInfo = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); fieldInfo.SetValue(o, value); } } public object ReadStruct() { Type type = Read(); object o = Activator.CreateInstance(type); ReadFields(o); return o; } private string ReadString() { int length = (int)Read(); Logging.Log(LogLevel.DEBUG, "ReadString({0})", length); byte[] buffer = new byte[length]; Stream.Read(buffer, 0, length); return Encoding.UTF8.GetString(buffer); } public void Dispose() { Stream.Close(); Stream.Dispose(); } } }