Fixed semantics of ODBEntities

pull/2/head
Harald Wolff 2019-09-20 11:42:02 +02:00
parent 71abdd8f00
commit 3d2f7a5ad0
39 changed files with 653 additions and 1196 deletions

78
Cast.cs 100644
View File

@ -0,0 +1,78 @@
// /**
// * File: Cast.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.Reflection;
using System.Linq;
using System.Threading;
namespace ln.types
{
public static class Cast
{
public static T To<T>(object value) => (T)To(value, typeof(T));
public static object To(object value, Type targetType)
{
if (Object.ReferenceEquals(null, value))
return null;
if (targetType.IsInstanceOfType(value))
return value;
object casted;
if (
!Implicit(value, targetType, out casted) &&
!Implicit(value, value.GetType(), targetType, out casted) &&
!Explicit(value, targetType, out casted) &&
!Explicit(value, value.GetType(), targetType, out casted)
)
throw new InvalidCastException();
return casted;
}
public static bool Implicit(object value, Type type, out object casted) => Implicit(value, type, type, out casted);
public static bool Implicit(object value, Type type, Type targetType, out object casted)
{
foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
if (methodInfo.Name.Equals("op_Implicit") && methodInfo.ReturnType.Equals(targetType))
{
ParameterInfo parameterInfo = methodInfo.GetParameters().FirstOrDefault();
if ((parameterInfo != null) && (parameterInfo.ParameterType.Equals(value.GetType())))
{
casted = methodInfo.Invoke(null, new object[] { value });
return true;
}
}
}
casted = null;
return false;
}
public static bool Explicit(object value, Type type, out object casted) => Implicit(value, type, type, out casted);
public static bool Explicit(object value, Type type, Type targetType, out object casted)
{
foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
if (methodInfo.Name.Equals("op_Explicit") && methodInfo.ReturnType.Equals(targetType))
{
ParameterInfo parameterInfo = methodInfo.GetParameters().FirstOrDefault();
if ((parameterInfo != null) && (parameterInfo.ParameterType.Equals(value.GetType())))
{
casted = methodInfo.Invoke(null, new object[] { value });
return true;
}
}
}
casted = null;
return false;
}
}
}

View File

@ -46,7 +46,7 @@
<Compile Include="odb\values\ODBGuid.cs" /> <Compile Include="odb\values\ODBGuid.cs" />
<Compile Include="odb\values\ODBNull.cs" /> <Compile Include="odb\values\ODBNull.cs" />
<Compile Include="odb\values\ODBStringValue.cs" /> <Compile Include="odb\values\ODBStringValue.cs" />
<Compile Include="odb\values\ODBValue.cs" /> <Compile Include="odb\values\ODBEntity.cs" />
<Compile Include="odb\values\ODBInteger.cs" /> <Compile Include="odb\values\ODBInteger.cs" />
<Compile Include="odb\values\ODBLong.cs" /> <Compile Include="odb\values\ODBLong.cs" />
<Compile Include="odb\values\ODBDouble.cs" /> <Compile Include="odb\values\ODBDouble.cs" />
@ -94,7 +94,6 @@
<Compile Include="threads\ThreadHelpers.cs" /> <Compile Include="threads\ThreadHelpers.cs" />
<Compile Include="threads\DynamicPool.cs" /> <Compile Include="threads\DynamicPool.cs" />
<Compile Include="threads\PoolThread.cs" /> <Compile Include="threads\PoolThread.cs" />
<Compile Include="odb\ng\DocumentChanges.cs" />
<Compile Include="net\IPv6.cs" /> <Compile Include="net\IPv6.cs" />
<Compile Include="arithmetics\Words.cs" /> <Compile Include="arithmetics\Words.cs" />
<Compile Include="odb\ng\storage\bases\StorageBase.cs" /> <Compile Include="odb\ng\storage\bases\StorageBase.cs" />
@ -112,6 +111,11 @@
<Compile Include="odb\ng\storage\fs\FSStorageContainer.cs" /> <Compile Include="odb\ng\storage\fs\FSStorageContainer.cs" />
<Compile Include="threads\LockingException.cs" /> <Compile Include="threads\LockingException.cs" />
<Compile Include="odb\ng\storage\bases\ChainedStorage.cs" /> <Compile Include="odb\ng\storage\bases\ChainedStorage.cs" />
<Compile Include="odb\values\ODBValue.cs" />
<Compile Include="Cast.cs" />
<Compile Include="test\CacheTests.cs" />
<Compile Include="test\ODBTests.cs" />
<Compile Include="test\TypesTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="odb\" /> <Folder Include="odb\" />

View File

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.types", "ln.types.csproj", "{8D9AB9A5-E513-4BA7-A450-534F6456BF28}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.types", "ln.types.csproj", "{8D9AB9A5-E513-4BA7-A450-534F6456BF28}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.types.test", "ln.types.test\ln.types.test.csproj", "{E39D8B11-7CF6-4C78-B723-F7E100121704}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.logging", "..\ln.logging\ln.logging.csproj", "{D471A566-9FB6-41B2-A777-3C32874ECD0E}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.logging", "..\ln.logging\ln.logging.csproj", "{D471A566-9FB6-41B2-A777-3C32874ECD0E}"
EndProject EndProject
Global Global
@ -17,10 +15,6 @@ Global
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.Build.0 = Release|Any CPU {8D9AB9A5-E513-4BA7-A450-534F6456BF28}.Release|Any CPU.Build.0 = Release|Any CPU
{E39D8B11-7CF6-4C78-B723-F7E100121704}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E39D8B11-7CF6-4C78-B723-F7E100121704}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E39D8B11-7CF6-4C78-B723-F7E100121704}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E39D8B11-7CF6-4C78-B723-F7E100121704}.Release|Any CPU.Build.0 = Release|Any CPU
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.Build.0 = Debug|Any CPU {D471A566-9FB6-41B2-A777-3C32874ECD0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D471A566-9FB6-41B2-A777-3C32874ECD0E}.Release|Any CPU.ActiveCfg = Release|Any CPU {D471A566-9FB6-41B2-A777-3C32874ECD0E}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@ -1,269 +0,0 @@
// /**
// * File: Program.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 ln.types.odb.ng.storage;
using ln.types.odb.ng;
using ln.logging;
using System.Linq;
using ln.types.threads;
using System.Collections.Generic;
using ln.types.odb.ng.mappings;
using System.Net;
using ln.types.odb.ng.storage.session;
namespace ln.types.test
{
class MainClass
{
public static void Main(string[] args)
{
IPv6 maskTest = IPv6.Parse("255.255.255.255");
Console.WriteLine("Mask Test: {0} => {1}", maskTest.ToCIDR(), maskTest.Network.ToCIDR());
for (int n=0;n<31;n++)
{
maskTest = new IPv6(maskTest, maskTest.Netmask-1);
Console.WriteLine("Mask Test: {0} => {1}", maskTest.ToCIDR(), maskTest.Network.ToCIDR());
}
ParseIPv6("1.2.3.4");
ParseIPv6("10.112.0.0/10");
ParseIPv6("::1234:5678:9ABC:DEF0");
ParseIPv6("1234:5678:9ABC:DEF0::");
ParseIPv6("::");
ParseIPv6(IPv6.V4Space.ToCIDR());
ParseIPv6("::ffff:127.0.0.1");
ParseIPv6("2001:db8::1428:57ab");
IPv6 ip = IPv6.V4Space;
Console.WriteLine("IPv4Space: {0}",ip.ToCIDR());
for (int n = 0; n < 10; n++)
{
ip++;
Console.WriteLine("+1: {0}", ip.ToCIDR());
}
for (int n = 0; n < 32; n++)
{
ip += 256;
Console.WriteLine("+256: {0}", ip.ToCIDR());
}
for (int n = 0; n < 32; n++)
{
ip += 1<<14;
Console.WriteLine("+(1<<14): {0}", ip.ToCIDR());
}
Console.WriteLine("->IPAddress: {0}", (IPAddress)ip);
IPAddress ip4 = IPAddress.Parse("10.112.1.254");
Console.WriteLine("IP4 = {0} => {1}",ip4,(IPv6)ip4);
IPv6 ten = IPv6.Parse("::ffff:10.0.0.0/104");
Console.WriteLine("Splitting Network: {0}",ten.ToCIDR());
foreach (IPv6 subnet in ten.Split(8))
Console.WriteLine(" {0}", subnet.ToCIDR());
IPv6 v6 = IPv6.Parse("2001:470:7408::/48");
Console.WriteLine("Splitting Network: {0}", v6.ToCIDR());
foreach (IPv6 subnet in v6.Split(4))
Console.WriteLine(" {0}", subnet.ToCIDR());
}
public static void ParseIPv6(string source)
{
IPv6 ip = IPv6.Parse(source);
Console.WriteLine("IPv6: {0,40} => {1} [ {3,24} ] = {2}", source, ip.ToString(false),ip,ip.Network.ToCIDR());
Console.WriteLine("CIDR: {0}", ip.ToCIDR());
Console.WriteLine("(IPAddress) = {0}", (IPAddress)ip);
}
public static void TestStorage(IStorageContainer container)
{
using (IStorage storage = container.GetStorage("test"))
{
if (!storage.IsOpen)
storage.Open();
foreach (Guid documentID in storage.GetDocumentIDs())
{
Logging.Log(LogLevel.INFO, "DocumentID: {0}", documentID);
Document doc = storage.Load(documentID);
Logging.Log(LogLevel.INFO, doc.ToString());
doc["FeldC"] = doc["FeldC"].AsLong + 1;
storage.Save(doc);
}
Document document = new Document();
document["FeldA"] = "Ich bin das Feld A";
document["FeldB"] = "Ich bin das Feld B";
document["FeldC"] = new Random().Next();
storage.Save(document);
storage.Save(document);
}
}
public static void TestMapper(IStorageContainer container)
{
Mapper mapper = new Mapper(container);
Logging.Log(LogLevel.INFO, "Cleaning up Person store");
foreach (Guid documentID in mapper.GetDocumentIDs<Person>())
mapper.Delete<Person>(documentID);
Logging.Log(LogLevel.INFO, "Storage counts {0} entities", mapper.GetDocumentIDs<Person>().Count());
Person[] persons = new Person[15000];
for (int n = 0; n < persons.Length; n++)
persons[n] = new Person();
Logging.Log(LogLevel.INFO, "Created {0} persons", persons.Length);
Timing.Meassure("store persons", () =>
{
foreach (Person person in persons)
mapper.Save(person);
});
Guid[] documentIDs = mapper.GetDocumentIDs<Person>().ToArray();
Random random = new Random();
//for (int n = 0; n < 20; n++)
//{
// Guid choosenID = documentIDs[random.Next(documentIDs.Length)];
// Person person = mapper.Load<Person>(choosenID);
// Logging.Log(LogLevel.INFO, "Querying: {0}", person.FirstName);
// IEnumerable<Guid> ids = Timing.Meassure(() => mapper.GetDocumentIDs<Person>(Query.Equals<Person>("MiddleNames[]", person.FirstName)));
// Guid[] matchedIDs = ids.ToArray();
// Logging.Log(LogLevel.INFO, "Found {0} persons.", matchedIDs.Length);
//}
IODBMapping pMapping = mapper.GetMapping<Person>();
Person p1 = new Person();
Document pd1 = pMapping.MapValue(mapper, p1) as Document;
p1.MiddleNames[1] = "N/A";
Document pd2 = pMapping.MapValue(mapper, p1) as Document;
DocumentChanges documentChanges = new DocumentChanges(pd1, pd2);
Logging.Log(LogLevel.INFO, "DocumentChanges: \n{0}",String.Join("\n",documentChanges.Changes.Select((x)=>x.ToString())));
mapper.EnsureIndex<Person>("MiddleNames[]");
mapper.EnsureIndex<Person>("FirstName");
Logging.Log(LogLevel.INFO, "using indeces");
for (int n = 0; n < 20; n++)
{
Guid choosenID = documentIDs[random.Next(documentIDs.Length)];
Person person = mapper.Load<Person>(choosenID);
IEnumerable<Guid> ids = Timing.Meassure(() => mapper.GetDocumentIDs<Person>(Query.Equals<Person>("MiddleNames[]", person.FirstName)));
Guid[] matchedIDs = ids.ToArray();
Logging.Log(LogLevel.INFO, "Queried '{0}' with {1,4} matches", person.FirstName, matchedIDs.Length);
}
for (int n = 0; n < 20; n++)
{
Guid choosenID = documentIDs[random.Next(documentIDs.Length)];
Person person = mapper.Load<Person>(choosenID);
IEnumerable<Guid> ids = Timing.Meassure(() => mapper.GetDocumentIDs<Person>(
Query.AND(
Query.Equals<Person>("MiddleNames[]", person.FirstName),
Query.Equals<Person>("FirstName", person.FirstName)
)
)
);
Guid[] matchedIDs = ids.ToArray();
Logging.Log(LogLevel.INFO, "Queried complex '{0}' with {1,4} matches", person.FirstName, matchedIDs.Length);
}
}
}
class Person
{
static Random random = new Random();
static string[] firstNames = new string[]
{
"Harald","Simone","Viola","Antigona","Peter","Paul","Maria","Karel","Bruno","Ilse","Sonja","Ute","Justus","Niclas","Pascal"
};
static string[] lastNames = new string[]
{
"Wolff","Thobaben","Schmidt","Seefeld","van der Heide","Schuhmacher","Brommer","Günther","Freilauf","Unger","Thomalla","Christensen","Person","Forghammer"
};
public string FirstName;
public string LastName;
public String[] MiddleNames;
public int Age;
public Person()
{
FirstName = firstNames[random.Next(firstNames.Length)];
LastName = lastNames[random.Next(lastNames.Length)];
MiddleNames = new string[]
{
firstNames[random.Next(firstNames.Length)],
firstNames[random.Next(firstNames.Length)],
firstNames[random.Next(firstNames.Length)]
};
Age = random.Next(120);
}
public override string ToString()
{
return string.Format("[Person FirstName={0} LastName={1} Age={2}]",FirstName,LastName,Age);
}
}
class MapableClass
{
public int ANumber { get; set; }
public String MyString;
public MapableClass()
{
ANumber = new Random().Next();
MyString = ANumber.ToString();
}
public override string ToString()
{
return String.Format("[MapableClass ANumber={0} MyString={1}]",ANumber,MyString);
}
}
}

