Beispiel #1
0
        private void EncodeCore(ref Writer writer, char *input, uint charsRemaining)
        {
            while (charsRemaining != 0)
            {
                int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(input, endOfString: (charsRemaining == 1));
                if (UnicodeHelpers.IsSupplementaryCodePoint(nextScalar))
                {
                    // Supplementary characters should always be encoded numerically.
                    WriteEncodedScalar(ref writer, (uint)nextScalar);

                    // We consume two UTF-16 characters for a single supplementary character.
                    input          += 2;
                    charsRemaining -= 2;
                }
                else
                {
                    // Otherwise, this was a BMP character.
                    input++;
                    charsRemaining--;
                    char c = (char)nextScalar;
                    if (IsCharacterAllowed(c))
                    {
                        writer.Write(c);
                    }
                    else
                    {
                        WriteEncodedScalar(ref writer, (uint)nextScalar);
                    }
                }
            }
        }
Beispiel #2
0
        private unsafe void EncodeCore(TextWriter output, char *value, int valueLength)
        {
            Debug.Assert(value != null & output != null);
            Debug.Assert(valueLength >= 0);

            int   bufferLength = MaxOutputCharactersPerInputCharacter;
            char *buffer       = stackalloc char[bufferLength];

            char firstChar        = *value;
            char secondChar       = firstChar;
            bool wasSurrogatePair = false;
            int  charsWritten;

            // this loop processes character pairs (in case they are surrogates).
            // there is an if block below to process single last character.
            for (int secondCharIndex = 1; secondCharIndex < valueLength; secondCharIndex++)
            {
                if (!wasSurrogatePair)
                {
                    firstChar = secondChar;
                }
                else
                {
                    firstChar = value[secondCharIndex - 1];
                }
                secondChar = value[secondCharIndex];

                if (!WillEncode(firstChar))
                {
                    wasSurrogatePair = false;
                    output.Write(firstChar);
                }
                else
                {
                    int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair);
                    if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten))
                    {
                        throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly.");
                    }
                    Write(output, buffer, charsWritten);

                    if (wasSurrogatePair)
                    {
                        secondCharIndex++;
                    }
                }
            }

            if (!wasSurrogatePair)
            {
                firstChar = value[valueLength - 1];
                int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair);
                if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten))
                {
                    throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly.");
                }
                Write(output, buffer, charsWritten);
            }
        }
Beispiel #3
0
        private static unsafe void EncodeCore(this TextEncoder encoder, char *value, int charCount, TextWriter output)
        {
            int   bufferLength = encoder.MaxOutputCharsPerInputChar;
            char *buffer       = stackalloc char[bufferLength];

            char firstChar        = *value;
            char secondChar       = firstChar;
            bool wasSurrogatePair = false;
            int  charsWritten;

            // this loop processes character pairs (in case they are surrogates).
            // there is an if block below to process single last character.
            for (int secondCharIndex = 1; secondCharIndex < charCount; secondCharIndex++)
            {
                if (!wasSurrogatePair)
                {
                    firstChar = secondChar;
                }
                else
                {
                    firstChar = value[secondCharIndex - 1];
                }
                secondChar = value[secondCharIndex];

                if (!encoder.Encodes(firstChar))
                {
                    wasSurrogatePair = false;
                    output.Write(firstChar);
                }
                else
                {
                    int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair);
                    if (!encoder.TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten))
                    {
                        throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly.");
                    }
                    output.Write(buffer, charsWritten);

                    if (wasSurrogatePair)
                    {
                        secondCharIndex++;
                    }
                }
            }

            if (!wasSurrogatePair)
            {
                firstChar = value[charCount - 1];
                int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair);
                if (!encoder.TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten))
                {
                    throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly.");
                }
                output.Write(buffer, charsWritten);
            }
        }
Beispiel #4
0
        // NOTE: The order of the parameters to this method is a work around for https://github.com/dotnet/corefx/issues/4455
        // and the underlying Mono bug: https://bugzilla.xamarin.com/show_bug.cgi?id=36052.
        // If changing the signature of this method, ensure this issue isn't regressing on Mono.
        private unsafe int EncodeIntoBuffer(char *buffer, int bufferLength, char *value, int valueLength, int firstCharacterToEncode)
        {
            int totalWritten = 0;

            if (firstCharacterToEncode > 0)
            {
                Debug.Assert(firstCharacterToEncode <= valueLength);
                Buffer.MemoryCopy(source: value,
                                  destination: buffer,
                                  destinationSizeInBytes: sizeof(char) * bufferLength,
                                  sourceBytesToCopy: sizeof(char) * firstCharacterToEncode);

                totalWritten += firstCharacterToEncode;
                bufferLength -= firstCharacterToEncode;
                buffer       += firstCharacterToEncode;
            }

            int valueIndex = firstCharacterToEncode;

            char firstChar        = value[valueIndex];
            char secondChar       = firstChar;
            bool wasSurrogatePair = false;
            int  charsWritten;

            // this loop processes character pairs (in case they are surrogates).
            // there is an if block below to process single last character.
            int secondCharIndex;

            for (secondCharIndex = valueIndex + 1; secondCharIndex < valueLength; secondCharIndex++)
            {
                if (!wasSurrogatePair)
                {
                    firstChar = secondChar;
                }
                else
                {
                    firstChar = value[secondCharIndex - 1];
                }
                secondChar = value[secondCharIndex];

                if (!WillEncode(firstChar))
                {
                    wasSurrogatePair = false;
                    *buffer = firstChar;
                    buffer++;
                    bufferLength--;
                    totalWritten++;
                }
                else
                {
                    int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair);
                    if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten))
                    {
                        throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly.");
                    }

                    buffer       += charsWritten;
                    bufferLength -= charsWritten;
                    totalWritten += charsWritten;
                    if (wasSurrogatePair)
                    {
                        secondCharIndex++;
                    }
                }
            }

            if (secondCharIndex == valueLength)
            {
                firstChar = value[valueLength - 1];
                int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair);
                if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out charsWritten))
                {
                    throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly.");
                }

                buffer       += charsWritten;
                bufferLength -= charsWritten;
                totalWritten += charsWritten;
            }

            return(totalWritten);
        }
        private unsafe OperationStatus EncodeIntoBuffer(
            char *buffer,
            int bufferLength,
            char *value,
            int valueLength,
            out int charsConsumed,
            out int charsWritten,
            int firstCharacterToEncode,
            bool isFinalBlock = true)
        {
            Debug.Assert(value != null);
            Debug.Assert(firstCharacterToEncode >= 0);

            char *originalBuffer = buffer;

            charsWritten = 0;

            if (firstCharacterToEncode > 0)
            {
                Debug.Assert(firstCharacterToEncode <= valueLength);
                Buffer.MemoryCopy(source: value,
                                  destination: buffer,
                                  destinationSizeInBytes: sizeof(char) * bufferLength,
                                  sourceBytesToCopy: sizeof(char) * firstCharacterToEncode);

                charsWritten += firstCharacterToEncode;
                bufferLength -= firstCharacterToEncode;
                buffer       += firstCharacterToEncode;
            }

            int valueIndex = firstCharacterToEncode;

            char firstChar        = value[valueIndex];
            char secondChar       = firstChar;
            bool wasSurrogatePair = false;

            // this loop processes character pairs (in case they are surrogates).
            // there is an if block below to process single last character.
            int secondCharIndex;

            for (secondCharIndex = valueIndex + 1; secondCharIndex < valueLength; secondCharIndex++)
            {
                if (!wasSurrogatePair)
                {
                    firstChar = secondChar;
                }
                else
                {
                    firstChar = value[secondCharIndex - 1];
                }

                secondChar = value[secondCharIndex];

                if (!WillEncode(firstChar))
                {
                    wasSurrogatePair = false;
                    *buffer = firstChar;
                    buffer++;
                    bufferLength--;
                    charsWritten++;
                }
                else
                {
                    int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair, out bool _);
                    if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out int charsWrittenThisTime))
                    {
                        charsConsumed = (int)(originalBuffer - buffer);
                        return(OperationStatus.DestinationTooSmall);
                    }

                    if (wasSurrogatePair)
                    {
                        secondCharIndex++;
                    }

                    buffer       += charsWrittenThisTime;
                    bufferLength -= charsWrittenThisTime;
                    charsWritten += charsWrittenThisTime;
                }
            }

            if (secondCharIndex == valueLength)
            {
                firstChar = value[valueLength - 1];
                int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair, out bool needMoreData);
                if (!isFinalBlock && needMoreData)
                {
                    Debug.Assert(wasSurrogatePair == false);
                    charsConsumed = (int)(buffer - originalBuffer);
                    return(OperationStatus.NeedMoreData);
                }

                if (!TryEncodeUnicodeScalar(nextScalar, buffer, bufferLength, out int charsWrittenThisTime))
                {
                    charsConsumed = (int)(buffer - originalBuffer);
                    return(OperationStatus.DestinationTooSmall);
                }

                buffer       += charsWrittenThisTime;
                bufferLength -= charsWrittenThisTime;
                charsWritten += charsWrittenThisTime;
            }

            charsConsumed = valueLength;
            return(OperationStatus.Done);
        }
