ln.types/serialize/ObjectReader.cs

198 lines
5.9 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;
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];
}
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<object> items = new List<object>();
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();
}
}
}