Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
            // 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);
            }
Пример #5
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);
        }
Пример #6
0
        // 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;
        }