View File

@ -1,35 +0,0 @@
// /**
// * File: AssemblyInfo.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.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("ln.types.test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

View File

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E39D8B11-7CF6-4C78-B723-F7E100121704}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ln.types.test</RootNamespace>
<AssemblyName>ln.types.test</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="nunit.framework">
<Package>nunit</Package>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TypesTests.cs" />
<Compile Include="ODBTests.cs" />
<Compile Include="CacheTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.types.csproj">
<Project>{8D9AB9A5-E513-4BA7-A450-534F6456BF28}</Project>
<Name>ln.types</Name>
</ProjectReference>
<ProjectReference Include="..\..\ln.logging\ln.logging.csproj">
<Project>{D471A566-9FB6-41B2-A777-3C32874ECD0E}</Project>
<Name>ln.logging</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -5,14 +5,16 @@ using ln.types.odb.values;
using System.Linq; using System.Linq;
namespace ln.types.odb.ng namespace ln.types.odb.ng
{ {
public class Document : ODBValue public class Document : ODBEntity
{ {
private Dictionary<ODBValue, ODBValue> properties = new Dictionary<ODBValue, ODBValue>(); public override ODBValue Identity => new ODBGuid(ID);
private Dictionary<ODBEntity, ODBEntity> properties = new Dictionary<ODBEntity, ODBEntity>();
public Document() public Document()
:base(0x1001) :base(0x1001)
{ {
ID = Guid.NewGuid(); ID = Guid.NewGuid();
} }
public Document(Guid id) public Document(Guid id)
@ -21,25 +23,26 @@ namespace ln.types.odb.ng
ID = id; ID = id;
} }
public Guid ID { get; internal set; } public Guid ID { get; }
public DateTime StorageTimeStamp { get; set; } public DateTime StorageTimeStamp { get; set; }
public Document(Guid documentID,byte[] bytes) public Document(byte[] bytes)
: this(documentID, bytes, 0, bytes.Length) : this(bytes, 0, bytes.Length)
{ } {}
public Document(Guid documentID,byte[] bytes,int offset,int length) public Document(byte[] bytes,int offset,int length)
:this(documentID) :this(new Guid(bytes.Slice(offset, 16)))
{ {
ID = documentID;
int endOffset = offset + length; int endOffset = offset + length;
offset += 16; // GUID (!!!) -> this(...)
int nProps = BitConverter.ToInt32(bytes, offset); int nProps = BitConverter.ToInt32(bytes, offset);
offset += 4; offset += 4;
for (int n=0;n<nProps;n++) for (int n=0;n<nProps;n++)
{ {
ODBValue propName = ODBValue.Deserialize(bytes,ref offset); ODBEntity propName = ODBEntity.Deserialize(bytes,ref offset);
ODBValue propValue = ODBValue.Deserialize(bytes, ref offset); ODBEntity propValue = ODBEntity.Deserialize(bytes, ref offset);
properties.Add(propName, propValue); properties.Add(propName, propValue);
} }
@ -47,7 +50,7 @@ namespace ln.types.odb.ng
throw new FormatException("Document deserialization read behind end of buffer"); throw new FormatException("Document deserialization read behind end of buffer");
} }
public ODBValue this[ODBValue propName] public ODBEntity this[ODBEntity propName]
{ {
get get
{ {
@ -68,22 +71,26 @@ namespace ln.types.odb.ng
} }
} }
} }
public ODBEntity this[string propName]
{
get => this[new ODBStringValue(propName)];
set => this[new ODBStringValue(propName)] = value;
}
public IEnumerable<ODBValue> Keys => properties.Keys; public IEnumerable<ODBEntity> Keys => properties.Keys;
public override int CompareLevel => 128; public bool Contains(string propName) => Contains(new ODBStringValue(propName));
public bool Contains(ODBEntity propName)
public bool Contains(ODBValue propName)
{ {
return !ODBNull.Instance.Equals(this[propName]); return !ODBNull.Instance.Equals(this[propName]);
} }
public override ODBValue Clone() public override ODBEntity Clone()
{ {
Document clone = new Document(ID); Document clone = new Document(ID);
clone.StorageTimeStamp = StorageTimeStamp; clone.StorageTimeStamp = StorageTimeStamp;
foreach (ODBValue fieldName in properties.Keys) foreach (ODBEntity fieldName in properties.Keys)
{ {
clone[fieldName] = this[fieldName].Clone(); clone[fieldName] = this[fieldName].Clone();
} }
@ -94,24 +101,25 @@ namespace ln.types.odb.ng
{ {
target.properties.Clear(); target.properties.Clear();
target.StorageTimeStamp = StorageTimeStamp; target.StorageTimeStamp = StorageTimeStamp;
foreach (ODBValue fieldName in properties.Keys) foreach (ODBEntity fieldName in properties.Keys)
{ {
target[fieldName] = this[fieldName].Clone(); target[fieldName] = this[fieldName].Clone();
} }
} }
public override byte[] ToStorage() public override byte[] GetStorageBytes()
{ {
MemoryStream stream = new MemoryStream(); MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream); BinaryWriter writer = new BinaryWriter(stream);
writer.Write(ID.ToByteArray());
writer.Write(properties.Count); writer.Write(properties.Count);
foreach (ODBValue propName in properties.Keys) foreach (ODBEntity propName in properties.Keys)
{ {
ODBValue propValue = properties[propName]; ODBEntity propValue = properties[propName];
propName.Store(writer); propName.Write(writer);
propValue.Store(writer); propValue.Write(writer);
} }
return stream.ToArray(); return stream.ToArray();
@ -136,37 +144,17 @@ namespace ln.types.odb.ng
return false; return false;
} }
public bool ContentEquals(Document other) protected override int compare(ODBEntity e)
{ {
if (object.ReferenceEquals(null, other)) Document other = e as Document;
return false; ODBEntity[] keys = Keys.Union(other.Keys).ToArray();
ODBValue[] keys = Keys.Union(other.Keys).ToArray(); foreach (ODBEntity key in keys)
foreach (ODBValue key in keys)
{ {
ODBValue value = this[key]; ODBEntity mine = this[key];
if (!value.ValueEquals(other[key])) ODBEntity yours = other[key];
return false;
}
return true;
}
public override bool ValueEquals(ODBValue other) int c = mine.CompareTo(yours);
{
return ContentEquals(other as Document);
}
public int CompareContent(Document other)
{
ODBValue[] keys = Keys.Union(other.Keys).ToArray();
foreach (ODBValue key in keys)
{
ODBValue mine = this[key];
ODBValue yours = other[key];
int c = ODBValue.Compare(mine, yours);
if (c != 0) if (c != 0)
return c; return c;
@ -174,18 +162,11 @@ namespace ln.types.odb.ng
return 0; return 0;
} }
public override int CompareInType(ODBValue other) public override T As<T>() => (T)Mapper.Default.UnmapValue(typeof(T), this);
{
return CompareContent(other as Document);
}
public override int CompareValueInType(ODBValue other)
{
return CompareContent(other as Document);
}
static Document() static Document()
{ {
RegisterDeserializer(0x1001, (b,o,l) => new Document(Guid.Empty,b,o+16,l)); RegisterDeserializer(0x1001, (b,o,l) => new Document(b,o+16,l));
} }
} }
} }

View File

