www.pudn.com > QRCodeLib.rar > QRCodeDataBlockReader.cs, change:2007-07-30,size:13019b


using System; 
using QRCodeDecoder = ThoughtWorks.QRCode.Codec.QRCodeDecoder; 
using InvalidDataBlockException = ThoughtWorks.QRCode.ExceptionHandler.InvalidDataBlockException; 
using DebugCanvas = ThoughtWorks.QRCode.Codec.Util.DebugCanvas; 
using SystemUtils = ThoughtWorks.QRCode.Codec.Util.SystemUtils; 
namespace ThoughtWorks.QRCode.Codec.Reader 
{ 
	 
	public class QRCodeDataBlockReader 
	{ 
		virtual internal int NextMode 
		{ 
			get 
			{ 
				//canvas.println("data blocks:"+ (blocks.length - numErrorCorrectionCode)); 
				if ((blockPointer > blocks.Length - numErrorCorrectionCode - 2)) 
					return 0; 
				else 
					return getNextBits(4); 
			} 
			 
		} 
		virtual public sbyte[] DataByte 
		{ 
			get 
			{ 
				canvas.println("Reading data blocks."); 
				System.IO.MemoryStream output = new System.IO.MemoryStream(); 
				 
				try 
				{ 
					do  
					{ 
						int mode = NextMode; 
						//canvas.println("mode: " + mode); 
						if (mode == 0) 
						{ 
							if (output.Length > 0) 
								break; 
							else 
								throw new InvalidDataBlockException("Empty data block"); 
						} 
						//if (mode != 1 && mode != 2 && mode != 4 && mode != 8) 
						//	break; 
						//} 
						if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER && mode != MODE_8BIT_BYTE && mode != MODE_KANJI) 
						{ 
							/*					canvas.println("Invalid mode: " + mode); 
							mode = guessMode(mode); 
							canvas.println("Guessed mode: " + mode); */ 
							throw new InvalidDataBlockException("Invalid mode: " + mode + " in (block:" + blockPointer + " bit:" + bitPointer + ")"); 
						} 
						dataLength = getDataLength(mode); 
						if (dataLength < 1) 
							throw new InvalidDataBlockException("Invalid data length: " + dataLength); 
						//canvas.println("length: " + dataLength); 
						switch (mode) 
						{ 
							 
							case MODE_NUMBER:  
								//canvas.println("Mode: Figure"); 
								sbyte[] temp_sbyteArray; 
								temp_sbyteArray = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getFigureString(dataLength))); 
								output.Write(SystemUtils.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length); 
								break; 
							 
							case MODE_ROMAN_AND_NUMBER:  
								//canvas.println("Mode: Roman&Figure"); 
								sbyte[] temp_sbyteArray2; 
								temp_sbyteArray2 = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getRomanAndFigureString(dataLength))); 
								output.Write(SystemUtils.ToByteArray(temp_sbyteArray2), 0, temp_sbyteArray2.Length); 
								break; 
							 
							case MODE_8BIT_BYTE:  
								//canvas.println("Mode: 8bit Byte"); 
								sbyte[] temp_sbyteArray3; 
								temp_sbyteArray3 = get8bitByteArray(dataLength); 
								output.Write(SystemUtils.ToByteArray(temp_sbyteArray3), 0, temp_sbyteArray3.Length); 
								break; 
							 
