PersistentMap/PersistentOrderedMap/KeyStrategies.cs

68 lines
1.9 KiB
C#
Raw Normal View History

2026-02-01 20:52:23 +01:00
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
2026-05-07 07:44:55 +02:00
namespace PersistentOrderedMap;
2026-02-01 20:52:23 +01:00
using System;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
public interface IKeyStrategy<K>
{
int Compare(K x, K y);
long GetPrefix(K key);
2026-02-11 20:59:55 +01:00
bool UsesPrefixes => true;
2026-04-16 10:20:24 +02:00
bool IsLossless => false;
bool UseBinarySearch => false;
2026-02-01 20:52:23 +01:00
}
2026-02-01 20:52:23 +01:00
public struct UnicodeStrategy : IKeyStrategy<string>
{
public bool UsesPrefixes => true;
public bool UseBinarySearch => false;
public bool IsLossLess => false;
2026-02-01 20:52:23 +01:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Compare(string? x, string? y) => string.CompareOrdinal(x, y);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long GetPrefix(string key)
{
if (string.IsNullOrEmpty(key)) return long.MinValue;
// 1. Prepare Buffer (8 bytes)
// stackalloc is virtually free (pointer bump)
Span<byte> utf8Bytes = stackalloc byte[8];
2026-02-01 20:52:23 +01:00
// 2. Transcode (The "Safe" Magic)
// This intrinsic handles ASCII efficiently and converts Surrogates/Chinese
// into bytes that maintain the correct "Magnitude" (Sort Order).
// Invalid surrogates become 0xEF (Replacement Char), which sorts > ASCII.
System.Text.Unicode.Utf8.FromUtf16(
key.AsSpan(0, Math.Min(key.Length, 8)),
utf8Bytes,
out _,
out _,
2026-02-01 20:52:23 +01:00
replaceInvalidSequences: true); // True ensures we get 0xEF for broken chars
// 3. Load as Big Endian Long
long packed = BinaryPrimitives.ReadInt64BigEndian(utf8Bytes);
// 4. Sign Toggle
// Maps the byte range 0x00..0xFF to the signed long range Min..Max
// Essential for the < and > operators to work correctly.
return packed ^ unchecked((long)0x8080808080808080);
}
2026-02-01 20:52:23 +01:00
}
2026-02-11 20:59:55 +01:00
2026-02-01 20:52:23 +01:00