You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ZXRSSExpandedGeneralAppIdDecoder.m 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /*
  2. * Copyright 2012 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. #import "ZXBitArray.h"
  17. #import "ZXErrors.h"
  18. #import "ZXRSSExpandedBlockParsedResult.h"
  19. #import "ZXRSSExpandedCurrentParsingState.h"
  20. #import "ZXRSSExpandedDecodedChar.h"
  21. #import "ZXRSSExpandedDecodedInformation.h"
  22. #import "ZXRSSExpandedDecodedNumeric.h"
  23. #import "ZXRSSExpandedFieldParser.h"
  24. #import "ZXRSSExpandedGeneralAppIdDecoder.h"
  25. @interface ZXRSSExpandedGeneralAppIdDecoder ()
  26. @property (nonatomic, strong, readonly) ZXBitArray *information;
  27. @property (nonatomic, strong, readonly) ZXRSSExpandedCurrentParsingState *current;
  28. @property (nonatomic, strong, readonly) NSMutableString *buffer;
  29. @end
  30. @implementation ZXRSSExpandedGeneralAppIdDecoder
  31. - (id)initWithInformation:(ZXBitArray *)information {
  32. if (self = [super init]) {
  33. _current = [[ZXRSSExpandedCurrentParsingState alloc] init];
  34. _buffer = [NSMutableString string];
  35. _information = information;
  36. }
  37. return self;
  38. }
  39. - (NSString *)decodeAllCodes:(NSMutableString *)buff initialPosition:(int)initialPosition error:(NSError **)error {
  40. int currentPosition = initialPosition;
  41. NSString *remaining = nil;
  42. do {
  43. ZXRSSExpandedDecodedInformation *info = [self decodeGeneralPurposeField:currentPosition remaining:remaining];
  44. if (!info) {
  45. if (error) *error = ZXFormatErrorInstance();
  46. return nil;
  47. }
  48. NSString *parsedFields = [ZXRSSExpandedFieldParser parseFieldsInGeneralPurpose:[info theNewString] error:error];
  49. if (!parsedFields) {
  50. return nil;
  51. } else if (parsedFields.length > 0) {
  52. [buff appendString:parsedFields];
  53. }
  54. if ([info remaining]) {
  55. remaining = [@([info remainingValue]) stringValue];
  56. } else {
  57. remaining = nil;
  58. }
  59. if (currentPosition == [info theNewPosition]) {// No step forward!
  60. break;
  61. }
  62. currentPosition = [info theNewPosition];
  63. } while (YES);
  64. return buff;
  65. }
  66. - (BOOL)isStillNumeric:(int)pos {
  67. // It's numeric if it still has 7 positions
  68. // and one of the first 4 bits is "1".
  69. if (pos + 7 > self.information.size) {
  70. return pos + 4 <= self.information.size;
  71. }
  72. for (int i = pos; i < pos + 3; ++i) {
  73. if ([self.information get:i]) {
  74. return YES;
  75. }
  76. }
  77. return [self.information get:pos + 3];
  78. }
  79. - (ZXRSSExpandedDecodedNumeric *)decodeNumeric:(int)pos {
  80. if (pos + 7 > self.information.size) {
  81. int numeric = [self extractNumericValueFromBitArray:pos bits:4];
  82. if (numeric == 0) {
  83. return [[ZXRSSExpandedDecodedNumeric alloc] initWithNewPosition:self.information.size
  84. firstDigit:ZX_FNC1_INT
  85. secondDigit:ZX_FNC1_INT];
  86. }
  87. return [[ZXRSSExpandedDecodedNumeric alloc] initWithNewPosition:self.information.size
  88. firstDigit:numeric - 1
  89. secondDigit:ZX_FNC1_INT];
  90. }
  91. int numeric = [self extractNumericValueFromBitArray:pos bits:7];
  92. int digit1 = (numeric - 8) / 11;
  93. int digit2 = (numeric - 8) % 11;
  94. return [[ZXRSSExpandedDecodedNumeric alloc] initWithNewPosition:pos + 7
  95. firstDigit:digit1
  96. secondDigit:digit2];
  97. }
  98. - (int)extractNumericValueFromBitArray:(int)pos bits:(int)bits {
  99. return [ZXRSSExpandedGeneralAppIdDecoder extractNumericValueFromBitArray:self.information pos:pos bits:bits];
  100. }
  101. + (int)extractNumericValueFromBitArray:(ZXBitArray *)information pos:(int)pos bits:(int)bits {
  102. if (bits > 32) {
  103. [NSException raise:NSInvalidArgumentException format:@"extractNumberValueFromBitArray can't handle more than 32 bits"];
  104. }
  105. int value = 0;
  106. for (int i = 0; i < bits; ++i) {
  107. if ([information get:pos + i]) {
  108. value |= 1 << (bits - i - 1);
  109. }
  110. }
  111. return value;
  112. }
  113. - (ZXRSSExpandedDecodedInformation *)decodeGeneralPurposeField:(int)pos remaining:(NSString *)remaining {
  114. [self.buffer setString:@""];
  115. if (remaining != nil) {
  116. [self.buffer appendString:remaining];
  117. }
  118. self.current.position = pos;
  119. NSError *error;
  120. ZXRSSExpandedDecodedInformation *lastDecoded = [self parseBlocksWithError:&error];
  121. if (error) {
  122. return nil;
  123. }
  124. if (lastDecoded != nil && [lastDecoded remaining]) {
  125. return [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
  126. newString:self.buffer
  127. remainingValue:lastDecoded.remainingValue];
  128. }
  129. return [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position newString:self.buffer];
  130. }
  131. - (ZXRSSExpandedDecodedInformation *)parseBlocksWithError:(NSError **)error {
  132. BOOL isFinished;
  133. ZXRSSExpandedBlockParsedResult *result;
  134. do {
  135. int initialPosition = self.current.position;
  136. NSError *localError;
  137. if (self.current.alpha) {
  138. result = [self parseAlphaBlock];
  139. isFinished = result.finished;
  140. } else if (self.current.isoIec646) {
  141. result = [self parseIsoIec646BlockWithError:&localError];
  142. isFinished = result.finished;
  143. } else {
  144. result = [self parseNumericBlockWithError:&localError];
  145. isFinished = result.finished;
  146. }
  147. if (localError) {
  148. if (error) *error = localError;
  149. return nil;
  150. }
  151. BOOL positionChanged = initialPosition != self.current.position;
  152. if (!positionChanged && !isFinished) {
  153. break;
  154. }
  155. } while (!isFinished);
  156. return result.decodedInformation;
  157. }
  158. - (ZXRSSExpandedBlockParsedResult *)parseNumericBlockWithError:(NSError **)error {
  159. while ([self isStillNumeric:self.current.position]) {
  160. ZXRSSExpandedDecodedNumeric *numeric = [self decodeNumeric:self.current.position];
  161. if (!numeric) {
  162. if (error) *error = ZXFormatErrorInstance();
  163. return nil;
  164. }
  165. self.current.position = numeric.theNewPosition;
  166. if ([numeric firstDigitFNC1]) {
  167. ZXRSSExpandedDecodedInformation *information;
  168. if ([numeric secondDigitFNC1]) {
  169. information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
  170. newString:self.buffer];
  171. } else {
  172. information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
  173. newString:self.buffer
  174. remainingValue:numeric.secondDigit];
  175. }
  176. return [[ZXRSSExpandedBlockParsedResult alloc] initWithInformation:information finished:YES];
  177. }
  178. [self.buffer appendFormat:@"%d", numeric.firstDigit];
  179. if (numeric.secondDigitFNC1) {
  180. ZXRSSExpandedDecodedInformation *information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
  181. newString:self.buffer];
  182. return [[ZXRSSExpandedBlockParsedResult alloc] initWithInformation:information finished:YES];
  183. }
  184. [self.buffer appendFormat:@"%d", numeric.secondDigit];
  185. }
  186. if ([self isNumericToAlphaNumericLatch:self.current.position]) {
  187. [self.current setAlpha];
  188. self.current.position += 4;
  189. }
  190. return [[ZXRSSExpandedBlockParsedResult alloc] initWithFinished:NO];
  191. }
  192. - (ZXRSSExpandedBlockParsedResult *)parseIsoIec646BlockWithError:(NSError **)error {
  193. while ([self isStillIsoIec646:self.current.position]) {
  194. ZXRSSExpandedDecodedChar *iso = [self decodeIsoIec646:self.current.position];
  195. if (!iso) {
  196. if (error) *error = ZXFormatErrorInstance();
  197. return nil;
  198. }
  199. self.current.position = iso.theNewPosition;
  200. if (iso.fnc1) {
  201. ZXRSSExpandedDecodedInformation *information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
  202. newString:self.buffer];
  203. return [[ZXRSSExpandedBlockParsedResult alloc] initWithInformation:information finished:YES];
  204. }
  205. [self.buffer appendFormat:@"%C", iso.value];
  206. }
  207. if ([self isAlphaOr646ToNumericLatch:self.current.position]) {
  208. self.current.position += 3;
  209. [self.current setNumeric];
  210. } else if ([self isAlphaTo646ToAlphaLatch:self.current.position]) {
  211. if (self.current.position + 5 < self.information.size) {
  212. self.current.position += 5;
  213. } else {
  214. self.current.position = self.information.size;
  215. }
  216. [self.current setAlpha];
  217. }
  218. return [[ZXRSSExpandedBlockParsedResult alloc] initWithFinished:NO];
  219. }
  220. - (ZXRSSExpandedBlockParsedResult *)parseAlphaBlock {
  221. while ([self isStillAlpha:self.current.position]) {
  222. ZXRSSExpandedDecodedChar *alpha = [self decodeAlphanumeric:self.current.position];
  223. self.current.position = alpha.theNewPosition;
  224. if (alpha.fnc1) {
  225. ZXRSSExpandedDecodedInformation *information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
  226. newString:self.buffer];
  227. return [[ZXRSSExpandedBlockParsedResult alloc] initWithInformation:information finished:YES];
  228. }
  229. [self.buffer appendFormat:@"%C", alpha.value];
  230. }
  231. if ([self isAlphaOr646ToNumericLatch:self.current.position]) {
  232. self.current.position += 3;
  233. [self.current setNumeric];
  234. } else if ([self isAlphaTo646ToAlphaLatch:self.current.position]) {
  235. if (self.current.position + 5 < self.information.size) {
  236. self.current.position += 5;
  237. } else {
  238. self.current.position = self.information.size;
  239. }
  240. [self.current setIsoIec646];
  241. }
  242. return [[ZXRSSExpandedBlockParsedResult alloc] initWithFinished:NO];
  243. }
  244. - (BOOL)isStillIsoIec646:(int)pos {
  245. if (pos + 5 > self.information.size) {
  246. return NO;
  247. }
  248. int fiveBitValue = [self extractNumericValueFromBitArray:pos bits:5];
  249. if (fiveBitValue >= 5 && fiveBitValue < 16) {
  250. return YES;
  251. }
  252. if (pos + 7 > self.information.size) {
  253. return NO;
  254. }
  255. int sevenBitValue = [self extractNumericValueFromBitArray:pos bits:7];
  256. if (sevenBitValue >= 64 && sevenBitValue < 116) {
  257. return YES;
  258. }
  259. if (pos + 8 > self.information.size) {
  260. return NO;
  261. }
  262. int eightBitValue = [self extractNumericValueFromBitArray:pos bits:8];
  263. return eightBitValue >= 232 && eightBitValue < 253;
  264. }
  265. - (ZXRSSExpandedDecodedChar *)decodeIsoIec646:(int)pos {
  266. int fiveBitValue = [self extractNumericValueFromBitArray:pos bits:5];
  267. if (fiveBitValue == 15) {
  268. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 5 value:ZX_FNC1_CHAR];
  269. }
  270. if (fiveBitValue >= 5 && fiveBitValue < 15) {
  271. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 5 value:(unichar)('0' + fiveBitValue - 5)];
  272. }
  273. int sevenBitValue = [self extractNumericValueFromBitArray:pos bits:7];
  274. if (sevenBitValue >= 64 && sevenBitValue < 90) {
  275. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 7 value:(unichar)(sevenBitValue + 1)];
  276. }
  277. if (sevenBitValue >= 90 && sevenBitValue < 116) {
  278. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 7 value:(unichar)(sevenBitValue + 7)];
  279. }
  280. int eightBitValue = [self extractNumericValueFromBitArray:pos bits:8];
  281. unichar c;
  282. switch (eightBitValue) {
  283. case 232:
  284. c = '!';
  285. break;
  286. case 233:
  287. c = '"';
  288. break;
  289. case 234:
  290. c ='%';
  291. break;
  292. case 235:
  293. c = '&';
  294. break;
  295. case 236:
  296. c = '\'';
  297. break;
  298. case 237:
  299. c = '(';
  300. break;
  301. case 238:
  302. c = ')';
  303. break;
  304. case 239:
  305. c = '*';
  306. break;
  307. case 240:
  308. c = '+';
  309. break;
  310. case 241:
  311. c = ',';
  312. break;
  313. case 242:
  314. c = '-';
  315. break;
  316. case 243:
  317. c = '.';
  318. break;
  319. case 244:
  320. c = '/';
  321. break;
  322. case 245:
  323. c = ':';
  324. break;
  325. case 246:
  326. c = ';';
  327. break;
  328. case 247:
  329. c = '<';
  330. break;
  331. case 248:
  332. c = '=';
  333. break;
  334. case 249:
  335. c = '>';
  336. break;
  337. case 250:
  338. c = '?';
  339. break;
  340. case 251:
  341. c = '_';
  342. break;
  343. case 252:
  344. c = ' ';
  345. break;
  346. default:
  347. return nil;
  348. }
  349. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 8 value:c];
  350. }
  351. - (BOOL)isStillAlpha:(int)pos {
  352. if (pos + 5 > self.information.size) {
  353. return NO;
  354. }
  355. // We now check if it's a valid 5-bit value (0..9 and FNC1)
  356. int fiveBitValue = [self extractNumericValueFromBitArray:pos bits:5];
  357. if (fiveBitValue >= 5 && fiveBitValue < 16) {
  358. return YES;
  359. }
  360. if (pos + 6 > self.information.size) {
  361. return NO;
  362. }
  363. int sixBitValue = [self extractNumericValueFromBitArray:pos bits:6];
  364. return sixBitValue >= 16 && sixBitValue < 63; // 63 not included
  365. }
  366. - (ZXRSSExpandedDecodedChar *)decodeAlphanumeric:(int)pos {
  367. int fiveBitValue = [self extractNumericValueFromBitArray:pos bits:5];
  368. if (fiveBitValue == 15) {
  369. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 5 value:ZX_FNC1_CHAR];
  370. }
  371. if (fiveBitValue >= 5 && fiveBitValue < 15) {
  372. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 5 value:(unichar)('0' + fiveBitValue - 5)];
  373. }
  374. int sixBitValue = [self extractNumericValueFromBitArray:pos bits:6];
  375. if (sixBitValue >= 32 && sixBitValue < 58) {
  376. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 6 value:(unichar)(sixBitValue + 33)];
  377. }
  378. unichar c;
  379. switch (sixBitValue){
  380. case 58:
  381. c = '*';
  382. break;
  383. case 59:
  384. c = ',';
  385. break;
  386. case 60:
  387. c = '-';
  388. break;
  389. case 61:
  390. c = '.';
  391. break;
  392. case 62:
  393. c = '/';
  394. break;
  395. default:
  396. @throw [NSException exceptionWithName:@"RuntimeException"
  397. reason:[NSString stringWithFormat:@"Decoding invalid alphanumeric value: %d", sixBitValue]
  398. userInfo:nil];
  399. }
  400. return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 6 value:c];
  401. }
  402. - (BOOL)isAlphaTo646ToAlphaLatch:(int)pos {
  403. if (pos + 1 > self.information.size) {
  404. return NO;
  405. }
  406. for (int i = 0; i < 5 && i + pos < self.information.size; ++i) {
  407. if (i == 2) {
  408. if (![self.information get:pos + 2]) {
  409. return NO;
  410. }
  411. } else if ([self.information get:pos + i]) {
  412. return NO;
  413. }
  414. }
  415. return YES;
  416. }
  417. - (BOOL)isAlphaOr646ToNumericLatch:(int)pos {
  418. // Next is alphanumeric if there are 3 positions and they are all zeros
  419. if (pos + 3 > self.information.size) {
  420. return NO;
  421. }
  422. for (int i = pos; i < pos + 3; ++i) {
  423. if ([self.information get:i]) {
  424. return NO;
  425. }
  426. }
  427. return YES;
  428. }
  429. - (BOOL)isNumericToAlphaNumericLatch:(int)pos {
  430. // Next is alphanumeric if there are 4 positions and they are all zeros, or
  431. // if there is a subset of this just before the end of the symbol
  432. if (pos + 1 > self.information.size) {
  433. return NO;
  434. }
  435. for (int i = 0; i < 4 && i + pos < self.information.size; ++i) {
  436. if ([self.information get:pos + i]) {
  437. return NO;
  438. }
  439. }
  440. return YES;
  441. }
  442. @end