Removed as many exceptions as possible from the C++ product readers
[zxing.git] / cpp / core / src / zxing / oned / UPCEANReader.cpp
index 133bd47..6f08e75 100644 (file)
@@ -2,7 +2,6 @@
  *  UPCEANReader.cpp
  *  ZXing
  *
- *  Created by Lukasz Warchol on 10-01-21.
  *  Copyright 2010 ZXing authors All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
 #include "UPCEANReader.h"
 #include <zxing/oned/OneDResultPoint.h>
 #include <zxing/ReaderException.h>
+
 namespace zxing {
   namespace oned {
-    
+
     /**
      * Start/end guard pattern.
      */
     static const int START_END_PATTERN[3] = {1, 1, 1};
-    
+
     /**
      * Pattern marking the middle of a UPC/EAN pattern, separating the two halves.
      */
     static const int MIDDLE_PATTERN_LEN = 5;
     static const int MIDDLE_PATTERN[MIDDLE_PATTERN_LEN] = {1, 1, 1, 1, 1};
-    
+
     /**
      * "Odd", or "L" patterns used to encode UPC/EAN digits.
      */
@@ -52,7 +52,7 @@ namespace zxing {
       {1, 2, 1, 3}, // 8
       {3, 1, 1, 2}  // 9
     };
-    
+
     /**
      * As above but also including the "even", or "G" patterns used to encode UPC/EAN digits.
      */
@@ -80,106 +80,105 @@ namespace zxing {
       {3, 1, 2, 1}, // 18 reversed 8
       {2, 1, 1, 3}  // 19 reversed 9
     };
-    
 
-    const int UPCEANReader::getMIDDLE_PATTERN_LEN(){
+
+    const int UPCEANReader::getMIDDLE_PATTERN_LEN() {
       return MIDDLE_PATTERN_LEN;
     }
-    const int* UPCEANReader::getMIDDLE_PATTERN(){
+
+    const int* UPCEANReader::getMIDDLE_PATTERN() {
       return MIDDLE_PATTERN;
     }
-    
-    UPCEANReader::UPCEANReader(){
+
+    UPCEANReader::UPCEANReader() {
     }
-    
-    
+
+
     Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
-                       int* start = NULL;
-                       try {
-                               start = findStartGuardPattern(row);
-                               Ref<Result> result = decodeRow(rowNumber, row, start);
-                               delete [] start;
-                               return result;
-                       } catch (ReaderException const& re) {
-                               delete [] start;
-                               throw re;
+                       int* start = findStartGuardPattern(row);
+                       if (start != NULL) {
+        try {
+          Ref<Result> result = decodeRow(rowNumber, row, start);
+          delete [] start;
+          return result;
+        } catch (ReaderException const& re) {
+          delete [] start;
+        }
                        }
+                       return Ref<Result>();
     }
-    
-    Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]){
-      int* endRange = NULL;
-      try {
-                               std::string tmpResultString;
-        std::string& tmpResultStringRef = tmpResultString;
-        int endStart;
-        endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , tmpResultStringRef);
-      
-        endRange = decodeEnd(row, endStart);
-                        
-        // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The
-        // spec might want more whitespace, but in practice this is the maximum we can count on.
-        size_t end = endRange[1];
-        size_t quietEnd = end + (end - endRange[0]);
-        if (quietEnd >= row->getSize() || !row->isRange(end, quietEnd, false)) {
-          throw ReaderException("Quiet zone asserrt fail.");
-        }
 
-        if (!checkChecksum(tmpResultString)) {
-          throw ReaderException("Checksum fail.");
-        }
-      
-        Ref<String> resultString(new String(tmpResultString));
-      
-        float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f;
-        float right = (float) (endRange[1] + endRange[0]) / 2.0f;
-      
-        std::vector< Ref<ResultPoint> > resultPoints(2);
-        Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
-        Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber));
-        resultPoints[0] = resultPoint1;
-        resultPoints[1] = resultPoint2;
-      
-        ArrayRef<unsigned char> resultBytes(1);
-      
-        Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
+    Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]) {
+      std::string tmpResultString;
+      std::string& tmpResultStringRef = tmpResultString;
+      int endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ ,
+          tmpResultStringRef);
+      if (endStart < 0) {
+        return Ref<Result>();
+      }
+      int* endRange = decodeEnd(row, endStart);
+      if (endRange == NULL) {
+        return Ref<Result>();
+      }
+
+      // Make sure there is a quiet zone at least as big as the end pattern after the barcode.
+      // The spec might want more whitespace, but in practice this is the maximum we can count on.
+      size_t end = endRange[1];
+      size_t quietEnd = end + (end - endRange[0]);
+      if (quietEnd >= row->getSize() || !row->isRange(end, quietEnd, false)) {
         delete [] endRange;
-        return res;
-      } catch (ReaderException const& re) {
+        return Ref<Result>();
+      }
+
+      if (!checkChecksum(tmpResultString)) {
         delete [] endRange;
-                               throw re;
-                       }
+        return Ref<Result>();
+      }
+
+      Ref<String> resultString(new String(tmpResultString));
 