							case MODE_KANJI:  
								//canvas.println("Mode: Kanji"); 
								sbyte[] temp_sbyteArray4; 
								temp_sbyteArray4 = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getKanjiString(dataLength))); 
								output.Write(SystemUtils.ToByteArray(temp_sbyteArray4), 0, temp_sbyteArray4.Length); 
								break; 
							} 
						//			 
						//canvas.println("DataLength: " + dataLength); 
						//Console.out.println(dataString); 
					} 
					while (true); 
				} 
				catch (System.IndexOutOfRangeException e) 
				{ 
					SystemUtils.WriteStackTrace(e, Console.Error); 
					throw new InvalidDataBlockException("Data Block Error in (block:" + blockPointer + " bit:" + bitPointer + ")"); 
				} 
				catch (System.IO.IOException e) 
				{ 
					throw new InvalidDataBlockException(e.Message); 
				} 
				return SystemUtils.ToSByteArray(output.ToArray()); 
			} 
			 
		} 
		virtual public String DataString 
		{ 
			get 
			{ 
				canvas.println("Reading data blocks..."); 
				String dataString = ""; 
				do  
				{ 
					int mode = NextMode; 
					canvas.println("mode: " + mode); 
					if (mode == 0) 
						break; 
					//if (mode != 1 && mode != 2 && mode != 4 && mode != 8) 
					//	break; 
					//} 
					if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER && mode != MODE_8BIT_BYTE && mode != MODE_KANJI) 
					{ 
						// mode = guessMode(mode); 
						// do not guesswork 
						//Console.out.println("guessed mode: " + mode); 
					} 
					 
					dataLength = getDataLength(mode); 
					canvas.println(System.Convert.ToString(blocks[blockPointer])); 
					System.Console.Out.WriteLine("length: " + dataLength); 
					switch (mode) 
					{ 
						 
						case MODE_NUMBER:  
							//canvas.println("Mode: Figure"); 
							dataString += getFigureString(dataLength); 
							break; 
						 
						case MODE_ROMAN_AND_NUMBER:  
							//canvas.println("Mode: Roman&Figure"); 
							dataString += getRomanAndFigureString(dataLength); 
							break; 
						 
						case MODE_8BIT_BYTE:  
							//canvas.println("Mode: 8bit Byte"); 
							dataString += get8bitByteString(dataLength); 
							break; 
						 
						case MODE_KANJI:  
							//canvas.println("Mode: Kanji"); 
							dataString += getKanjiString(dataLength); 
							break; 
						} 
					//canvas.println("DataLength: " + dataLength); 
					//Console.out.println(dataString); 
				} 
				while (true); 
				System.Console.Out.WriteLine(""); 
				return dataString; 
			} 
			 
		} 
		internal int[] blocks; 
		internal int dataLengthMode; 
		internal int blockPointer; 
		internal int bitPointer; 
		internal int dataLength; 
		internal int numErrorCorrectionCode; 
		internal DebugCanvas canvas; 
	 
		const  int MODE_NUMBER = 1; 
	    const int MODE_ROMAN_AND_NUMBER = 2; 
	    const int MODE_8BIT_BYTE = 4; 
	    const int MODE_KANJI = 8; 
	    int[][] sizeOfDataLengthInfo = new int[][] { new int[] { 10, 9, 8, 8 }, new int[] { 12, 11, 16, 10 }, new int[] { 14, 13, 16, 12 } }; 
		 
		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 bits = 0; 
			if (numBits < bitPointer + 1) 
			{ 
				// next word fits into current data block 
				int mask = 0; 
				for (int i = 0; i < numBits; i++) 
				{ 
					mask += (1 << i); 
				} 
				mask <<= (bitPointer - numBits + 1); 
				 
				bits = (blocks[blockPointer] & mask) >> (bitPointer - numBits + 1); 
				bitPointer -= numBits; 
				return bits; 
			} 
			else if (numBits < bitPointer + 1 + 8) 
			{ 
				// next word crosses 2 data blocks 
				int mask1 = 0; 
				for (int i = 0; i < bitPointer + 1; i++) 
				{ 
					mask1 += (1 << i); 
				} 
				bits = (blocks[blockPointer] & mask1) << (numBits - (bitPointer + 1)); 
                blockPointer++; 
				bits += ((blocks[blockPointer]) >> (8 - (numBits - (bitPointer + 1)))); 
				 
				bitPointer = bitPointer - numBits % 8; 
				if (bitPointer < 0) 
				{ 
					bitPointer = 8 + bitPointer; 
				} 
				return bits; 
			} 
			else if (numBits < bitPointer + 1 + 16) 
			{ 
				// next word crosses 3 data blocks 
				int mask1 = 0; // mask of first block 
				int mask3 = 0; // mask of 3rd block 
				//bitPointer + 1 : number of bits of the 1st block 
				//8 : number of the 2nd block (note that use already 8bits because next word uses 3 data blocks) 
				//numBits - (bitPointer + 1 + 8) : number of bits of the 3rd block  
				for (int i = 0; i < bitPointer + 1; i++) 
				{ 
					mask1 += (1 << i); 
				} 
				int bitsFirstBlock = (blocks[blockPointer] & mask1) << (numBits - (bitPointer + 1)); 
				blockPointer++; 
				 
				int bitsSecondBlock = blocks[blockPointer] << (numBits - (bitPointer + 1 + 8)); 
				blockPointer++; 
				 
				for (int i = 0; i < numBits - (bitPointer + 1 + 8); i++) 
				{ 
					mask3 += (1 << i); 
				} 
				mask3 <<= 8 - (numBits - (bitPointer + 1 + 8)); 
				int bitsThirdBlock = (blocks[blockPointer] & mask3) >> (8 - (numBits - (bitPointer + 1 + 8))); 
				 
				bits = bitsFirstBlock + bitsSecondBlock + bitsThirdBlock; 
				bitPointer = bitPointer - (numBits - 8) % 8; 
				if (bitPointer < 0) 
				{ 
					bitPointer = 8 + bitPointer; 
				} 
				return bits; 
			} 
			else 
			{ 
				System.Console.Out.WriteLine("ERROR!"); 
				return 0; 
			} 
		} 
		 
		internal virtual int guessMode(int mode) 
		{ 
			//correct modes: 0001 0010 0100 1000 
			//possible data: 0000 0011 0101 1001 0110 1010 1100 
			//               0111 1101 1011 1110 1111 
			//		MODE_NUMBER = 1; 
			//		MODE_ROMAN_AND_NUMBER = 2; 
			//		MODE_8BIT_BYTE = 4; 
			//		MODE_KANJI = 8; 
			switch (mode) 
			{ 
				 
				case 3:  
					return MODE_NUMBER; 
				 
				case 5:  
					return MODE_8BIT_BYTE; 
				 
				case 6:  
					return MODE_8BIT_BYTE; 
				 
				case 7:  
					return MODE_8BIT_BYTE; 
				 
				case 9:  
					return MODE_KANJI; 
				 
				case 10:  
					return MODE_KANJI; 
				 
				case 11:  
					return MODE_KANJI; 
				 
				case 12:  
					return MODE_8BIT_BYTE; 
				 
				case 13:  
					return MODE_8BIT_BYTE; 
				 
				case 14:  
					return MODE_8BIT_BYTE; 
				 
				case 15:  
					return MODE_8BIT_BYTE; 
				 
				default:  
					return MODE_KANJI; 
				 
			} 
		} 
		 
		internal virtual int getDataLength(int modeIndicator) 
		{ 
			int index = 0; 
			while (true) 
			{ 
				if ((modeIndicator >> index) == 1) 
					break; 
				index++; 
			} 
			 
			return getNextBits(sizeOfDataLengthInfo[dataLengthMode][index]); 
		} 
		 
		 
		internal virtual String getFigureString(int dataLength) 
		{ 
			int length = dataLength; 
			int intData = 0; 
			String strData = ""; 
			do  
			{ 
				if (length >= 3) 
				{ 
					intData = getNextBits(10); 
					if (intData < 100) 
						strData += "0"; 
					if (intData < 10) 
						strData += "0"; 
					length -= 3; 
				} 
				else if (length == 2) 
				{ 
					intData = getNextBits(7); 
					if (intData < 10) 
						strData += "0"; 
					length -= 2; 
				} 
				else if (length == 1) 
				{ 
					intData = getNextBits(4); 
					length -= 1; 
				} 
				strData += System.Convert.ToString(intData); 
			} 
			while (length > 0); 
			 
			return strData; 
		} 
		 
		internal virtual String getRomanAndFigureString(int dataLength) 
		{ 
			int length = dataLength; 
			int intData = 0; 
			String strData = ""; 
			char[] tableRomanAndFigure = new char[]{'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 (length > 1) 
				{ 
					intData = getNextBits(11); 
					int firstLetter = intData / 45; 
					int secondLetter = intData % 45; 
					strData += System.Convert.ToString(tableRomanAndFigure[firstLetter]); 
					strData += System.Convert.ToString(tableRomanAndFigure[secondLetter]); 
					length -= 2; 
				} 
				else if (length == 1) 
				{ 
					intData = getNextBits(6); 
					strData += System.Convert.ToString(tableRomanAndFigure[intData]); 
					length -= 1; 
				} 
			} 
			while (length > 0); 
			 
			return strData; 
		} 
		 
		public virtual sbyte[] get8bitByteArray(int dataLength) 
		{ 
			int length = dataLength; 
			int intData = 0; 
			System.IO.MemoryStream output = new System.IO.MemoryStream(); 
			 
			do  
			{ 
                canvas.println("Length: " + length); 
				intData = getNextBits(8); 
				output.WriteByte((byte) intData); 
				length--; 
			} 
			while (length > 0); 
			return SystemUtils.ToSByteArray(output.ToArray()); 
		} 
		 
		internal virtual String get8bitByteString(int dataLength) 
		{ 
			int length = dataLength; 
			int intData = 0; 
			String strData = ""; 
			do  
			{ 
				intData = getNextBits(8); 
				strData += (char) intData; 
				length--; 
			} 
			while (length > 0); 
			return strData; 
		} 
		 
		internal virtual String getKanjiString(int dataLength) 
		{ 
			int length = dataLength; 
			int intData = 0; 
			String unicodeString = ""; 
			do  
			{ 
				intData = getNextBits(13); 
				int lowerByte = intData % 0xC0; 
				int higherByte = intData / 0xC0; 
				 
				int tempWord = (higherByte << 8) + lowerByte; 
				int shiftjisWord = 0; 
				if (tempWord + 0x8140 <= 0x9FFC) 
				{ 
					// between 8140 - 9FFC on Shift_JIS character set 
					shiftjisWord = tempWord + 0x8140; 
				} 
				else 
				{ 
					// between E040 - EBBF on Shift_JIS character set 
					shiftjisWord = tempWord + 0xC140; 
				} 
				 
				sbyte[] tempByte = new sbyte[2]; 
				tempByte[0] = (sbyte) (shiftjisWord >> 8); 
				tempByte[1] = (sbyte) (shiftjisWord & 0xFF); 
				unicodeString += new String(SystemUtils.ToCharArray(SystemUtils.ToByteArray(tempByte))); 
				length--; 
			} 
			while (length > 0); 
			 
			 
			return unicodeString; 
		} 
	} 
}