internal override unsafe 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 // BCLDebug.Assert(bytes != null, "[GB18030Encoding.GetBytes]bytes is null"); BCLDebug.Assert(byteCount >= 0, "[GB18030Encoding.GetBytes]byteCount is negative"); BCLDebug.Assert(chars != null, "[GB18030Encoding.GetBytes]chars is null"); BCLDebug.Assert(charCount >= 0, "[GB18030Encoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. BCLDebug.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 Encoding.EncodingByteBuffer buffer = new Encoding.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) { BCLDebug.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 thow) 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; BCLDebug.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)) { 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; BCLDebug.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; }
internal override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { char charFallback = '\0'; if (encoder != null) { charFallback = encoder.charLeftOver; } Encoding.EncodingByteBuffer buffer = new Encoding.EncodingByteBuffer(this, encoder, bytes, byteCount, chars, charCount); Label_0183: while (buffer.MoreData) { char nextChar = buffer.GetNextChar(); if (charFallback != '\0') { if (!char.IsLowSurrogate(nextChar)) { buffer.MovePrevious(false); if (!buffer.Fallback(charFallback)) { charFallback = '\0'; break; } charFallback = '\0'; } else { int num = ((charFallback - 0xd800) << 10) + (nextChar - 0xdc00); byte num2 = (byte) ((num % 10) + 0x30); num /= 10; byte num3 = (byte) ((num % 0x7e) + 0x81); num /= 0x7e; byte num4 = (byte) ((num % 10) + 0x30); num /= 10; charFallback = '\0'; if (!buffer.AddByte((byte) (num + 0x90), num4, num3, num2)) { buffer.MovePrevious(false); break; } charFallback = '\0'; } } else { if (nextChar <= '\x007f') { if (buffer.AddByte((byte) nextChar)) { continue; } break; } if (char.IsHighSurrogate(nextChar)) { charFallback = nextChar; } else { if (char.IsLowSurrogate(nextChar)) { if (buffer.Fallback(nextChar)) { continue; } break; } ushort num5 = base.mapUnicodeToBytes[nextChar]; if (this.Is4Byte(nextChar)) { byte num6 = (byte) ((num5 % 10) + 0x30); num5 = (ushort) (num5 / 10); byte num7 = (byte) ((num5 % 0x7e) + 0x81); num5 = (ushort) (num5 / 0x7e); byte num8 = (byte) ((num5 % 10) + 0x30); num5 = (ushort) (num5 / 10); if (buffer.AddByte((byte) (num5 + 0x81), num8, num7, num6)) { continue; } break; } if (!buffer.AddByte((byte) (num5 >> 8), (byte) (num5 & 0xff))) { break; } } } } if (((encoder == null) || encoder.MustFlush) && (charFallback > '\0')) { buffer.Fallback(charFallback); charFallback = '\0'; goto Label_0183; } if (encoder != null) { if (bytes != null) { encoder.charLeftOver = charFallback; } encoder.m_charsUsed = buffer.CharsUsed; } return buffer.Count; }