209 lines
7.4 KiB
C#
209 lines
7.4 KiB
C#
using ln.type;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
|
|
/**
|
|
* typeCode list
|
|
*
|
|
* 0x0000 ODBNull
|
|
* 0x0001 ODBStringValue
|
|
* 0x0002 ODBList
|
|
* 0x0003 ODBGuid
|
|
* 0x0004 ODBBool
|
|
* 0x0005 ODBObject
|
|
*
|
|
* 0x0010 ODBInteger
|
|
* 0x0011 ODBUInteger
|
|
* 0x0012 ODBLong
|
|
* 0x0013 ODBULong
|
|
*
|
|
* 0x0018 ODBDouble
|
|
*
|
|
* 0x0020 ODBTypedMapping
|
|
*
|
|
* 0x0800 ODBByteBuffer
|
|
*
|
|
* 0x1000 ODBDocument
|
|
* 0x1001 Document (ln.types.odb.ng)
|
|
*
|
|
*
|
|
*
|
|
**/
|
|
|
|
|
|
|
|
namespace ln.objects.catalog
|
|
{
|
|
public delegate ODBEntity ODBValueFactory(object value);
|
|
public delegate ODBEntity ODBDeserialize(byte[] storageBytes, int offset, int length);
|
|
|
|
/// <summary>
|
|
/// ODBEntity. The base of all ODB types.
|
|
/// </summary>
|
|
/// <remarks>The data model used by ODB can be described as follows:
|
|
///
|
|
/// Each piece of information to be used with ODB may be called an entity.
|
|
/// ODB provides support for several types of entities (e.g. numbers, strings, documents, lists,...)
|
|
/// An entity has an identity and a state.
|
|
/// Two entities of same type having the same identity are considered to be "equal".
|
|
/// Two entities of same type having the same identity may represent different states of the same entity. (different "Versions", e.g. an old and up to date
|
|
///
|
|
/// <c>ODBEntity</c> instances
|
|
/// - define identity through <c>Identity</c>
|
|
/// - may be seen as a "container" holding a certain state
|
|
///
|
|
/// <c>ODBValue</c> instances
|
|
/// extend <c>ODBEntity</c>
|
|
/// - implement <c>Identity</c> to return itself
|
|
/// - implement <c>CompareTo</c> as simple "substraction"
|
|
///
|
|
/// other <c>ODBEntity</c> subtypes
|
|
/// - implement a read-only <c>Identity</c> to return a <c>ODBvalue</c> instance
|
|
/// - implement <c>CompareTo</c> type specific without defined semantic meaning
|
|
///
|
|
///
|
|
/// </remarks>
|
|
///
|
|
public abstract class ODBEntity : IComparable<ODBEntity>
|
|
{
|
|
int storageTypeCode;
|
|
|
|
/// <summary>
|
|
/// Gets the identity of this Entity.
|
|
/// </summary>
|
|
/// <value>The identity.</value>
|
|
public virtual ODBValue Identity { get; }
|
|
|
|
/// <summary>
|
|
/// Independently clone this instance.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// For immutable values this returns the instance itself.
|
|
/// Complex ODBEntities will return a copy of themself that is completly independend of the source.
|
|
/// </remarks>
|
|
/// <returns>The clone.</returns>
|
|
public abstract ODBEntity Clone();
|
|
|
|
/// <summary>
|
|
/// Implements the internal comparison within the same subclass of ODBEntity.
|
|
/// </summary>
|
|
/// <returns>The compare.</returns>
|
|
/// <param name="other">Other.</param>
|
|
protected abstract int compare(ODBEntity other);
|
|
|
|
|
|
|
|
|
|
protected ODBEntity(int storageTypeCode)
|
|
{
|
|
this.storageTypeCode = storageTypeCode;
|
|
}
|
|
|
|
|
|
public int CompareTo(ODBEntity other)
|
|
{
|
|
if (storageTypeCode != other.storageTypeCode)
|
|
return storageTypeCode - other.storageTypeCode;
|
|
return compare(other);
|
|
}
|
|
|
|
public abstract byte[] Serialize();
|
|
public virtual void Serialize(BinaryWriter storage)
|
|
{
|
|
byte[] storageBytes = Serialize();
|
|
|
|
storage.Write(storageTypeCode);
|
|
storage.Write(storageBytes.Length);
|
|
storage.Write(storageBytes, 0, storageBytes.Length);
|
|
}
|
|
|
|
public override int GetHashCode() => Identity.GetHashCode();
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (Equals(GetType(), obj.GetType()) && obj is ODBEntity)
|
|
return Equals(Identity, (obj as ODBEntity).Identity);
|
|
return false;
|
|
}
|
|
|
|
public static bool operator <(ODBEntity a, ODBEntity b) => a.CompareTo(b) < 0;
|
|
public static bool operator >(ODBEntity a, ODBEntity b) => a.CompareTo(b) > 0;
|
|
public static bool operator <=(ODBEntity a, ODBEntity b) => a.CompareTo(b) <= 0;
|
|
public static bool operator >=(ODBEntity a, ODBEntity b) => a.CompareTo(b) >= 0;
|
|
public static bool operator ==(ODBEntity a, ODBEntity b) => a is null ? b is null : a.CompareTo(b) == 0;
|
|
public static bool operator !=(ODBEntity a, ODBEntity b) => a is null ? !(b is null) : a.CompareTo(b) != 0;
|
|
|
|
//public static implicit operator ODBEntity(ValueType v)
|
|
//{
|
|
// return Mapper.Default.MapValue(v);
|
|
//}
|
|
//public static implicit operator ODBEntity(String v)
|
|
//{
|
|
// return Mapper.Default.MapValue(v);
|
|
//}
|
|
|
|
//public static ODBEntity FromNative(object v)
|
|
//{
|
|
// return Mapper.Default.MapValue(v);
|
|
//}
|
|
|
|
static Dictionary<int, ODBDeserialize> valueDeserializers = new Dictionary<int, ODBDeserialize>();
|
|
public static void RegisterDeserializer(int storageTypeCode, ODBDeserialize deserialize)
|
|
{
|
|
valueDeserializers.Add(storageTypeCode, deserialize);
|
|
}
|
|
|
|
public static ODBEntity Deserialize(byte[] buffer, ref int offset)
|
|
{
|
|
int storageTypeCode = BitConverter.ToInt32(buffer, offset);
|
|
int storageLength = BitConverter.ToInt32(buffer, offset + 4);
|
|
if (!valueDeserializers.ContainsKey(storageTypeCode))
|
|
throw new KeyNotFoundException(string.Format("StorageTypeCode 0x{0:x8} at offset 0x{1:x8}", storageTypeCode, offset));
|
|
|
|
ODBEntity value = valueDeserializers[storageTypeCode](buffer, offset + 8, storageLength);
|
|
offset += 8 + storageLength;
|
|
return value;
|
|
}
|
|
|
|
public static ODBEntity Deserialize(Stream stream)
|
|
{
|
|
int storageTypeCode = stream.ReadInteger();
|
|
int storageLength = stream.ReadInteger();
|
|
byte[] b = new byte[storageLength];
|
|
stream.Read(b, 0, storageLength);
|
|
|
|
if (valueDeserializers.ContainsKey(storageTypeCode))
|
|
return valueDeserializers[storageTypeCode](b, 0, storageLength);
|
|
else
|
|
throw new FormatException("wrong storage type code");
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return string.Format("[{0} Identity={1}]", GetType().Name, Identity);
|
|
}
|
|
|
|
public string TreeString => ToTreeString(0);
|
|
public abstract string ToTreeString(int indent);
|
|
|
|
static ODBEntity()
|
|
{
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBNull).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBObject).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBList).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBStringValue).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBInteger).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBUInteger).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBLong).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBULong).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBDouble).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBGuid).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBBool).TypeHandle);
|
|
RuntimeHelpers.RunClassConstructor(typeof(ODBByteBuffer).TypeHandle);
|
|
}
|
|
}
|
|
}
|