#pragma warning disable IDE0060 // 'this' taken explicitly to avoid argument shuffling by caller static int TryEncodeScalarAsHex(object @this, uint scalarValue, Span <char> destination) #pragma warning restore IDE0060 { UnicodeDebug.AssertIsValidScalar(scalarValue); // For inputs 0x0000..0x10FFFF, log2 will return 0..20. // (It counts the number of bits following the highest set bit.) // // We divide by 4 to get the number of nibbles (this rounds down), // then +1 to account for rounding effects. This also accounts for // that when log2 results in an exact multiple of 4, no rounding has // taken place, but we need to include a char for the preceding '0x1'. // Finally, we +4 to account for the "&#x" prefix and the ";" suffix, // then -1 to get the index of the last legal location we want to write to. // >> +1 +4 -1 = +4 int idxOfSemicolon = (int)((uint)BitOperations.Log2(scalarValue) / 4) + 4; Debug.Assert(4 <= idxOfSemicolon && idxOfSemicolon <= 9, "Expected '�'..''."); if (!SpanUtility.IsValidIndex(destination, idxOfSemicolon)) { goto OutOfSpaceInner; } destination[idxOfSemicolon] = ';'; // It's more efficient to write 4 chars at a time instead of 1 char. // The '0' at the end will be overwritten. if (!SpanUtility.TryWriteChars(destination, '&', '#', 'x', '0')) { Debug.Fail("We should've had enough room to write 4 chars."); } destination = destination.Slice(3, idxOfSemicolon - 3); for (int i = destination.Length - 1; SpanUtility.IsValidIndex(destination, i); i--) { char asUpperHex = HexConverter.ToCharUpper((int)scalarValue); destination[i] = asUpperHex; scalarValue >>= 4; // write a nibble - not a byte - at a time } return(destination.Length + 4); OutOfSpaceInner: return(-1); }
internal override int EncodeUtf16(Rune value, Span <char> destination) { if (value.Value == '<') { if (!SpanUtility.TryWriteChars(destination, '&', 'l', 't', ';')) { goto OutOfSpace; } return(4); } else if (value.Value == '>') { if (!SpanUtility.TryWriteChars(destination, '&', 'g', 't', ';')) { goto OutOfSpace; } return(4); } else if (value.Value == '&') { if (!SpanUtility.TryWriteChars(destination, '&', 'a', 'm', 'p', ';')) { goto OutOfSpace; } return(5); } else if (value.Value == '\"') { if (!SpanUtility.TryWriteChars(destination, '&', 'q', 'u', 'o', 't', ';')) { goto OutOfSpace; } return(6); } else { return(TryEncodeScalarAsHex(this, (uint)value.Value, destination)); } OutOfSpace: return(-1);