Пример #1
0
            public static TransformationStatus ComputeEncodedBytesFromUtf16(ReadOnlySpan <byte> source, out int bytesNeeded)
            {
                bytesNeeded = 0;

                // try? because Convert.ConvertToUtf32 can throw
                // if the high/low surrogates aren't valid; no point
                // running all the tests twice per code-point
                try
                {
                    ref char utf16       = ref Unsafe.As <byte, char>(ref source.DangerousGetPinnableReference());
                    int      utf16Length = source.Length >> 1; // byte => char count

                    for (int i = 0; i < utf16Length; i++)
                    {
                        var ch = Unsafe.Add(ref utf16, i);

                        if ((ushort)ch <= 0x7f) // Fast path for ASCII
                        {
                            bytesNeeded++;
                        }
                        else if (!char.IsSurrogate(ch))
                        {
                            bytesNeeded += EncodingHelper.GetUtf8EncodedBytes((uint)ch);
                        }
                        else
                        {
                            if (++i >= utf16Length)
                            {
                                return(TransformationStatus.NeedMoreSourceData);
                            }

                            uint codePoint = (uint)char.ConvertToUtf32(ch, Unsafe.Add(ref utf16, i));
                            bytesNeeded += EncodingHelper.GetUtf8EncodedBytes(codePoint);
                        }
                    }

                    if ((utf16Length << 1) != source.Length)
                    {
                        return(TransformationStatus.NeedMoreSourceData);
                    }

                    return(TransformationStatus.Done);
                }