Beispiel #6
0
        public static string Encode(this TextEncoder encoder, string value)
        {
            if (value == null)
            {
                return(value);
            }

            unsafe
            {
                fixed(char *valuePointer = value)
                {
                    int firstCharacterToEncode = encoder.FindFirstCharacterToEncode(valuePointer, value.Length);

                    if (firstCharacterToEncode == -1)
                    {
                        return(value);
                    }

                    int   bufferSize   = encoder.MaxOutputCharsPerInputChar * value.Length;
                    char *wholebuffer  = stackalloc char[bufferSize];
                    char *buffer       = wholebuffer;
                    int   totalWritten = 0;

                    if (firstCharacterToEncode > 0)
                    {
                        int bytesToCopy = firstCharacterToEncode + firstCharacterToEncode;
                        Buffer.MemoryCopy(valuePointer, buffer, bytesToCopy, bytesToCopy);
                        totalWritten += firstCharacterToEncode;
                        bufferSize   -= firstCharacterToEncode;
                        buffer       += firstCharacterToEncode;
                    }

                    int valueIndex = firstCharacterToEncode;

                    char firstChar        = value[valueIndex];
                    char secondChar       = firstChar;
                    bool wasSurrogatePair = false;
                    int  charsWritten;

                    // this loop processes character pairs (in case they are surrogates).
                    // there is an if block below to process single last character.
                    for (int secondCharIndex = valueIndex + 1; secondCharIndex < value.Length; secondCharIndex++)
                    {
                        if (!wasSurrogatePair)
                        {
                            firstChar = secondChar;
                        }
                        else
                        {
                            firstChar = value[secondCharIndex - 1];
                        }
                        secondChar = value[secondCharIndex];

                        if (!encoder.Encodes(firstChar))
                        {
                            wasSurrogatePair = false;
                            *buffer = firstChar;
                            buffer++;
                            bufferSize--;
                            totalWritten++;
                        }
                        else
                        {
                            int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, secondChar, out wasSurrogatePair);
                            if (!encoder.TryEncodeUnicodeScalar(nextScalar, buffer, bufferSize, out charsWritten))
                            {
                                throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly.");
                            }

                            buffer       += charsWritten;
                            bufferSize   -= charsWritten;
                            totalWritten += charsWritten;
                            if (wasSurrogatePair)
                            {
                                secondCharIndex++;
                            }
                        }
                    }

                    if (!wasSurrogatePair)
                    {
                        firstChar = value[value.Length - 1];
                        int nextScalar = UnicodeHelpers.GetScalarValueFromUtf16(firstChar, null, out wasSurrogatePair);
                        if (!encoder.TryEncodeUnicodeScalar(nextScalar, buffer, bufferSize, out charsWritten))
                        {
                            throw new ArgumentException("Argument encoder does not implement MaxOutputCharsPerInputChar correctly.");
                        }

                        buffer       += charsWritten;
                        bufferSize   -= charsWritten;
                        totalWritten += charsWritten;
                    }

                    var result = new String(wholebuffer, 0, totalWritten);

                    return(result);
                }
            }
        }