System.Text.ISO2022Encoding.GetBytesCP52936 C# (CSharp) Method

GetBytesCP52936() private method

private GetBytesCP52936 ( char chars, int charCount, byte bytes, int byteCount, ISO2022Encoder encoder ) : int
chars char
charCount int
bytes byte
byteCount int
encoder ISO2022Encoder
return int
        private unsafe int GetBytesCP52936(char* chars, int charCount,
                                           byte* bytes, int byteCount, ISO2022Encoder encoder)
        {
            // prepare our helpers
            EncodingByteBuffer buffer = new EncodingByteBuffer(this, encoder, bytes, byteCount, chars, charCount);

            // Mode
            ISO2022Modes currentMode = ISO2022Modes.ModeASCII;

            // Check our encoder
            if (encoder != null)
            {
                char charLeftOver = encoder.charLeftOver;
                currentMode = encoder.currentMode;

                // We may have a left over character from last time, try and process it.
                if (charLeftOver > 0)
                {
                    Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP52936]leftover character should be high surrogate");

                    // It has to be a high surrogate, which we don't support, so it has to be a fallback
                    buffer.Fallback(charLeftOver);
                }
            }

            while (buffer.MoreData)
            {
                // Get our char
                char ch = buffer.GetNextChar();

                // Get our bytes
                ushort sChar = mapUnicodeToBytes[ch];
                if (sChar == 0 && ch != 0)
                {
                    // Wasn't a legal byte sequence, its a surrogate or fallback
                    // Throws if recursive (knows because we called InternalGetNextChar)
                    buffer.Fallback(ch);

                    // Done with our char, now process fallback
                    continue;
                }

                // Check for halfwidth bytes
                byte bLeadByte = (byte)(sChar >> 8);
                byte bTrailByte = (byte)(sChar & 0xff);

                // If its a double byte, it has to fit in the lead byte 0xa1 - 0xf7, trail byte 0xa1 - 0xfe range
                // (including the 0x8080 that our codepage or's to the value)
                if ((bLeadByte != 0 &&
                     (bLeadByte < 0xa1 || bLeadByte > 0xf7 || bTrailByte < 0xa1 || bTrailByte > 0xfe)) ||
                    (bLeadByte == 0 && bTrailByte > 0x80 && bTrailByte != 0xff))
                {
                    // Illegal character, in 936 code page, but not in HZ subset, get fallback for it
                    buffer.Fallback(ch);
                    continue;
                }

                // sChar is now either ASCII or has an 0x8080 mask
                if (bLeadByte != 0)
                {
                    // Its a double byte mode
                    if (currentMode != ISO2022Modes.ModeHZ)
                    {
                        // Need to add the double byte mode marker
                        if (!buffer.AddByte((byte)'~', (byte)'{', 2))
                            break;                                      // Stop if no buffer space in convert

                        currentMode = ISO2022Modes.ModeHZ;
                    }

                    // Go ahead and add the 2 bytes
                    if (!buffer.AddByte(unchecked((byte)(bLeadByte & 0x7f)), unchecked((byte)(bTrailByte & 0x7f))))
                        break;                                      // Stop if no buffer space in convert
                }
                else
                {
                    // Its supposed to be ASCII
                    if (currentMode != ISO2022Modes.ModeASCII)
                    {
                        // Need to add the ASCII mode marker
                        // Will have 1 more byte (or 2 if ~)
                        if (!buffer.AddByte((byte)'~', (byte)'}', bTrailByte == '~' ? 2 : 1))
                            break;

                        currentMode = ISO2022Modes.ModeASCII;
                    }

                    // If its a '~' we'll need an extra one
                    if (bTrailByte == '~')
                    {
                        // Need to add the extra ~
                        if (!buffer.AddByte((byte)'~', 1))
                            break;
                    }

                    // Need to add the character
                    if (!buffer.AddByte(bTrailByte))
                        break;
                }
            }

            // Add ASCII shift out if we're at end of decoder
            if (currentMode != ISO2022Modes.ModeASCII &&
                (encoder == null || encoder.MustFlush))
            {
                // Need to add the ASCII mode marker
                // Only turn off other mode if this works
                if (buffer.AddByte((byte)'~', (byte)'}'))
                    currentMode = ISO2022Modes.ModeASCII;
                else
                    // If not successful, convert will maintain state for next time, also
                    // AddByte will have decremented our char count, however we need it to remain the same
                    buffer.GetNextChar();
            }

            // Need to remember our mode
            if (encoder != null && bytes != null)
            {
                // This is ASCII if we had to flush
                encoder.currentMode = currentMode;

                if (!buffer.fallbackBufferHelper.bUsedEncoder)
                {
                    encoder.charLeftOver = (char)0;
                }

                encoder.m_charsUsed = buffer.CharsUsed;
            }

            // Return our length
            return buffer.Count;
        }