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

GetBytesCP5022xJP() private method

private GetBytesCP5022xJP ( 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 GetBytesCP5022xJP(char* chars, int charCount,
                                                  byte* bytes, int byteCount, ISO2022Encoder encoder)
        {
            // prepare our helpers
            EncodingByteBuffer buffer = new EncodingByteBuffer(this, encoder, bytes, byteCount, chars, charCount);

            // Get our mode
            ISO2022Modes currentMode = ISO2022Modes.ModeASCII;      // Mode
            ISO2022Modes shiftInMode = ISO2022Modes.ModeASCII;      // Mode that shift in will go back to (only used by CP 50222)

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

                currentMode = encoder.currentMode;
                shiftInMode = encoder.shiftInOutMode;

                // We may have a left over character from last time, try and process it.
                if (charLeftOver > 0)
                {
                    Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP5022xJP]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 iBytes = mapUnicodeToBytes[ch];

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

                if (bLeadByte == LEADBYTE_HALFWIDTH)
                {
                    // Its Halfwidth Katakana
                    if (CodePage == 50220)
                    {
                        // CodePage 50220 doesn't use halfwidth Katakana, convert to fullwidth
                        // See if its out of range, fallback if so, throws if recursive fallback
                        if (bTrailByte < 0x21 || bTrailByte >= 0x21 + s_HalfToFullWidthKanaTable.Length)
                        {
                            buffer.Fallback(ch);
                            continue;
                        }

                        // Get the full width katakana char to use.
                        iBytes = unchecked((ushort)(s_HalfToFullWidthKanaTable[bTrailByte - 0x21] & 0x7F7F));

                        // May have to do all sorts of fun stuff for mode, go back to start convert
                        goto StartConvert;
                    }

                    // Can use halfwidth Katakana, make sure we're in right mode

                    // Make sure we're in right mode
                    if (currentMode != ISO2022Modes.ModeHalfwidthKatakana)
                    {
                        // 50222 or 50221, either shift in/out or escape to get to Katakana mode
                        if (CodePage == 50222)
                        {
                            // Shift Out
                            if (!buffer.AddByte(SHIFT_OUT))
                                break;  // convert out of space, stop

                            // Don't change modes until after AddByte in case it fails for convert
                            // We get to shift out to Katakana, make sure we'll go back to the right mode
                            // (This ends up always being ASCII)
                            shiftInMode = currentMode;
                            currentMode = ISO2022Modes.ModeHalfwidthKatakana;
                        }
                        else
                        {
                            // 50221 does halfwidth katakana by escape sequence
                            Debug.Assert(CodePage == 50221, "[ISO2022Encoding.GetBytesCP5022xJP]Expected Code Page 50221");

                            // Add our escape sequence
                            if (!buffer.AddByte(ESCAPE, unchecked((byte)'('), unchecked((byte)'I')))
                                break;  // convert out of space, stop

                            currentMode = ISO2022Modes.ModeHalfwidthKatakana;
                        }
                    }

                    // We know we're in Katakana mode now, so add it.
                    // Go ahead and add the Katakana byte.  Our table tail bytes are 0x80 too big.
                    if (!buffer.AddByte(unchecked((byte)(bTrailByte & 0x7F))))
                        break;  // convert out of space, stop

                    // Done with this one
                    continue;
                }
                else if (bLeadByte != 0)
                {
                    //
                    //  It's a double byte character.
                    //

                    // If we're CP 50222 we may have to shift in from Katakana mode first
                    if (CodePage == 50222 && currentMode == ISO2022Modes.ModeHalfwidthKatakana)
                    {
                        // Shift In
                        if (!buffer.AddByte(SHIFT_IN))
                            break;    // convert out of space, stop

                        // Need to shift in from katakana.  (Still might not be right, but won't be shifted out anyway)
                        currentMode = shiftInMode;
                    }

                    // Make sure we're in the right mode (JIS 0208 or JIS 0212)
                    // Note: Right now we don't use JIS 0212.  Also this table'd be wrong

                    // Its JIS extension 0208
                    if (currentMode != ISO2022Modes.ModeJIS0208)
                    {
                        // Escape sequence, we can fail after this, mode will be correct for convert
                        if (!buffer.AddByte(ESCAPE, unchecked((byte)'$'), unchecked((byte)'B')))
                            break;  // Convert out of space, stop

                        currentMode = ISO2022Modes.ModeJIS0208;
                    }

                    // Add our double bytes
                    if (!buffer.AddByte(unchecked((byte)(bLeadByte)), unchecked((byte)(bTrailByte))))
                        break; // Convert out of space, stop
                    continue;
                }
                else if (iBytes != 0 || ch == 0)
                {
                    // Single byte Char
                    // If we're CP 50222 we may have to shift in from Katakana mode first
                    if (CodePage == 50222 && currentMode == ISO2022Modes.ModeHalfwidthKatakana)
                    {
                        // Shift IN
                        if (!buffer.AddByte(SHIFT_IN))
                            break; // convert ran out of room

                        // Need to shift in from katakana.  (Still might not be right, but won't be shifted out anyway)
                        currentMode = shiftInMode;
                    }

                    // Its a single byte character, switch to ASCII if we have to
                    if (currentMode != ISO2022Modes.ModeASCII)
                    {
                        if (!buffer.AddByte(ESCAPE, unchecked((byte)'('), unchecked((byte)'B')))
                            break; // convert ran out of room

                        currentMode = ISO2022Modes.ModeASCII;
                    }

                    // Add the ASCII char
                    if (!buffer.AddByte(bTrailByte))
                        break; // convert had no room left
                    continue;
                }

                // Its unknown, do fallback, throws if recursive (knows because we called InternalGetNextChar)
                buffer.Fallback(ch);
            }

            // Switch back to ASCII if MustFlush or no encoder
            if (currentMode != ISO2022Modes.ModeASCII &&
                (encoder == null || encoder.MustFlush))
            {
                // If we're CP 50222 we may have to shift in from Katakana mode first
                if (CodePage == 50222 && currentMode == ISO2022Modes.ModeHalfwidthKatakana)
                {
                    // Shift IN, only shift mode if necessary.
                    if (buffer.AddByte(SHIFT_IN))
                        // Need to shift in from katakana.  (Still might not be right, but won't be shifted out anyway)
                        currentMode = shiftInMode;
                    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();
                }

                // switch back to ASCII to finish neatly
                if (currentMode != ISO2022Modes.ModeASCII &&
                    (CodePage != 50222 || currentMode != ISO2022Modes.ModeHalfwidthKatakana))
                {
                    // only shift if it was successful
                    if (buffer.AddByte(ESCAPE, unchecked((byte)'('), unchecked((byte)'B')))
                        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();
                }
            }

            // Remember our encoder state
            if (bytes != null && encoder != null)
            {
                // This is ASCII if we had to flush
                encoder.currentMode = currentMode;
                encoder.shiftInOutMode = shiftInMode;

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

                encoder.m_charsUsed = buffer.CharsUsed;
            }

            // Return our length
            return buffer.Count;
        }