PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/BlackBerry/BarcodeScanner/OS5/Library/src/com/phonegap/plugins/barcodescanner/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java

https://github.com/brycecurtis/phonegap-plugins
Java | 414 lines | 331 code | 53 blank | 30 comment | 60 complexity | 975cdcee8c08d7f80f916d2a181176d4 MD5 | raw file
  1. /*
  2. * Copyright (C) 2010 ZXing authors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * These authors would like to acknowledge the Spanish Ministry of Industry,
  18. * Tourism and Trade, for the support in the project TSI020301-2008-2
  19. * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
  20. * Mobile Dynamic Environments", led by Treelogic
  21. * ( http://www.treelogic.com/ ):
  22. *
  23. * http://www.piramidepse.com/
  24. */
  25. package com.phonegap.plugins.barcodescanner.google.zxing.oned.rss.expanded.decoders;
  26. import com.phonegap.plugins.barcodescanner.google.zxing.NotFoundException;
  27. import com.phonegap.plugins.barcodescanner.google.zxing.common.BitArray;
  28. /**
  29. * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
  30. * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
  31. */
  32. final class GeneralAppIdDecoder {
  33. private final BitArray information;
  34. private final CurrentParsingState current = new CurrentParsingState();
  35. private final StringBuffer buffer = new StringBuffer();
  36. GeneralAppIdDecoder(BitArray information){
  37. this.information = information;
  38. }
  39. String decodeAllCodes(StringBuffer buff, int initialPosition) throws NotFoundException {
  40. int currentPosition = initialPosition;
  41. String remaining = null;
  42. do{
  43. DecodedInformation info = this.decodeGeneralPurposeField(currentPosition, remaining);
  44. String parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString());
  45. buff.append(parsedFields);
  46. if(info.isRemaining()) {
  47. remaining = String.valueOf(info.getRemainingValue());
  48. } else {
  49. remaining = null;
  50. }
  51. if(currentPosition == info.getNewPosition()) {// No step forward!
  52. break;
  53. }
  54. currentPosition = info.getNewPosition();
  55. }while(true);
  56. return buff.toString();
  57. }
  58. private boolean isStillNumeric(int pos) {
  59. // It's numeric if it still has 7 positions
  60. // and one of the first 4 bits is "1".
  61. if(pos + 7 > this.information.size){
  62. return pos + 4 <= this.information.size;
  63. }
  64. for(int i = pos; i < pos + 3; ++i) {
  65. if (this.information.get(i)) {
  66. return true;
  67. }
  68. }
  69. return this.information.get(pos + 3);
  70. }
  71. private DecodedNumeric decodeNumeric(int pos) {
  72. if(pos + 7 > this.information.size){
  73. int numeric = extractNumericValueFromBitArray(pos, 4);
  74. if(numeric == 0) {
  75. return new DecodedNumeric(this.information.size, DecodedNumeric.FNC1, DecodedNumeric.FNC1);
  76. }
  77. return new DecodedNumeric(this.information.size, numeric - 1, DecodedNumeric.FNC1);
  78. }
  79. int numeric = extractNumericValueFromBitArray(pos, 7);
  80. int digit1 = (numeric - 8) / 11;
  81. int digit2 = (numeric - 8) % 11;
  82. return new DecodedNumeric(pos + 7, digit1, digit2);
  83. }
  84. int extractNumericValueFromBitArray(int pos, int bits){
  85. return extractNumericValueFromBitArray(this.information, pos, bits);
  86. }
  87. static int extractNumericValueFromBitArray(BitArray information, int pos, int bits) {
  88. if(bits > 32) {
  89. throw new IllegalArgumentException("extractNumberValueFromBitArray can't handle more than 32 bits");
  90. }
  91. int value = 0;
  92. for(int i = 0; i < bits; ++i) {
  93. if (information.get(pos + i)) {
  94. value |= (1 << (bits - i - 1));
  95. }
  96. }
  97. return value;
  98. }
  99. DecodedInformation decodeGeneralPurposeField(int pos, String remaining) {
  100. this.buffer.setLength(0);
  101. if(remaining != null) {
  102. this.buffer.append(remaining);
  103. }
  104. this.current.position = pos;
  105. DecodedInformation lastDecoded = parseBlocks();
  106. if(lastDecoded != null && lastDecoded.isRemaining()) {
  107. return new DecodedInformation(this.current.position, this.buffer.toString(), lastDecoded.getRemainingValue());
  108. }
  109. return new DecodedInformation(this.current.position, this.buffer.toString());
  110. }
  111. private DecodedInformation parseBlocks() {
  112. boolean isFinished;
  113. BlockParsedResult result;
  114. do{
  115. int initialPosition = current.position;
  116. if (current.isAlpha()){
  117. result = parseAlphaBlock();
  118. isFinished = result.isFinished();
  119. }else if (current.isIsoIec646()){
  120. result = parseIsoIec646Block();
  121. isFinished = result.isFinished();
  122. }else{ // it must be numeric
  123. result = parseNumericBlock();
  124. isFinished = result.isFinished();
  125. }
  126. boolean positionChanged = initialPosition != current.position;
  127. if(!positionChanged && !isFinished) {
  128. break;
  129. }
  130. } while (!isFinished);
  131. return result.getDecodedInformation();
  132. }
  133. private BlockParsedResult parseNumericBlock() {
  134. while(isStillNumeric(current.position)){
  135. DecodedNumeric numeric = decodeNumeric(current.position);
  136. current.position = numeric.getNewPosition();
  137. if(numeric.isFirstDigitFNC1()){
  138. DecodedInformation information;
  139. if (numeric.isSecondDigitFNC1()) {
  140. information = new DecodedInformation(current.position, buffer.toString());
  141. } else {
  142. information = new DecodedInformation(current.position, buffer.toString(), numeric.getSecondDigit());
  143. }
  144. return new BlockParsedResult(information, true);
  145. }
  146. buffer.append(numeric.getFirstDigit());
  147. if(numeric.isSecondDigitFNC1()){
  148. DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
  149. return new BlockParsedResult(information, true);
  150. }
  151. buffer.append(numeric.getSecondDigit());
  152. }
  153. if(isNumericToAlphaNumericLatch(current.position)){
  154. current.setAlpha();
  155. current.position += 4;
  156. }
  157. return new BlockParsedResult(false);
  158. }
  159. private BlockParsedResult parseIsoIec646Block() {
  160. while (isStillIsoIec646(current.position)) {
  161. DecodedChar iso = decodeIsoIec646(current.position);
  162. current.position = iso.getNewPosition();
  163. if (iso.isFNC1()) {
  164. DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
  165. return new BlockParsedResult(information, true);
  166. }
  167. buffer.append(iso.getValue());
  168. }
  169. if (isAlphaOr646ToNumericLatch(current.position)) {
  170. current.position += 3;
  171. current.setNumeric();
  172. } else if (isAlphaTo646ToAlphaLatch(current.position)) {
  173. if (current.position + 5 < this.information.size) {
  174. current.position += 5;
  175. } else {
  176. current.position = this.information.size;
  177. }
  178. current.setAlpha();
  179. }
  180. return new BlockParsedResult(false);
  181. }
  182. private BlockParsedResult parseAlphaBlock() {
  183. while (isStillAlpha(current.position)) {
  184. DecodedChar alpha = decodeAlphanumeric(current.position);
  185. current.position = alpha.getNewPosition();
  186. if(alpha.isFNC1()) {
  187. DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
  188. return new BlockParsedResult(information, true); //end of the char block
  189. }
  190. buffer.append(alpha.getValue());
  191. }
  192. if (isAlphaOr646ToNumericLatch(current.position)) {
  193. current.position += 3;
  194. current.setNumeric();
  195. } else if (isAlphaTo646ToAlphaLatch(current.position)) {
  196. if (current.position + 5 < this.information.size) {
  197. current.position += 5;
  198. } else {
  199. current.position = this.information.size;
  200. }
  201. current.setIsoIec646();
  202. }
  203. return new BlockParsedResult(false);
  204. }
  205. private boolean isStillIsoIec646(int pos) {
  206. if(pos + 5 > this.information.size) {
  207. return false;
  208. }
  209. int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
  210. if(fiveBitValue >= 5 && fiveBitValue < 16) {
  211. return true;
  212. }
  213. if(pos + 7 > this.information.size) {
  214. return false;
  215. }
  216. int sevenBitValue = extractNumericValueFromBitArray(pos, 7);
  217. if(sevenBitValue >= 64 && sevenBitValue < 116) {
  218. return true;
  219. }
  220. if(pos + 8 > this.information.size) {
  221. return false;
  222. }
  223. int eightBitValue = extractNumericValueFromBitArray(pos, 8);
  224. return eightBitValue >= 232 && eightBitValue < 253;
  225. }
  226. private DecodedChar decodeIsoIec646(int pos) {
  227. int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
  228. if(fiveBitValue == 15) {
  229. return new DecodedChar(pos + 5, DecodedChar.FNC1);
  230. }
  231. if(fiveBitValue >= 5 && fiveBitValue < 15) {
  232. return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5));
  233. }
  234. int sevenBitValue = extractNumericValueFromBitArray(pos, 7);
  235. if(sevenBitValue >= 64 && sevenBitValue < 90) {
  236. return new DecodedChar(pos + 7, (char) (sevenBitValue + 1));
  237. }
  238. if(sevenBitValue >= 90 && sevenBitValue < 116) {
  239. return new DecodedChar(pos + 7, (char) (sevenBitValue + 7));
  240. }
  241. int eightBitValue = extractNumericValueFromBitArray(pos, 8);
  242. switch (eightBitValue){
  243. case 232: return new DecodedChar(pos + 8, '!');
  244. case 233: return new DecodedChar(pos + 8, '"');
  245. case 234: return new DecodedChar(pos + 8, '%');
  246. case 235: return new DecodedChar(pos + 8, '&');
  247. case 236: return new DecodedChar(pos + 8, '\'');
  248. case 237: return new DecodedChar(pos + 8, '(');
  249. case 238: return new DecodedChar(pos + 8, ')');
  250. case 239: return new DecodedChar(pos + 8, '*');
  251. case 240: return new DecodedChar(pos + 8, '+');
  252. case 241: return new DecodedChar(pos + 8, ',');
  253. case 242: return new DecodedChar(pos + 8, '-');
  254. case 243: return new DecodedChar(pos + 8, '.');
  255. case 244: return new DecodedChar(pos + 8, '/');
  256. case 245: return new DecodedChar(pos + 8, ':');
  257. case 246: return new DecodedChar(pos + 8, ';');
  258. case 247: return new DecodedChar(pos + 8, '<');
  259. case 248: return new DecodedChar(pos + 8, '=');
  260. case 249: return new DecodedChar(pos + 8, '>');
  261. case 250: return new DecodedChar(pos + 8, '?');
  262. case 251: return new DecodedChar(pos + 8, '_');
  263. case 252: return new DecodedChar(pos + 8, ' ');
  264. }
  265. throw new RuntimeException("Decoding invalid ISO/IEC 646 value: " + eightBitValue);
  266. }
  267. private boolean isStillAlpha(int pos) {
  268. if(pos + 5 > this.information.size) {
  269. return false;
  270. }
  271. // We now check if it's a valid 5-bit value (0..9 and FNC1)
  272. int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
  273. if(fiveBitValue >= 5 && fiveBitValue < 16) {
  274. return true;
  275. }
  276. if(pos + 6 > this.information.size) {
  277. return false;
  278. }
  279. int sixBitValue = extractNumericValueFromBitArray(pos, 6);
  280. return sixBitValue >= 16 && sixBitValue < 63; // 63 not included
  281. }
  282. private DecodedChar decodeAlphanumeric(int pos) {
  283. int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
  284. if(fiveBitValue == 15) {
  285. return new DecodedChar(pos + 5, DecodedChar.FNC1);
  286. }
  287. if(fiveBitValue >= 5 && fiveBitValue < 15) {
  288. return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5));
  289. }
  290. int sixBitValue = extractNumericValueFromBitArray(pos, 6);
  291. if(sixBitValue >= 32 && sixBitValue < 58) {
  292. return new DecodedChar(pos + 6, (char) (sixBitValue + 33));
  293. }
  294. switch(sixBitValue){
  295. case 58: return new DecodedChar(pos + 6, '*');
  296. case 59: return new DecodedChar(pos + 6, ',');
  297. case 60: return new DecodedChar(pos + 6, '-');
  298. case 61: return new DecodedChar(pos + 6, '.');
  299. case 62: return new DecodedChar(pos + 6, '/');
  300. }
  301. throw new RuntimeException("Decoding invalid alphanumeric value: " + sixBitValue);
  302. }
  303. private boolean isAlphaTo646ToAlphaLatch(int pos) {
  304. if(pos + 1 > this.information.size) {
  305. return false;
  306. }
  307. for(int i = 0; i < 5 && i + pos < this.information.size; ++i){
  308. if(i == 2){
  309. if(!this.information.get(pos + 2)) {
  310. return false;
  311. }
  312. } else if(this.information.get(pos + i)) {
  313. return false;
  314. }
  315. }
  316. return true;
  317. }
  318. private boolean isAlphaOr646ToNumericLatch(int pos) {
  319. // Next is alphanumeric if there are 3 positions and they are all zeros
  320. if (pos + 3 > this.information.size) {
  321. return false;
  322. }
  323. for (int i = pos; i < pos + 3; ++i) {
  324. if (this.information.get(i)) {
  325. return false;
  326. }
  327. }
  328. return true;
  329. }
  330. private boolean isNumericToAlphaNumericLatch(int pos) {
  331. // Next is alphanumeric if there are 4 positions and they are all zeros, or
  332. // if there is a subset of this just before the end of the symbol
  333. if (pos + 1 > this.information.size) {
  334. return false;
  335. }
  336. for (int i = 0; i < 4 && i + pos < this.information.size; ++i) {
  337. if (this.information.get(pos + i)) {
  338. return false;
  339. }
  340. }
  341. return true;
  342. }
  343. }