public static bool TryDecodeCodePoint(Span<byte> buffer, out UnicodeCodePoint codePoint, out int encodedBytes)
{
if (buffer.Length < 2)
{
codePoint = default(UnicodeCodePoint);
encodedBytes = default(int);
// buffer too small
return false;
}
uint codePointValue = buffer.ReadUInt16();
encodedBytes = 2;
if (UnicodeCodePoint.IsSurrogate((UnicodeCodePoint)codePointValue))
{
// TODO: Check if compiler optimized it so codePointValue low range is checked only once
if (!UnicodeCodePoint.IsHighSurrogate((UnicodeCodePoint)codePointValue) || buffer.Length < 4)
{
codePoint = default(UnicodeCodePoint);
encodedBytes = default(int);
// invalid high surrogate or buffer too small
return false;
}
unchecked
{
codePointValue -= UnicodeConstants.Utf16HighSurrogateFirstCodePoint;
encodedBytes += 2;
}
// high surrogate contains 10 first bits of the code point
codePointValue <<= 10;
uint lowSurrogate = buffer.ReadUInt32() >> 16;
if (!UnicodeCodePoint.IsLowSurrogate((UnicodeCodePoint)lowSurrogate))
{
codePoint = default(UnicodeCodePoint);
encodedBytes = default(int);
// invalid low surrogate character
return false;
}
unchecked
{
lowSurrogate -= UnicodeConstants.Utf16LowSurrogateFirstCodePoint;
}
codePointValue |= lowSurrogate;
}
codePoint = (UnicodeCodePoint)codePointValue;
return true;
}