public unsafe override bool TryEncodeUnicodeScalar(int unicodeScalar, char *buffer, int bufferLength, out int numberOfCharactersWritten) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (!WillEncode(unicodeScalar)) { return(TryWriteScalarAsChar(unicodeScalar, buffer, bufferLength, out numberOfCharactersWritten)); } numberOfCharactersWritten = 0; uint asUtf8 = unchecked ((uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)unicodeScalar)); do { if (numberOfCharactersWritten + 3 > bufferLength) { numberOfCharactersWritten = 0; return(false); } *buffer = '%'; buffer++; *buffer = HexConverter.ToCharUpper((int)asUtf8 >> 4); buffer++; *buffer = HexConverter.ToCharUpper((int)asUtf8); buffer++; numberOfCharactersWritten += 3; }while ((asUtf8 >>= 8) != 0); return(true); }
public unsafe override bool TryEncodeUnicodeScalar(int unicodeScalar, char *buffer, int bufferLength, out int numberOfCharactersWritten) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (!WillEncode(unicodeScalar)) { return(TryWriteScalarAsChar(unicodeScalar, buffer, bufferLength, out numberOfCharactersWritten)); } numberOfCharactersWritten = 0; uint asUtf8 = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)unicodeScalar); do { char highNibble, lowNibble; HexUtil.ByteToHexDigits((byte)asUtf8, out highNibble, out lowNibble); if (numberOfCharactersWritten + 3 > bufferLength) { numberOfCharactersWritten = 0; return(false); } *buffer = '%'; buffer++; *buffer = highNibble; buffer++; *buffer = lowNibble; buffer++; numberOfCharactersWritten += 3; }while ((asUtf8 >>= 8) != 0); return(true); }
public unsafe override bool TryEncodeUnicodeScalar(int unicodeScalar, char *buffer, int length, out int writtenChars) { if (!Encodes(unicodeScalar)) { return(unicodeScalar.TryWriteScalarAsChar(buffer, length, out writtenChars)); } writtenChars = 0; uint asUtf8 = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)unicodeScalar); do { char highNibble, lowNibble; HexUtil.WriteHexEncodedByte((byte)asUtf8, out highNibble, out lowNibble); if (length < 3) { writtenChars = 0; return(false); } *buffer = '%'; buffer++; *buffer = highNibble; buffer++; *buffer = lowNibble; buffer++; writtenChars += 3; }while ((asUtf8 >>= 8) != 0); return(true); }
// Writes a scalar value as a percent-encoded sequence of UTF8 bytes, per RFC 3987. protected override void WriteEncodedScalar(ref Writer writer, uint value) { uint asUtf8 = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue(value); do { char highNibble, lowNibble; HexUtil.WriteHexEncodedByte((byte)asUtf8, out highNibble, out lowNibble); writer.Write('%'); writer.Write(highNibble); writer.Write(lowNibble); } while ((asUtf8 >>= 8) != 0); }
private bool TryEncodeUnicodeScalarUtf8(uint unicodeScalar, Span <char> utf16ScratchBuffer, Span <byte> utf8Destination, out int bytesWritten) { if (!TryEncodeUnicodeScalar(unicodeScalar, utf16ScratchBuffer, out int charsWritten)) { // We really don't expect any encoder to exceed 24 escaped chars per input scalar. // If this happens, throw an exception and we can figure out if we want to support it // in the future. ThrowArgumentException_MaxOutputCharsPerInputChar(); } // Transcode chars -> bytes one at a time. utf16ScratchBuffer = utf16ScratchBuffer.Slice(0, charsWritten); int dstIdx = 0; while (!utf16ScratchBuffer.IsEmpty) { if (Rune.DecodeFromUtf16(utf16ScratchBuffer, out Rune nextScalarValue, out int scalarUtf16CodeUnitCount) != OperationStatus.Done) { // Wrote bad UTF-16 data, we cannot transcode to UTF-8. ThrowArgumentException_MaxOutputCharsPerInputChar(); } uint utf8lsb = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)nextScalarValue.Value); do { if (SpanUtility.IsValidIndex(utf8Destination, dstIdx)) { utf8Destination[dstIdx++] = (byte)utf8lsb; } else { bytesWritten = 0; // ran out of space in the destination return(false); } } while ((utf8lsb >>= 8) != 0); utf16ScratchBuffer = utf16ScratchBuffer.Slice(scalarUtf16CodeUnitCount); } bytesWritten = dstIdx; return(true); }
// skips the call to FindFirstCharacterToEncodeUtf8 private protected virtual OperationStatus EncodeUtf8Core( ReadOnlySpan <byte> utf8Source, Span <byte> utf8Destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock) { int originalUtf8SourceLength = utf8Source.Length; int originalUtf8DestinationLength = utf8Destination.Length; const int TempUtf16CharBufferLength = 24; // arbitrarily chosen, but sufficient for any reasonable implementation Span <char> utf16ScratchBuffer = stackalloc char[TempUtf16CharBufferLength]; while (!utf8Source.IsEmpty) { OperationStatus opStatus = Rune.DecodeFromUtf8(utf8Source, out Rune scalarValue, out int bytesConsumedJustNow); if (opStatus != OperationStatus.Done) { if (!isFinalBlock && opStatus == OperationStatus.NeedMoreData) { goto NeedMoreData; } Debug.Assert(scalarValue == Rune.ReplacementChar); // DecodeFromUtf8 should've performed substitution goto MustEncode; } if (!WillEncode(scalarValue.Value)) { uint utf8lsb = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)scalarValue.Value); int dstIdxTemp = 0; do { if ((uint)dstIdxTemp >= (uint)utf8Destination.Length) { goto DestinationTooSmall; } utf8Destination[dstIdxTemp++] = (byte)utf8lsb; } while ((utf8lsb >>= 8) != 0); utf8Source = utf8Source.Slice(bytesConsumedJustNow); utf8Destination = utf8Destination.Slice(dstIdxTemp); continue; } MustEncode: if (!TryEncodeUnicodeScalarUtf8((uint)scalarValue.Value, utf16ScratchBuffer, utf8Destination, out int bytesWrittenJustNow)) { goto DestinationTooSmall; } utf8Source = utf8Source.Slice(bytesConsumedJustNow); utf8Destination = utf8Destination.Slice(bytesWrittenJustNow); } // And we're finished! OperationStatus retVal = OperationStatus.Done; ReturnCommon: bytesConsumed = originalUtf8SourceLength - utf8Source.Length; bytesWritten = originalUtf8DestinationLength - utf8Destination.Length; return(retVal); NeedMoreData: retVal = OperationStatus.NeedMoreData; goto ReturnCommon; DestinationTooSmall: retVal = OperationStatus.DestinationTooSmall; goto ReturnCommon; }