123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 |
- /*
- * Copyright 2012 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.
- */
-
- #import "ZXBitArray.h"
- #import "ZXErrors.h"
- #import "ZXRSSExpandedBlockParsedResult.h"
- #import "ZXRSSExpandedCurrentParsingState.h"
- #import "ZXRSSExpandedDecodedChar.h"
- #import "ZXRSSExpandedDecodedInformation.h"
- #import "ZXRSSExpandedDecodedNumeric.h"
- #import "ZXRSSExpandedFieldParser.h"
- #import "ZXRSSExpandedGeneralAppIdDecoder.h"
-
- @interface ZXRSSExpandedGeneralAppIdDecoder ()
-
- @property (nonatomic, strong, readonly) ZXBitArray *information;
- @property (nonatomic, strong, readonly) ZXRSSExpandedCurrentParsingState *current;
- @property (nonatomic, strong, readonly) NSMutableString *buffer;
-
- @end
-
- @implementation ZXRSSExpandedGeneralAppIdDecoder
-
- - (id)initWithInformation:(ZXBitArray *)information {
- if (self = [super init]) {
- _current = [[ZXRSSExpandedCurrentParsingState alloc] init];
- _buffer = [NSMutableString string];
- _information = information;
- }
-
- return self;
- }
-
- - (NSString *)decodeAllCodes:(NSMutableString *)buff initialPosition:(int)initialPosition error:(NSError **)error {
- int currentPosition = initialPosition;
- NSString *remaining = nil;
- do {
- ZXRSSExpandedDecodedInformation *info = [self decodeGeneralPurposeField:currentPosition remaining:remaining];
- if (!info) {
- if (error) *error = ZXFormatErrorInstance();
- return nil;
- }
- NSString *parsedFields = [ZXRSSExpandedFieldParser parseFieldsInGeneralPurpose:[info theNewString] error:error];
- if (!parsedFields) {
- return nil;
- } else if (parsedFields.length > 0) {
- [buff appendString:parsedFields];
- }
-
- if ([info remaining]) {
- remaining = [@([info remainingValue]) stringValue];
- } else {
- remaining = nil;
- }
-
- if (currentPosition == [info theNewPosition]) {// No step forward!
- break;
- }
- currentPosition = [info theNewPosition];
- } while (YES);
-
- return buff;
- }
-
- - (BOOL)isStillNumeric:(int)pos {
- // It's numeric if it still has 7 positions
- // and one of the first 4 bits is "1".
- if (pos + 7 > self.information.size) {
- return pos + 4 <= self.information.size;
- }
-
- for (int i = pos; i < pos + 3; ++i) {
- if ([self.information get:i]) {
- return YES;
- }
- }
-
- return [self.information get:pos + 3];
- }
-
- - (ZXRSSExpandedDecodedNumeric *)decodeNumeric:(int)pos {
- if (pos + 7 > self.information.size) {
- int numeric = [self extractNumericValueFromBitArray:pos bits:4];
- if (numeric == 0) {
- return [[ZXRSSExpandedDecodedNumeric alloc] initWithNewPosition:self.information.size
- firstDigit:ZX_FNC1_INT
- secondDigit:ZX_FNC1_INT];
- }
- return [[ZXRSSExpandedDecodedNumeric alloc] initWithNewPosition:self.information.size
- firstDigit:numeric - 1
- secondDigit:ZX_FNC1_INT];
- }
- int numeric = [self extractNumericValueFromBitArray:pos bits:7];
-
- int digit1 = (numeric - 8) / 11;
- int digit2 = (numeric - 8) % 11;
-
- return [[ZXRSSExpandedDecodedNumeric alloc] initWithNewPosition:pos + 7
- firstDigit:digit1
- secondDigit:digit2];
- }
-
- - (int)extractNumericValueFromBitArray:(int)pos bits:(int)bits {
- return [ZXRSSExpandedGeneralAppIdDecoder extractNumericValueFromBitArray:self.information pos:pos bits:bits];
- }
-
- + (int)extractNumericValueFromBitArray:(ZXBitArray *)information pos:(int)pos bits:(int)bits {
- if (bits > 32) {
- [NSException raise:NSInvalidArgumentException format:@"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;
- }
-
- - (ZXRSSExpandedDecodedInformation *)decodeGeneralPurposeField:(int)pos remaining:(NSString *)remaining {
- [self.buffer setString:@""];
-
- if (remaining != nil) {
- [self.buffer appendString:remaining];
- }
-
- self.current.position = pos;
-
- NSError *error;
- ZXRSSExpandedDecodedInformation *lastDecoded = [self parseBlocksWithError:&error];
- if (error) {
- return nil;
- }
-
- if (lastDecoded != nil && [lastDecoded remaining]) {
- return [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
- newString:self.buffer
- remainingValue:lastDecoded.remainingValue];
- }
- return [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position newString:self.buffer];
- }
-
- - (ZXRSSExpandedDecodedInformation *)parseBlocksWithError:(NSError **)error {
- BOOL isFinished;
- ZXRSSExpandedBlockParsedResult *result;
- do {
- int initialPosition = self.current.position;
-
- NSError *localError;
- if (self.current.alpha) {
- result = [self parseAlphaBlock];
- isFinished = result.finished;
- } else if (self.current.isoIec646) {
- result = [self parseIsoIec646BlockWithError:&localError];
- isFinished = result.finished;
- } else {
- result = [self parseNumericBlockWithError:&localError];
- isFinished = result.finished;
- }
-
- if (localError) {
- if (error) *error = localError;
- return nil;
- }
-
- BOOL positionChanged = initialPosition != self.current.position;
- if (!positionChanged && !isFinished) {
- break;
- }
- } while (!isFinished);
- return result.decodedInformation;
- }
-
- - (ZXRSSExpandedBlockParsedResult *)parseNumericBlockWithError:(NSError **)error {
- while ([self isStillNumeric:self.current.position]) {
- ZXRSSExpandedDecodedNumeric *numeric = [self decodeNumeric:self.current.position];
- if (!numeric) {
- if (error) *error = ZXFormatErrorInstance();
- return nil;
- }
- self.current.position = numeric.theNewPosition;
-
- if ([numeric firstDigitFNC1]) {
- ZXRSSExpandedDecodedInformation *information;
- if ([numeric secondDigitFNC1]) {
- information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
- newString:self.buffer];
- } else {
- information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
- newString:self.buffer
- remainingValue:numeric.secondDigit];
- }
- return [[ZXRSSExpandedBlockParsedResult alloc] initWithInformation:information finished:YES];
- }
- [self.buffer appendFormat:@"%d", numeric.firstDigit];
-
- if (numeric.secondDigitFNC1) {
- ZXRSSExpandedDecodedInformation *information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
- newString:self.buffer];
- return [[ZXRSSExpandedBlockParsedResult alloc] initWithInformation:information finished:YES];
- }
- [self.buffer appendFormat:@"%d", numeric.secondDigit];
- }
-
- if ([self isNumericToAlphaNumericLatch:self.current.position]) {
- [self.current setAlpha];
- self.current.position += 4;
- }
- return [[ZXRSSExpandedBlockParsedResult alloc] initWithFinished:NO];
- }
-
- - (ZXRSSExpandedBlockParsedResult *)parseIsoIec646BlockWithError:(NSError **)error {
- while ([self isStillIsoIec646:self.current.position]) {
- ZXRSSExpandedDecodedChar *iso = [self decodeIsoIec646:self.current.position];
- if (!iso) {
- if (error) *error = ZXFormatErrorInstance();
- return nil;
- }
- self.current.position = iso.theNewPosition;
-
- if (iso.fnc1) {
- ZXRSSExpandedDecodedInformation *information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
- newString:self.buffer];
- return [[ZXRSSExpandedBlockParsedResult alloc] initWithInformation:information finished:YES];
- }
- [self.buffer appendFormat:@"%C", iso.value];
- }
-
- if ([self isAlphaOr646ToNumericLatch:self.current.position]) {
- self.current.position += 3;
- [self.current setNumeric];
- } else if ([self isAlphaTo646ToAlphaLatch:self.current.position]) {
- if (self.current.position + 5 < self.information.size) {
- self.current.position += 5;
- } else {
- self.current.position = self.information.size;
- }
-
- [self.current setAlpha];
- }
- return [[ZXRSSExpandedBlockParsedResult alloc] initWithFinished:NO];
- }
-
- - (ZXRSSExpandedBlockParsedResult *)parseAlphaBlock {
- while ([self isStillAlpha:self.current.position]) {
- ZXRSSExpandedDecodedChar *alpha = [self decodeAlphanumeric:self.current.position];
- self.current.position = alpha.theNewPosition;
-
- if (alpha.fnc1) {
- ZXRSSExpandedDecodedInformation *information = [[ZXRSSExpandedDecodedInformation alloc] initWithNewPosition:self.current.position
- newString:self.buffer];
- return [[ZXRSSExpandedBlockParsedResult alloc] initWithInformation:information finished:YES];
- }
-
- [self.buffer appendFormat:@"%C", alpha.value];
- }
-
- if ([self isAlphaOr646ToNumericLatch:self.current.position]) {
- self.current.position += 3;
- [self.current setNumeric];
- } else if ([self isAlphaTo646ToAlphaLatch:self.current.position]) {
- if (self.current.position + 5 < self.information.size) {
- self.current.position += 5;
- } else {
- self.current.position = self.information.size;
- }
-
- [self.current setIsoIec646];
- }
- return [[ZXRSSExpandedBlockParsedResult alloc] initWithFinished:NO];
- }
-
- - (BOOL)isStillIsoIec646:(int)pos {
- if (pos + 5 > self.information.size) {
- return NO;
- }
-
- int fiveBitValue = [self extractNumericValueFromBitArray:pos bits:5];
- if (fiveBitValue >= 5 && fiveBitValue < 16) {
- return YES;
- }
-
- if (pos + 7 > self.information.size) {
- return NO;
- }
-
- int sevenBitValue = [self extractNumericValueFromBitArray:pos bits:7];
- if (sevenBitValue >= 64 && sevenBitValue < 116) {
- return YES;
- }
-
- if (pos + 8 > self.information.size) {
- return NO;
- }
-
- int eightBitValue = [self extractNumericValueFromBitArray:pos bits:8];
- return eightBitValue >= 232 && eightBitValue < 253;
- }
-
- - (ZXRSSExpandedDecodedChar *)decodeIsoIec646:(int)pos {
- int fiveBitValue = [self extractNumericValueFromBitArray:pos bits:5];
- if (fiveBitValue == 15) {
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 5 value:ZX_FNC1_CHAR];
- }
-
- if (fiveBitValue >= 5 && fiveBitValue < 15) {
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 5 value:(unichar)('0' + fiveBitValue - 5)];
- }
-
- int sevenBitValue = [self extractNumericValueFromBitArray:pos bits:7];
-
- if (sevenBitValue >= 64 && sevenBitValue < 90) {
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 7 value:(unichar)(sevenBitValue + 1)];
- }
-
- if (sevenBitValue >= 90 && sevenBitValue < 116) {
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 7 value:(unichar)(sevenBitValue + 7)];
- }
-
- int eightBitValue = [self extractNumericValueFromBitArray:pos bits:8];
- unichar c;
- switch (eightBitValue) {
- case 232:
- c = '!';
- break;
- case 233:
- c = '"';
- break;
- case 234:
- c ='%';
- break;
- case 235:
- c = '&';
- break;
- case 236:
- c = '\'';
- break;
- case 237:
- c = '(';
- break;
- case 238:
- c = ')';
- break;
- case 239:
- c = '*';
- break;
- case 240:
- c = '+';
- break;
- case 241:
- c = ',';
- break;
- case 242:
- c = '-';
- break;
- case 243:
- c = '.';
- break;
- case 244:
- c = '/';
- break;
- case 245:
- c = ':';
- break;
- case 246:
- c = ';';
- break;
- case 247:
- c = '<';
- break;
- case 248:
- c = '=';
- break;
- case 249:
- c = '>';
- break;
- case 250:
- c = '?';
- break;
- case 251:
- c = '_';
- break;
- case 252:
- c = ' ';
- break;
- default:
- return nil;
- }
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 8 value:c];
- }
-
- - (BOOL)isStillAlpha:(int)pos {
- if (pos + 5 > self.information.size) {
- return NO;
- }
-
- // We now check if it's a valid 5-bit value (0..9 and FNC1)
- int fiveBitValue = [self extractNumericValueFromBitArray:pos bits:5];
- if (fiveBitValue >= 5 && fiveBitValue < 16) {
- return YES;
- }
-
- if (pos + 6 > self.information.size) {
- return NO;
- }
-
- int sixBitValue = [self extractNumericValueFromBitArray:pos bits:6];
- return sixBitValue >= 16 && sixBitValue < 63; // 63 not included
- }
-
- - (ZXRSSExpandedDecodedChar *)decodeAlphanumeric:(int)pos {
- int fiveBitValue = [self extractNumericValueFromBitArray:pos bits:5];
- if (fiveBitValue == 15) {
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 5 value:ZX_FNC1_CHAR];
- }
-
- if (fiveBitValue >= 5 && fiveBitValue < 15) {
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 5 value:(unichar)('0' + fiveBitValue - 5)];
- }
-
- int sixBitValue = [self extractNumericValueFromBitArray:pos bits:6];
-
- if (sixBitValue >= 32 && sixBitValue < 58) {
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 6 value:(unichar)(sixBitValue + 33)];
- }
-
- unichar c;
- switch (sixBitValue){
- case 58:
- c = '*';
- break;
- case 59:
- c = ',';
- break;
- case 60:
- c = '-';
- break;
- case 61:
- c = '.';
- break;
- case 62:
- c = '/';
- break;
- default:
- @throw [NSException exceptionWithName:@"RuntimeException"
- reason:[NSString stringWithFormat:@"Decoding invalid alphanumeric value: %d", sixBitValue]
- userInfo:nil];
- }
-
- return [[ZXRSSExpandedDecodedChar alloc] initWithNewPosition:pos + 6 value:c];
- }
-
- - (BOOL)isAlphaTo646ToAlphaLatch:(int)pos {
- if (pos + 1 > self.information.size) {
- return NO;
- }
-
- for (int i = 0; i < 5 && i + pos < self.information.size; ++i) {
- if (i == 2) {
- if (![self.information get:pos + 2]) {
- return NO;
- }
- } else if ([self.information get:pos + i]) {
- return NO;
- }
- }
-
- return YES;
- }
-
- - (BOOL)isAlphaOr646ToNumericLatch:(int)pos {
- // Next is alphanumeric if there are 3 positions and they are all zeros
- if (pos + 3 > self.information.size) {
- return NO;
- }
-
- for (int i = pos; i < pos + 3; ++i) {
- if ([self.information get:i]) {
- return NO;
- }
- }
-
- return YES;
- }
-
- - (BOOL)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 > self.information.size) {
- return NO;
- }
-
- for (int i = 0; i < 4 && i + pos < self.information.size; ++i) {
- if ([self.information get:pos + i]) {
- return NO;
- }
- }
-
- return YES;
- }
-
- @end
|