internal static void ToLower(char h, char l, out char hr, out char lr) { Debug.Assert(char.IsHighSurrogate(h)); Debug.Assert(char.IsLowSurrogate(l)); UnicodeUtility.GetUtf16SurrogatesFromSupplementaryPlaneScalar(CharUnicodeInfo.ToLower(UnicodeUtility.GetScalarFromUtf16SurrogatePair(h, l)), out hr, out lr); }
public bool MoveNext() { // Make copies of fields to avoid tearing issues since we're // about to perform unsafe accesses. uint currentCharPair = _currentCharPair; if (currentCharPair > char.MaxValue) { // There was a surrogate pair smuggled in here from a previous operation. // Shift out the high surrogate value and return immediately. _currentCharPair = currentCharPair >> 16; return(true); } ReadOnlySpan <byte> bytes = _obj.AsBytesSkipNullCheck(); int nextByteIdx = _nextByteIdx; if ((uint)nextByteIdx >= (uint)bytes.Length) { return(false); // no more data } // TODO_UTF8STRING: Can we skip correctness checks below? // Perhaps not, this enumerator struct is potentially tearable. OperationStatus status = Rune.DecodeFromUtf8(bytes.Slice(nextByteIdx), out Rune currentRune, out int bytesConsumedJustNow); Debug.Assert(status == OperationStatus.Done); _nextByteIdx = nextByteIdx + bytesConsumedJustNow; if (currentRune.IsBmp) { // Common case - BMP scalar value. _currentCharPair = (uint)currentRune.Value; } else { // Uncommon case - supplementary (astral) plane scalar value. // We'll smuggle the two UTF-16 code units into a single 32-bit value, // with the leading surrogate packed into the low 16 bits of the value, // and the trailing surrogate packed into the high 16 bits of the value. UnicodeUtility.GetUtf16SurrogatesFromSupplementaryPlaneScalar((uint)currentRune.Value, out char leadingCodeUnit, out char trailingCodeUnit); _currentCharPair = (uint)leadingCodeUnit + ((uint)trailingCodeUnit << 16); } return(true); }