System.Text.SBCSCodePageEncoding.GetChars C# (CSharp) Method

GetChars() private method

private GetChars ( byte bytes, int byteCount, char chars, int charCount, DecoderNLS decoder ) : int
bytes byte
byteCount int
chars char
charCount int
decoder DecoderNLS
return int
        public unsafe override int GetChars(byte* bytes, int byteCount,
                                                char* chars, int charCount, DecoderNLS decoder)
        {
            // Just need to ASSERT, this is called by something else internal that checked parameters already
            Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetChars]bytes is null");
            Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetChars]byteCount is negative");
            Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetChars]chars is null");
            Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetChars]charCount is negative");

            CheckMemorySection();

            // See if we have best fit
            bool bUseBestFit = false;

            // Do it fast way if using ? replacement or best fit fallbacks
            byte* byteEnd = bytes + byteCount;
            byte* byteStart = bytes;
            char* charStart = chars;

            // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback.
            DecoderReplacementFallback fallback = null;

            if (decoder == null)
            {
                fallback = DecoderFallback as DecoderReplacementFallback;
                bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback;
            }
            else
            {
                fallback = decoder.Fallback as DecoderReplacementFallback;
                bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback;
                Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
                    decoder.FallbackBuffer.Remaining == 0,
                    "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start");
            }

            if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1))
            {
                // Try it the fast way
                char replacementChar;
                if (fallback == null)
                    replacementChar = '?';  // Best fit always has ? for fallback for SBCS
                else
                    replacementChar = fallback.DefaultString[0];

                // Need byteCount chars, otherwise too small buffer
                if (charCount < byteCount)
                {
                    // Need at least 1 output byte, throw if must throw
                    ThrowCharsOverflow(decoder, charCount < 1);

                    // Not throwing, use what we can
                    byteEnd = bytes + charCount;
                }

                // Quick loop, just do '?' replacement because we don't have fallbacks for decodings.
                while (bytes < byteEnd)
                {
                    char c;
                    if (bUseBestFit)
                    {
                        if (arrayBytesBestFit == null)
                        {
                            ReadBestFitTable();
                        }
                        c = arrayBytesBestFit[*bytes];
                    }
                    else
                        c = _mapBytesToUnicode[*bytes];
                    bytes++;

                    if (c == UNKNOWN_CHAR)
                        // This is an invalid byte in the ASCII encoding.
                        *chars = replacementChar;
                    else
                        *chars = c;
                    chars++;
                }

                // bytes & chars used are the same
                if (decoder != null)
                    decoder.m_bytesUsed = (int)(bytes - byteStart);
                return (int)(chars - charStart);
            }

            // Slower way's going to need a fallback buffer
            DecoderFallbackBuffer fallbackBuffer = null;
            byte[] byteBuffer = new byte[1];
            char* charEnd = chars + charCount;

            DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(
                decoder != null ? decoder.FallbackBuffer : DecoderFallback.CreateFallbackBuffer());

            // Not quite so fast loop
            while (bytes < byteEnd)
            {
                // Faster if don't use *bytes++;
                char c = _mapBytesToUnicode[*bytes];
                bytes++;

                // See if it was unknown
                if (c == UNKNOWN_CHAR)
                {
                    // Make sure we have a fallback buffer
                    if (fallbackBuffer == null)
                    {
                        if (decoder == null)
                            fallbackBuffer = DecoderFallback.CreateFallbackBuffer();
                        else
                            fallbackBuffer = decoder.FallbackBuffer;

                        fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);

                        fallbackHelper.InternalInitialize(byteEnd - byteCount, charEnd);
                    }

                    // Use fallback buffer
                    Debug.Assert(bytes > byteStart,
                        "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (unknown byte)");
                    byteBuffer[0] = *(bytes - 1);
                    // Fallback adds fallback to chars, but doesn't increment chars unless the whole thing fits.
                    if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars))
                    {
                        // May or may not throw, but we didn't get this byte
                        bytes--;                                            // unused byte
                        fallbackHelper.InternalReset();                     // Didn't fall this back
                        ThrowCharsOverflow(decoder, bytes == byteStart);    // throw?
                        break;                                              // don't throw, but stop loop
                    }
                }
                else
                {
                    // Make sure we have buffer space
                    if (chars >= charEnd)
                    {
                        Debug.Assert(bytes > byteStart,
                            "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (known byte)");
                        bytes--;                                            // unused byte
                        ThrowCharsOverflow(decoder, bytes == byteStart);    // throw?
                        break;                                              // don't throw, but stop loop
                    }

                    *(chars) = c;
                    chars++;
                }
            }

            // Might have had decoder fallback stuff.
            if (decoder != null)
                decoder.m_bytesUsed = (int)(bytes - byteStart);

            // Expect Empty fallback buffer for GetChars
            Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
                "[SBCSEncoding.GetChars]Expected Empty fallback buffer at end");

            return (int)(chars - charStart);
        }