public
Created

Byte keys for RaptorDB

  • Download Gist
ByteKey.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
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);
}
}
}
DataTypes.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
// 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);
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.