/BlackBerry/BarcodeScanner/OS5/Library/src/com/phonegap/plugins/barcodescanner/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java
Java | 414 lines | 331 code | 53 blank | 30 comment | 60 complexity | 975cdcee8c08d7f80f916d2a181176d4 MD5 | raw file
- /*
- * Copyright (C) 2010 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * These authors would like to acknowledge the Spanish Ministry of Industry,
- * Tourism and Trade, for the support in the project TSI020301-2008-2
- * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
- * Mobile Dynamic Environments", led by Treelogic
- * ( http://www.treelogic.com/ ):
- *
- * http://www.piramidepse.com/
- */
- package com.phonegap.plugins.barcodescanner.google.zxing.oned.rss.expanded.decoders;
- import com.phonegap.plugins.barcodescanner.google.zxing.NotFoundException;
- import com.phonegap.plugins.barcodescanner.google.zxing.common.BitArray;
- /**
- * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
- * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
- */
- final class GeneralAppIdDecoder {
- private final BitArray information;
- private final CurrentParsingState current = new CurrentParsingState();
- private final StringBuffer buffer = new StringBuffer();
- GeneralAppIdDecoder(BitArray information){
- this.information = information;
- }
- String decodeAllCodes(StringBuffer buff, int initialPosition) throws NotFoundException {
- int currentPosition = initialPosition;
- String remaining = null;
- do{
- DecodedInformation info = this.decodeGeneralPurposeField(currentPosition, remaining);
- String parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString());
- buff.append(parsedFields);
- if(info.isRemaining()) {
- remaining = String.valueOf(info.getRemainingValue());
- } else {
- remaining = null;
- }
- if(currentPosition == info.getNewPosition()) {// No step forward!
- break;
- }
- currentPosition = info.getNewPosition();
- }while(true);
- return buff.toString();
- }
- private boolean isStillNumeric(int pos) {
- // It's numeric if it still has 7 positions
- // and one of the first 4 bits is "1".
- if(pos + 7 > this.information.size){
- return pos + 4 <= this.information.size;
- }
- for(int i = pos; i < pos + 3; ++i) {
- if (this.information.get(i)) {
- return true;
- }
- }
- return this.information.get(pos + 3);
- }
- private DecodedNumeric decodeNumeric(int pos) {
- if(pos + 7 > this.information.size){
- int numeric = extractNumericValueFromBitArray(pos, 4);
- if(numeric == 0) {
- return new DecodedNumeric(this.information.size, DecodedNumeric.FNC1, DecodedNumeric.FNC1);
- }
- return new DecodedNumeric(this.information.size, numeric - 1, DecodedNumeric.FNC1);
- }
- int numeric = extractNumericValueFromBitArray(pos, 7);
- int digit1 = (numeric - 8) / 11;
- int digit2 = (numeric - 8) % 11;
- return new DecodedNumeric(pos + 7, digit1, digit2);
- }
- int extractNumericValueFromBitArray(int pos, int bits){
- return extractNumericValueFromBitArray(this.information, pos, bits);
- }
- static int extractNumericValueFromBitArray(BitArray information, int pos, int bits) {
- if(bits > 32) {
- throw new IllegalArgumentException("extractNumberValueFromBitArray can't handle more than 32 bits");
- }
- int value = 0;
- for(int i = 0; i < bits; ++i) {
- if (information.get(pos + i)) {
- value |= (1 << (bits - i - 1));
- }
- }
- return value;
- }
- DecodedInformation decodeGeneralPurposeField(int pos, String remaining) {
- this.buffer.setLength(0);
- if(remaining != null) {
- this.buffer.append(remaining);
- }
- this.current.position = pos;
- DecodedInformation lastDecoded = parseBlocks();
- if(lastDecoded != null && lastDecoded.isRemaining()) {
- return new DecodedInformation(this.current.position, this.buffer.toString(), lastDecoded.getRemainingValue());
- }
- return new DecodedInformation(this.current.position, this.buffer.toString());
- }
- private DecodedInformation parseBlocks() {
- boolean isFinished;
- BlockParsedResult result;
- do{
- int initialPosition = current.position;
- if (current.isAlpha()){
- result = parseAlphaBlock();
- isFinished = result.isFinished();
- }else if (current.isIsoIec646()){
- result = parseIsoIec646Block();
- isFinished = result.isFinished();
- }else{ // it must be numeric
- result = parseNumericBlock();
- isFinished = result.isFinished();
- }
- boolean positionChanged = initialPosition != current.position;
- if(!positionChanged && !isFinished) {
- break;
- }
- } while (!isFinished);
- return result.getDecodedInformation();
- }
- private BlockParsedResult parseNumericBlock() {
- while(isStillNumeric(current.position)){
- DecodedNumeric numeric = decodeNumeric(current.position);
- current.position = numeric.getNewPosition();
- if(numeric.isFirstDigitFNC1()){
- DecodedInformation information;
- if (numeric.isSecondDigitFNC1()) {
- information = new DecodedInformation(current.position, buffer.toString());
- } else {
- information = new DecodedInformation(current.position, buffer.toString(), numeric.getSecondDigit());
- }
- return new BlockParsedResult(information, true);
- }
- buffer.append(numeric.getFirstDigit());
- if(numeric.isSecondDigitFNC1()){
- DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
- return new BlockParsedResult(information, true);
- }
- buffer.append(numeric.getSecondDigit());
- }
- if(isNumericToAlphaNumericLatch(current.position)){
- current.setAlpha();
- current.position += 4;
- }
- return new BlockParsedResult(false);
- }
- private BlockParsedResult parseIsoIec646Block() {
- while (isStillIsoIec646(current.position)) {
- DecodedChar iso = decodeIsoIec646(current.position);
- current.position = iso.getNewPosition();
- if (iso.isFNC1()) {
- DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
- return new BlockParsedResult(information, true);
- }
- buffer.append(iso.getValue());
- }
- if (isAlphaOr646ToNumericLatch(current.position)) {
- current.position += 3;
- current.setNumeric();
- } else if (isAlphaTo646ToAlphaLatch(current.position)) {
- if (current.position + 5 < this.information.size) {
- current.position += 5;
- } else {
- current.position = this.information.size;
- }
- current.setAlpha();
- }
- return new BlockParsedResult(false);
- }
- private BlockParsedResult parseAlphaBlock() {
- while (isStillAlpha(current.position)) {
- DecodedChar alpha = decodeAlphanumeric(current.position);
- current.position = alpha.getNewPosition();
- if(alpha.isFNC1()) {
- DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
- return new BlockParsedResult(information, true); //end of the char block
- }
- buffer.append(alpha.getValue());
- }
- if (isAlphaOr646ToNumericLatch(current.position)) {
- current.position += 3;
- current.setNumeric();
- } else if (isAlphaTo646ToAlphaLatch(current.position)) {
- if (current.position + 5 < this.information.size) {
- current.position += 5;
- } else {
- current.position = this.information.size;
- }
- current.setIsoIec646();
- }
- return new BlockParsedResult(false);
- }
- private boolean isStillIsoIec646(int pos) {
- if(pos + 5 > this.information.size) {
- return false;
- }
- int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
- if(fiveBitValue >= 5 && fiveBitValue < 16) {
- return true;
- }
- if(pos + 7 > this.information.size) {
- return false;
- }
- int sevenBitValue = extractNumericValueFromBitArray(pos, 7);
- if(sevenBitValue >= 64 && sevenBitValue < 116) {
- return true;
- }
- if(pos + 8 > this.information.size) {
- return false;
- }
- int eightBitValue = extractNumericValueFromBitArray(pos, 8);
- return eightBitValue >= 232 && eightBitValue < 253;
- }
- private DecodedChar decodeIsoIec646(int pos) {
- int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
- if(fiveBitValue == 15) {
- return new DecodedChar(pos + 5, DecodedChar.FNC1);
- }
- if(fiveBitValue >= 5 && fiveBitValue < 15) {
- return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5));
- }
- int sevenBitValue = extractNumericValueFromBitArray(pos, 7);
- if(sevenBitValue >= 64 && sevenBitValue < 90) {
- return new DecodedChar(pos + 7, (char) (sevenBitValue + 1));
- }
- if(sevenBitValue >= 90 && sevenBitValue < 116) {
- return new DecodedChar(pos + 7, (char) (sevenBitValue + 7));
- }
- int eightBitValue = extractNumericValueFromBitArray(pos, 8);
- switch (eightBitValue){
- case 232: return new DecodedChar(pos + 8, '!');
- case 233: return new DecodedChar(pos + 8, '"');
- case 234: return new DecodedChar(pos + 8, '%');
- case 235: return new DecodedChar(pos + 8, '&');
- case 236: return new DecodedChar(pos + 8, '\'');
- case 237: return new DecodedChar(pos + 8, '(');
- case 238: return new DecodedChar(pos + 8, ')');
- case 239: return new DecodedChar(pos + 8, '*');
- case 240: return new DecodedChar(pos + 8, '+');
- case 241: return new DecodedChar(pos + 8, ',');
- case 242: return new DecodedChar(pos + 8, '-');
- case 243: return new DecodedChar(pos + 8, '.');
- case 244: return new DecodedChar(pos + 8, '/');
- case 245: return new DecodedChar(pos + 8, ':');
- case 246: return new DecodedChar(pos + 8, ';');
- case 247: return new DecodedChar(pos + 8, '<');
- case 248: return new DecodedChar(pos + 8, '=');
- case 249: return new DecodedChar(pos + 8, '>');
- case 250: return new DecodedChar(pos + 8, '?');
- case 251: return new DecodedChar(pos + 8, '_');
- case 252: return new DecodedChar(pos + 8, ' ');
- }
- throw new RuntimeException("Decoding invalid ISO/IEC 646 value: " + eightBitValue);
- }
- private boolean isStillAlpha(int pos) {
- if(pos + 5 > this.information.size) {
- return false;
- }
- // We now check if it's a valid 5-bit value (0..9 and FNC1)
- int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
- if(fiveBitValue >= 5 && fiveBitValue < 16) {
- return true;
- }
- if(pos + 6 > this.information.size) {
- return false;
- }
- int sixBitValue = extractNumericValueFromBitArray(pos, 6);
- return sixBitValue >= 16 && sixBitValue < 63; // 63 not included
- }
- private DecodedChar decodeAlphanumeric(int pos) {
- int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
- if(fiveBitValue == 15) {
- return new DecodedChar(pos + 5, DecodedChar.FNC1);
- }
- if(fiveBitValue >= 5 && fiveBitValue < 15) {
- return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5));
- }
- int sixBitValue = extractNumericValueFromBitArray(pos, 6);
- if(sixBitValue >= 32 && sixBitValue < 58) {
- return new DecodedChar(pos + 6, (char) (sixBitValue + 33));
- }
- switch(sixBitValue){
- case 58: return new DecodedChar(pos + 6, '*');
- case 59: return new DecodedChar(pos + 6, ',');
- case 60: return new DecodedChar(pos + 6, '-');
- case 61: return new DecodedChar(pos + 6, '.');
- case 62: return new DecodedChar(pos + 6, '/');
- }
- throw new RuntimeException("Decoding invalid alphanumeric value: " + sixBitValue);
- }
- private boolean isAlphaTo646ToAlphaLatch(int pos) {
- if(pos + 1 > this.information.size) {
- return false;
- }
- for(int i = 0; i < 5 && i + pos < this.information.size; ++i){
- if(i == 2){
- if(!this.information.get(pos + 2)) {
- return false;
- }
- } else if(this.information.get(pos + i)) {
- return false;
- }
- }
- return true;
- }
- private boolean isAlphaOr646ToNumericLatch(int pos) {
- // Next is alphanumeric if there are 3 positions and they are all zeros
- if (pos + 3 > this.information.size) {
- return false;
- }
- for (int i = pos; i < pos + 3; ++i) {
- if (this.information.get(i)) {
- return false;
- }
- }
- return true;
- }
- private boolean isNumericToAlphaNumericLatch(int pos) {
- // Next is alphanumeric if there are 4 positions and they are all zeros, or
- // if there is a subset of this just before the end of the symbol
- if (pos + 1 > this.information.size) {
- return false;
- }
- for (int i = 0; i < 4 && i + pos < this.information.size; ++i) {
- if (this.information.get(pos + i)) {
- return false;
- }
- }
- return true;
- }
- }