2019-03-13 08:22:08 +01:00
|
|
|
|
// /**
|
|
|
|
|
// * 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;
|
2019-03-14 13:31:21 +01:00
|
|
|
|
using ln.logging;
|
|
|
|
|
using System.Collections;
|
2019-03-13 08:22:08 +01:00
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-14 13:31:21 +01:00
|
|
|
|
private object QueryObjectReplacement(object replacement)
|
|
|
|
|
{
|
|
|
|
|
if (replacement is ListReplacement)
|
|
|
|
|
{
|
|
|
|
|
ListReplacement listReplacement = (ListReplacement)replacement;
|
|
|
|
|
|
2019-03-15 07:43:18 +01:00
|
|
|
|
IList ilist = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { listReplacement.elementType }));
|
|
|
|
|
|
|
|
|
|
foreach (object e in listReplacement.elements)
|
|
|
|
|
ilist.Add(e);
|
|
|
|
|
|
|
|
|
|
return ilist;
|
2019-03-14 13:31:21 +01:00
|
|
|
|
|
|
|
|
|
} 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();
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-13 08:22:08 +01:00
|
|
|
|
public object Read()
|
|
|
|
|
{
|
|
|
|
|
byte[] b;
|
2019-03-14 13:31:21 +01:00
|
|
|
|
int pos = (int)Stream.Position;
|
2019-03-13 08:22:08 +01:00
|
|
|
|
char ch = (char)Stream.ReadByte();
|
2019-03-14 13:31:21 +01:00
|
|
|
|
|
2019-03-13 08:22:08 +01:00
|
|
|
|
switch (ch)
|
|
|
|
|
{
|
|
|
|
|
case 'N':
|
|
|
|
|
return null;
|
|
|
|
|
case 'O':
|
|
|
|
|
return ReadObject();
|
|
|
|
|
case 'o':
|
2019-03-14 13:31:21 +01:00
|
|
|
|
return QueryObjectReplacement(Read());
|
2019-03-13 08:22:08 +01:00
|
|
|
|
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();
|
2019-03-14 13:31:21 +01:00
|
|
|
|
case 'T':
|
|
|
|
|
return ReadType();
|
2019-03-13 08:22:08 +01:00
|
|
|
|
default:
|
|
|
|
|
throw new NotImplementedException(String.Format("Identifier {0} (0x{1:x8})",ch,(int)ch));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-14 13:31:21 +01:00
|
|
|
|
private Type ReadType()
|
2019-03-13 08:22:08 +01:00
|
|
|
|
{
|
|
|
|
|
string assemblyName = Read() as string;
|
|
|
|
|
String typeName = Read() as string;
|
2019-03-14 13:31:21 +01:00
|
|
|
|
object nn = Read();
|
|
|
|
|
int nGenericArgs = (int)nn;
|
|
|
|
|
Type[] genericArgs = new Type[nGenericArgs];
|
2019-03-13 08:22:08 +01:00
|
|
|
|
|
2019-03-14 13:31:21 +01:00
|
|
|
|
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();
|
2019-03-13 08:22:08 +01:00
|
|
|
|
|
|
|
|
|
Array array = Array.CreateInstance(eType, length);
|
|
|
|
|
|
|
|
|
|
for (int n = 0; n < length; n++)
|
|
|
|
|
array.SetValue(Read(), n);
|
|
|
|
|
|
|
|
|
|
return array;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public object ReadObject()
|
|
|
|
|
{
|
2019-03-14 13:31:21 +01:00
|
|
|
|
Type type = Read<Type>();
|
|
|
|
|
object o = Activator.CreateInstance(type,true);
|
2019-03-13 08:22:08 +01:00
|
|
|
|
|
|
|
|
|
referencedObjects.Add(o);
|
|
|
|
|
|
|
|
|
|
ReadFields(o);
|
|
|
|
|
|
|
|
|
|
return o;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ReadThis(object o)
|
|
|
|
|
{
|
|
|
|
|
Stream.ReadByte();
|
2019-03-14 13:31:21 +01:00
|
|
|
|
Read<Type>();
|
2019-03-13 08:22:08 +01:00
|
|
|
|
ReadFields(o);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ReadFields(object o)
|
|
|
|
|
{
|
|
|
|
|
Type type = o.GetType();
|
2019-03-14 13:31:21 +01:00
|
|
|
|
int nFields = Read<int>();
|
2019-03-13 08:22:08 +01:00
|
|
|
|
|
|
|
|
|
for (int n = 0; n < nFields; n++)
|
|
|
|
|
{
|
2019-03-14 13:31:21 +01:00
|
|
|
|
string fieldName = Read<string>();
|
2019-03-13 08:22:08 +01:00
|
|
|
|
object value = Read();
|
|
|
|
|
|
|
|
|
|
FieldInfo fieldInfo = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
|
|
|
fieldInfo.SetValue(o, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public object ReadStruct()
|
|
|
|
|
{
|
2019-03-14 13:31:21 +01:00
|
|
|
|
Type type = Read<Type>();
|
|
|
|
|
object o = Activator.CreateInstance(type);
|
2019-03-13 08:22:08 +01:00
|
|
|
|
|
2019-03-14 13:31:21 +01:00
|
|
|
|
ReadFields(o);
|
2019-03-13 08:22:08 +01:00
|
|
|
|
|
|
|
|
|
return o;
|
|
|
|
|
}
|
|
|
|
|
private string ReadString()
|
|
|
|
|
{
|
|
|
|
|
int length = (int)Read();
|
2019-03-14 13:31:21 +01:00
|
|
|
|
|
2019-03-13 08:22:08 +01:00
|
|
|
|
byte[] buffer = new byte[length];
|
|
|
|
|
Stream.Read(buffer, 0, length);
|
|
|
|
|
return Encoding.UTF8.GetString(buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
Stream.Close();
|
|
|
|
|
Stream.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|