/// <summary> /// Creates a <see cref="Rune"/> from the provided UTF-16 code unit. /// </summary> /// <exception cref="ArgumentOutOfRangeException"> /// If <paramref name="ch"/> represents a UTF-16 surrogate code point /// U+D800..U+DFFF, inclusive. /// </exception> public Rune(char ch) { uint expanded = ch; if (UnicodeUtility.IsSurrogateCodePoint(expanded)) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.ch); } _value = expanded; }
/// <summary> /// Attempts to create a <see cref="Rune"/> from the provided input value. /// </summary> public static bool TryCreate(char ch, out Rune result) { uint extendedValue = ch; if (!UnicodeUtility.IsSurrogateCodePoint(extendedValue)) { result = UnsafeCreate(extendedValue); return(true); } else { result = default; return(false); } }
// returns a negative number on failure private static int ReadRuneFromString(string input, int index) { if (input is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); } if ((uint)index >= (uint)input.Length) { ThrowHelper.ThrowArgumentOutOfRange_IndexException(); } // Optimistically assume input is within BMP. uint returnValue = input[index]; if (UnicodeUtility.IsSurrogateCodePoint(returnValue)) { if (!UnicodeUtility.IsHighSurrogateCodePoint(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 ((uint)index >= (uint)input.Length) { return(-1); // not an argument exception - just a "bad data" failure } uint potentialLowSurrogate = input[index]; if (!UnicodeUtility.IsLowSurrogateCodePoint(potentialLowSurrogate)) { return(-1); } returnValue = UnicodeUtility.GetScalarFromUtf16SurrogatePair(returnValue, potentialLowSurrogate); } return((int)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 (UnicodeUtility.IsSurrogateCodePoint(returnValue)) { if (!UnicodeUtility.IsHighSurrogateCodePoint(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 (!UnicodeUtility.IsLowSurrogateCodePoint(potentialLowSurrogate)) { return(-1); } returnValue = UnicodeUtility.GetScalarFromUtf16SurrogatePair(returnValue, potentialLowSurrogate); } return((int)returnValue); }