+      float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f;
+      float right = (float) (endRange[1] + endRange[0]) / 2.0f;
+
+      std::vector< Ref<ResultPoint> > resultPoints(2);
+      Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
+      Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber));
+      resultPoints[0] = resultPoint1;
+      resultPoints[1] = resultPoint2;
+
+      ArrayRef<unsigned char> resultBytes(1);
+      Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
+      delete [] endRange;
+      return res;
     }
-    
-    int* UPCEANReader::findStartGuardPattern(Ref<BitArray> row){
+
+    int* UPCEANReader::findStartGuardPattern(Ref<BitArray> row) {
       bool foundStart = false;
-      
       int* startRange = NULL;
       int nextStart = 0;
-      try {
-        while (!foundStart) {
-          delete [] startRange;
-          startRange = NULL;
-          startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, sizeof(START_END_PATTERN)/sizeof(int));
-          int start = startRange[0];
-          nextStart = startRange[1];
-          // Make sure there is a quiet zone at least as big as the start pattern before the barcode.
-          // If this check would run off the left edge of the image, do not accept this barcode,
-          // as it is very likely to be a false positive.
-          int quietStart = start - (nextStart - start);
-          if (quietStart >= 0) {
-            foundStart = row->isRange(quietStart, start, false);
-          }
-        }
-        return startRange;
-      } catch (ReaderException const& re) {
+      while (!foundStart) {
         delete [] startRange;
-        throw re;
+        startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN,
+            sizeof(START_END_PATTERN) / sizeof(int));
+        if (startRange == NULL) {
+          return NULL;
+        }
+        int start = startRange[0];
+        nextStart = startRange[1];
+        // Make sure there is a quiet zone at least as big as the start pattern before the barcode.
+        // If this check would run off the left edge of the image, do not accept this barcode,
+        // as it is very likely to be a false positive.
+        int quietStart = start - (nextStart - start);
+        if (quietStart >= 0) {
+          foundStart = row->isRange(quietStart, start, false);
+        }
       }
+      return startRange;
     }
-    
+
     // TODO(flyashi): Return a pair<int, int> for return value to avoid using the heap.
-    int* UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen){
+    int* UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
+        const int pattern[], int patternLen) {
       int patternLength = patternLen;
       int counters[patternLength];
       int countersCount = sizeof(counters) / sizeof(int);
@@ -195,7 +194,7 @@ namespace zxing {
         }
         rowOffset++;
       }
