Byte keys for RaptorDB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Runtime.InteropServices; | |
using System.Security; | |
using System.Text; | |
namespace RaptorDB | |
{ | |
public sealed class ByteKey : IComparable<ByteKey> | |
{ | |
[SuppressUnmanagedCodeSecurity] | |
private static class NativeMethods | |
{ | |
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] | |
public static extern int memcmp(byte[] b1, byte[] b2, long count); | |
} | |
public readonly byte[] Data; | |
public readonly int Hash; | |
private static readonly MurmurHash2Unsafe _murmur = new MurmurHash2Unsafe(); | |
public ByteKey(byte[] data) | |
{ | |
if (data == null) throw new ArgumentNullException("data"); | |
Data = data; | |
Hash = (int)_murmur.Hash(Data); | |
} | |
public ByteKey(byte[] buffer, int offset, int count) | |
{ | |
if (buffer == null) throw new ArgumentNullException("data"); | |
if (offset + count > buffer.Length) throw new ArgumentOutOfRangeException("offset"); | |
if (offset < 0) throw new ArgumentOutOfRangeException("offset"); | |
Data = new byte[count]; | |
Buffer.BlockCopy(buffer, offset, Data, 0, count); | |
Hash = (int)_murmur.Hash(Data); | |
} | |
public int CompareTo(ByteKey other) | |
{ | |
if (other == null) throw new ArgumentNullException("other"); | |
// Do some basic comparisons first to avoid unessecary | |
// pinvoke cost. | |
if (object.ReferenceEquals(Data, other.Data)) return 0; | |
else if (Data.Length == 0 && other.Data.Length == 0) return 0; | |
else if (Data.Length == 0) return -1; | |
else if (other.Data.Length == 0) return 1; | |
else if (Data[0] < other.Data[0]) return -1; | |
else if (Data[0] > other.Data[0]) return 1; | |
var cmpResult = NativeMethods.memcmp(Data, other.Data, Math.Min(Data.Length, other.Data.Length)); | |
if (cmpResult == 0) | |
{ | |
if (Data.Length < other.Data.Length) return -1; | |
else if (Data.Length > other.Data.Length) return 1; | |
} | |
return cmpResult; | |
} | |
public override int GetHashCode() | |
{ | |
return Hash; | |
} | |
public override bool Equals(object obj) | |
{ | |
return this.CompareTo(obj as ByteKey) == 0; | |
} | |
public static implicit operator byte[](ByteKey key) | |
{ | |
if (key == null) return null; | |
return key.Data; | |
} | |
public static implicit operator ByteKey(byte[] key) | |
{ | |
if (key == null) return null; | |
return new ByteKey(key); | |
} | |
public static implicit operator ArraySegment<byte>(ByteKey key) | |
{ | |
if (key == null) return default(ArraySegment<byte>); | |
return new ArraySegment<byte>(key.Data, 0, key.Data.Length); | |
} | |
public static implicit operator ByteKey(ArraySegment<byte> key) | |
{ | |
if (key.Array == null) return null; | |
return new ByteKey(key.Array, key.Offset, key.Count); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Additions | |
internal class RDBDataType<T> | |
{ | |
public static IGetBytes<T> ByteHandler() | |
{ | |
// ... | |
else if (type == typeof(ByteKey)) return (IGetBytes<T>)new ByteKey_handler<T>(); | |
// ... | |
} | |
public static byte GetByteSize(byte keysize) | |
{ | |
// ... | |
if (t == typeof(ByteKey)) size = keysize; | |
// ... | |
} | |
internal static object GetEmpty() | |
{ | |
// ... | |
if (t == typeof(ByteKey)) | |
return new ByteKey(new byte[0]); | |
// ... | |
} | |
} | |
internal class ByteKey_handler<T> : IGetBytes<ByteKey> | |
{ | |
public byte[] GetBytes(ByteKey obj) | |
{ | |
var copy = new byte[obj.Data.Length]; | |
Buffer.BlockCopy(obj.Data, 0, copy, 0, obj.Data.Length); | |
return copy; | |
} | |
public ByteKey GetObject(byte[] buffer, int offset, int count) | |
{ | |
return new ByteKey(buffer, offset, count); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment