GB18030Encoding
namespace System.Text
{
internal sealed class GB18030Encoding : DBCSCodePageEncoding
{
internal sealed class GB18030Decoder : System.Text.DecoderNLS
{
internal short bLeftOver1 = -1;
internal short bLeftOver2 = -1;
internal short bLeftOver3 = -1;
internal short bLeftOver4 = -1;
internal override bool HasState => bLeftOver1 >= 0;
internal GB18030Decoder(EncodingNLS encoding)
: base(encoding)
{
}
public override void Reset()
{
bLeftOver1 = -1;
bLeftOver2 = -1;
bLeftOver3 = -1;
bLeftOver4 = -1;
if (m_fallbackBuffer != null)
m_fallbackBuffer.Reset();
}
}
private const int GBLast4ByteCode = 39419;
internal unsafe char* map4BytesToUnicode = null;
internal unsafe byte* mapUnicodeTo4BytesFlags = null;
private const int GB18030 = 54936;
private const int GBSurrogateOffset = 189000;
private const int GBLastSurrogateOffset = 1237575;
private readonly ushort[] _tableUnicodeToGBDiffs = new ushort[439] {
32896,
36,
32769,
2,
32770,
7,
32770,
5,
32769,
31,
32769,
8,
32770,
6,
32771,
1,
32770,
4,
32770,
3,
32769,
1,
32770,
1,
32769,
4,
32769,
17,
32769,
7,
32769,
15,
32769,
24,
32769,
3,
32769,
4,
32769,
29,
32769,
98,
32769,
1,
32769,
1,
32769,
1,
32769,
1,
32769,
1,
32769,
1,
32769,
1,
32769,
28,
43199,
87,
32769,
15,
32769,
101,
32769,
1,
32771,
13,
32769,
183,
32785,
1,
32775,
7,
32785,
1,
32775,
55,
32769,
14,
32832,
1,
32769,
7102,
32769,
2,
32772,
1,
32770,
2,
32770,
7,
32770,
9,
32769,
1,
32770,
1,
32769,
5,
32769,
112,
41699,
86,
32769,
1,
32769,
3,
32769,
12,
32769,
10,
32769,
62,
32780,
4,
32778,
22,
32772,
2,
32772,
110,
32769,
6,
32769,
1,
32769,
3,
32769,
4,
32769,
2,
32772,
2,
32769,
1,
32769,
1,
32773,
2,
32769,
5,
32772,
5,
32769,
10,
32769,
3,
32769,
5,
32769,
13,
32770,
2,
32772,
6,
32770,
37,
32769,
3,
32769,
11,
32769,
25,
32769,
82,
32769,
333,
32778,
10,
32808,
100,
32844,
4,
32804,
13,
32783,
3,
32771,
10,
32770,
16,
32770,
8,
32770,
8,
32770,
3,
32769,
2,
32770,
18,
32772,
31,
32770,
2,
32769,
54,
32769,
1,
32769,
2110,
65104,
2,
65108,
3,
65111,
2,
65112,
65117,
10,
65118,
15,
65131,
2,
65134,
3,
65137,
4,
65139,
2,
65140,
65141,
3,
65145,
14,
65156,
293,
43402,
43403,
43404,
43405,
43406,
43407,
43408,
43409,
43410,
43411,
43412,
43413,
4,
32772,
1,
32787,
5,
32770,
2,
32777,
20,
43401,
2,
32851,
7,
32772,
2,
32854,
5,
32771,
6,
32805,
246,
32778,
7,
32769,
113,
32769,
234,
32770,
12,
32771,
2,
32769,
34,
32769,
9,
32769,
2,
32770,
2,
32769,
113,
65110,
43,
65109,
298,
65114,
111,
65116,
11,
65115,
765,
65120,
85,
65119,
96,
65122,
65125,
14,
65123,
147,
65124,
218,
65128,
287,
65129,
113,
65130,
885,
65135,
264,
65136,
471,
65138,
116,
65144,
4,
65143,
43,
65146,
248,
65147,
373,
65149,
20,
65148,
193,
65152,
5,
65153,
82,
65154,
16,
65155,
441,
65157,
50,
65158,
2,
65159,
4,
65160,
65161,
1,
65162,
65163,
20,
65165,
3,
65164,
22,
65167,
65166,
703,
65174,
39,
65171,
65172,
65173,
65175,
65170,
111,
65176,
65177,
65178,
65179,
65180,
65181,
65182,
148,
65183,
81,
53670,
14426,
36716,
1,
32859,
1,
32798,
13,
32801,
1,
32771,
5,
32769,
7,
32769,
4,
32770,
4,
32770,
8,
32769,
7,
32769,
16,
32770,
14,
32769,
4295,
32769,
76,
32769,
27,
32769,
81,
32769,
9,
32769,
26,
32772,
1,
32769,
1,
32770,
3,
32769,
6,
32771,
1,
32770,
2,
32771,
1030,
32770,
1,
32786,
4,
32778,
1,
32772,
1,
32782,
1,
32772,
149,
32862,
129,
32774,
26
};
internal unsafe GB18030Encoding()
: base(54936, 936, EncoderFallback.ReplacementFallback, DecoderFallback.ReplacementFallback)
{
}
protected unsafe override void LoadManagedCodePage()
{
iExtraBytes = 87032;
base.LoadManagedCodePage();
byte* ptr = (byte*)(void*)safeNativeMemoryHandle.DangerousGetHandle();
mapUnicodeTo4BytesFlags = ptr + 262144;
map4BytesToUnicode = (char*)(ptr + 262144 + 8192);
char c = ' ';
ushort num = 0;
for (int i = 0; i < _tableUnicodeToGBDiffs.Length; i++) {
ushort num2 = _tableUnicodeToGBDiffs[i];
if ((num2 & 32768) != 0) {
if (num2 > 36864 && num2 != 53670) {
mapBytesToUnicode[(int)num2] = c;
mapUnicodeToBytes[(int)c] = num2;
c = (char)(c + 1);
} else
c = (char)(c + (ushort)(num2 & 32767));
} else {
while (num2 > 0) {
map4BytesToUnicode[(int)num] = c;
mapUnicodeToBytes[(int)c] = num;
byte* intPtr = mapUnicodeTo4BytesFlags + (int)c / 8;
*intPtr = (byte)(*intPtr | (byte)(1 << (int)c % 8));
c = (char)(c + 1);
num = (ushort)(num + 1);
num2 = (ushort)(num2 - 1);
}
}
}
}
internal unsafe bool Is4Byte(char charTest)
{
byte b = mapUnicodeTo4BytesFlags[(int)charTest / 8];
if (b != 0)
return (b & (1 << (int)charTest % 8)) != 0;
return false;
}
public unsafe override int GetByteCount(char* chars, int count, System.Text.EncoderNLS encoder)
{
return GetBytes(chars, count, null, 0, encoder);
}
public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, System.Text.EncoderNLS encoder)
{
char c = ' ';
if (encoder != null)
c = encoder.charLeftOver;
EncodingByteBuffer encodingByteBuffer = new EncodingByteBuffer(this, encoder, bytes, byteCount, chars, charCount);
while (true) {
if (encodingByteBuffer.MoreData) {
char nextChar = encodingByteBuffer.GetNextChar();
if (c != 0) {
if (!char.IsLowSurrogate(nextChar)) {
encodingByteBuffer.MovePrevious(false);
if (encodingByteBuffer.Fallback(c)) {
c = ' ';
continue;
}
c = ' ';
} else {
int num = (c - 55296 << 10) + (nextChar - 56320);
byte b = (byte)(num % 10 + 48);
num /= 10;
byte b2 = (byte)(num % 126 + 129);
num /= 126;
byte b3 = (byte)(num % 10 + 48);
num /= 10;
c = ' ';
if (encodingByteBuffer.AddByte((byte)(num + 144), b3, b2, b)) {
c = ' ';
continue;
}
encodingByteBuffer.MovePrevious(false);
}
} else if (nextChar <= '') {
if (encodingByteBuffer.AddByte((byte)nextChar))
continue;
} else {
if (char.IsHighSurrogate(nextChar)) {
c = nextChar;
continue;
}
if (char.IsLowSurrogate(nextChar)) {
if (encodingByteBuffer.Fallback(nextChar))
continue;
} else {
ushort num2 = mapUnicodeToBytes[(int)nextChar];
if (Is4Byte(nextChar)) {
byte b4 = (byte)((int)num2 % 10 + 48);
num2 = (ushort)((int)num2 / 10);
byte b5 = (byte)((int)num2 % 126 + 129);
num2 = (ushort)((int)num2 / 126);
byte b6 = (byte)((int)num2 % 10 + 48);
num2 = (ushort)((int)num2 / 10);
if (encodingByteBuffer.AddByte((byte)(num2 + 129), b6, b5, b4))
continue;
} else if (encodingByteBuffer.AddByte((byte)(num2 >> 8), (byte)(num2 & 255))) {
continue;
}
}
}
}
if ((encoder != null && !encoder.MustFlush) || c <= ' ')
break;
encodingByteBuffer.Fallback(c);
c = ' ';
}
if (encoder != null) {
if (bytes != null)
encoder.charLeftOver = c;
encoder.m_charsUsed = encodingByteBuffer.CharsUsed;
}
return encodingByteBuffer.Count;
}
internal bool IsGBLeadByte(short ch)
{
if (ch >= 129)
return ch <= 254;
return false;
}
internal bool IsGBTwoByteTrailing(short ch)
{
if (ch < 64 || ch > 126) {
if (ch >= 128)
return ch <= 254;
return false;
}
return true;
}
internal bool IsGBFourByteTrailing(short ch)
{
if (ch >= 48)
return ch <= 57;
return false;
}
internal int GetFourBytesOffset(short offset1, short offset2, short offset3, short offset4)
{
return (offset1 - 129) * 10 * 126 * 10 + (offset2 - 48) * 126 * 10 + (offset3 - 129) * 10 + offset4 - 48;
}
public unsafe override int GetCharCount(byte* bytes, int count, System.Text.DecoderNLS baseDecoder)
{
return GetChars(bytes, count, null, 0, baseDecoder);
}
public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount, System.Text.DecoderNLS baseDecoder)
{
GB18030Decoder gB18030Decoder = (GB18030Decoder)baseDecoder;
EncodingCharBuffer encodingCharBuffer = new EncodingCharBuffer(this, gB18030Decoder, chars, charCount, bytes, byteCount);
short num = -1;
short num2 = -1;
short num3 = -1;
short num4 = -1;
if (gB18030Decoder != null && gB18030Decoder.bLeftOver1 != -1) {
num = gB18030Decoder.bLeftOver1;
num2 = gB18030Decoder.bLeftOver2;
num3 = gB18030Decoder.bLeftOver3;
num4 = gB18030Decoder.bLeftOver4;
while (num != -1) {
if (!IsGBLeadByte(num)) {
if (num <= 127) {
if (!encodingCharBuffer.AddChar((char)num))
break;
} else if (!encodingCharBuffer.Fallback((byte)num)) {
break;
}
num = num2;
num2 = num3;
num3 = num4;
num4 = -1;
} else {
while (num2 == -1 || (IsGBFourByteTrailing(num2) && num4 == -1)) {
if (!encodingCharBuffer.MoreData) {
if (gB18030Decoder.MustFlush)
break;
if (chars != null) {
gB18030Decoder.bLeftOver1 = num;
gB18030Decoder.bLeftOver2 = num2;
gB18030Decoder.bLeftOver3 = num3;
gB18030Decoder.bLeftOver4 = num4;
}
gB18030Decoder.m_bytesUsed = encodingCharBuffer.BytesUsed;
return encodingCharBuffer.Count;
}
if (num2 == -1)
num2 = encodingCharBuffer.GetNextByte();
else if (num3 == -1) {
num3 = encodingCharBuffer.GetNextByte();
} else {
num4 = encodingCharBuffer.GetNextByte();
}
}
if (IsGBTwoByteTrailing(num2)) {
int num5 = num << 8;
num5 |= (byte)num2;
if (!encodingCharBuffer.AddChar(mapBytesToUnicode[num5], 2))
break;
num = -1;
num2 = -1;
} else if (IsGBFourByteTrailing(num2) && IsGBLeadByte(num3) && IsGBFourByteTrailing(num4)) {
int fourBytesOffset = GetFourBytesOffset(num, num2, num3, num4);
if (fourBytesOffset <= 39419) {
if (!encodingCharBuffer.AddChar(map4BytesToUnicode[fourBytesOffset], 4))
break;
} else if (fourBytesOffset >= 189000 && fourBytesOffset <= 1237575) {
fourBytesOffset -= 189000;
if (!encodingCharBuffer.AddChar((char)(55296 + fourBytesOffset / 1024), (char)(56320 + fourBytesOffset % 1024), 4))
break;
} else if (!encodingCharBuffer.Fallback((byte)num, (byte)num2, (byte)num3, (byte)num4)) {
break;
}
num = -1;
num2 = -1;
num3 = -1;
num4 = -1;
} else {
if (!encodingCharBuffer.Fallback((byte)num))
break;
num = num2;
num2 = num3;
num3 = num4;
num4 = -1;
}
}
}
}
while (encodingCharBuffer.MoreData) {
byte nextByte = encodingCharBuffer.GetNextByte();
if (nextByte <= 127) {
if (!encodingCharBuffer.AddChar((char)nextByte))
break;
} else if (IsGBLeadByte(nextByte)) {
if (encodingCharBuffer.MoreData) {
byte nextByte2 = encodingCharBuffer.GetNextByte();
if (IsGBTwoByteTrailing(nextByte2)) {
int num6 = nextByte << 8;
num6 |= nextByte2;
if (!encodingCharBuffer.AddChar(mapBytesToUnicode[num6], 2))
break;
} else if (IsGBFourByteTrailing(nextByte2)) {
if (encodingCharBuffer.EvenMoreData(2)) {
byte nextByte3 = encodingCharBuffer.GetNextByte();
byte nextByte4 = encodingCharBuffer.GetNextByte();
if (IsGBLeadByte(nextByte3) && IsGBFourByteTrailing(nextByte4)) {
int fourBytesOffset2 = GetFourBytesOffset(nextByte, nextByte2, nextByte3, nextByte4);
if (fourBytesOffset2 <= 39419) {
if (!encodingCharBuffer.AddChar(map4BytesToUnicode[fourBytesOffset2], 4))
break;
} else if (fourBytesOffset2 >= 189000 && fourBytesOffset2 <= 1237575) {
fourBytesOffset2 -= 189000;
if (!encodingCharBuffer.AddChar((char)(55296 + fourBytesOffset2 / 1024), (char)(56320 + fourBytesOffset2 % 1024), 4))
break;
} else if (!encodingCharBuffer.Fallback(nextByte, nextByte2, nextByte3, nextByte4)) {
break;
}
} else {
encodingCharBuffer.AdjustBytes(-3);
if (!encodingCharBuffer.Fallback(nextByte))
break;
}
} else {
if (gB18030Decoder != null && !gB18030Decoder.MustFlush) {
if (chars != null) {
num = nextByte;
num2 = nextByte2;
num3 = (short)((!encodingCharBuffer.MoreData) ? (-1) : encodingCharBuffer.GetNextByte());
num4 = -1;
}
break;
}
if (!encodingCharBuffer.Fallback(nextByte, nextByte2))
break;
}
} else {
encodingCharBuffer.AdjustBytes(-1);
if (!encodingCharBuffer.Fallback(nextByte))
break;
}
} else {
if (gB18030Decoder != null && !gB18030Decoder.MustFlush) {
if (chars != null) {
num = nextByte;
num2 = -1;
num3 = -1;
num4 = -1;
}
break;
}
if (!encodingCharBuffer.Fallback(nextByte))
break;
}
} else if (!encodingCharBuffer.Fallback(nextByte)) {
break;
}
}
if (gB18030Decoder != null) {
if (chars != null) {
gB18030Decoder.bLeftOver1 = num;
gB18030Decoder.bLeftOver2 = num2;
gB18030Decoder.bLeftOver3 = num3;
gB18030Decoder.bLeftOver4 = num4;
}
gB18030Decoder.m_bytesUsed = encodingCharBuffer.BytesUsed;
}
return encodingCharBuffer.Count;
}
public override int GetMaxByteCount(int charCount)
{
if (charCount < 0)
throw new ArgumentOutOfRangeException("charCount", System.SR.ArgumentOutOfRange_NeedNonNegNum);
long num = (long)charCount + 1;
if (base.EncoderFallback.MaxCharCount > 1)
num *= base.EncoderFallback.MaxCharCount;
num *= 4;
if (num > 2147483647)
throw new ArgumentOutOfRangeException("charCount", System.SR.ArgumentOutOfRange_GetByteCountOverflow);
return (int)num;
}
public override int GetMaxCharCount(int byteCount)
{
if (byteCount < 0)
throw new ArgumentOutOfRangeException("byteCount", System.SR.ArgumentOutOfRange_NeedNonNegNum);
long num = (long)byteCount + 3;
if (base.DecoderFallback.MaxCharCount > 1)
num *= base.DecoderFallback.MaxCharCount;
if (num > 2147483647)
throw new ArgumentOutOfRangeException("byteCount", System.SR.ArgumentOutOfRange_GetCharCountOverflow);
return (int)num;
}
public override Decoder GetDecoder()
{
return new GB18030Decoder(this);
}
}
}