| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 | 
							- /*
 -  * 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 "ZXIntArray.h"
 - #import "ZXUPCEReader.h"
 - 
 - // For an UPC-E barcode, the final digit is represented by the parities used
 - // to encode the middle six digits, according to the table below.
 - //
 - //                Parity of next 6 digits
 - //    Digit   0     1     2     3     4     5
 - //       0    Even   Even  Even Odd  Odd   Odd
 - //       1    Even   Even  Odd  Even Odd   Odd
 - //       2    Even   Even  Odd  Odd  Even  Odd
 - //       3    Even   Even  Odd  Odd  Odd   Even
 - //       4    Even   Odd   Even Even Odd   Odd
 - //       5    Even   Odd   Odd  Even Even  Odd
 - //       6    Even   Odd   Odd  Odd  Even  Even
 - //       7    Even   Odd   Even Odd  Even  Odd
 - //       8    Even   Odd   Even Odd  Odd   Even
 - //       9    Even   Odd   Odd  Even Odd   Even
 - //
 - // The encoding is represented by the following array, which is a bit pattern
 - // using Odd = 0 and Even = 1. For example, 5 is represented by:
 - //
 - //              Odd Even Even Odd Odd Even
 - // in binary:
 - //                0    1    1   0   0    1   == 0x19
 - //
 - const int CHECK_DIGIT_ENCODINGS[] = {
 -   0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25
 - };
 - 
 - const int ZX_UPCE_MIDDLE_END_PATTERN_LEN = 6;
 - 
 - /**
 -  * The pattern that marks the middle, and end, of a UPC-E pattern.
 -  * There is no "second half" to a UPC-E barcode.
 -  */
 - const int ZX_UPCE_MIDDLE_END_PATTERN[] = {1, 1, 1, 1, 1, 1};
 - 
 - /**
 -  * See ZX_UCPE_L_AND_G_PATTERNS; these values similarly represent patterns of
 -  * even-odd parity encodings of digits that imply both the number system (0 or 1)
 -  * used, and the check digit.
 -  */
 - const int ZX_UCPE_NUMSYS_AND_CHECK_DIGIT_PATTERNS[][10] = {
 -   {0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25},
 -   {0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A}
 - };
 - 
 - @interface ZXUPCEReader ()
 - 
 - @property (nonatomic, strong, readonly) ZXIntArray *decodeMiddleCounters;
 - 
 - @end
 - 
 - @implementation ZXUPCEReader
 - 
 - - (id)init {
 -   if (self = [super init]) {
 -     _decodeMiddleCounters = [[ZXIntArray alloc] initWithLength:4];
 -   }
 - 
 -   return self;
 - }
 - 
 - - (int)decodeMiddle:(ZXBitArray *)row startRange:(NSRange)startRange result:(NSMutableString *)result error:(NSError **)error {
 -   ZXIntArray *counters = self.decodeMiddleCounters;
 -   [counters clear];
 - 
 -   int end = [row size];
 -   int rowOffset = (int)NSMaxRange(startRange);
 -   int lgPatternFound = 0;
 - 
 -   for (int x = 0; x < 6 && rowOffset < end; x++) {
 -     int bestMatch = [ZXUPCEANReader decodeDigit:row counters:counters rowOffset:rowOffset patternType:ZX_UPC_EAN_PATTERNS_L_AND_G_PATTERNS error:error];
 -     if (bestMatch == -1) {
 -       return -1;
 -     }
 -     [result appendFormat:@"%C", (unichar)('0' + bestMatch % 10)];
 - 
 -     rowOffset += [counters sum];
 - 
 -     if (bestMatch >= 10) {
 -       lgPatternFound |= 1 << (5 - x);
 -     }
 -   }
 - 
 -   if (![self determineNumSysAndCheckDigit:result lgPatternFound:lgPatternFound]) {
 -     if (error) *error = ZXNotFoundErrorInstance();
 -     return -1;
 -   }
 -   return rowOffset;
 - }
 - 
 - - (NSRange)decodeEnd:(ZXBitArray *)row endStart:(int)endStart error:(NSError **)error {
 -   return [ZXUPCEANReader findGuardPattern:row
 -                                 rowOffset:endStart
 -                                whiteFirst:YES
 -                                   pattern:ZX_UPCE_MIDDLE_END_PATTERN
 -                                patternLen:sizeof(ZX_UPCE_MIDDLE_END_PATTERN) / sizeof(int)
 -                                     error:error];
 - }
 - 
 - - (BOOL)checkChecksum:(NSString *)s error:(NSError **)error {
 -   return [super checkChecksum:[ZXUPCEReader convertUPCEtoUPCA:s] error:error];
 - }
 - 
 - - (BOOL)determineNumSysAndCheckDigit:(NSMutableString *)resultString lgPatternFound:(int)lgPatternFound {
 -   for (int numSys = 0; numSys <= 1; numSys++) {
 -     for (int d = 0; d < 10; d++) {
 -       if (lgPatternFound == ZX_UCPE_NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) {
 -         [resultString insertString:[NSString stringWithFormat:@"%C", (unichar)('0' + numSys)] atIndex:0];
 -         [resultString appendFormat:@"%C", (unichar)('0' + d)];
 -         return YES;
 -       }
 -     }
 -   }
 - 
 -   return NO;
 - }
 - 
 - - (ZXBarcodeFormat)barcodeFormat {
 -   return kBarcodeFormatUPCE;
 - }
 - 
 - /**
 -  * Expands a UPC-E value back into its full, equivalent UPC-A code value.
 -  *
 -  * @param upce UPC-E code as string of digits
 -  * @return equivalent UPC-A code as string of digits
 -  */
 - + (NSString *)convertUPCEtoUPCA:(NSString *)upce {
 -   NSString *upceChars = [upce substringWithRange:NSMakeRange(1, 6)];
 -   NSMutableString *result = [NSMutableString stringWithCapacity:12];
 -   [result appendFormat:@"%C", [upce characterAtIndex:0]];
 -   unichar lastChar = [upceChars characterAtIndex:5];
 -   switch (lastChar) {
 -     case '0':
 -     case '1':
 -     case '2':
 -       [result appendString:[upceChars substringToIndex:2]];
 -       [result appendFormat:@"%C", lastChar];
 -       [result appendString:@"0000"];
 -       [result appendString:[upceChars substringWithRange:NSMakeRange(2, 3)]];
 -       break;
 -     case '3':
 -       [result appendString:[upceChars substringToIndex:3]];
 -       [result appendString:@"00000"];
 -       [result appendString:[upceChars substringWithRange:NSMakeRange(3, 2)]];
 -       break;
 -     case '4':
 -       [result appendString:[upceChars substringToIndex:4]];
 -       [result appendString:@"00000"];
 -       [result appendString:[upceChars substringWithRange:NSMakeRange(4, 1)]];
 -       break;
 -     default:
 -       [result appendString:[upceChars substringToIndex:5]];
 -       [result appendString:@"0000"];
 -       [result appendFormat:@"%C", lastChar];
 -       break;
 -   }
 -   [result appendFormat:@"%C", [upce characterAtIndex:7]];
 -   return result;
 - }
 - 
 - @end
 
 
  |