System.Text.GB18030Encoding.GetBytes C# (CSharp) Method

GetBytes() private method

private GetBytes ( char chars, int charCount, byte bytes, int byteCount, EncoderNLS encoder ) : int
chars char
charCount int
bytes byte
byteCount int
encoder EncoderNLS
return int
        public unsafe override int GetBytes(char* chars, int charCount,
                                                byte* bytes, int byteCount, EncoderNLS encoder)
        {
            // Just need to ASSERT, this is called by something else internal that checked parameters already
            // We'll allow null bytes as a count
            //            Debug.Assert(bytes != null, "[GB18030Encoding.GetBytes]bytes is null");
            Debug.Assert(byteCount >= 0, "[GB18030Encoding.GetBytes]byteCount is negative");
            Debug.Assert(chars != null, "[GB18030Encoding.GetBytes]chars is null");
            Debug.Assert(charCount >= 0, "[GB18030Encoding.GetBytes]charCount is negative");

            // Assert because we shouldn't be able to have a null encoder.
            Debug.Assert(EncoderFallback != null, "[GB18030Encoding.GetBytes]Attempting to use null encoder fallback");

            // Get any left over characters
            char charLeftOver = (char)0;
            if (encoder != null)
                charLeftOver = encoder.charLeftOver;

            // prepare our helpers
            EncodingByteBuffer buffer = new EncodingByteBuffer(this, encoder, bytes, byteCount, chars, charCount);

            // Try again if we were MustFlush
            TryAgain:

            // Go ahead and do it, including the fallback.
            while (buffer.MoreData)
            {
                // Get next char
                char ch = buffer.GetNextChar();

                // Have to check for charLeftOver
                if (charLeftOver != 0)
                {
                    Debug.Assert(Char.IsHighSurrogate(charLeftOver),
                        "[GB18030Encoding.GetBytes] leftover character should be high surrogate, not 0x" + ((int)charLeftOver).ToString("X4", CultureInfo.InvariantCulture));

                    // If our next char isn't a low surrogate, then we need to do fallback.
                    if (!Char.IsLowSurrogate(ch))
                    {
                        // No low surrogate, fallback high surrogate & try this one again
                        buffer.MovePrevious(false);                  // (Ignoring this character, don't throw)
                        if (!buffer.Fallback(charLeftOver))
                        {
                            charLeftOver = (char)0;
                            break;
                        }
                        charLeftOver = (char)0;
                        continue;
                    }
                    else
                    {
                        // Next is a surrogate, add it as surrogate pair

                        // Need 4 bytes for surrogates
                        // Get our offset
                        int offset = ((charLeftOver - 0xd800) << 10) + (ch - 0xdc00);

                        byte byte4 = (byte)((offset % 0x0a) + 0x30);
                        offset /= 0x0a;
                        byte byte3 = (byte)((offset % 0x7e) + 0x81);
                        offset /= 0x7e;
                        byte byte2 = (byte)((offset % 0x0a) + 0x30);
                        offset /= 0x0a;
                        Debug.Assert(offset < 0x6f,
                            "[GB18030Encoding.GetBytes](1) Expected offset < 0x6f, not 0x" + offset.ToString("X2", CultureInfo.InvariantCulture));

                        charLeftOver = (char)0;
                        if (!buffer.AddByte((byte)(offset + 0x90), byte2, byte3, byte4))
                        {
                            // Didn't work, need to back up for both surrogates (AddByte already backed up one)
                            buffer.MovePrevious(false);             // (don't throw)
                            break;
                        }
                    }
                    charLeftOver = '\0';
                }
                // ASCII's easiest
                else if (ch <= 0x7f)
                {
                    // Need a byte
                    if (!buffer.AddByte((byte)ch))
                        break;
                }
                // See if its a surrogate pair
                else if (Char.IsHighSurrogate(ch))
                {
                    // Remember it for next time
                    charLeftOver = ch;
                }
                else if (Char.IsLowSurrogate(ch))
                {
                    // Low surrogates should've been found already
                    if (!buffer.Fallback(ch))
                        break;
                }
                else
                {
                    // Not surrogate or ASCII, get value
                    ushort iBytes = mapUnicodeToBytes[ch];

                    // See what kind it is
                    if (Is4Byte(ch))
                    {
                        //
                        // This Unicode character will be converted to four-byte GB18030.
                        //
                        // Need 4 bytes
                        byte byte4 = (byte)((iBytes % 0x0a) + 0x30);
                        iBytes /= 0x0a;
                        byte byte3 = (byte)((iBytes % 0x7e) + 0x81);
                        iBytes /= 0x7e;
                        byte byte2 = (byte)((iBytes % 0x0a) + 0x30);
                        iBytes /= 0x0a;
                        Debug.Assert(iBytes < 0x7e,
                            "[GB18030Encoding.GetBytes]Expected iBytes < 0x7e, not 0x" + iBytes.ToString("X2", CultureInfo.InvariantCulture));
                        if (!buffer.AddByte((byte)(iBytes + 0x81), byte2, byte3, byte4))
                            break;
                    }
                    else
                    {
                        // Its 2 byte, use it
                        if (!buffer.AddByte(unchecked((byte)(iBytes >> 8)), unchecked((byte)(iBytes & 0xff))))
                            break;
                    }
                }
            }

            // Do we need to flush our charLeftOver?
            if ((encoder == null || encoder.MustFlush) && (charLeftOver > 0))
            {
                // Fall it back
                buffer.Fallback(charLeftOver);
                charLeftOver = (char)0;
                goto TryAgain;
            }

            // Fallback stuck it in encoder if necessary, but we have to clear MustFlash cases
            // (Check bytes != null, don't clear it if we're just counting)
            if (encoder != null)
            {
                // Remember our charLeftOver
                if (bytes != null)
                    encoder.charLeftOver = charLeftOver;

                encoder.m_charsUsed = buffer.CharsUsed;
            }

            // Return our length
            return buffer.Count;
        }