private static Int32 ReadRuneFromString(String input, Int32 index) { if (input is null) { throw new ArgumentNullException(nameof(input)); } if ((UInt32)index >= (UInt32)input !.Length) { throw new ArgumentOutOfRangeException(nameof(index)); } // Optimistically assume input is within BMP. UInt32 returnValue = input[index]; if (Utf16.IsSurrogate(returnValue)) { if (!Utf16.IsHighSurrogate(returnValue)) { return(-1); } // Treat 'returnValue' as the high surrogate. // // If this becomes a hot code path, we can skip the below bounds check by reading // off the end of the string using unsafe code. Since strings are null-terminated, // we're guaranteed not to read a valid low surrogate, so we'll fail correctly if // the string terminates unexpectedly. index++; if ((UInt32)index >= (UInt32)input.Length) { return(-1); // not an argument exception - just a "bad data" failure } UInt32 potentialLowSurrogate = input[index]; if (!Utf16.IsLowSurrogate(potentialLowSurrogate)) { return(-1); } returnValue = Unsafe.Utf16Decode(returnValue, potentialLowSurrogate); } return((Int32)returnValue); }
// returns a negative number on failure internal static int ReadFirstRuneFromUtf16Buffer(ReadOnlySpan <char> input) { if (input.IsEmpty) { return(-1); } // Optimistically assume input is within BMP. uint returnValue = input[0]; if (Utf16.IsSurrogate(returnValue)) { if (!Utf16.IsHighSurrogate(returnValue)) { return(-1); } // Treat 'returnValue' as the high surrogate. if (1 >= (uint)input.Length) { return(-1); // not an argument exception - just a "bad data" failure } uint potentialLowSurrogate = input[1]; if (!Utf16.IsLowSurrogate(potentialLowSurrogate)) { return(-1); } returnValue = Unsafe.Utf16Decode(returnValue, potentialLowSurrogate); } return((int)returnValue); }