@ -1,115 +0,0 @@
using System;
using System.Collections.Generic;
using ln.types.odb.values;
using System.Xml.Serialization;
using System.Linq;
namespace ln.types.odb.ng
{
public class DocumentChanges
{
public Document Source { get; }
public Document Destination { get; }
List<DocumentChange> changes = new List<DocumentChange>();
public DocumentChange[] Changes => changes.ToArray();
public DocumentChanges(Document src,Document dst)
{
Source = src;
Destination = dst;
diffDocument(src, dst);
}
private void diffDocument(Document src, Document dst) => diffDocument(new Stack<ODBValue>(), src, dst);
private void diffDocument(Stack<ODBValue> path,Document src,Document dst)
{
HashSet<ODBValue> keys = new HashSet<ODBValue>(src.Keys);
foreach (ODBValue key in dst.Keys)
keys.Add(key);
foreach (ODBValue key in keys)
{
path.Push(key);
diff(path, src[key], dst[key]);
path.Pop();
}
}
private void diffList(Stack<ODBValue> path,ODBList src,ODBList dst)
{
int commonLength = src.Count < dst.Count ? src.Count : dst.Count;
for (int i = 0; i < commonLength; i++)
{
path.Push(i);
diff(path, src[i], dst[i]);
path.Pop();
}
for (int i = commonLength; i < src.Count; i++)
{
path.Push(i);
diff(path, src[i], null);
path.Pop();
}
for (int i = commonLength; i < dst.Count; i++)
{
path.Push(i);
diff(path, ODBNull.Instance, dst[i]);
path.Pop();
}
}
private void diff(Stack<ODBValue> path,ODBValue srcValue,ODBValue dstValue)
{
if ((srcValue is ODBList) && (dstValue is ODBList))
{
diffList(path, srcValue as ODBList, dstValue as ODBList);
}
else if ((srcValue is Document) && (dstValue is Document))
{
diffDocument(path, srcValue as Document, dstValue as Document);
}
else if (!srcValue.Equals(dstValue))
{
changes.Add(new DocumentChange(path.Reverse(), dstValue));
}
}
public class DocumentChange
{
public ODBValue[] Path { get; }
public ODBValue Key => Path[Path.Length - 1];
public ODBValue Value { get; }
public DocumentChange(ODBValue value)
{
Value = value;
}
public DocumentChange(IEnumerable<ODBValue> path,ODBValue value)
:this(value)
{
if (path is ODBValue[])
Path = path as ODBValue[];
else
Path = path.ToArray();
}
public void Apply(Document document)
{
}
public override string ToString()
{
return String.Format("[DocumentChange Path={0} Value={1}]", String.Join("/", Path.Select((x) => x?.AsString)), Value);
}
}
}
}

View File

@ -4,7 +4,7 @@ namespace ln.types.odb.ng
{ {
public interface IODBMapping public interface IODBMapping
{ {
ODBValue MapValue(Mapper mapper, object value); ODBEntity MapValue(Mapper mapper, object value);
object UnmapValue(Mapper mapper, ODBValue oval); object UnmapValue(Mapper mapper, ODBEntity oval);
} }
} }

View File

@ -118,8 +118,8 @@ namespace ln.types.odb.ng
return storage.GetDocumentIDs(); return storage.GetDocumentIDs();
} }
public IEnumerable<Guid> GetDocumentIDs<T>(string path, Predicate<ODBValue> predicate) => GetDocumentIDs(typeof(T), path, predicate); public IEnumerable<Guid> GetDocumentIDs<T>(string path, Predicate<ODBEntity> predicate) => GetDocumentIDs(typeof(T), path, predicate);
public IEnumerable<Guid> GetDocumentIDs(Type type, string path, Predicate<ODBValue> predicate) public IEnumerable<Guid> GetDocumentIDs(Type type, string path, Predicate<ODBEntity> predicate)
{ {
IStorage storage = StorageContainer.GetStorage(type.FullName); IStorage storage = StorageContainer.GetStorage(type.FullName);
return storage.GetDocumentIDs(path,predicate); return storage.GetDocumentIDs(path,predicate);

View File

@ -12,10 +12,10 @@ using ln.types.odb.ng.storage.fs;
namespace ln.types.odb.ng namespace ln.types.odb.ng
{ {
public delegate ODBValue ODBMap(Mapper mapper, object value); public delegate ODBEntity ODBMap(Mapper mapper, object value);
public delegate object ODBUnmap(Mapper mapper, ODBValue oval); public delegate object ODBUnmap(Mapper mapper, ODBEntity oval);
public delegate ODBValue ODBMap<T>(Mapper mapper, T value); public delegate ODBEntity ODBMap<T>(Mapper mapper, T value);
public delegate T ODBUnmap<T>(Mapper mapper, ODBValue oval); public delegate T ODBUnmap<T>(Mapper mapper, ODBEntity oval);
public partial class Mapper : IDisposable public partial class Mapper : IDisposable
{ {
@ -39,74 +39,74 @@ namespace ln.types.odb.ng
RegisterMapping<string>( RegisterMapping<string>(
(mapper, value) => new ODBStringValue(value), (mapper, value) => new ODBStringValue(value),
(mapper, oval) => oval.AsString (mapper, oval) => oval.As<String>()
); );
RegisterMapping<int>( RegisterMapping<int>(
(mapper, value) => new ODBInteger(value), (mapper, value) => new ODBInteger(value),
(mapper, oval) => oval.AsInt (mapper, oval) => oval.As<int>()
); );
RegisterMapping<short>( RegisterMapping<short>(
(mapper, value) => new ODBInteger(value), (mapper, value) => new ODBInteger(value),
(mapper, oval) => oval.AsShort (mapper, oval) => oval.As<short>()
); );
RegisterMapping<byte>( RegisterMapping<byte>(
(mapper, value) => new ODBInteger(value), (mapper, value) => new ODBInteger(value),
(mapper, oval) => oval.AsByte (mapper, oval) => oval.As<Byte>()
); );
RegisterMapping<uint>( RegisterMapping<uint>(
(mapper, value) => new ODBUInteger(value), (mapper, value) => new ODBUInteger(value),
(mapper, oval) => oval.AsUInt (mapper, oval) => oval.As<uint>()
); );
RegisterMapping<ushort>( RegisterMapping<ushort>(
(mapper, value) => new ODBUInteger(value), (mapper, value) => new ODBUInteger(value),
(mapper, oval) => oval.AsUShort (mapper, oval) => oval.As<ushort>()
); );
RegisterMapping<char>( RegisterMapping<char>(
(mapper, value) => new ODBUInteger(value), (mapper, value) => new ODBUInteger(value),
(mapper, oval) => oval.AsChar (mapper, oval) => oval.As<Char>()
); );
RegisterMapping<double>( RegisterMapping<double>(
(mapper, value) => new ODBDouble(value), (mapper, value) => new ODBDouble(value),
(mapper, oval) => oval.AsDouble (mapper, oval) => oval.As<double>()
); );
RegisterMapping<float>( RegisterMapping<float>(
(mapper, value) => new ODBDouble(value), (mapper, value) => new ODBDouble(value),
(mapper, oval) => oval.AsFloat (mapper, oval) => oval.As<float>()
); );
RegisterMapping<DateTime>( RegisterMapping<DateTime>(
(mapper, value) => new ODBLong(DateTime.MinValue.Equals(value) ? 0 : new DateTimeOffset(value.ToUniversalTime()).ToUnixTimeMilliseconds() ), (mapper, value) => new ODBLong(DateTime.MinValue.Equals(value) ? 0 : new DateTimeOffset(value.ToUniversalTime()).ToUnixTimeMilliseconds() ),
(mapper, oval) => DateTimeOffset.FromUnixTimeMilliseconds(oval.AsLong).DateTime (mapper, oval) => DateTimeOffset.FromUnixTimeMilliseconds(oval.As<long>()).DateTime
); );
RegisterMapping<TimeSpan>( RegisterMapping<TimeSpan>(
(mapper, value) => new ODBDouble(value.TotalMilliseconds), (mapper, value) => new ODBDouble(value.TotalMilliseconds),
(mapper, oval) => TimeSpan.FromMilliseconds(oval.AsDouble) (mapper, oval) => TimeSpan.FromMilliseconds(oval.As<double>())
); );
RegisterMapping<Guid>( RegisterMapping<Guid>(
(mapper, value) => new ODBGuid(value), (mapper, value) => new ODBGuid(value),
(mapper, oval) => oval.AsGuid (mapper, oval) => oval.As<Guid>()
); );
RegisterMapping<long>( RegisterMapping<long>(
(mapper, value) => new ODBLong(value), (mapper, value) => new ODBLong(value),
(mapper, oval) => oval.AsLong (mapper, oval) => oval.As<long>()
); );
RegisterMapping<ulong>( RegisterMapping<ulong>(
(mapper, value) => new ODBULong(value), (mapper, value) => new ODBULong(value),
(mapper, oval) => oval.AsULong (mapper, oval) => oval.As<ulong>()
); );
RegisterMapping<bool>( RegisterMapping<bool>(
(mapper, value) => new ODBBool(value), (mapper, value) => (bool)value ? ODBBool.True : ODBBool.False,
(mapper, oval) => oval.AsBool (mapper, oval) => oval.As<bool>()
); );
RegisterMapping<IPv4>( RegisterMapping<IPv4>(
(mapper, value) => new ODBUInteger(value.AsUInt), (mapper, value) => new ODBUInteger(value.AsUInt),
(mapper, oval) => new IPv4(oval.AsUInt) (mapper, oval) => new IPv4(oval.As<uint>())
); );
ObjectMapping = new mappings.ObjectMapping(); ObjectMapping = new mappings.ObjectMapping();
@ -216,7 +216,7 @@ namespace ln.types.odb.ng
// return null; // return null;
//} //}
public virtual ODBValue MapValue(object value) public virtual ODBEntity MapValue(object value)
{ {
if (value == null) if (value == null)
return ODBNull.Instance; return ODBNull.Instance;
@ -227,7 +227,7 @@ namespace ln.types.odb.ng
throw new NotSupportedException(String.Format("Can't map {0} ({1})",value.GetType(),value)); throw new NotSupportedException(String.Format("Can't map {0} ({1})",value.GetType(),value));
} }
public virtual object UnmapValue(Type targetType,ODBValue value) public virtual object UnmapValue(Type targetType,ODBEntity value)
{ {
if (ODBNull.Instance.Equals(value)) if (ODBNull.Instance.Equals(value))
return null; return null;
@ -235,22 +235,23 @@ namespace ln.types.odb.ng
if (value is Document) if (value is Document)
{ {
Document doc = value as Document; Document doc = value as Document;
String asmname = doc["__asm__"].AsString; String asmname = doc["__asm__"].As<string>();
String typename = doc["__type__"].AsString; String typename = doc["__type__"].As<string>();
if (typename != null) if (typename != null)
targetType = Type.GetType(String.Format("{0}, {1}",typename,asmname)); //Assembly.Load(asmname).GetType(typename); targetType = Type.GetType(String.Format("{0}, {1}",typename,asmname)); //Assembly.Load(asmname).GetType(typename);
} else if (value is ODBTypedValue)
{
ODBTypedValue typedValue = value as ODBTypedValue;
targetType = typedValue.TargetType;
} }
//else if (value is ODBTypedValue)
//{
// ODBTypedValue typedValue = value as ODBTypedValue;
// targetType = typedValue.TargetType;
//}
IODBMapping mapping = GetMapping(targetType); IODBMapping mapping = GetMapping(targetType);
if (mapping != null) if (mapping != null)
return mapping.UnmapValue(this,value); return mapping.UnmapValue(this,value);
return Convert.ChangeType(value.Value, targetType); return value.As(targetType);
} }
public virtual object TryImplicitMapping(object value,Type targetType) public virtual object TryImplicitMapping(object value,Type targetType)

View File

@ -36,37 +36,37 @@ namespace ln.types.odb.ng
} }
public static Query Equals<T>(string propertyName, object value) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), Mapper.Default.MapValue(value)); public static Query Equals<T>(string propertyName, object value) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), Mapper.Default.MapValue(value));
public static Query Equals(String propertyName, ODBValue value) public static Query Equals(String propertyName, ODBEntity value)
{ {
if (object.ReferenceEquals(value,null)) if (object.ReferenceEquals(value,null))
value = ODBNull.Instance; value = ODBNull.Instance;
return IF(propertyName, (v) => value.ValueEquals(v)); return IF(propertyName, (v) => value.Equals(v));
} }
public static Query EqualsNot<T>(string propertyName, ODBValue value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value); public static Query EqualsNot<T>(string propertyName, ODBEntity value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value);
public static Query EqualsNot(String propertyName, ODBValue value) public static Query EqualsNot(String propertyName, ODBEntity value)
{ {
if (object.ReferenceEquals(value, null)) if (object.ReferenceEquals(value, null))
value = ODBNull.Instance; value = ODBNull.Instance;
return IF(propertyName, (v) => !value.ValueEquals(v)); return IF(propertyName, (v) => !value.Equals(v));
} }
public static Query Equals<T>(string propertyName, ODBValue[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values); public static Query Equals<T>(string propertyName, ODBEntity[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values);
public static Query Equals(String propertyName, ODBValue[] values) public static Query Equals(String propertyName, ODBEntity[] values)
{ {
return IF(propertyName, (v) => values.Contains(v)); return IF(propertyName, (v) => values.Contains(v));
} }
public static Query Contains<T, A>(string propertyName, IEnumerable<A> values) public static Query Contains<T, A>(string propertyName, IEnumerable<A> values)
{ {
ODBValue[] oValues = values.Select(v => Mapper.Default.MapValue(v)).ToArray(); ODBEntity[] oValues = values.Select(v => Mapper.Default.MapValue(v)).ToArray();
return IF(IndexPath.TranslatePropertyPath(typeof(T), propertyName), v => oValues.Contains(v)); return IF(IndexPath.TranslatePropertyPath(typeof(T), propertyName), v => oValues.Contains(v));
} }
public static Query IF<T>(string propertyName, Predicate<ODBValue> predicate) => IF(IndexPath.TranslatePropertyPath(typeof(T),propertyName), predicate); public static Query IF<T>(string propertyName, Predicate<ODBEntity> predicate) => IF(IndexPath.TranslatePropertyPath(typeof(T),propertyName), predicate);
public static Query IF(string propertyName,Predicate<ODBValue> predicate) public static Query IF(string propertyName,Predicate<ODBEntity> predicate)
{ {
return new IMPL.IF(propertyName, predicate); return new IMPL.IF(propertyName, predicate);
} }
@ -79,9 +79,9 @@ namespace ln.types.odb.ng
public class IF : Query public class IF : Query
{ {
public string PropertyName { get; } public string PropertyName { get; }
public Predicate<ODBValue> Predicate { get; } public Predicate<ODBEntity> Predicate { get; }
public IF(string propertyName,Predicate<ODBValue> predicate) public IF(string propertyName,Predicate<ODBEntity> predicate)
{ {
PropertyName = propertyName; PropertyName = propertyName;
Predicate = predicate; Predicate = predicate;

View File

@ -18,14 +18,14 @@ namespace ln.types.odb.ng.index
IndexName = IndexPath.Complete; IndexName = IndexPath.Complete;
} }
public virtual void Replace(Guid documentID, ODBValue value) { public virtual void Replace(Guid documentID, ODBEntity value) {
Remove(documentID); Remove(documentID);
Add(documentID, value); Add(documentID, value);
} }
public abstract void Add(Guid documentID, ODBValue value); public abstract void Add(Guid documentID, ODBEntity value);
public abstract void Remove(Guid documentID); public abstract void Remove(Guid documentID);
public abstract IEnumerable<Guid> GetDocumentIDs(Predicate<ODBValue> predicate); public abstract IEnumerable<Guid> GetDocumentIDs(Predicate<ODBEntity> predicate);
public abstract bool LoadIndex(string basePath, long lastCloseTimestamp); public abstract bool LoadIndex(string basePath, long lastCloseTimestamp);
public abstract bool SaveIndex(string basePath, long lastCloseTimestamp); public abstract bool SaveIndex(string basePath, long lastCloseTimestamp);

View File

@ -25,16 +25,16 @@ namespace ln.types.odb.ng.index
public abstract bool Ensure(Path path); public abstract bool Ensure(Path path);
public abstract bool Indexed(Path path); public abstract bool Indexed(Path path);
public virtual void Replace(Guid documentID, ODBValue value) public virtual void Replace(Guid documentID, ODBEntity value)
{ {
Remove(documentID); Remove(documentID);
Add(documentID, value); Add(documentID, value);
} }
public abstract void Add(Guid documentID, ODBValue value); public abstract void Add(Guid documentID, ODBEntity value);
public abstract void Remove(Guid documentID); public abstract void Remove(Guid documentID);
public abstract IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBValue> predicate); public abstract IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate);
public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate) public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate)
{ {
return GetDocumentIDs(SplitPath(path), predicate); return GetDocumentIDs(SplitPath(path), predicate);
} }
@ -49,7 +49,7 @@ namespace ln.types.odb.ng.index
{ {
} }
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBValue> predicate) public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{ {
return children[path.Element].GetDocumentIDs(path.Next, predicate); return children[path.Element].GetDocumentIDs(path.Next, predicate);
} }
@ -72,14 +72,14 @@ namespace ln.types.odb.ng.index
next.Remove(documentID); next.Remove(documentID);
} }
public override void Add(Guid documentID, ODBValue value) public override void Add(Guid documentID, ODBEntity value)
{ {
foreach (string childName in children.Keys) foreach (string childName in children.Keys)
{ {
children[childName].Add(documentID, (value as Document)[childName]); children[childName].Add(documentID, (value as Document)[childName]);
} }
} }
public override void Replace(Guid documentID, ODBValue value) public override void Replace(Guid documentID, ODBEntity value)
{ {
foreach (string childName in children.Keys) foreach (string childName in children.Keys)
{ {
@ -126,7 +126,7 @@ namespace ln.types.odb.ng.index
} }
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBValue> predicate) public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{ {
return nextPath.GetDocumentIDs(path.Next, predicate); return nextPath.GetDocumentIDs(path.Next, predicate);
} }
@ -135,10 +135,10 @@ namespace ln.types.odb.ng.index
{ {
nextPath.Remove(documentID); nextPath.Remove(documentID);
} }
public override void Add(Guid documentID, ODBValue value) public override void Add(Guid documentID, ODBEntity value)
{ {
if (!ODBNull.Instance.Equals(value)) if (!ODBNull.Instance.Equals(value))
foreach (ODBValue v in ((ODBList)value)) foreach (ODBEntity v in ((ODBList)value))
{ {
nextPath.Add(documentID, v); nextPath.Add(documentID, v);
} }
@ -159,7 +159,7 @@ namespace ln.types.odb.ng.index
public override bool Indexed(Path path) => true; public override bool Indexed(Path path) => true;
public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBValue> predicate) public override IEnumerable<Guid> GetDocumentIDs(Path path, Predicate<ODBEntity> predicate)
{ {
return index.GetDocumentIDs(predicate); return index.GetDocumentIDs(predicate);
} }
@ -169,11 +169,11 @@ namespace ln.types.odb.ng.index
index.Remove(documentID); index.Remove(documentID);
} }
public override void Add(Guid documentID, ODBValue value) public override void Add(Guid documentID, ODBEntity value)
{ {
index.Add(documentID, value); index.Add(documentID, value);
} }
public override void Replace(Guid documentID, ODBValue value) public override void Replace(Guid documentID, ODBEntity value)
{ {
index.Replace(documentID, value); index.Replace(documentID, value);
} }

