#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); }
#pragma warning disable IDE0060 // 'this' taken explicitly to avoid argument shuffling by caller static int TryEncodeScalarAsHex(object @this, uint scalarValue, Span <byte> destination) #pragma warning restore IDE0060 { UnicodeDebug.AssertIsValidScalar(scalarValue); // See comments in the UTF-16 equivalent method later in this file. 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] = (byte)';'; if (!SpanUtility.TryWriteBytes(destination, (byte)'&', (byte)'#', (byte)'x', (byte)'0')) { Debug.Fail("We should've had enough room to write 4 bytes."); } 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] = (byte)asUpperHex; scalarValue >>= 4; // write a nibble - not a byte - at a time } return(destination.Length + 4); OutOfSpaceInner: return(-1); }