ln.types/serialize/ObjectReader.cs

242 lines
7.1 KiB
C#

// /**
// * 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<object>(value);
}
List<object> referencedObjects = new List<object>();
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;
IList ilist = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { listReplacement.elementType }));
foreach (object e in listReplacement.elements)
ilist.Add(e);
return ilist;
} 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<dictionaryReplacement.keys.Length;n++)
{
dictionary.Add(dictionaryReplacement.keys[n], dictionaryReplacement.values[n]);
}
return dictionary;
}
return QueryReferencedObject(replacement);
}
public T Read<T>()
{
return (T)Read();
}
public object Read()
{
byte[] b;
int pos = (int)Stream.Position;
char ch = (char)Stream.ReadByte();
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()
{
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<nGenericArgs;n++)
{
genericArgs[n] = (Type)Read();
}
Type type = Assembly.Load(assemblyName).GetType(typeName);
if (nGenericArgs > 0)
{
type = type.MakeGenericType(genericArgs);
}
return type;
}
public Array ReadArray()
{
List<object> items = new List<object>();
Type eType = Read<Type>();
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<Type>();
object o = Activator.CreateInstance(type,true);
referencedObjects.Add(o);
ReadFields(o);
return o;
}
public void ReadThis(object o)
{
Stream.ReadByte();
Read<Type>();
ReadFields(o);
}
private void ReadFields(object o)
{
Type type = o.GetType();
int nFields = Read<int>();
for (int n = 0; n < nFields; n++)
{
string fieldName = Read<string>();
object value = Read();
FieldInfo fieldInfo = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
fieldInfo.SetValue(o, value);
}
}
public object ReadStruct()
{
Type type = Read<Type>();
object o = Activator.CreateInstance(type);
ReadFields(o);
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();
}
}
}