View File

@ -10,18 +10,18 @@ namespace ln.types.odb.ng.index
{ {
public class SimpleIndex : Index public class SimpleIndex : Index
{ {
BTreeValueList<ODBValue, Guid> valueIndex = new BTreeValueList<ODBValue, Guid>(); BTreeValueList<ODBEntity, Guid> valueIndex = new BTreeValueList<ODBEntity, Guid>();
BTreeValueList<Guid, ODBValue> reverseIndex = new BTreeValueList<Guid, ODBValue>(); BTreeValueList<Guid, ODBEntity> reverseIndex = new BTreeValueList<Guid, ODBEntity>();
public SimpleIndex(Path path) public SimpleIndex(Path path)
: base(path) : base(path)
{ {
} }
public override IEnumerable<Guid> GetDocumentIDs(Predicate<ODBValue> predicate) public override IEnumerable<Guid> GetDocumentIDs(Predicate<ODBEntity> predicate)
{ {
HashSet<Guid> matchedIDs = new HashSet<Guid>(); HashSet<Guid> matchedIDs = new HashSet<Guid>();
foreach (ODBValue value in valueIndex.Keys) foreach (ODBEntity value in valueIndex.Keys)
{ {
if (predicate(value)) if (predicate(value))
foreach (Guid id in valueIndex[value]) foreach (Guid id in valueIndex[value])
@ -30,7 +30,7 @@ namespace ln.types.odb.ng.index
return matchedIDs; return matchedIDs;
} }
public override void Add(Guid documentID, ODBValue value) public override void Add(Guid documentID, ODBEntity value)
{ {
valueIndex.Add(value, documentID); valueIndex.Add(value, documentID);
reverseIndex.Add(documentID, value); reverseIndex.Add(documentID, value);
@ -40,7 +40,7 @@ namespace ln.types.odb.ng.index
{ {
if (reverseIndex.ContainsKey(documentID)) if (reverseIndex.ContainsKey(documentID))
{ {
foreach (ODBValue value in reverseIndex[documentID].ToArray()) foreach (ODBEntity value in reverseIndex[documentID].ToArray())
{ {
valueIndex.Remove(value, documentID); valueIndex.Remove(value, documentID);
} }
@ -54,9 +54,9 @@ namespace ln.types.odb.ng.index
using (FileStream fileStream = new FileStream(System.IO.Path.Combine(basePath, String.Format("{0}.idx", IndexName)), FileMode.Open)) using (FileStream fileStream = new FileStream(System.IO.Path.Combine(basePath, String.Format("{0}.idx", IndexName)), FileMode.Open))
{ {
byte[] indexBytes = fileStream.ReadBytes((int)fileStream.Length); byte[] indexBytes = fileStream.ReadBytes((int)fileStream.Length);
Document indexDocument = new Document(Guid.Empty, indexBytes, 16, indexBytes.Length - 16); Document indexDocument = new Document(indexBytes, 16, indexBytes.Length - 16);
long idxLastCloseTimestamp = indexDocument["LastCloseTimestamp"].AsLong; long idxLastCloseTimestamp = indexDocument["LastCloseTimestamp"].As<long>();
if (idxLastCloseTimestamp != lastCloseTimestamp) if (idxLastCloseTimestamp != lastCloseTimestamp)
{ {
Logging.Log(LogLevel.WARNING, "Index timestamp {0} is not matching ( {1} != {2} )", IndexName, idxLastCloseTimestamp, lastCloseTimestamp); Logging.Log(LogLevel.WARNING, "Index timestamp {0} is not matching ( {1} != {2} )", IndexName, idxLastCloseTimestamp, lastCloseTimestamp);
@ -64,13 +64,13 @@ namespace ln.types.odb.ng.index
} }
else else
{ {
foreach (ODBValue key in indexDocument.Keys) foreach (ODBEntity key in indexDocument.Keys)
{ {
if (key is ODBGuid) if (key is ODBGuid)
{ {
Guid documentID = key.AsGuid; Guid documentID = key.As<Guid>();
ODBList valueList = indexDocument[key] as ODBList; ODBList valueList = indexDocument[key] as ODBList;
foreach (ODBValue value in valueList) foreach (ODBEntity value in valueList)
{ {
Add(documentID, value); Add(documentID, value);
} }
@ -85,16 +85,16 @@ namespace ln.types.odb.ng.index
public override bool SaveIndex(string basePath, long lastCloseTimestamp) public override bool SaveIndex(string basePath, long lastCloseTimestamp)
{ {
Document indexDocument = new Document(); Document indexDocument = new Document();
indexDocument["LastCloseTimestamp"] = lastCloseTimestamp; indexDocument["LastCloseTimestamp"] = new ODBLong(lastCloseTimestamp);
foreach (Guid documentID in reverseIndex.Keys) foreach (Guid documentID in reverseIndex.Keys)
{ {
ODBList valueList = new ODBList(); ODBList valueList = new ODBList();
valueList.AddRange(reverseIndex[documentID]); valueList.AddRange(reverseIndex[documentID]);
indexDocument[documentID] = valueList; indexDocument[new ODBGuid(documentID)] = valueList;
} }
byte[] indexBytes = indexDocument.ToStorage(); byte[] indexBytes = indexDocument.GetStorageBytes();
using (FileStream fileStream = new FileStream(System.IO.Path.Combine(basePath, String.Format("{0}.idx", IndexName)), FileMode.Create)) using (FileStream fileStream = new FileStream(System.IO.Path.Combine(basePath, String.Format("{0}.idx", IndexName)), FileMode.Create))
{ {

View File

@ -65,7 +65,7 @@ namespace ln.types.odb.ng.mappings
return false; return false;
} }
public object UnmapValue(Mapper mapper,ODBValue oval) public object UnmapValue(Mapper mapper,ODBEntity oval)
{ {
Document document = oval as Document; Document document = oval as Document;
object o = Activator.CreateInstance(MappedType, true); object o = Activator.CreateInstance(MappedType, true);
@ -107,13 +107,13 @@ namespace ln.types.odb.ng.mappings
public Document MapDocument(Mapper mapper,Guid documentID,object value) public Document MapDocument(Mapper mapper,Guid documentID,object value)
{ {
Document document = new Document(documentID); Document document = new Document(documentID);
document["__asm__"] = value.GetType().Assembly.GetName().Name; document["__asm__"] = new ODBStringValue(value.GetType().Assembly.GetName().Name);
document["__type__"] = value.GetType().FullName; document["__type__"] = new ODBStringValue(value.GetType().FullName);
foreach (FieldInfo fieldInfo in mappedFields) foreach (FieldInfo fieldInfo in mappedFields)
{ {
object fv = fieldInfo.GetValue(value); object fv = fieldInfo.GetValue(value);
ODBValue ov = null; ODBEntity ov = null;
if (false) //(fieldInfo.GetCustomAttribute<ByReferenceAttribute>() != null) if (false) //(fieldInfo.GetCustomAttribute<ByReferenceAttribute>() != null)
{ {
@ -135,7 +135,7 @@ namespace ln.types.odb.ng.mappings
return document; return document;
} }
public ODBValue MapValue(Mapper mapper,object value) public ODBEntity MapValue(Mapper mapper,object value)
{ {
if (Object.ReferenceEquals(value, null)) if (Object.ReferenceEquals(value, null))
return ODBNull.Instance; return ODBNull.Instance;
@ -157,20 +157,20 @@ namespace ln.types.odb.ng.mappings
public class ObjectMapping : IODBMapping public class ObjectMapping : IODBMapping
{ {
public ODBValue MapValue(Mapper mapper, object value) public ODBEntity MapValue(Mapper mapper, object value)
{ {
return new Document(); return new Document();
} }
public object UnmapValue(Mapper mapper, ODBValue oval) public object UnmapValue(Mapper mapper, ODBEntity oval)
{ {
if (oval is Document) if (oval is Document)
{ {
Document document = oval as Document; Document document = oval as Document;
if (!document.Contains("__type__")) if (!document.Contains(new ODBStringValue("__type__")))
return new object(); return new object();
Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].AsString, document["__asm__"].AsString)); //Assembly.Load(document["__asm__"].AsString).GetType(document["__type__"].AsString); Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].As<String>(), document["__asm__"].As<String>()));
return mapper.UnmapValue(dType, oval); return mapper.UnmapValue(dType, oval);
} else if (oval is ODBList) } else if (oval is ODBList)
{ {
@ -220,10 +220,12 @@ namespace ln.types.odb.ng.mappings
return array; return array;
} }
else else if (oval is ODBValue)
{ {
return oval.Value; return (oval as ODBValue).Value;
} }
throw new NotImplementedException();
} }
} }

View File

@ -13,7 +13,7 @@ namespace ln.types.odb.ng.mappings
{ {
} }
public ODBValue MapValue(Mapper mapper, object value) public ODBEntity MapValue(Mapper mapper, object value)
{ {
Type dType = value.GetType(); Type dType = value.GetType();
@ -22,8 +22,8 @@ namespace ln.types.odb.ng.mappings
IDictionary dictionary = value as IDictionary; IDictionary dictionary = value as IDictionary;
Document document = new Document(); Document document = new Document();
document["__asm__"] = value.GetType().Assembly.GetName().Name; document["__asm__"] = new ODBStringValue(value.GetType().Assembly.GetName().Name);
document["__type__"] = value.GetType().FullName; document["__type__"] = new ODBStringValue(value.GetType().FullName);
Document kTypes = new Document(); Document kTypes = new Document();
Document vTypes = new Document(); Document vTypes = new Document();
@ -34,21 +34,21 @@ namespace ln.types.odb.ng.mappings
foreach (object key in dictionary.Keys) foreach (object key in dictionary.Keys)
{ {
object v = dictionary[key]; object v = dictionary[key];
ODBValue okey = mapper.MapValue(key); ODBEntity okey = mapper.MapValue(key);
document[okey] = mapper.MapValue(v); document[okey] = mapper.MapValue(v);
kTypes[okey] = Mapper.GetTypeName(key?.GetType()); kTypes[okey] = new ODBStringValue(Mapper.GetTypeName(key?.GetType()));
vTypes[okey] = Mapper.GetTypeName(v?.GetType()); vTypes[okey] = new ODBStringValue(Mapper.GetTypeName(v?.GetType()));
} }
return document; return document;
} }
throw new NotImplementedException(); throw new NotImplementedException();
} }
public object UnmapValue(Mapper mapper, ODBValue oval) public object UnmapValue(Mapper mapper, ODBEntity oval)
{ {
Document document = oval as Document; Document document = oval as Document;
Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].AsString,document["__asm__"].AsString)); //;Assembly.Load(document["__asm__"].AsString).GetType(document["__type__"].AsString); Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].As<String>(),document["__asm__"].As<String>())); //;Assembly.Load(document["__asm__"].AsString).GetType(document["__type__"].AsString);
if (dType.IsGenericType) if (dType.IsGenericType)
{ {
@ -62,13 +62,13 @@ namespace ln.types.odb.ng.mappings
Document ktypes = document.Contains("__ktypes__") ? document["__ktypes__"] as Document : new Document(); Document ktypes = document.Contains("__ktypes__") ? document["__ktypes__"] as Document : new Document();
Document vtypes = document.Contains("__vtypes__") ? document["__vtypes__"] as Document : new Document(); Document vtypes = document.Contains("__vtypes__") ? document["__vtypes__"] as Document : new Document();
foreach (ODBValue key in document.Keys) foreach (ODBEntity key in document.Keys)
{ {
string skey = key.AsString; string skey = key.As<String>();
if (!skey.StartsWith("__", StringComparison.InvariantCulture) || !skey.EndsWith("__",StringComparison.InvariantCulture)) if (!skey.StartsWith("__", StringComparison.InvariantCulture) || !skey.EndsWith("__",StringComparison.InvariantCulture))
{ {
Type kt = ktypes.Contains(key) ? Type.GetType(ktypes[key].AsString) : kType; Type kt = ktypes.Contains(key) ? Type.GetType(ktypes[key].As<String>()) : kType;
Type vt = vtypes.Contains(key) ? Type.GetType(vtypes[key].AsString) : vType; Type vt = vtypes.Contains(key) ? Type.GetType(vtypes[key].As<String>()) : vType;
dictionary.Add(mapper.UnmapValue(kt, key), mapper.UnmapValue(vt, document[key])); dictionary.Add(mapper.UnmapValue(kt, key), mapper.UnmapValue(vt, document[key]));
} }

View File

@ -77,7 +77,7 @@ namespace ln.types.odb.ng.mappings
return list; return list;
} }
public object UnmapValue(Mapper mapper, ODBValue oval) public object UnmapValue(Mapper mapper, ODBEntity oval)
{ {
if (TargetType.IsArray) if (TargetType.IsArray)
return UnmapArray(mapper, (ODBList)oval); return UnmapArray(mapper, (ODBList)oval);
@ -97,7 +97,7 @@ namespace ln.types.odb.ng.mappings
throw new NotImplementedException(); throw new NotImplementedException();
} }
public ODBValue MapValue(Mapper mapper, object value) public ODBEntity MapValue(Mapper mapper, object value)
{ {
if (TargetType.IsArray) if (TargetType.IsArray)
return MapArray(mapper, (Array)value); return MapArray(mapper, (Array)value);
@ -131,7 +131,7 @@ namespace ln.types.odb.ng.mappings
public IEnumerator<T> GetEnumerator() public IEnumerator<T> GetEnumerator()
{ {
foreach (ODBValue item in list) foreach (ODBEntity item in list)
yield return (T)mapper.UnmapValue(TargetType, item); yield return (T)mapper.UnmapValue(TargetType, item);
} }

View File

@ -13,12 +13,12 @@ namespace ln.types.odb.ng.mappings
this.unmap = unmap; this.unmap = unmap;
} }
public ODBValue MapValue(Mapper mapper, object value) public ODBEntity MapValue(Mapper mapper, object value)
{ {
return map(mapper, value); return map(mapper, value);
} }
public object UnmapValue(Mapper mapper, ODBValue oval) public object UnmapValue(Mapper mapper, ODBEntity oval)
{ {
return unmap(mapper, oval); return unmap(mapper, oval);
} }

View File

@ -23,7 +23,7 @@ namespace ln.types.odb.ng.storage
bool Contains(Guid documentID); bool Contains(Guid documentID);
IEnumerable<Guid> GetDocumentIDs(); IEnumerable<Guid> GetDocumentIDs();
IEnumerable<Guid> GetDocumentIDs(string path,Predicate<ODBValue> predicate); IEnumerable<Guid> GetDocumentIDs(string path,Predicate<ODBEntity> predicate);
DateTime GetStorageTimestamp(Guid documentID); DateTime GetStorageTimestamp(Guid documentID);
void EnsureIndex(params string[] path); void EnsureIndex(params string[] path);

View File

@ -78,9 +78,9 @@ namespace ln.types.odb.ng.storage
freeAreas.Add(fileArea); freeAreas.Add(fileArea);
} }
} }
public OrganizedFileArea Store(ODBValue value) public OrganizedFileArea Store(ODBEntity value)
{ {
byte[] storageBytes = value.ToStorage(); byte[] storageBytes = value.GetStorageBytes();
return Store(storageBytes); return Store(storageBytes);
} }
public OrganizedFileArea Store(byte[] bytes) public OrganizedFileArea Store(byte[] bytes)

View File

@ -65,7 +65,7 @@ namespace ln.types.odb.ng.storage.bases
return Storage.GetDocumentIDs(); return Storage.GetDocumentIDs();
} }
public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate) public virtual IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate)
{ {
return Storage.GetDocumentIDs(path, predicate); return Storage.GetDocumentIDs(path, predicate);
} }

View File

@ -69,7 +69,7 @@ namespace ln.types.odb.ng.storage.bases
/* Enumeration */ /* Enumeration */
public abstract IEnumerable<Guid> GetDocumentIDs(); public abstract IEnumerable<Guid> GetDocumentIDs();
public abstract IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate); public abstract IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate);
/* Indeces */ /* Indeces */
public abstract void EnsureIndex(params string[] path); public abstract void EnsureIndex(params string[] path);

View File

@ -52,7 +52,7 @@ namespace ln.types.odb.ng.storage.cache
public override void EnsureIndex(params string[] path) => storage.EnsureIndex(path); public override void EnsureIndex(params string[] path) => storage.EnsureIndex(path);
public override IEnumerable<Guid> GetDocumentIDs() => storage.GetDocumentIDs(); public override IEnumerable<Guid> GetDocumentIDs() => storage.GetDocumentIDs();
public override IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate) => storage.GetDocumentIDs(path, predicate); public override IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate) => storage.GetDocumentIDs(path, predicate);
public override Document Load(Guid documentID) public override Document Load(Guid documentID)
{ {

View File

@ -119,9 +119,9 @@ namespace ln.types.odb.ng.storage
byte[] indexLstBytes = indexLst.ReadBytes((int)indexLst.Length); byte[] indexLstBytes = indexLst.ReadBytes((int)indexLst.Length);
ODBList idxList = new ODBList(indexLstBytes, 0, indexLstBytes.Length); ODBList idxList = new ODBList(indexLstBytes, 0, indexLstBytes.Length);
foreach (ODBValue indexName in idxList) foreach (ODBEntity indexName in idxList)
{ {
indexRoot.Ensure(IndexPath.SplitPath(indexName.AsString)); indexRoot.Ensure(IndexPath.SplitPath(indexName.As<String>()));
} }
} }
@ -165,10 +165,10 @@ namespace ln.types.odb.ng.storage
} }
ODBList indexList = new ODBList(); ODBList indexList = new ODBList();
indexList.AddRange(indexNames.Select((x) => ODBValue.FromNative(x))); indexList.AddRange(indexNames.Select((x) => ODBEntity.FromNative(x)));
FileStream indexLst = new FileStream(System.IO.Path.Combine(StoragePath, "indeces.lst"), FileMode.Create); FileStream indexLst = new FileStream(System.IO.Path.Combine(StoragePath, "indeces.lst"), FileMode.Create);
indexLst.WriteBytes(indexList.ToStorage()); indexLst.WriteBytes(indexList.GetStorageBytes());
indexLst.Close(); indexLst.Close();
indexLst.Dispose(); indexLst.Dispose();
} }
@ -203,7 +203,7 @@ namespace ln.types.odb.ng.storage
try try
{ {
return new Document(segment.ID, storageBytes) { StorageTimeStamp = segment.TimeStamp, }; return new Document(storageBytes) { StorageTimeStamp = segment.TimeStamp, };
} catch (Exception e) } catch (Exception e)
{ {
Logging.Log(LogLevel.DEBUG, "Exception while Deserializing Document from FSStorage: {1} ID={0}",segment.ID,StoragePath); Logging.Log(LogLevel.DEBUG, "Exception while Deserializing Document from FSStorage: {1} ID={0}",segment.ID,StoragePath);
@ -220,7 +220,7 @@ namespace ln.types.odb.ng.storage
if (GetDocumentLocked(document.ID)) if (GetDocumentLocked(document.ID))
throw new LockingException(); throw new LockingException();
byte[] storageBytes = document.ToStorage(); byte[] storageBytes = document.GetStorageBytes();
SegmentedFile.Segment segment = PopUnusedSegment(storageBytes.Length); SegmentedFile.Segment segment = PopUnusedSegment(storageBytes.Length);
if (segment == null) if (segment == null)
@ -299,7 +299,7 @@ namespace ln.types.odb.ng.storage
return default(DateTime); return default(DateTime);
} }
public override IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBValue> predicate) public override IEnumerable<Guid> GetDocumentIDs(string path, Predicate<ODBEntity> predicate)
{ {
lock (this) lock (this)
{ {

View File

@ -8,39 +8,36 @@
// * // *
// **/ // **/
using System; using System;
using NUnit.Framework;
namespace ln.types.odb.values namespace ln.types.odb.values
{ {
public class ODBBool : ODBValue public class ODBBool : ODBValue
{ {
public override int CompareLevel => 254; public static ODBBool True = new ODBBool(true);
public static ODBBool False = new ODBBool(false);
public ODBBool() bool isTrue;
:base(0x04)
{}
public ODBBool(bool b) private ODBBool(bool b)
:this() :base(0x04,b)
{ {
Value = b; isTrue = b;
} }
public override byte[] ToStorage() public override byte[] GetStorageBytes() => new byte[] { isTrue ? (byte)0xFF : (byte)0x00 };
{
return new byte[] { AsBool ? (byte)0xFF : (byte)0x00 };
}
public override int CompareInType(ODBValue other) protected override int compare(ODBEntity other)
{ {
if (AsBool == other.AsBool) if (Object.ReferenceEquals(this,other))
return 0; return 0;
if (AsBool) if (isTrue)
return 1; return 1;
return -1; return -1;
} }
static ODBBool() static ODBBool()
{ {
RegisterDeserializer(0x04, (b, o, l) => new ODBBool(b[o] != 0)); RegisterDeserializer(0x04, (b, o, l) => (b[o] != 0) ? True : False);
} }
} }
} }

View File

@ -3,27 +3,15 @@ namespace ln.types.odb.values
{ {
public class ODBDouble : ODBValue public class ODBDouble : ODBValue
{ {
public override int CompareLevel => 2;
public ODBDouble()
:base(0x18)
{
}
public ODBDouble(double value) public ODBDouble(double value)
: this() :base(0x18,value)
{ {}
Value = value;
}
public override byte[] ToStorage() public override byte[] GetStorageBytes() => BitConverter.GetBytes((double)Value);
protected override int compare(ODBEntity other)
{ {
return BitConverter.GetBytes(AsDouble); double a = (double)Value;
} double b = (double)(other as ODBValue).Value;
public override int CompareInType(ODBValue other)
{
double a = AsDouble;
double b = other.AsDouble;
if (Math.Abs(a - b) < double.Epsilon) if (Math.Abs(a - b) < double.Epsilon)
return 0; return 0;
@ -34,9 +22,7 @@ namespace ln.types.odb.values
static ODBDouble() static ODBDouble()
{ {
RegisterDeserializer(0x0018, (b, o, l) => BitConverter.ToDouble(b, o)); RegisterDeserializer(0x0018, (b, o, l) => new ODBDouble(BitConverter.ToDouble(b, o)));
//RegisterValueFactory(typeof(double), v => new ODBDouble((double)v));
//RegisterValueFactory(typeof(float), v => new ODBDouble((double)v));
} }
} }
} }

View File

@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.IO;
using ln.types.odb.ng;
using System.Reflection;
using System.Runtime.CompilerServices;
/**
* typeCode list
*
* 0x0000 ODBNull
* 0x0001 ODBStringValue
* 0x0002 ODBList
* 0x0003 ODBGuid
* 0x0004 ODBBool
*
* 0x0010 ODBInteger
* 0x0011 ODBUInteger
* 0x0012 ODBLong
* 0x0013 ODBULong
*
* 0x0018 ODBDouble
*
* 0x0020 ODBTypedMapping
*
* 0x1000 ODBDocument
* 0x1001 Document (ln.types.odb.ng)
*
*
*
**/
namespace ln.types.odb.values
{
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>
///
/// </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>
/// Return a .NET native value / object that semantically equals this ODBEntity instance.
/// </summary>
/// <returns>The native .NET value</returns>
/// <typeparam name="T">The type to which this ODBEntity should be casted/converted.</typeparam>
public abstract T As<T>();
/// <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[] GetStorageBytes();
public virtual void Write(BinaryWriter storage)
{
byte[] storageBytes = GetStorageBytes();
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 (obj is ODBEntity)
return Identity.Equals((obj as ODBEntity).Identity);
return false;
}
public virtual object As(Type targetType)
{
MethodInfo methodInfo = GetType().GetMethod("As");
return methodInfo.MakeGenericMethod(targetType).Invoke(this, new object[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.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 Read(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);
}
static ODBEntity()
{
RuntimeHelpers.RunClassConstructor(typeof(ODBNull).TypeHandle);
RuntimeHelpers.RunClassConstructor(typeof(Document).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);
}
}
}

View File

@ -4,39 +4,19 @@ namespace ln.types.odb.values
{ {
public class ODBGuid : ODBValue public class ODBGuid : ODBValue
{ {
public override int CompareLevel => 20;
public ODBGuid() public ODBGuid()
:base(0x03) :base(0x03, Guid.NewGuid())
{ {}
Value = Guid.NewGuid();
}
public ODBGuid(Guid guid) public ODBGuid(Guid guid)
:this() :base(0x03,guid)
{ {}
Value = guid;
}
public override byte[] ToStorage() public override byte[] GetStorageBytes() => As<Guid>().ToByteArray();
{ protected override int compare(ODBEntity other) => ((Guid)Value).CompareTo((other as ODBGuid).Value);
return AsGuid.ToByteArray();
}
static Guid FromByteArray(byte[] b,int offset)
{
byte[] s = new byte[16];
Array.Copy(b, offset, s, 0, 16);
return new Guid(s);
}
public override int CompareInType(ODBValue other)
{
return AsGuid.CompareTo(other.AsGuid);
}
static ODBGuid() static ODBGuid()
{ {
RegisterDeserializer(0x03, (b,o,l) => FromByteArray(b,o)); RegisterDeserializer(0x03, (b, o, l) => new ODBGuid(new Guid(b.Slice(o, 16))));
} }
} }

View File

@ -4,55 +4,28 @@ namespace ln.types.odb.values
{ {
public class ODBInteger : ODBValue public class ODBInteger : ODBValue
{ {
public ODBInteger()
: base(0x10)
{
}
public ODBInteger(int i) public ODBInteger(int i)
: this() : base(0x10,i)
{ {}
Value = i; public override byte[] GetStorageBytes() => BitConverter.GetBytes((int)Value);
} protected override int compare(ODBEntity other) => (int)Value - (int)(other as ODBValue).Value;
public override bool AsBool => AsInt != 0;
public override int CompareLevel => 0;
public override byte[] ToStorage() => BitConverter.GetBytes(AsInt);
public override int CompareInType(ODBValue other)
{
return AsInt - other.AsInt;
}
static ODBInteger() static ODBInteger()
{ {
RegisterDeserializer(0x10, (b, o, l) => BitConverter.ToInt32(b, o)); RegisterDeserializer(0x10, (b, o, l) => new ODBInteger(BitConverter.ToInt32(b, o)));
//RegisterValueFactory(typeof(int), v => new ODBInteger((int)v));
//RegisterValueFactory(typeof(short), v => new ODBInteger((int)(short)v));
//RegisterValueFactory(typeof(byte), v => new ODBInteger((int)(byte)v));
} }
} }
public class ODBUInteger : ODBValue public class ODBUInteger : ODBValue
{ {
public override int CompareLevel => 5;
public ODBUInteger()
: base(0x11)
{
}
public ODBUInteger(uint i) public ODBUInteger(uint i)
: this() : base(0x11,i)
{ {}
Value = i;
}
public override byte[] ToStorage() => BitConverter.GetBytes(AsUInt); public override byte[] GetStorageBytes() => BitConverter.GetBytes((uint)Value);
protected override int compare(ODBEntity other)
public override int CompareInType(ODBValue other)
{ {
long d = (long)AsUInt - (long)other.AsUInt; long d = (long)Value - (long)(other as ODBValue).Value;
if (d == 0) if (d == 0)
return 0; return 0;
if (d < 0) if (d < 0)
@ -62,10 +35,7 @@ namespace ln.types.odb.values
static ODBUInteger() static ODBUInteger()
{ {
RegisterDeserializer(0x11, (b, o, l) => BitConverter.ToUInt32(b, o)); RegisterDeserializer(0x11, (b, o, l) => new ODBUInteger(BitConverter.ToUInt32(b, o)));
//RegisterValueFactory(typeof(uint), v => new ODBUInteger((uint)v));
//RegisterValueFactory(typeof(ushort), v => new ODBUInteger((uint)(ushort)v));
//RegisterValueFactory(typeof(char), v => new ODBUInteger((uint)(char)v));
} }
} }

View File

@ -3,11 +3,15 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Collections; using System.Collections;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using ln.types.odb.ng;
namespace ln.types.odb.values namespace ln.types.odb.values
{ {
public class ODBList : ODBValue, IEnumerable<ODBValue> public class ODBList : ODBEntity, IEnumerable<ODBEntity>
{ {
List<ODBValue> items = new List<ODBValue>(); Guid identity = Guid.NewGuid();
public override ODBValue Identity => Identity;
List<ODBEntity> items = new List<ODBEntity>();
public ODBList() public ODBList()
:base(0x02) :base(0x02)
@ -17,34 +21,36 @@ namespace ln.types.odb.values
:this() :this()
{ {
MemoryStream stream = new MemoryStream(bytes, offset, length); MemoryStream stream = new MemoryStream(bytes, offset, length);
identity = new Guid(stream.ReadBytes(16));
int nItems = stream.ReadInteger(); int nItems = stream.ReadInteger();
for (int n = 0; n < nItems; n++) for (int n = 0; n < nItems; n++)
items.Add(ODBValue.Read(stream)); items.Add(ODBEntity.Read(stream));
} }
public ODBValue this[int i] public ODBEntity this[int i]
{ {
get => items[i]; get => items[i];
set => items[i] = value; set => items[i] = value;
} }
public ODBValue this[ODBValue i] public ODBEntity this[ODBEntity i]
{ {
get => items[i.AsInt]; get => items[i.As<int>()];
set => items[i.AsInt] = value; set => items[i.As<int>()] = value;
} }
public void AddRange(IEnumerable<ODBValue> values) public void AddRange(IEnumerable<ODBEntity> values)
{ {
foreach (ODBValue value in values) foreach (ODBEntity value in values)
Add(value); Add(value);
} }
public void Add(ODBValue value) public void Add(ODBEntity value)
{ {
items.Add(value); items.Add(value);
} }
public void Remove(ODBValue value) public void Remove(ODBEntity value)
{ {
items.Remove(value); items.Remove(value);
} }
@ -55,42 +61,32 @@ namespace ln.types.odb.values
public int Count => items.Count; public int Count => items.Count;
public override ODBValue Clone() public override ODBEntity Clone()
{ {
ODBList clone = new ODBList(); ODBList clone = new ODBList();
clone.items.AddRange(this.items); clone.identity = identity;
return clone;
foreach (ODBEntity item in items)
clone.items.Add(item.Clone());
return clone;
} }
public override object Value { public override byte[] GetStorageBytes()
get
{
object[] a = new object[items.Count];
((IList)items).CopyTo(a, 0);
return a;
}
protected set
{
throw new NotSupportedException();
}
}
public override int CompareLevel => 253;
public override byte[] ToStorage()
{ {
MemoryStream stream = new MemoryStream(); MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream); BinaryWriter writer = new BinaryWriter(stream);
writer.Write(identity.ToByteArray());
writer.Write(items.Count); writer.Write(items.Count);
foreach (ODBValue value in items) foreach (ODBEntity value in items)
value.Store(writer); value.Write(writer);
return stream.ToArray(); return stream.ToArray();
} }
public override int CompareInType(ODBValue other) protected override int compare(ODBEntity other)
{ {
ODBList you = other as ODBList; ODBList you = other as ODBList;
@ -107,24 +103,7 @@ namespace ln.types.odb.values
return 0; return 0;
} }
public override bool ValueEquals(ODBValue other) public IEnumerator<ODBEntity> GetEnumerator()
{
if (other is ODBList)
{
ODBList you = other as ODBList;
if (Count != you.Count)
return false;
for (int n = 0; n < Count; n++)
if (!this[n].ValueEquals(you[n]))
return false;
return true;
}
return false;
}
public IEnumerator<ODBValue> GetEnumerator()
{ {
return items.GetEnumerator(); return items.GetEnumerator();
} }
@ -134,6 +113,8 @@ namespace ln.types.odb.values
return items.GetEnumerator(); return items.GetEnumerator();
} }
public override T As<T>() => (T)Mapper.Default.UnmapValue(typeof(T), this);
static ODBList() static ODBList()
{ {
RegisterDeserializer(0x02, (b, o, l) => new ODBList(b,o,l)); RegisterDeserializer(0x02, (b, o, l) => new ODBList(b,o,l));

View File

@ -4,23 +4,17 @@ namespace ln.types.odb.values
{ {
public class ODBLong : ODBValue public class ODBLong : ODBValue
{ {
public ODBLong() public ODBLong(long value)
: base(0x12) : base(0x12, value)
{ {}
}
public ODBLong(long i)
: this()
{
Value = i;
}
public override byte[] ToStorage() => BitConverter.GetBytes(AsLong); public override byte[] GetStorageBytes() => BitConverter.GetBytes(As<long>());
public override int CompareInType(ODBValue other) protected override int compare(ODBEntity other)
{ {
long a, b; long a, b;
a = AsLong; a = (long)Value;
b = other.AsLong; b = (long)(other as ODBValue).Value;
long d = a - b; long d = a - b;
if (d == 0) if (d == 0)
@ -30,39 +24,28 @@ namespace ln.types.odb.values
return 1; return 1;
} }
public override DateTime AsDateTime => DateTimeOffset.FromUnixTimeMilliseconds(AsLong).DateTime; public static implicit operator DateTime(ODBLong l) => DateTimeOffset.FromUnixTimeMilliseconds((long)l.Value).DateTime;
public override TimeSpan AsTimeSpan => TimeSpan.FromMilliseconds(AsDouble); public static implicit operator TimeSpan(ODBLong l) => TimeSpan.FromMilliseconds((long)l.Value);
public override int CompareLevel => 1;
static ODBLong() static ODBLong()
{ {
RegisterDeserializer(0x12, (b, o, l) => BitConverter.ToInt64(b, o)); RegisterDeserializer(0x12, (b, o, l) => new ODBLong(BitConverter.ToInt64(b, o)));
//RegisterValueFactory(typeof(long), v => new ODBLong((long)v));
//RegisterValueFactory(typeof(DateTime), v => new ODBLong(new DateTimeOffset((DateTime)v).ToUnixTimeMilliseconds()));
} }
} }
public class ODBULong : ODBValue public class ODBULong : ODBValue
{ {
public override int CompareLevel => 6; public ODBULong(ulong value)
: base(0x13,value)
{}
public ODBULong() public override byte[] GetStorageBytes() => BitConverter.GetBytes(As<ulong>());
: base(0x13) protected override int compare(ODBEntity other)
{ {
} ulong a = (ulong)Value;
public ODBULong(ulong i) ulong b = (ulong)(other as ODBValue).Value;
: this()
{
Value = i;
}
public override byte[] ToStorage() => BitConverter.GetBytes(AsULong);
public override int CompareInType(ODBValue other)
{
ulong a = AsULong;
ulong b = other.AsULong;
if (a == b) if (a == b)
return 0; return 0;
@ -73,8 +56,7 @@ namespace ln.types.odb.values
static ODBULong() static ODBULong()
{ {
RegisterDeserializer(0x13, (b, o, l) => BitConverter.ToUInt64(b, o)); RegisterDeserializer(0x13, (b, o, l) => new ODBULong(BitConverter.ToUInt64(b, o)));
//RegisterValueFactory(typeof(ulong), v => new ODBULong((ulong)v));
} }
} }

View File

@ -6,34 +6,19 @@ namespace ln.types.odb.values
{ {
public static readonly ODBNull Instance = new ODBNull(); public static readonly ODBNull Instance = new ODBNull();
public override int CompareLevel => 255; private ODBNull()
: base(0x00,null)
{}
public ODBNull() public override byte[] GetStorageBytes() => new byte[0];
: base(0x00) protected override int compare(ODBEntity other) => 0;
{ }
public override byte[] ToStorage() public override int GetHashCode() => 0;
{ public override bool Equals(object obj) => Object.ReferenceEquals(this, obj);
return new byte[0];
}
static ODBNull() static ODBNull()
{ {
RegisterDeserializer(0x00, (b,o,l) => Instance); RegisterDeserializer(0x00, (b,o,l) => Instance);
} }
public override int GetHashCode()
{
return 0;
}
public override bool Equals(object obj)
{
return (object.ReferenceEquals(obj,null)) || (obj is ODBNull);
}
public override int CompareInType(ODBValue other)
{
return 0;
}
} }
} }

View File

@ -5,39 +5,17 @@ namespace ln.types.odb.values
{ {
public class ODBStringValue : ODBValue public class ODBStringValue : ODBValue
{ {
public override int CompareLevel => 10;
public ODBStringValue() public ODBStringValue(string s)
: base(0x01) : base(0x01,s)
{ } {}
public ODBStringValue(String text)
: this()
{
Value = text;
}
public override byte[] ToStorage()
{
return Encoding.UTF8.GetBytes(AsString);
}
public override int CompareInType(ODBValue other)
{
return AsString.CompareTo(other.AsString);
}
public static implicit operator ODBStringValue(String text)
{
return new ODBStringValue(text);
}
public override byte[] GetStorageBytes() => Encoding.UTF8.GetBytes((string)Value);
protected override int compare(ODBEntity other) => ((string)Value).CompareTo((other as ODBValue).Value);
static ODBStringValue() static ODBStringValue()
{ {
RegisterDeserializer(0x01, (b, o, l) => new ODBStringValue(Encoding.UTF8.GetString(b, o, l))); RegisterDeserializer(0x01, (b, o, l) => new ODBStringValue(Encoding.UTF8.GetString(b, o, l)));
// RegisterValueFactory(typeof(string), v => new ODBStringValue((string)v));
} }
} }
} }

View File

@ -11,74 +11,74 @@ using System;
using System.IO; using System.IO;
namespace ln.types.odb.values namespace ln.types.odb.values
{ {
public class ODBTypedValue : ODBValue //public class ODBTypedValue : ODBEntity
{ //{
public ODBValue ODBValue { get; private set; } // public ODBEntity ODBValue { get; private set; }
public Type TargetType { get; private set; } // public Type TargetType { get; private set; }
public override uint AsUInt => ODBValue.AsUInt; // public override uint AsUInt => ODBValue.AsUInt;
internal ODBTypedValue() // internal ODBTypedValue()
: base(0x0020) // : base(0x0020)
{ // {
} // }
public ODBTypedValue(Type targetType,ODBValue value) // public ODBTypedValue(Type targetType,ODBEntity value)
: this() // : this()
{ // {
TargetType = targetType; // TargetType = targetType;
ODBValue = value; // ODBValue = value;
} // }
public ODBTypedValue(byte[] bytes,int offset,int length) // public ODBTypedValue(byte[] bytes,int offset,int length)
: this() // : this()
{ // {
String aname = ODBValue.Deserialize(bytes, ref offset).AsString; // String aname = ODBEntity.Deserialize(bytes, ref offset).AsString;
String tname = ODBValue.Deserialize(bytes, ref offset).AsString; // String tname = ODBEntity.Deserialize(bytes, ref offset).AsString;
ODBValue = ODBValue.Deserialize(bytes, ref offset); // ODBValue = ODBEntity.Deserialize(bytes, ref offset);
TargetType = Type.GetType(String.Format("{0}, {1}", tname, aname)); // TargetType = Type.GetType(String.Format("{0}, {1}", tname, aname));
} // }
public override int CompareLevel => 126; // public override int CompareLevel => 126;
public override int CompareInType(ODBValue other) // public override int CompareInType(ODBEntity other)
{ // {
ODBTypedValue typedValue = other as ODBTypedValue; // ODBTypedValue typedValue = other as ODBTypedValue;
return ODBValue.CompareTo(typedValue.ODBValue); // return ODBValue.CompareTo(typedValue.ODBValue);
} // }
public override byte[] ToStorage() // public override byte[] GetStorageBytes()
{ // {
MemoryStream stream = new MemoryStream(); // MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream); // BinaryWriter writer = new BinaryWriter(stream);
ODBStringValue aname = TargetType.Assembly.GetName().Name; // ODBStringValue aname = TargetType.Assembly.GetName().Name;
ODBStringValue tname = TargetType.FullName; // ODBStringValue tname = TargetType.FullName;
aname.Store(writer); // aname.Write(writer);
tname.Store(writer); // tname.Write(writer);
ODBValue.Store(writer); // ODBValue.Write(writer);
return stream.ToArray(); // return stream.ToArray();
} // }
public override int GetHashCode() // public override int GetHashCode()
{ // {
return ODBValue.GetHashCode(); // return ODBValue.GetHashCode();
} // }
public override bool Equals(object obj) // public override bool Equals(object obj)
{ // {
if (obj is ODBTypedValue) // if (obj is ODBTypedValue)
{ // {
ODBTypedValue typedValue = obj as ODBTypedValue; // ODBTypedValue typedValue = obj as ODBTypedValue;
return ODBValue.Equals(typedValue.ODBValue); // return ODBValue.Equals(typedValue.ODBValue);
} // }
return false; // return false;
} // }
static ODBTypedValue() // static ODBTypedValue()
{ // {
RegisterDeserializer(0x0020, (b, o, l) => new ODBTypedValue(b,o,l)); // RegisterDeserializer(0x0020, (b, o, l) => new ODBTypedValue(b,o,l));
} // }
} //}
} }

View File

@ -1,251 +1,68 @@
using System; // /**
using System.Collections.Generic; // * File: ODBValue.cs
using System.IO; // * Author: haraldwolff
using ln.types.odb.ng; // *
// * 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.
* typeCode list // *
* // *
* 0x0000 ODBNull // **/
* 0x0001 ODBStringValue using System;
* 0x0002 ODBList
* 0x0003 ODBGuid
* 0x0004 ODBBool
*
* 0x0010 ODBInteger
* 0x0011 ODBUInteger
* 0x0012 ODBLong
* 0x0013 ODBULong
*
* 0x0018 ODBDouble
*
* 0x0020 ODBTypedMapping
*
* 0x1000 ODBDocument
* 0x1001 Document (ln.types.odb.ng)
*
*
*
**/
namespace ln.types.odb.values namespace ln.types.odb.values
{ {
public delegate ODBValue ODBValueFactory(object value); /// <summary>
public delegate ODBValue ODBDeserialize(byte[] storageBytes, int offset, int length); /// The base type of all immutable ODB types
/// </summary>
public abstract class ODBValue : IComparable<ODBValue> public abstract class ODBValue : ODBEntity
{ {
int storageTypeCode; public object Value { get; }
public virtual object Value { get; protected set; } public override ODBValue Identity => this;
public override T As<T>() => Cast.To<T>(Value);
protected ODBValue(int storageTypeCode) public override ODBEntity Clone() => this;
{
this.storageTypeCode = storageTypeCode;
}
protected ODBValue(int storageTypeCode, object value) protected ODBValue(int storageTypeCode, object value)
: this(storageTypeCode) : base(storageTypeCode)
{ {
Value = value; Value = value;
} }
public abstract int CompareLevel { get; } public override int GetHashCode() => Value.GetHashCode();
public abstract int CompareInType(ODBValue other);
public virtual int CompareValueInType(ODBValue other) => CompareInType(other);
public abstract byte[] ToStorage();
public object AsObject => Value;
public virtual string AsString
{
get
{
return Value?.ToString();
}
}
public virtual bool AsBool
{
get
{
return (bool)Value;
}
}
public virtual byte AsByte => Convert.ToByte(Value);
public virtual char AsChar => (char)Value;
public virtual short AsShort => Convert.ToInt16(Value);
public virtual int AsInt => Convert.ToInt32(Value);
public virtual long AsLong => Convert.ToInt64(Value);
public virtual ushort AsUShort => Convert.ToUInt16(Value);
public virtual uint AsUInt => (uint)Value;
public virtual ulong AsULong => (ulong)Value;
public virtual double AsDouble => (double)Value;
public virtual float AsFloat => (float)Value;
public virtual Guid AsGuid => (Guid)Value;
public virtual DateTime AsDateTime => (DateTime)Mapper.Default.UnmapValue(typeof(DateTime), this);
public virtual TimeSpan AsTimeSpan => (TimeSpan)Mapper.Default.UnmapValue(typeof(TimeSpan), this);
public virtual ODBTypedValue AsTypedValue => this as ODBTypedValue;
public virtual Document AsDocument => (Document)this;
public virtual ODBValue Clone()
{
return this;
}
public virtual void Store(BinaryWriter storage)
{
byte[] storageBytes = ToStorage();
storage.Write(storageTypeCode);
storage.Write(storageBytes.Length);
storage.Write(storageBytes, 0, storageBytes.Length);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj is ODBValue) if (obj is ODBValue)
{ return Object.Equals(Value, (obj as ODBValue).Value);
ODBValue you = obj as ODBValue; if (obj is ODBEntity)
return Value.Equals(you.Value); return Identity.Equals((obj as ODBEntity).Identity);
} return false;
return Value.Equals(obj);
}
public virtual bool ValueEquals(ODBValue other)
{
return Equals(other);
}
public static bool operator <(ODBValue a, ODBValue b)
{
return a.CompareTo(b) < 0;
}
public static bool operator >(ODBValue a, ODBValue b)
{
return a.CompareTo(b) > 0;
}
public static bool operator <=(ODBValue a, ODBValue b)
{
return a.CompareTo(b) <= 0;
}
public static bool operator >=(ODBValue a, ODBValue b)
{
return a.CompareTo(b) >= 0;
}
public static bool operator ==(ODBValue a, ODBValue b)
{
if (Object.ReferenceEquals(a, null))
return object.ReferenceEquals(b, null);
return a.CompareTo(b) == 0;
}
public static bool operator !=(ODBValue a, ODBValue b)
{
return a.CompareTo(b) != 0;
}
public static implicit operator ODBValue(ValueType v)
{
return Mapper.Default.MapValue(v);
}
public static implicit operator ODBValue(String v)
{
return Mapper.Default.MapValue(v);
}
public static ODBValue 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 ODBValue 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));
ODBValue value = valueDeserializers[storageTypeCode](buffer, offset + 8, storageLength);
offset += 8 + storageLength;
return value;
}
public static ODBValue Read(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 int CompareTo(ODBValue other)
{
if (CompareLevel != other.CompareLevel)
return CompareLevel - other.CompareLevel;
return CompareInType(other);
}
public virtual int CompareValueTo(ODBValue other)
{
if (CompareLevel != other.CompareLevel)
return CompareLevel - other.CompareLevel;
return CompareValueInType(other);
} }
public override string ToString() public override string ToString()
{ {
return String.Format("[ODBValue Value={0}]", Value); return String.Format("[{0} Value={1}]", GetType().Name, Value);
} }
public static int Compare(ODBValue a,ODBValue b)
{
return a.CompareTo(b);
}
public static int CompareValue(ODBValue a, ODBValue b)
{
return a.CompareValueTo(b);
}
static ODBValue()
{
new Document();
new ODBNull();
new ODBStringValue(); //public virtual string AsString => As<string>();
new ODBBool(); //public virtual bool AsBool => As<bool>();
new ODBList(); //public virtual byte AsByte => As<byte>();
new ODBInteger(); //public virtual char AsChar => (char)Value;
new ODBUInteger(); //public virtual short AsShort => Convert.ToInt16(Value);
new ODBLong(); //public virtual int AsInt => Convert.ToInt32(Value);
new ODBULong(); //public virtual long AsLong => Convert.ToInt64(Value);
new ODBDouble(); //public virtual ushort AsUShort => Convert.ToUInt16(Value);
new ODBGuid(); //public virtual uint AsUInt => (uint)Value;
new ODBTypedValue(); //public virtual ulong AsULong => (ulong)Value;
}
} //public virtual double AsDouble => (double)Value;
//public virtual float AsFloat => (float)Value;
//public virtual Guid AsGuid => (Guid)Value;
//public virtual DateTime AsDateTime => (DateTime)Mapper.Default.UnmapValue(typeof(DateTime), this);
//public virtual TimeSpan AsTimeSpan => (TimeSpan)Mapper.Default.UnmapValue(typeof(TimeSpan), this);
}
} }

View File

@ -132,25 +132,25 @@ namespace ln.types.test
{ {
Document origin = new Document(); Document origin = new Document();
origin["FeldA"] = "OriginalA"; origin["FeldA"] = new ODBStringValue("OriginalA");
origin["FeldB"] = "OriginalB"; origin["FeldB"] = new ODBStringValue("OriginalB");
origin["FeldC"] = "OriginalC"; origin["FeldC"] = new ODBStringValue("OriginalC");
storage1.Save(origin); storage1.Save(origin);
Document secondary = storage2.Load(origin.ID); Document secondary = storage2.Load(origin.ID);
Assert.IsTrue(origin.ContentEquals(secondary)); Assert.IsTrue(origin.CompareTo(secondary) == 0);
secondary["FeldB"] = "ZweiB"; secondary["FeldB"] = new ODBStringValue("ZweiB");
storage2.Save(secondary); storage2.Save(secondary);
Assert.IsFalse(origin.ContentEquals(secondary)); Assert.IsFalse(origin.CompareTo(secondary) == 0);
Document reloaded1 = storage1.Load(origin.ID); Document reloaded1 = storage1.Load(origin.ID);
Assert.AreSame(reloaded1, origin); Assert.AreSame(reloaded1, origin);
Assert.IsTrue(secondary.ContentEquals(reloaded1)); Assert.IsTrue(secondary.CompareTo(reloaded1) == 0);
} }
} }