using System; using System.IO; using MessagingToolkit.QRCode.Codec.Util; using MessagingToolkit.QRCode.ExceptionHandler; namespace MessagingToolkit.QRCode.Codec.Reader; public class QRCodeDataBlockReader { private const int MODE_NUMBER = 1; private const int MODE_ROMAN_AND_NUMBER = 2; private const int MODE_8BIT_BYTE = 4; private const int MODE_KANJI = 8; internal int[] blocks; internal int dataLengthMode; internal int blockPointer; internal int bitPointer; internal int dataLength; internal int numErrorCorrectionCode; internal DebugCanvas canvas; private int[][] sizeOfDataLengthInfo = new int[3][] { new int[4] { 10, 9, 8, 8 }, new int[4] { 12, 11, 16, 10 }, new int[4] { 14, 13, 16, 12 } }; internal virtual int NextMode { get { if (blockPointer > blocks.Length - numErrorCorrectionCode - 2) { return 0; } return getNextBits(4); } } public virtual sbyte[] DataByte { get { canvas.println("Reading data blocks."); MemoryStream memoryStream = new MemoryStream(); try { while (true) { int nextMode = NextMode; switch (nextMode) { case 0: if (memoryStream.Length > 0) { goto end_IL_0019; } throw new InvalidDataBlockException("Empty data block"); default: if (nextMode != 8) { throw new InvalidDataBlockException("Invalid mode: " + nextMode + " in (block:" + blockPointer + " bit:" + bitPointer + ")"); } break; case 1: case 2: case 4: break; } dataLength = getDataLength(nextMode); if (dataLength < 1) { throw new InvalidDataBlockException("Invalid data length: " + dataLength); } switch (nextMode) { case 1: { sbyte[] array4 = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getFigureString(dataLength))); memoryStream.Write(SystemUtils.ToByteArray(array4), 0, array4.Length); break; } case 2: { sbyte[] array3 = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getRomanAndFigureString(dataLength))); memoryStream.Write(SystemUtils.ToByteArray(array3), 0, array3.Length); break; } case 4: { sbyte[] array2 = get8bitByteArray(dataLength); memoryStream.Write(SystemUtils.ToByteArray(array2), 0, array2.Length); break; } case 8: { sbyte[] array = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getKanjiString(dataLength))); memoryStream.Write(SystemUtils.ToByteArray(array), 0, array.Length); break; } } bool flag = true; continue; end_IL_0019: break; } } catch (IndexOutOfRangeException throwable) { SystemUtils.WriteStackTrace(throwable, Console.Error); throw new InvalidDataBlockException("Data Block Error in (block:" + blockPointer + " bit:" + bitPointer + ")"); } catch (IOException ex) { throw new InvalidDataBlockException(ex.Message); } return SystemUtils.ToSByteArray(memoryStream.ToArray()); } } public virtual string DataString { get { canvas.println("Reading data blocks..."); string text = ""; while (true) { int nextMode = NextMode; canvas.println("mode: " + nextMode); if (nextMode == 0) { break; } if (nextMode == 1 || nextMode == 2 || nextMode == 4 || nextMode != 8) { } dataLength = getDataLength(nextMode); canvas.println(Convert.ToString(blocks[blockPointer])); Console.Out.WriteLine("length: " + dataLength); switch (nextMode) { case 1: text += getFigureString(dataLength); break; case 2: text += getRomanAndFigureString(dataLength); break; case 4: text += get8bitByteString(dataLength); break; case 8: text += getKanjiString(dataLength); break; } bool flag = true; } Console.Out.WriteLine(""); return text; } } public QRCodeDataBlockReader(int[] blocks, int version, int numErrorCorrectionCode) { blockPointer = 0; bitPointer = 7; dataLength = 0; this.blocks = blocks; this.numErrorCorrectionCode = numErrorCorrectionCode; if (version <= 9) { dataLengthMode = 0; } else if (version >= 10 && version <= 26) { dataLengthMode = 1; } else if (version >= 27 && version <= 40) { dataLengthMode = 2; } canvas = QRCodeDecoder.Canvas; } internal virtual int getNextBits(int numBits) { int num = 0; if (numBits < bitPointer + 1) { int num2 = 0; for (int i = 0; i < numBits; i++) { num2 += 1 << i; } num2 <<= bitPointer - numBits + 1; num = (blocks[blockPointer] & num2) >> bitPointer - numBits + 1; bitPointer -= numBits; return num; } if (numBits < bitPointer + 1 + 8) { int num3 = 0; for (int i = 0; i < bitPointer + 1; i++) { num3 += 1 << i; } num = (blocks[blockPointer] & num3) << numBits - (bitPointer + 1); blockPointer++; num += blocks[blockPointer] >> 8 - (numBits - (bitPointer + 1)); bitPointer -= numBits % 8; if (bitPointer < 0) { bitPointer = 8 + bitPointer; } return num; } if (numBits < bitPointer + 1 + 16) { int num3 = 0; int num4 = 0; for (int i = 0; i < bitPointer + 1; i++) { num3 += 1 << i; } int num5 = (blocks[blockPointer] & num3) << numBits - (bitPointer + 1); blockPointer++; int num6 = blocks[blockPointer] << numBits - (bitPointer + 1 + 8); blockPointer++; for (int i = 0; i < numBits - (bitPointer + 1 + 8); i++) { num4 += 1 << i; } num4 <<= 8 - (numBits - (bitPointer + 1 + 8)); int num7 = (blocks[blockPointer] & num4) >> 8 - (numBits - (bitPointer + 1 + 8)); num = num5 + num6 + num7; bitPointer -= (numBits - 8) % 8; if (bitPointer < 0) { bitPointer = 8 + bitPointer; } return num; } Console.Out.WriteLine("ERROR!"); return 0; } internal virtual int guessMode(int mode) { return mode switch { 3 => 1, 5 => 4, 6 => 4, 7 => 4, 9 => 8, 10 => 8, 11 => 8, 12 => 4, 13 => 4, 14 => 4, 15 => 4, _ => 8, }; } internal virtual int getDataLength(int modeIndicator) { int num = 0; while (true) { bool flag = true; if (modeIndicator >> num == 1) { break; } num++; } return getNextBits(sizeOfDataLengthInfo[dataLengthMode][num]); } internal virtual string getFigureString(int dataLength) { int num = dataLength; int num2 = 0; string text = ""; do { if (num >= 3) { num2 = getNextBits(10); if (num2 < 100) { text += "0"; } if (num2 < 10) { text += "0"; } num -= 3; } else { switch (num) { case 2: num2 = getNextBits(7); if (num2 < 10) { text += "0"; } num -= 2; break; case 1: num2 = getNextBits(4); num--; break; } } text += Convert.ToString(num2); } while (num > 0); return text; } internal virtual string getRomanAndFigureString(int dataLength) { int num = dataLength; int num2 = 0; string text = ""; char[] array = new char[45] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':' }; do { if (num > 1) { num2 = getNextBits(11); int num3 = num2 / 45; int num4 = num2 % 45; text += Convert.ToString(array[num3]); text += Convert.ToString(array[num4]); num -= 2; } else if (num == 1) { num2 = getNextBits(6); text += Convert.ToString(array[num2]); num--; } } while (num > 0); return text; } public virtual sbyte[] get8bitByteArray(int dataLength) { int num = dataLength; int num2 = 0; MemoryStream memoryStream = new MemoryStream(); do { canvas.println("Length: " + num); num2 = getNextBits(8); memoryStream.WriteByte((byte)num2); num--; } while (num > 0); return SystemUtils.ToSByteArray(memoryStream.ToArray()); } internal virtual string get8bitByteString(int dataLength) { int num = dataLength; int num2 = 0; string text = ""; do { num2 = getNextBits(8); text += (char)num2; num--; } while (num > 0); return text; } internal virtual string getKanjiString(int dataLength) { int num = dataLength; int num2 = 0; string text = ""; do { num2 = getNextBits(13); int num3 = num2 % 192; int num4 = num2 / 192; int num5 = (num4 << 8) + num3; int num6 = 0; num6 = ((num5 + 33088 > 40956) ? (num5 + 49472) : (num5 + 33088)); text += new string(SystemUtils.ToCharArray(SystemUtils.ToByteArray(new sbyte[2] { (sbyte)(num6 >> 8), (sbyte)(num6 & 0xFF) }))); num--; } while (num > 0); return text; } }