-      
+
       int counterPosition = 0;
       int patternStart = rowOffset;
       for (int x = rowOffset; x < width; x++) {
@@ -204,7 +203,8 @@ namespace zxing {
           counters[counterPosition]++;
         } else {
           if (counterPosition == patternLength - 1) {
-            if (patternMatchVariance(counters, countersCount, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
+            if (patternMatchVariance(counters, countersCount, pattern,
+                MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
               int* resultValue = new int[2];
               resultValue[0] = patternStart;
               resultValue[1] = x;
@@ -224,19 +224,22 @@ namespace zxing {
           isWhite = !isWhite;
         }
       }
-      throw ReaderException("findGuardPattern");
+      return NULL;
     }
-    
-    int* UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart){
-      return findGuardPattern(row, endStart, false, START_END_PATTERN, sizeof(START_END_PATTERN)/sizeof(int));
+
+    int* UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart) {
+      return findGuardPattern(row, endStart, false, START_END_PATTERN,
+          sizeof(START_END_PATTERN) / sizeof(int));
     }
-    
-//    int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset, int** patterns/*[][]*/, int paterns1Len, int paterns2Len)    
-    int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset, UPC_EAN_PATTERNS patternType){
-      recordPattern(row, rowOffset, counters, countersLen);
+
+    int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
+        UPC_EAN_PATTERNS patternType) {
+      if (!recordPattern(row, rowOffset, counters, countersLen)) {
+        return -1;
+      }
       unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
       int bestMatch = -1;
-      
+
       int max = 0;
       switch (patternType) {
         case UPC_EAN_PATTERNS_L_PATTERNS:
@@ -246,8 +249,9 @@ namespace zxing {
             for(int j = 0; j< countersLen; j++){
               pattern[j] = L_PATTERNS[i][j];
             }
-            
-            unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE);
+
+            unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
+                MAX_INDIVIDUAL_VARIANCE);
             if (variance < bestVariance) {
               bestVariance = variance;
               bestMatch = i;
@@ -261,8 +265,9 @@ namespace zxing {
             for(int j = 0; j< countersLen; j++){
               pattern[j] = L_AND_G_PATTERNS[i][j];
             }
-            
-            unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE);
+
+            unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
+                MAX_INDIVIDUAL_VARIANCE);
             if (variance < bestVariance) {
               bestVariance = variance;
               bestMatch = i;
@@ -272,40 +277,34 @@ namespace zxing {
         default:
           break;
       }
-      if (bestMatch >= 0) {
-        return bestMatch;
-      } else {
-        throw ReaderException("UPCEANReader::decodeDigit: No best mach");
-      }
+      return bestMatch;
     }
-    
-    
+
     /**
      * @return {@link #checkStandardUPCEANChecksum(String)}
      */
-    bool UPCEANReader::checkChecksum(std::string s){
+    bool UPCEANReader::checkChecksum(std::string s) {
       return checkStandardUPCEANChecksum(s);
     }
-    
+
     /**
      * Computes the UPC/EAN checksum on a string of digits, and reports
      * whether the checksum is correct or not.
      *
      * @param s string of digits to check
      * @return true iff string of digits passes the UPC/EAN checksum algorithm
-     * @throws ReaderException if the string does not contain only digits
      */
-    bool UPCEANReader::checkStandardUPCEANChecksum(std::string s){
+    bool UPCEANReader::checkStandardUPCEANChecksum(std::string s) {
       int length = s.length();
       if (length == 0) {
         return false;
       }
-      
+
       int sum = 0;
       for (int i = length - 2; i >= 0; i -= 2) {
         int digit = (int) s[i] - (int) '0';
         if (digit < 0 || digit > 9) {
-          throw ReaderException("checkStandardUPCEANChecksum");
+          return false;
         }
         sum += digit;
       }
@@ -313,13 +312,14 @@ namespace zxing {
       for (int i = length - 1; i >= 0; i -= 2) {
         int digit = (int) s[i] - (int) '0';
         if (digit < 0 || digit > 9) {
-          throw ReaderException("checkStandardUPCEANChecksum");
+          return false;
         }
         sum += digit;
       }
       return sum % 10 == 0;
     }
-    UPCEANReader::~UPCEANReader(){
+
+    UPCEANReader::~UPCEANReader() {
     }
   }
 }