mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-25 20:02:34 +00:00
begin port of rss_expanded
This commit is contained in:
@@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader;
|
||||
|
||||
use crate::{common::BitArray, BarcodeFormat, Exceptions, RXingResult};
|
||||
|
||||
use super::{OneDReader, one_d_reader};
|
||||
use super::{one_d_reader, OneDReader};
|
||||
|
||||
/**
|
||||
* <p>Decodes Code 128 barcodes.</p>
|
||||
@@ -434,7 +434,8 @@ impl Code128Reader {
|
||||
for d in 0..CODE_PATTERNS.len() {
|
||||
// for (int d = 0; d < CODE_PATTERNS.len(); d++) {
|
||||
let pattern = &CODE_PATTERNS[d];
|
||||
let variance = one_d_reader::patternMatchVariance(counters, &pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
let variance =
|
||||
one_d_reader::patternMatchVariance(counters, &pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
if variance < bestVariance {
|
||||
bestVariance = variance;
|
||||
bestMatch = d as isize;
|
||||
|
||||
@@ -19,7 +19,7 @@ use one_d_reader_derive::OneDReader;
|
||||
use crate::common::BitArray;
|
||||
use crate::{BarcodeFormat, Exceptions, RXingResult};
|
||||
|
||||
use super::{OneDReader, one_d_reader};
|
||||
use super::{one_d_reader, OneDReader};
|
||||
|
||||
/**
|
||||
* <p>Decodes Code 39 barcodes. Supports "Full ASCII Code 39" if USE_CODE_39_EXTENDED_MODE is set.</p>
|
||||
|
||||
@@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader;
|
||||
|
||||
use crate::{common::BitArray, BarcodeFormat, Exceptions, RXingResult};
|
||||
|
||||
use super::{OneDReader, one_d_reader};
|
||||
use super::{one_d_reader, OneDReader};
|
||||
|
||||
/**
|
||||
* <p>Decodes Code 93 barcodes.</p>
|
||||
|
||||
@@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader;
|
||||
|
||||
use crate::{common::BitArray, BarcodeFormat, DecodeHintValue, Exceptions, RXingResult};
|
||||
|
||||
use super::{OneDReader, one_d_reader};
|
||||
use super::{one_d_reader, OneDReader};
|
||||
|
||||
const MAX_AVG_VARIANCE: f32 = 0.38;
|
||||
const MAX_INDIVIDUAL_VARIANCE: f32 = 0.5;
|
||||
@@ -375,8 +375,11 @@ impl ITFReader {
|
||||
counters[counterPosition] += 1;
|
||||
} else {
|
||||
if counterPosition == patternLength - 1 {
|
||||
if one_d_reader::patternMatchVariance(&counters, pattern, MAX_INDIVIDUAL_VARIANCE)
|
||||
< MAX_AVG_VARIANCE
|
||||
if one_d_reader::patternMatchVariance(
|
||||
&counters,
|
||||
pattern,
|
||||
MAX_INDIVIDUAL_VARIANCE,
|
||||
) < MAX_AVG_VARIANCE
|
||||
{
|
||||
return Ok([patternStart, x]);
|
||||
}
|
||||
@@ -412,7 +415,8 @@ impl ITFReader {
|
||||
for i in 0..max {
|
||||
// for (int i = 0; i < max; i++) {
|
||||
let pattern = &PATTERNS[i];
|
||||
let variance = one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
let variance =
|
||||
one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
if variance < bestVariance {
|
||||
bestVariance = variance;
|
||||
bestMatch = i as isize;
|
||||
|
||||
@@ -166,7 +166,6 @@ pub trait OneDReader: Reader {
|
||||
) -> Result<RXingResult, Exceptions>;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines how closely a set of observed counts of runs of black/white values matches a given
|
||||
* target pattern. This is reported as the ratio of the total variance from the expected pattern
|
||||
@@ -177,11 +176,7 @@ pub trait OneDReader: Reader {
|
||||
* @param maxIndividualVariance The most any counter can differ before we give up
|
||||
* @return ratio of total variance between counters and pattern compared to total pattern size
|
||||
*/
|
||||
pub fn patternMatchVariance(
|
||||
counters: &[u32],
|
||||
pattern: &[u32],
|
||||
maxIndividualVariance: f32,
|
||||
) -> f32 {
|
||||
pub fn patternMatchVariance(counters: &[u32], pattern: &[u32], maxIndividualVariance: f32) -> f32 {
|
||||
let mut maxIndividualVariance = maxIndividualVariance;
|
||||
let numCounters = counters.len();
|
||||
let mut total = 0.0;
|
||||
@@ -218,76 +213,72 @@ pub fn patternMatchVariance(
|
||||
return totalVariance / total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the size of successive runs of white and black pixels in a row, starting at a given point.
|
||||
* The values are recorded in the given array, and the number of runs recorded is equal to the size
|
||||
* of the array. If the row starts on a white pixel at the given start point, then the first count
|
||||
* recorded is the run of white pixels starting from that point; likewise it is the count of a run
|
||||
* of black pixels if the row begin on a black pixels at that point.
|
||||
*
|
||||
* @param row row to count from
|
||||
* @param start offset into row to start at
|
||||
* @param counters array into which to record counts
|
||||
* @throws NotFoundException if counters cannot be filled entirely from row before running out
|
||||
* of pixels
|
||||
*/
|
||||
pub fn recordPattern(
|
||||
row: &BitArray,
|
||||
start: usize,
|
||||
counters: &mut [u32],
|
||||
) -> Result<(), Exceptions> {
|
||||
let numCounters = counters.len();
|
||||
// Arrays.fill(counters, 0, numCounters, 0);
|
||||
counters.fill(0);
|
||||
let end = row.getSize();
|
||||
if start >= end {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
let mut isWhite = !row.get(start);
|
||||
let mut counterPosition = 0;
|
||||
let mut i = start;
|
||||
while i < end {
|
||||
if row.get(i) != isWhite {
|
||||
counters[counterPosition] += 1;
|
||||
} else {
|
||||
counterPosition += 1;
|
||||
if counterPosition == numCounters {
|
||||
break;
|
||||
} else {
|
||||
counters[counterPosition] = 1;
|
||||
isWhite = !isWhite;
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
// If we read fully the last section of pixels and filled up our counters -- or filled
|
||||
// the last counter but ran off the side of the image, OK. Otherwise, a problem.
|
||||
if !(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end)) {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
Ok(())
|
||||
/**
|
||||
* Records the size of successive runs of white and black pixels in a row, starting at a given point.
|
||||
* The values are recorded in the given array, and the number of runs recorded is equal to the size
|
||||
* of the array. If the row starts on a white pixel at the given start point, then the first count
|
||||
* recorded is the run of white pixels starting from that point; likewise it is the count of a run
|
||||
* of black pixels if the row begin on a black pixels at that point.
|
||||
*
|
||||
* @param row row to count from
|
||||
* @param start offset into row to start at
|
||||
* @param counters array into which to record counts
|
||||
* @throws NotFoundException if counters cannot be filled entirely from row before running out
|
||||
* of pixels
|
||||
*/
|
||||
pub fn recordPattern(row: &BitArray, start: usize, counters: &mut [u32]) -> Result<(), Exceptions> {
|
||||
let numCounters = counters.len();
|
||||
// Arrays.fill(counters, 0, numCounters, 0);
|
||||
counters.fill(0);
|
||||
let end = row.getSize();
|
||||
if start >= end {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
|
||||
pub fn recordPatternInReverse(
|
||||
row: &BitArray,
|
||||
start: usize,
|
||||
counters: &mut [u32],
|
||||
) -> Result<(), Exceptions> {
|
||||
let mut start = start;
|
||||
// This could be more efficient I guess
|
||||
let mut numTransitionsLeft = counters.len() as isize;
|
||||
let mut last = row.get(start);
|
||||
while start > 0 && numTransitionsLeft >= 0 {
|
||||
start -= 1;
|
||||
if row.get(start) != last {
|
||||
numTransitionsLeft -= 1;
|
||||
last = !last;
|
||||
let mut isWhite = !row.get(start);
|
||||
let mut counterPosition = 0;
|
||||
let mut i = start;
|
||||
while i < end {
|
||||
if row.get(i) != isWhite {
|
||||
counters[counterPosition] += 1;
|
||||
} else {
|
||||
counterPosition += 1;
|
||||
if counterPosition == numCounters {
|
||||
break;
|
||||
} else {
|
||||
counters[counterPosition] = 1;
|
||||
isWhite = !isWhite;
|
||||
}
|
||||
}
|
||||
if numTransitionsLeft >= 0 {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
recordPattern(row, start + 1, counters)?;
|
||||
i += 1;
|
||||
}
|
||||
// If we read fully the last section of pixels and filled up our counters -- or filled
|
||||
// the last counter but ran off the side of the image, OK. Otherwise, a problem.
|
||||
if !(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end)) {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn recordPatternInReverse(
|
||||
row: &BitArray,
|
||||
start: usize,
|
||||
counters: &mut [u32],
|
||||
) -> Result<(), Exceptions> {
|
||||
let mut start = start;
|
||||
// This could be more efficient I guess
|
||||
let mut numTransitionsLeft = counters.len() as isize;
|
||||
let mut last = row.get(start);
|
||||
while start > 0 && numTransitionsLeft >= 0 {
|
||||
start -= 1;
|
||||
if row.get(start) != last {
|
||||
numTransitionsLeft -= 1;
|
||||
last = !last;
|
||||
}
|
||||
}
|
||||
if numTransitionsLeft >= 0 {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
recordPattern(row, start + 1, counters)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::{oned::{OneDReader, one_d_reader}, Exceptions};
|
||||
use crate::{
|
||||
oned::{one_d_reader, OneDReader},
|
||||
Exceptions,
|
||||
};
|
||||
|
||||
/**
|
||||
* Superclass of {@link OneDReader} implementations that read barcodes in the RSS family
|
||||
@@ -97,7 +100,7 @@ pub trait AbstractRSSReaderTrait: OneDReader {
|
||||
array[index] -= 1;
|
||||
}
|
||||
|
||||
fn isFinderPattern( counters: &[u32]) -> bool {
|
||||
fn isFinderPattern(counters: &[u32]) -> bool {
|
||||
let firstTwoSum = counters[0] + counters[1];
|
||||
let sum = firstTwoSum + counters[2] + counters[3];
|
||||
let ratio: f32 = (firstTwoSum as f32) / (sum as f32);
|
||||
|
||||
@@ -25,7 +25,7 @@ pub(crate) trait DataCharacterTrait: Display + Eq + PartialEq + Hash {
|
||||
/**
|
||||
* Encapsulates a since character value in an RSS barcode, including its checksum information.
|
||||
*/
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
#[derive(Hash, PartialEq, Eq, Debug)]
|
||||
pub struct DataCharacter {
|
||||
value: u32,
|
||||
checksumPortion: u32,
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded;
|
||||
|
||||
import com.google.zxing.common.BitArray;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
*/
|
||||
public final class BinaryUtil {
|
||||
|
||||
private static final Pattern ONE = Pattern.compile("1");
|
||||
private static final Pattern ZERO = Pattern.compile("0");
|
||||
private static final Pattern SPACE = Pattern.compile(" ");
|
||||
|
||||
private BinaryUtil() {
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructs a BitArray from a String like the one returned from BitArray.toString()
|
||||
*/
|
||||
public static BitArray buildBitArrayFromString(CharSequence data) {
|
||||
CharSequence dotsAndXs = ZERO.matcher(ONE.matcher(data).replaceAll("X")).replaceAll(".");
|
||||
BitArray binary = new BitArray(SPACE.matcher(dotsAndXs).replaceAll("").length());
|
||||
int counter = 0;
|
||||
|
||||
for (int i = 0; i < dotsAndXs.length(); ++i) {
|
||||
if (i % 9 == 0) { // spaces
|
||||
if (dotsAndXs.charAt(i) != ' ') {
|
||||
throw new IllegalStateException("space expected");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
char currentChar = dotsAndXs.charAt(i);
|
||||
if (currentChar == 'X' || currentChar == 'x') {
|
||||
binary.set(counter);
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return binary;
|
||||
}
|
||||
|
||||
public static BitArray buildBitArrayFromStringWithoutSpaces(CharSequence data) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
CharSequence dotsAndXs = ZERO.matcher(ONE.matcher(data).replaceAll("X")).replaceAll(".");
|
||||
int current = 0;
|
||||
while (current < dotsAndXs.length()) {
|
||||
sb.append(' ');
|
||||
for (int i = 0; i < 8 && current < dotsAndXs.length(); ++i) {
|
||||
sb.append(dotsAndXs.charAt(current));
|
||||
current++;
|
||||
}
|
||||
}
|
||||
return buildBitArrayFromString(sb.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded;
|
||||
|
||||
import com.google.zxing.common.BitArray;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
*/
|
||||
public final class BinaryUtilTest extends Assert {
|
||||
|
||||
private static final Pattern SPACE = Pattern.compile(" ");
|
||||
|
||||
@Test
|
||||
public void testBuildBitArrayFromString() {
|
||||
|
||||
CharSequence data = " ..X..X.. ..XXX... XXXXXXXX ........";
|
||||
check(data);
|
||||
|
||||
data = " XXX..X..";
|
||||
check(data);
|
||||
|
||||
data = " XX";
|
||||
check(data);
|
||||
|
||||
data = " ....XX.. ..XX";
|
||||
check(data);
|
||||
|
||||
data = " ....XX.. ..XX..XX ....X.X. ........";
|
||||
check(data);
|
||||
}
|
||||
|
||||
private static void check(CharSequence data) {
|
||||
BitArray binary = BinaryUtil.buildBitArrayFromString(data);
|
||||
assertEquals(data, binary.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildBitArrayFromStringWithoutSpaces() {
|
||||
CharSequence data = " ..X..X.. ..XXX... XXXXXXXX ........";
|
||||
checkWithoutSpaces(data);
|
||||
|
||||
data = " XXX..X..";
|
||||
checkWithoutSpaces(data);
|
||||
|
||||
data = " XX";
|
||||
checkWithoutSpaces(data);
|
||||
|
||||
data = " ....XX.. ..XX";
|
||||
checkWithoutSpaces(data);
|
||||
|
||||
data = " ....XX.. ..XX..XX ....X.X. ........";
|
||||
checkWithoutSpaces(data);
|
||||
}
|
||||
|
||||
private static void checkWithoutSpaces(CharSequence data) {
|
||||
CharSequence dataWithoutSpaces = SPACE.matcher(data).replaceAll("");
|
||||
BitArray binary = BinaryUtil.buildBitArrayFromStringWithoutSpaces(dataWithoutSpaces);
|
||||
assertEquals(data, binary.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded;
|
||||
|
||||
import com.google.zxing.common.BitArray;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
final class BitArrayBuilder {
|
||||
|
||||
private BitArrayBuilder() {
|
||||
}
|
||||
|
||||
static BitArray buildBitArray(List<ExpandedPair> pairs) {
|
||||
int charNumber = (pairs.size() * 2) - 1;
|
||||
if (pairs.get(pairs.size() - 1).getRightChar() == null) {
|
||||
charNumber -= 1;
|
||||
}
|
||||
|
||||
int size = 12 * charNumber;
|
||||
|
||||
BitArray binary = new BitArray(size);
|
||||
int accPos = 0;
|
||||
|
||||
ExpandedPair firstPair = pairs.get(0);
|
||||
int firstValue = firstPair.getRightChar().getValue();
|
||||
for (int i = 11; i >= 0; --i) {
|
||||
if ((firstValue & (1 << i)) != 0) {
|
||||
binary.set(accPos);
|
||||
}
|
||||
accPos++;
|
||||
}
|
||||
|
||||
for (int i = 1; i < pairs.size(); ++i) {
|
||||
ExpandedPair currentPair = pairs.get(i);
|
||||
|
||||
int leftValue = currentPair.getLeftChar().getValue();
|
||||
for (int j = 11; j >= 0; --j) {
|
||||
if ((leftValue & (1 << j)) != 0) {
|
||||
binary.set(accPos);
|
||||
}
|
||||
accPos++;
|
||||
}
|
||||
|
||||
if (currentPair.getRightChar() != null) {
|
||||
int rightValue = currentPair.getRightChar().getValue();
|
||||
for (int j = 11; j >= 0; --j) {
|
||||
if ((rightValue & (1 << j)) != 0) {
|
||||
binary.set(accPos);
|
||||
}
|
||||
accPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return binary;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded;
|
||||
|
||||
import com.google.zxing.common.BitArray;
|
||||
import com.google.zxing.oned.rss.DataCharacter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
public final class BitArrayBuilderTest extends Assert {
|
||||
|
||||
@Test
|
||||
public void testBuildBitArray1() {
|
||||
int[][] pairValues = {{19}, {673, 16}};
|
||||
|
||||
String expected = " .......X ..XX..X. X.X....X .......X ....";
|
||||
|
||||
checkBinary(pairValues, expected);
|
||||
}
|
||||
|
||||
private static void checkBinary(int[][] pairValues, String expected) {
|
||||
BitArray binary = buildBitArray(pairValues);
|
||||
assertEquals(expected, binary.toString());
|
||||
}
|
||||
|
||||
private static BitArray buildBitArray(int[][] pairValues) {
|
||||
List<ExpandedPair> pairs = new ArrayList<>();
|
||||
for (int i = 0; i < pairValues.length; ++i) {
|
||||
int [] pair = pairValues[i];
|
||||
|
||||
DataCharacter leftChar;
|
||||
if (i == 0) {
|
||||
leftChar = null;
|
||||
} else {
|
||||
leftChar = new DataCharacter(pair[0], 0);
|
||||
}
|
||||
|
||||
DataCharacter rightChar;
|
||||
if (i == 0) {
|
||||
rightChar = new DataCharacter(pair[0], 0);
|
||||
} else if (pair.length == 2) {
|
||||
rightChar = new DataCharacter(pair[1], 0);
|
||||
} else {
|
||||
rightChar = null;
|
||||
}
|
||||
|
||||
ExpandedPair expandedPair = new ExpandedPair(leftChar, rightChar, null);
|
||||
pairs.add(expandedPair);
|
||||
}
|
||||
|
||||
return BitArrayBuilder.buildBitArray(pairs);
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded;
|
||||
|
||||
import com.google.zxing.oned.rss.DataCharacter;
|
||||
import com.google.zxing.oned.rss.FinderPattern;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
*/
|
||||
final class ExpandedPair {
|
||||
|
||||
private final DataCharacter leftChar;
|
||||
private final DataCharacter rightChar;
|
||||
private final FinderPattern finderPattern;
|
||||
|
||||
ExpandedPair(DataCharacter leftChar,
|
||||
DataCharacter rightChar,
|
||||
FinderPattern finderPattern) {
|
||||
this.leftChar = leftChar;
|
||||
this.rightChar = rightChar;
|
||||
this.finderPattern = finderPattern;
|
||||
}
|
||||
|
||||
DataCharacter getLeftChar() {
|
||||
return this.leftChar;
|
||||
}
|
||||
|
||||
DataCharacter getRightChar() {
|
||||
return this.rightChar;
|
||||
}
|
||||
|
||||
FinderPattern getFinderPattern() {
|
||||
return this.finderPattern;
|
||||
}
|
||||
|
||||
boolean mustBeLast() {
|
||||
return this.rightChar == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"[ " + leftChar + " , " + rightChar + " : " +
|
||||
(finderPattern == null ? "null" : finderPattern.getValue()) + " ]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof ExpandedPair)) {
|
||||
return false;
|
||||
}
|
||||
ExpandedPair that = (ExpandedPair) o;
|
||||
return Objects.equals(leftChar, that.leftChar) &&
|
||||
Objects.equals(rightChar, that.rightChar) &&
|
||||
Objects.equals(finderPattern, that.finderPattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(leftChar) ^ Objects.hashCode(rightChar) ^ Objects.hashCode(finderPattern);
|
||||
}
|
||||
|
||||
}
|
||||
148
src/oned/rss/expanded/binary_util.rs
Normal file
148
src/oned/rss/expanded/binary_util.rs
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
*/
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::{common::BitArray, Exceptions};
|
||||
|
||||
lazy_static! {
|
||||
static ref ONE: Regex = Regex::new("1").unwrap();
|
||||
static ref ZERO: Regex = Regex::new("0").unwrap();
|
||||
static ref SPACE: Regex = Regex::new(" ").unwrap();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructs a BitArray from a String like the one returned from BitArray.toString()
|
||||
*/
|
||||
pub fn buildBitArrayFromString(data: &str) -> Result<BitArray, Exceptions> {
|
||||
let dotsAndXs = ZERO
|
||||
.replace_all(&ONE.replace_all(data, "X"), ".")
|
||||
.to_string();
|
||||
let mut binary = BitArray::with_size(SPACE.replace_all(&dotsAndXs, "").chars().count());
|
||||
let mut counter = 0;
|
||||
|
||||
for i in 0..dotsAndXs.chars().count() {
|
||||
// for (int i = 0; i < dotsAndXs.length(); ++i) {
|
||||
if i % 9 == 0 {
|
||||
// spaces
|
||||
if dotsAndXs.chars().nth(i).unwrap() != ' ' {
|
||||
return Err(Exceptions::IllegalStateException(
|
||||
"space expected".to_owned(),
|
||||
));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let currentChar = dotsAndXs.chars().nth(i).unwrap();
|
||||
if currentChar == 'X' || currentChar == 'x' {
|
||||
binary.set(counter);
|
||||
}
|
||||
counter += 1;
|
||||
}
|
||||
Ok(binary)
|
||||
}
|
||||
|
||||
pub fn buildBitArrayFromStringWithoutSpaces(data: &str) -> Result<BitArray, Exceptions> {
|
||||
let mut sb = String::new();
|
||||
|
||||
// let dotsAndXs = ZERO.matcher(ONE.matcher(data).replaceAll("X")).replaceAll(".");
|
||||
let dotsAndXs = ZERO
|
||||
.replace_all(&ONE.replace_all(data, "X"), ".")
|
||||
.to_string();
|
||||
let mut current = 0;
|
||||
while current < dotsAndXs.chars().count() {
|
||||
sb.push(' ');
|
||||
let mut i = 0;
|
||||
while i < 8 && current < dotsAndXs.chars().count() {
|
||||
// for (int i = 0; i < 8 && current < dotsAndXs.length(); ++i) {
|
||||
sb.push(dotsAndXs.chars().nth(current).unwrap());
|
||||
current += 1;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
buildBitArrayFromString(&sb)
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
*/
|
||||
#[cfg(test)]
|
||||
mod BinaryUtilTest {
|
||||
|
||||
#[test]
|
||||
fn testBuildBitArrayFromString() {
|
||||
let data = " ..X..X.. ..XXX... XXXXXXXX ........";
|
||||
check(data);
|
||||
|
||||
let data = " XXX..X..";
|
||||
check(data);
|
||||
|
||||
let data = " XX";
|
||||
check(data);
|
||||
|
||||
let data = " ....XX.. ..XX";
|
||||
check(data);
|
||||
|
||||
let data = " ....XX.. ..XX..XX ....X.X. ........";
|
||||
check(data);
|
||||
}
|
||||
|
||||
fn check(data: &str) {
|
||||
let binary = super::buildBitArrayFromString(data).expect("check");
|
||||
assert_eq!(data, binary.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testBuildBitArrayFromStringWithoutSpaces() {
|
||||
let data = " ..X..X.. ..XXX... XXXXXXXX ........";
|
||||
checkWithoutSpaces(data);
|
||||
|
||||
let data = " XXX..X..";
|
||||
checkWithoutSpaces(data);
|
||||
|
||||
let data = " XX";
|
||||
checkWithoutSpaces(data);
|
||||
|
||||
let data = " ....XX.. ..XX";
|
||||
checkWithoutSpaces(data);
|
||||
|
||||
let data = " ....XX.. ..XX..XX ....X.X. ........";
|
||||
checkWithoutSpaces(data);
|
||||
}
|
||||
|
||||
fn checkWithoutSpaces(data: &str) {
|
||||
let dataWithoutSpaces = super::SPACE.replace_all(data, "");
|
||||
let binary =
|
||||
super::buildBitArrayFromStringWithoutSpaces(&dataWithoutSpaces).expect("success");
|
||||
assert_eq!(data, binary.to_string());
|
||||
}
|
||||
}
|
||||
145
src/oned/rss/expanded/bit_array_builder.rs
Normal file
145
src/oned/rss/expanded/bit_array_builder.rs
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
use crate::{common::BitArray, oned::rss::DataCharacterTrait};
|
||||
|
||||
use super::ExpandedPair;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
|
||||
pub fn buildBitArray(pairs: &Vec<ExpandedPair>) -> BitArray {
|
||||
let mut charNumber = (pairs.len() * 2) - 1;
|
||||
if pairs.get(pairs.len() - 1).unwrap().getRightChar().is_none() {
|
||||
charNumber -= 1;
|
||||
}
|
||||
|
||||
let size = 12 * charNumber;
|
||||
|
||||
let mut binary = BitArray::with_size(size);
|
||||
let mut accPos = 0;
|
||||
|
||||
let firstPair = pairs.get(0).unwrap();
|
||||
let Some(rp) = firstPair.getRightChar() else { panic!("first char must exist");};
|
||||
let firstValue = rp.getValue();
|
||||
let mut i = 11;
|
||||
while i >= 0 {
|
||||
// for (int i = 11; i >= 0; --i) {
|
||||
if (firstValue & (1 << i)) != 0 {
|
||||
binary.set(accPos);
|
||||
}
|
||||
accPos += 1;
|
||||
|
||||
i -= 1;
|
||||
}
|
||||
|
||||
for i in 1..pairs.len() {
|
||||
// for (int i = 1; i < pairs.size(); ++i) {
|
||||
let currentPair = pairs.get(i).unwrap();
|
||||
let Some(lv) = currentPair.getLeftChar() else { panic!("I'm not sure how we get here ");};
|
||||
let leftValue = lv.getValue();
|
||||
let mut j = 11;
|
||||
while j >= 0 {
|
||||
// for (int j = 11; j >= 0; --j) {
|
||||
if (leftValue & (1 << j)) != 0 {
|
||||
binary.set(accPos);
|
||||
}
|
||||
accPos += 1;
|
||||
|
||||
j -= 1;
|
||||
}
|
||||
|
||||
if let Some(rc) = currentPair.getRightChar() {
|
||||
let rightValue = rc.getValue(); //currentPair.getRightChar().getValue();
|
||||
let mut j = 11;
|
||||
while j >= 0 {
|
||||
// for (int j = 11; j >= 0; --j) {
|
||||
if (rightValue & (1 << j)) != 0 {
|
||||
binary.set(accPos);
|
||||
}
|
||||
accPos += 1;
|
||||
|
||||
j -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return binary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
#[cfg(test)]
|
||||
mod BitArrayBuilderTest {
|
||||
use crate::{
|
||||
common::BitArray,
|
||||
oned::rss::{expanded::ExpandedPair, DataCharacter},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn testBuildBitArray1() {
|
||||
let pairValues = vec![vec![19], vec![673, 16]];
|
||||
|
||||
let expected = " .......X ..XX..X. X.X....X .......X ....";
|
||||
|
||||
checkBinary(&pairValues, expected);
|
||||
}
|
||||
|
||||
fn checkBinary(pairValues: &Vec<Vec<u32>>, expected: &str) {
|
||||
let binary = buildBitArray(pairValues);
|
||||
assert_eq!(expected, binary.to_string());
|
||||
}
|
||||
|
||||
fn buildBitArray(pairValues: &Vec<Vec<u32>>) -> BitArray {
|
||||
let mut pairs = Vec::new(); //new ArrayList<>();
|
||||
for i in 0..pairValues.len() {
|
||||
// for (int i = 0; i < pairValues.length; ++i) {
|
||||
let pair = &pairValues[i];
|
||||
|
||||
let leftChar = if i == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(DataCharacter::new(pair[0], 0))
|
||||
};
|
||||
|
||||
let rightChar = if i == 0 {
|
||||
Some(DataCharacter::new(pair[0], 0))
|
||||
} else if pair.len() == 2 {
|
||||
Some(DataCharacter::new(pair[1], 0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let expandedPair = ExpandedPair::new(leftChar, rightChar, None);
|
||||
pairs.push(expandedPair);
|
||||
}
|
||||
|
||||
super::buildBitArray(&pairs)
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
|
||||
import com.google.zxing.FormatException;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.common.BitArray;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
public abstract class AbstractExpandedDecoder {
|
||||
|
||||
private final BitArray information;
|
||||
private final GeneralAppIdDecoder generalDecoder;
|
||||
|
||||
AbstractExpandedDecoder(BitArray information) {
|
||||
this.information = information;
|
||||
this.generalDecoder = new GeneralAppIdDecoder(information);
|
||||
}
|
||||
|
||||
protected final BitArray getInformation() {
|
||||
return information;
|
||||
}
|
||||
|
||||
protected final GeneralAppIdDecoder getGeneralDecoder() {
|
||||
return generalDecoder;
|
||||
}
|
||||
|
||||
public abstract String parseInformation() throws NotFoundException, FormatException;
|
||||
|
||||
public static AbstractExpandedDecoder createDecoder(BitArray information) {
|
||||
if (information.get(1)) {
|
||||
return new AI01AndOtherAIs(information);
|
||||
}
|
||||
if (!information.get(2)) {
|
||||
return new AnyAIDecoder(information);
|
||||
}
|
||||
|
||||
int fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4);
|
||||
|
||||
switch (fourBitEncodationMethod) {
|
||||
case 4: return new AI013103decoder(information);
|
||||
case 5: return new AI01320xDecoder(information);
|
||||
}
|
||||
|
||||
int fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5);
|
||||
switch (fiveBitEncodationMethod) {
|
||||
case 12: return new AI01392xDecoder(information);
|
||||
case 13: return new AI01393xDecoder(information);
|
||||
}
|
||||
|
||||
int sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7);
|
||||
switch (sevenBitEncodationMethod) {
|
||||
case 56: return new AI013x0x1xDecoder(information, "310", "11");
|
||||
case 57: return new AI013x0x1xDecoder(information, "320", "11");
|
||||
case 58: return new AI013x0x1xDecoder(information, "310", "13");
|
||||
case 59: return new AI013x0x1xDecoder(information, "320", "13");
|
||||
case 60: return new AI013x0x1xDecoder(information, "310", "15");
|
||||
case 61: return new AI013x0x1xDecoder(information, "320", "15");
|
||||
case 62: return new AI013x0x1xDecoder(information, "310", "17");
|
||||
case 63: return new AI013x0x1xDecoder(information, "320", "17");
|
||||
}
|
||||
|
||||
throw new IllegalStateException("unknown decoder: " + information);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
final class DecodedInformation extends DecodedObject {
|
||||
|
||||
private final String newString;
|
||||
private final int remainingValue;
|
||||
private final boolean remaining;
|
||||
|
||||
DecodedInformation(int newPosition, String newString) {
|
||||
super(newPosition);
|
||||
this.newString = newString;
|
||||
this.remaining = false;
|
||||
this.remainingValue = 0;
|
||||
}
|
||||
|
||||
DecodedInformation(int newPosition, String newString, int remainingValue) {
|
||||
super(newPosition);
|
||||
this.remaining = true;
|
||||
this.remainingValue = remainingValue;
|
||||
this.newString = newString;
|
||||
}
|
||||
|
||||
String getNewString() {
|
||||
return this.newString;
|
||||
}
|
||||
|
||||
boolean isRemaining() {
|
||||
return this.remaining;
|
||||
}
|
||||
|
||||
int getRemainingValue() {
|
||||
return this.remainingValue;
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
|
||||
import com.google.zxing.NotFoundException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
final class FieldParser {
|
||||
|
||||
private static final Map<String,DataLength> TWO_DIGIT_DATA_LENGTH = new HashMap<>();
|
||||
static {
|
||||
TWO_DIGIT_DATA_LENGTH.put("00", DataLength.fixed(18));
|
||||
TWO_DIGIT_DATA_LENGTH.put("01", DataLength.fixed(14));
|
||||
TWO_DIGIT_DATA_LENGTH.put("02", DataLength.fixed(14));
|
||||
TWO_DIGIT_DATA_LENGTH.put("10", DataLength.variable(20));
|
||||
TWO_DIGIT_DATA_LENGTH.put("11", DataLength.fixed(6));
|
||||
TWO_DIGIT_DATA_LENGTH.put("12", DataLength.fixed(6));
|
||||
TWO_DIGIT_DATA_LENGTH.put("13", DataLength.fixed(6));
|
||||
TWO_DIGIT_DATA_LENGTH.put("15", DataLength.fixed(6));
|
||||
TWO_DIGIT_DATA_LENGTH.put("17", DataLength.fixed(6));
|
||||
TWO_DIGIT_DATA_LENGTH.put("20", DataLength.fixed(2));
|
||||
TWO_DIGIT_DATA_LENGTH.put("21", DataLength.variable(20));
|
||||
TWO_DIGIT_DATA_LENGTH.put("22", DataLength.variable(29));
|
||||
TWO_DIGIT_DATA_LENGTH.put("30", DataLength.variable(8));
|
||||
TWO_DIGIT_DATA_LENGTH.put("37", DataLength.variable(8));
|
||||
//internal company codes
|
||||
for (int i = 90; i <= 99; i++) {
|
||||
TWO_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.variable(30));
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<String,DataLength> THREE_DIGIT_DATA_LENGTH = new HashMap<>();
|
||||
static {
|
||||
THREE_DIGIT_DATA_LENGTH.put("240", DataLength.variable(30));
|
||||
THREE_DIGIT_DATA_LENGTH.put("241", DataLength.variable(30));
|
||||
THREE_DIGIT_DATA_LENGTH.put("242", DataLength.variable(6));
|
||||
THREE_DIGIT_DATA_LENGTH.put("250", DataLength.variable(30));
|
||||
THREE_DIGIT_DATA_LENGTH.put("251", DataLength.variable(30));
|
||||
THREE_DIGIT_DATA_LENGTH.put("253", DataLength.variable(17));
|
||||
THREE_DIGIT_DATA_LENGTH.put("254", DataLength.variable(20));
|
||||
THREE_DIGIT_DATA_LENGTH.put("400", DataLength.variable(30));
|
||||
THREE_DIGIT_DATA_LENGTH.put("401", DataLength.variable(30));
|
||||
THREE_DIGIT_DATA_LENGTH.put("402", DataLength.fixed(17));
|
||||
THREE_DIGIT_DATA_LENGTH.put("403", DataLength.variable(30));
|
||||
THREE_DIGIT_DATA_LENGTH.put("410", DataLength.fixed(13));
|
||||
THREE_DIGIT_DATA_LENGTH.put("411", DataLength.fixed(13));
|
||||
THREE_DIGIT_DATA_LENGTH.put("412", DataLength.fixed(13));
|
||||
THREE_DIGIT_DATA_LENGTH.put("413", DataLength.fixed(13));
|
||||
THREE_DIGIT_DATA_LENGTH.put("414", DataLength.fixed(13));
|
||||
THREE_DIGIT_DATA_LENGTH.put("420", DataLength.variable(20));
|
||||
THREE_DIGIT_DATA_LENGTH.put("421", DataLength.variable(15));
|
||||
THREE_DIGIT_DATA_LENGTH.put("422", DataLength.fixed(3));
|
||||
THREE_DIGIT_DATA_LENGTH.put("423", DataLength.variable(15));
|
||||
THREE_DIGIT_DATA_LENGTH.put("424", DataLength.fixed(3));
|
||||
THREE_DIGIT_DATA_LENGTH.put("425", DataLength.fixed(3));
|
||||
THREE_DIGIT_DATA_LENGTH.put("426", DataLength.fixed(3));
|
||||
}
|
||||
|
||||
private static final Map<String,DataLength> THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH = new HashMap<>();
|
||||
static {
|
||||
for (int i = 310; i <= 316; i++) {
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.fixed(6));
|
||||
}
|
||||
for (int i = 320; i <= 336; i++) {
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.fixed(6));
|
||||
}
|
||||
for (int i = 340; i <= 357; i++) {
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.fixed(6));
|
||||
}
|
||||
for (int i = 360; i <= 369; i++) {
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.fixed(6));
|
||||
}
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("390", DataLength.variable(15));
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("391", DataLength.variable(18));
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("392", DataLength.variable(15));
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("393", DataLength.variable(18));
|
||||
THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("703", DataLength.variable(30));
|
||||
}
|
||||
|
||||
private static final Map<String,DataLength> FOUR_DIGIT_DATA_LENGTH = new HashMap<>();
|
||||
static {
|
||||
FOUR_DIGIT_DATA_LENGTH.put("7001", DataLength.fixed(13));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("7002", DataLength.variable(30));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("7003", DataLength.fixed(10));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8001", DataLength.fixed(14));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8002", DataLength.variable(20));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8003", DataLength.variable(30));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8004", DataLength.variable(30));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8005", DataLength.fixed(6));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8006", DataLength.fixed(18));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8007", DataLength.variable(30));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8008", DataLength.variable(12));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8018", DataLength.fixed(18));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8020", DataLength.variable(25));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8100", DataLength.fixed(6));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8101", DataLength.fixed(10));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8102", DataLength.fixed(2));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8110", DataLength.variable(70));
|
||||
FOUR_DIGIT_DATA_LENGTH.put("8200", DataLength.variable(70));
|
||||
}
|
||||
|
||||
private FieldParser() {
|
||||
}
|
||||
|
||||
static String parseFieldsInGeneralPurpose(String rawInformation) throws NotFoundException {
|
||||
if (rawInformation.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Processing 2-digit AIs
|
||||
|
||||
if (rawInformation.length() < 2) {
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
}
|
||||
|
||||
DataLength twoDigitDataLength = TWO_DIGIT_DATA_LENGTH.get(rawInformation.substring(0, 2));
|
||||
if (twoDigitDataLength != null) {
|
||||
if (twoDigitDataLength.variable) {
|
||||
return processVariableAI(2, twoDigitDataLength.length, rawInformation);
|
||||
}
|
||||
return processFixedAI(2, twoDigitDataLength.length, rawInformation);
|
||||
}
|
||||
|
||||
if (rawInformation.length() < 3) {
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
}
|
||||
|
||||
String firstThreeDigits = rawInformation.substring(0, 3);
|
||||
DataLength threeDigitDataLength = THREE_DIGIT_DATA_LENGTH.get(firstThreeDigits);
|
||||
if (threeDigitDataLength != null) {
|
||||
if (threeDigitDataLength.variable) {
|
||||
return processVariableAI(3, threeDigitDataLength.length, rawInformation);
|
||||
}
|
||||
return processFixedAI(3, threeDigitDataLength.length, rawInformation);
|
||||
}
|
||||
|
||||
if (rawInformation.length() < 4) {
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
}
|
||||
|
||||
DataLength threeDigitPlusDigitDataLength = THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.get(firstThreeDigits);
|
||||
if (threeDigitPlusDigitDataLength != null) {
|
||||
if (threeDigitPlusDigitDataLength.variable) {
|
||||
return processVariableAI(4, threeDigitPlusDigitDataLength.length, rawInformation);
|
||||
}
|
||||
return processFixedAI(4, threeDigitPlusDigitDataLength.length, rawInformation);
|
||||
}
|
||||
|
||||
DataLength firstFourDigitLength = FOUR_DIGIT_DATA_LENGTH.get(rawInformation.substring(0, 4));
|
||||
if (firstFourDigitLength != null) {
|
||||
if (firstFourDigitLength.variable) {
|
||||
return processVariableAI(4, firstFourDigitLength.length, rawInformation);
|
||||
}
|
||||
return processFixedAI(4, firstFourDigitLength.length, rawInformation);
|
||||
}
|
||||
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
}
|
||||
|
||||
private static String processFixedAI(int aiSize, int fieldSize, String rawInformation) throws NotFoundException {
|
||||
if (rawInformation.length() < aiSize) {
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
}
|
||||
|
||||
String ai = rawInformation.substring(0, aiSize);
|
||||
|
||||
if (rawInformation.length() < aiSize + fieldSize) {
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
}
|
||||
|
||||
String field = rawInformation.substring(aiSize, aiSize + fieldSize);
|
||||
String remaining = rawInformation.substring(aiSize + fieldSize);
|
||||
String result = '(' + ai + ')' + field;
|
||||
String parsedAI = parseFieldsInGeneralPurpose(remaining);
|
||||
return parsedAI == null ? result : result + parsedAI;
|
||||
}
|
||||
|
||||
private static String processVariableAI(int aiSize, int variableFieldSize, String rawInformation)
|
||||
throws NotFoundException {
|
||||
String ai = rawInformation.substring(0, aiSize);
|
||||
int maxSize = Math.min(rawInformation.length(), aiSize + variableFieldSize);
|
||||
String field = rawInformation.substring(aiSize, maxSize);
|
||||
String remaining = rawInformation.substring(maxSize);
|
||||
String result = '(' + ai + ')' + field;
|
||||
String parsedAI = parseFieldsInGeneralPurpose(remaining);
|
||||
return parsedAI == null ? result : result + parsedAI;
|
||||
}
|
||||
|
||||
private static final class DataLength {
|
||||
|
||||
final boolean variable;
|
||||
final int length;
|
||||
|
||||
private DataLength(boolean variable, int length) {
|
||||
this.variable = variable;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
static DataLength fixed(int length) {
|
||||
return new DataLength(false, length);
|
||||
}
|
||||
|
||||
static DataLength variable(int length) {
|
||||
return new DataLength(true, length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
|
||||
import com.google.zxing.NotFoundException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
public final class FieldParserTest extends Assert {
|
||||
|
||||
private static void checkFields(String expected) throws NotFoundException {
|
||||
String field = expected.replace("(", "").replace(")","");
|
||||
String actual = FieldParser.parseFieldsInGeneralPurpose(field);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseField() throws Exception {
|
||||
checkFields("(15)991231(3103)001750(10)12A");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseField2() throws Exception {
|
||||
checkFields("(15)991231(15)991231(3103)001750(10)12A");
|
||||
}
|
||||
}
|
||||
@@ -1,470 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
|
||||
import com.google.zxing.FormatException;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.common.BitArray;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
final class GeneralAppIdDecoder {
|
||||
|
||||
private final BitArray information;
|
||||
private final CurrentParsingState current = new CurrentParsingState();
|
||||
private final StringBuilder buffer = new StringBuilder();
|
||||
|
||||
GeneralAppIdDecoder(BitArray information) {
|
||||
this.information = information;
|
||||
}
|
||||
|
||||
String decodeAllCodes(StringBuilder buff, int initialPosition) throws NotFoundException, FormatException {
|
||||
int currentPosition = initialPosition;
|
||||
String remaining = null;
|
||||
do {
|
||||
DecodedInformation info = this.decodeGeneralPurposeField(currentPosition, remaining);
|
||||
String parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString());
|
||||
if (parsedFields != null) {
|
||||
buff.append(parsedFields);
|
||||
}
|
||||
if (info.isRemaining()) {
|
||||
remaining = String.valueOf(info.getRemainingValue());
|
||||
} else {
|
||||
remaining = null;
|
||||
}
|
||||
|
||||
if (currentPosition == info.getNewPosition()) { // No step forward!
|
||||
break;
|
||||
}
|
||||
currentPosition = info.getNewPosition();
|
||||
} while (true);
|
||||
|
||||
return buff.toString();
|
||||
}
|
||||
|
||||
private boolean isStillNumeric(int pos) {
|
||||
// It's numeric if it still has 7 positions
|
||||
// and one of the first 4 bits is "1".
|
||||
if (pos + 7 > this.information.getSize()) {
|
||||
return pos + 4 <= this.information.getSize();
|
||||
}
|
||||
|
||||
for (int i = pos; i < pos + 3; ++i) {
|
||||
if (this.information.get(i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return this.information.get(pos + 3);
|
||||
}
|
||||
|
||||
private DecodedNumeric decodeNumeric(int pos) throws FormatException {
|
||||
if (pos + 7 > this.information.getSize()) {
|
||||
int numeric = extractNumericValueFromBitArray(pos, 4);
|
||||
if (numeric == 0) {
|
||||
return new DecodedNumeric(this.information.getSize(), DecodedNumeric.FNC1, DecodedNumeric.FNC1);
|
||||
}
|
||||
return new DecodedNumeric(this.information.getSize(), numeric - 1, DecodedNumeric.FNC1);
|
||||
}
|
||||
int numeric = extractNumericValueFromBitArray(pos, 7);
|
||||
|
||||
int digit1 = (numeric - 8) / 11;
|
||||
int digit2 = (numeric - 8) % 11;
|
||||
|
||||
return new DecodedNumeric(pos + 7, digit1, digit2);
|
||||
}
|
||||
|
||||
int extractNumericValueFromBitArray(int pos, int bits) {
|
||||
return extractNumericValueFromBitArray(this.information, pos, bits);
|
||||
}
|
||||
|
||||
static int extractNumericValueFromBitArray(BitArray information, int pos, int bits) {
|
||||
int value = 0;
|
||||
for (int i = 0; i < bits; ++i) {
|
||||
if (information.get(pos + i)) {
|
||||
value |= 1 << (bits - i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
DecodedInformation decodeGeneralPurposeField(int pos, String remaining) throws FormatException {
|
||||
this.buffer.setLength(0);
|
||||
|
||||
if (remaining != null) {
|
||||
this.buffer.append(remaining);
|
||||
}
|
||||
|
||||
this.current.setPosition(pos);
|
||||
|
||||
DecodedInformation lastDecoded = parseBlocks();
|
||||
if (lastDecoded != null && lastDecoded.isRemaining()) {
|
||||
return new DecodedInformation(this.current.getPosition(),
|
||||
this.buffer.toString(), lastDecoded.getRemainingValue());
|
||||
}
|
||||
return new DecodedInformation(this.current.getPosition(), this.buffer.toString());
|
||||
}
|
||||
|
||||
private DecodedInformation parseBlocks() throws FormatException {
|
||||
boolean isFinished;
|
||||
BlockParsedRXingResult result;
|
||||
do {
|
||||
int initialPosition = current.getPosition();
|
||||
|
||||
if (current.isAlpha()) {
|
||||
result = parseAlphaBlock();
|
||||
isFinished = result.isFinished();
|
||||
} else if (current.isIsoIec646()) {
|
||||
result = parseIsoIec646Block();
|
||||
isFinished = result.isFinished();
|
||||
} else { // it must be numeric
|
||||
result = parseNumericBlock();
|
||||
isFinished = result.isFinished();
|
||||
}
|
||||
|
||||
boolean positionChanged = initialPosition != current.getPosition();
|
||||
if (!positionChanged && !isFinished) {
|
||||
break;
|
||||
}
|
||||
} while (!isFinished);
|
||||
|
||||
return result.getDecodedInformation();
|
||||
}
|
||||
|
||||
private BlockParsedRXingResult parseNumericBlock() throws FormatException {
|
||||
while (isStillNumeric(current.getPosition())) {
|
||||
DecodedNumeric numeric = decodeNumeric(current.getPosition());
|
||||
current.setPosition(numeric.getNewPosition());
|
||||
|
||||
if (numeric.isFirstDigitFNC1()) {
|
||||
DecodedInformation information;
|
||||
if (numeric.isSecondDigitFNC1()) {
|
||||
information = new DecodedInformation(current.getPosition(), buffer.toString());
|
||||
} else {
|
||||
information = new DecodedInformation(current.getPosition(), buffer.toString(), numeric.getSecondDigit());
|
||||
}
|
||||
return new BlockParsedRXingResult(information, true);
|
||||
}
|
||||
buffer.append(numeric.getFirstDigit());
|
||||
|
||||
if (numeric.isSecondDigitFNC1()) {
|
||||
DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString());
|
||||
return new BlockParsedRXingResult(information, true);
|
||||
}
|
||||
buffer.append(numeric.getSecondDigit());
|
||||
}
|
||||
|
||||
if (isNumericToAlphaNumericLatch(current.getPosition())) {
|
||||
current.setAlpha();
|
||||
current.incrementPosition(4);
|
||||
}
|
||||
return new BlockParsedRXingResult();
|
||||
}
|
||||
|
||||
private BlockParsedRXingResult parseIsoIec646Block() throws FormatException {
|
||||
while (isStillIsoIec646(current.getPosition())) {
|
||||
DecodedChar iso = decodeIsoIec646(current.getPosition());
|
||||
current.setPosition(iso.getNewPosition());
|
||||
|
||||
if (iso.isFNC1()) {
|
||||
DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString());
|
||||
return new BlockParsedRXingResult(information, true);
|
||||
}
|
||||
buffer.append(iso.getValue());
|
||||
}
|
||||
|
||||
if (isAlphaOr646ToNumericLatch(current.getPosition())) {
|
||||
current.incrementPosition(3);
|
||||
current.setNumeric();
|
||||
} else if (isAlphaTo646ToAlphaLatch(current.getPosition())) {
|
||||
if (current.getPosition() + 5 < this.information.getSize()) {
|
||||
current.incrementPosition(5);
|
||||
} else {
|
||||
current.setPosition(this.information.getSize());
|
||||
}
|
||||
|
||||
current.setAlpha();
|
||||
}
|
||||
return new BlockParsedRXingResult();
|
||||
}
|
||||
|
||||
private BlockParsedRXingResult parseAlphaBlock() {
|
||||
while (isStillAlpha(current.getPosition())) {
|
||||
DecodedChar alpha = decodeAlphanumeric(current.getPosition());
|
||||
current.setPosition(alpha.getNewPosition());
|
||||
|
||||
if (alpha.isFNC1()) {
|
||||
DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString());
|
||||
return new BlockParsedRXingResult(information, true); //end of the char block
|
||||
}
|
||||
|
||||
buffer.append(alpha.getValue());
|
||||
}
|
||||
|
||||
if (isAlphaOr646ToNumericLatch(current.getPosition())) {
|
||||
current.incrementPosition(3);
|
||||
current.setNumeric();
|
||||
} else if (isAlphaTo646ToAlphaLatch(current.getPosition())) {
|
||||
if (current.getPosition() + 5 < this.information.getSize()) {
|
||||
current.incrementPosition(5);
|
||||
} else {
|
||||
current.setPosition(this.information.getSize());
|
||||
}
|
||||
|
||||
current.setIsoIec646();
|
||||
}
|
||||
return new BlockParsedRXingResult();
|
||||
}
|
||||
|
||||
private boolean isStillIsoIec646(int pos) {
|
||||
if (pos + 5 > this.information.getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
|
||||
if (fiveBitValue >= 5 && fiveBitValue < 16) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pos + 7 > this.information.getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int sevenBitValue = extractNumericValueFromBitArray(pos, 7);
|
||||
if (sevenBitValue >= 64 && sevenBitValue < 116) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pos + 8 > this.information.getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int eightBitValue = extractNumericValueFromBitArray(pos, 8);
|
||||
return eightBitValue >= 232 && eightBitValue < 253;
|
||||
|
||||
}
|
||||
|
||||
private DecodedChar decodeIsoIec646(int pos) throws FormatException {
|
||||
int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
|
||||
if (fiveBitValue == 15) {
|
||||
return new DecodedChar(pos + 5, DecodedChar.FNC1);
|
||||
}
|
||||
|
||||
if (fiveBitValue >= 5 && fiveBitValue < 15) {
|
||||
return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5));
|
||||
}
|
||||
|
||||
int sevenBitValue = extractNumericValueFromBitArray(pos, 7);
|
||||
|
||||
if (sevenBitValue >= 64 && sevenBitValue < 90) {
|
||||
return new DecodedChar(pos + 7, (char) (sevenBitValue + 1));
|
||||
}
|
||||
|
||||
if (sevenBitValue >= 90 && sevenBitValue < 116) {
|
||||
return new DecodedChar(pos + 7, (char) (sevenBitValue + 7));
|
||||
}
|
||||
|
||||
int eightBitValue = extractNumericValueFromBitArray(pos, 8);
|
||||
char 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:
|
||||
throw FormatException.getFormatInstance();
|
||||
}
|
||||
return new DecodedChar(pos + 8, c);
|
||||
}
|
||||
|
||||
private boolean isStillAlpha(int pos) {
|
||||
if (pos + 5 > this.information.getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We now check if it's a valid 5-bit value (0..9 and FNC1)
|
||||
int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
|
||||
if (fiveBitValue >= 5 && fiveBitValue < 16) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pos + 6 > this.information.getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int sixBitValue = extractNumericValueFromBitArray(pos, 6);
|
||||
return sixBitValue >= 16 && sixBitValue < 63; // 63 not included
|
||||
}
|
||||
|
||||
private DecodedChar decodeAlphanumeric(int pos) {
|
||||
int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
|
||||
if (fiveBitValue == 15) {
|
||||
return new DecodedChar(pos + 5, DecodedChar.FNC1);
|
||||
}
|
||||
|
||||
if (fiveBitValue >= 5 && fiveBitValue < 15) {
|
||||
return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5));
|
||||
}
|
||||
|
||||
int sixBitValue = extractNumericValueFromBitArray(pos, 6);
|
||||
|
||||
if (sixBitValue >= 32 && sixBitValue < 58) {
|
||||
return new DecodedChar(pos + 6, (char) (sixBitValue + 33));
|
||||
}
|
||||
|
||||
char 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 new IllegalStateException("Decoding invalid alphanumeric value: " + sixBitValue);
|
||||
}
|
||||
return new DecodedChar(pos + 6, c);
|
||||
}
|
||||
|
||||
private boolean isAlphaTo646ToAlphaLatch(int pos) {
|
||||
if (pos + 1 > this.information.getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5 && i + pos < this.information.getSize(); ++i) {
|
||||
if (i == 2) {
|
||||
if (!this.information.get(pos + 2)) {
|
||||
return false;
|
||||
}
|
||||
} else if (this.information.get(pos + i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isAlphaOr646ToNumericLatch(int pos) {
|
||||
// Next is alphanumeric if there are 3 positions and they are all zeros
|
||||
if (pos + 3 > this.information.getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = pos; i < pos + 3; ++i) {
|
||||
if (this.information.get(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean 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 > this.information.getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4 && i + pos < this.information.getSize(); ++i) {
|
||||
if (this.information.get(pos + i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
95
src/oned/rss/expanded/decoders/abstract_expanded_decoder.rs
Normal file
95
src/oned/rss/expanded/decoders/abstract_expanded_decoder.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
use crate::{Exceptions, common::BitArray};
|
||||
|
||||
use super::GeneralAppIdDecoder;
|
||||
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
|
||||
|
||||
pub trait AbstractExpandedDecoder {
|
||||
|
||||
// private final BitArray information;
|
||||
// private final GeneralAppIdDecoder generalDecoder;
|
||||
|
||||
// AbstractExpandedDecoder(BitArray information) {
|
||||
// this.information = information;
|
||||
// this.generalDecoder = new GeneralAppIdDecoder(information);
|
||||
// }
|
||||
|
||||
// protected final BitArray getInformation() {
|
||||
// return information;
|
||||
// }
|
||||
|
||||
// protected final GeneralAppIdDecoder getGeneralDecoder() {
|
||||
// return generalDecoder;
|
||||
// }
|
||||
|
||||
fn parseInformation(&mut self) -> Result<String,Exceptions>;
|
||||
fn getGeneralDecoder(&self) -> &GeneralAppIdDecoder;
|
||||
// fn new(information:&BitArray) -> Self where Self:Sized;
|
||||
}
|
||||
|
||||
// pub fn createDecoder( information:&BitArray) -> Box<dyn AbstractExpandedDecoder>{
|
||||
// if information.get(1) {
|
||||
// return new AI01AndOtherAIs(information);
|
||||
// }
|
||||
// if !information.get(2) {
|
||||
// return new AnyAIDecoder(information);
|
||||
// }
|
||||
|
||||
// let fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4);
|
||||
|
||||
// switch (fourBitEncodationMethod) {
|
||||
// case 4: return new AI013103decoder(information);
|
||||
// case 5: return new AI01320xDecoder(information);
|
||||
// }
|
||||
|
||||
// int fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5);
|
||||
// switch (fiveBitEncodationMethod) {
|
||||
// case 12: return new AI01392xDecoder(information);
|
||||
// case 13: return new AI01393xDecoder(information);
|
||||
// }
|
||||
|
||||
// int sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7);
|
||||
// switch (sevenBitEncodationMethod) {
|
||||
// case 56: return new AI013x0x1xDecoder(information, "310", "11");
|
||||
// case 57: return new AI013x0x1xDecoder(information, "320", "11");
|
||||
// case 58: return new AI013x0x1xDecoder(information, "310", "13");
|
||||
// case 59: return new AI013x0x1xDecoder(information, "320", "13");
|
||||
// case 60: return new AI013x0x1xDecoder(information, "310", "15");
|
||||
// case 61: return new AI013x0x1xDecoder(information, "320", "15");
|
||||
// case 62: return new AI013x0x1xDecoder(information, "310", "17");
|
||||
// case 63: return new AI013x0x1xDecoder(information, "320", "17");
|
||||
// }
|
||||
|
||||
// throw new IllegalStateException("unknown decoder: " + information);
|
||||
// }
|
||||
@@ -24,35 +24,42 @@
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
use crate::common::BitArray;
|
||||
|
||||
import com.google.zxing.FormatException;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.common.BitArray;
|
||||
use super::{AI01decoder, AbstractExpandedDecoder, GeneralAppIdDecoder};
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
final class AI01AndOtherAIs extends AI01decoder {
|
||||
pub struct AI01AndOtherAIs<'a>(&'a BitArray,GeneralAppIdDecoder<'a>);
|
||||
impl<'a> AI01decoder for AI01AndOtherAIs<'_> {}
|
||||
impl AbstractExpandedDecoder for AI01AndOtherAIs<'_> {
|
||||
fn parseInformation(&mut self) -> Result<String,crate::Exceptions> {
|
||||
let mut buff = String::new();//new StringBuilder();
|
||||
|
||||
private static final int HEADER_SIZE = 1 + 1 + 2; //first bit encodes the linkage flag,
|
||||
//the second one is the encodation method, and the other two are for the variable length
|
||||
AI01AndOtherAIs(BitArray information) {
|
||||
super(information);
|
||||
}
|
||||
buff.push_str("(01)");
|
||||
let initialGtinPosition = buff.chars().count();
|
||||
let firstGtinDigit = self.getGeneralDecoder().extractNumericValueFromBitArray(Self::HEADER_SIZE, 4);
|
||||
buff.push_str(&firstGtinDigit.to_string());
|
||||
|
||||
self.encodeCompressedGtinWithoutAI(&mut buff, Self::HEADER_SIZE + 4, initialGtinPosition);
|
||||
|
||||
self.1.decodeAllCodes(buff, Self::HEADER_SIZE + 44)
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseInformation() throws NotFoundException, FormatException {
|
||||
StringBuilder buff = new StringBuilder();
|
||||
|
||||
buff.append("(01)");
|
||||
int initialGtinPosition = buff.length();
|
||||
int firstGtinDigit = this.getGeneralDecoder().extractNumericValueFromBitArray(HEADER_SIZE, 4);
|
||||
buff.append(firstGtinDigit);
|
||||
|
||||
this.encodeCompressedGtinWithoutAI(buff, HEADER_SIZE + 4, initialGtinPosition);
|
||||
|
||||
return this.getGeneralDecoder().decodeAllCodes(buff, HEADER_SIZE + 44);
|
||||
}
|
||||
fn getGeneralDecoder(&self) -> &super::GeneralAppIdDecoder {
|
||||
&self.1
|
||||
}
|
||||
}
|
||||
impl<'a> AI01AndOtherAIs<'_> {
|
||||
fn new(information:&'a BitArray) -> AI01AndOtherAIs<'a> {
|
||||
AI01AndOtherAIs( information,GeneralAppIdDecoder::new(information))
|
||||
}
|
||||
|
||||
const HEADER_SIZE : usize = 1 + 1 + 2; //first bit encodes the linkage flag,
|
||||
//the second one is the encodation method, and the other two are for the variable length
|
||||
// AI01AndOtherAIs(BitArray information) {
|
||||
// super(information);
|
||||
// }
|
||||
}
|
||||
@@ -24,58 +24,57 @@
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
use super::AbstractExpandedDecoder;
|
||||
|
||||
import com.google.zxing.common.BitArray;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
abstract class AI01decoder extends AbstractExpandedDecoder {
|
||||
pub trait AI01decoder : AbstractExpandedDecoder {
|
||||
|
||||
static final int GTIN_SIZE = 40;
|
||||
const GTIN_SIZE : u32 = 40;
|
||||
|
||||
AI01decoder(BitArray information) {
|
||||
super(information);
|
||||
fn encodeCompressedGtin(&self, buf:&mut String, currentPos:usize) {
|
||||
buf.push_str("(01)");
|
||||
let initialPosition = buf.chars().count();
|
||||
buf.push('9');
|
||||
|
||||
self.encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);
|
||||
}
|
||||
|
||||
final void encodeCompressedGtin(StringBuilder buf, int currentPos) {
|
||||
buf.append("(01)");
|
||||
int initialPosition = buf.length();
|
||||
buf.append('9');
|
||||
|
||||
encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);
|
||||
}
|
||||
|
||||
final void encodeCompressedGtinWithoutAI(StringBuilder buf, int currentPos, int initialBufferPosition) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int currentBlock = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10);
|
||||
if (currentBlock / 100 == 0) {
|
||||
buf.append('0');
|
||||
fn encodeCompressedGtinWithoutAI(&self, buf:&mut String, currentPos:usize, initialBufferPosition:usize) {
|
||||
for i in 0..4 {
|
||||
// for (int i = 0; i < 4; ++i) {
|
||||
let currentBlock = self.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10);
|
||||
if currentBlock / 100 == 0 {
|
||||
buf.push('0');
|
||||
}
|
||||
if (currentBlock / 10 == 0) {
|
||||
buf.append('0');
|
||||
if currentBlock / 10 == 0 {
|
||||
buf.push('0');
|
||||
}
|
||||
buf.append(currentBlock);
|
||||
buf.push_str(¤tBlock.to_string());
|
||||
}
|
||||
|
||||
appendCheckDigit(buf, initialBufferPosition);
|
||||
}
|
||||
|
||||
private static void appendCheckDigit(StringBuilder buf, int currentPos) {
|
||||
int checkDigit = 0;
|
||||
for (int i = 0; i < 13; i++) {
|
||||
int digit = buf.charAt(i + currentPos) - '0';
|
||||
checkDigit += (i & 0x01) == 0 ? 3 * digit : digit;
|
||||
}
|
||||
|
||||
checkDigit = 10 - (checkDigit % 10);
|
||||
if (checkDigit == 10) {
|
||||
checkDigit = 0;
|
||||
}
|
||||
|
||||
buf.append(checkDigit);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
pub(super) fn appendCheckDigit( buf:&mut String, currentPos:usize) {
|
||||
let mut checkDigit = 0;
|
||||
for i in 0..13 {
|
||||
// for (int i = 0; i < 13; i++) {
|
||||
let digit = buf.chars().nth(i + currentPos).unwrap() as u32 - '0' as u32;
|
||||
checkDigit += if (i & 0x01) == 0 {3 * digit} else {digit};
|
||||
}
|
||||
|
||||
checkDigit = 10 - (checkDigit % 10);
|
||||
if checkDigit == 10 {
|
||||
checkDigit = 0;
|
||||
}
|
||||
|
||||
buf.push_str(&checkDigit.to_string());
|
||||
}
|
||||
@@ -24,31 +24,33 @@
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
use super::DecodedInformation;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
final class BlockParsedRXingResult {
|
||||
|
||||
private final DecodedInformation decodedInformation;
|
||||
private final boolean finished;
|
||||
|
||||
BlockParsedRXingResult() {
|
||||
this(null, false);
|
||||
}
|
||||
|
||||
BlockParsedRXingResult(DecodedInformation information, boolean finished) {
|
||||
this.finished = finished;
|
||||
this.decodedInformation = information;
|
||||
}
|
||||
|
||||
DecodedInformation getDecodedInformation() {
|
||||
return this.decodedInformation;
|
||||
}
|
||||
|
||||
boolean isFinished() {
|
||||
return this.finished;
|
||||
}
|
||||
pub struct BlockParsedRXingResult {
|
||||
decodedInformation: Option<DecodedInformation>,
|
||||
finished: bool,
|
||||
}
|
||||
impl BlockParsedRXingResult {
|
||||
pub fn new() -> Self {
|
||||
Self::with_information(None, false)
|
||||
}
|
||||
|
||||
pub fn with_information(information: Option<DecodedInformation>, finished: bool) -> Self {
|
||||
Self {
|
||||
decodedInformation: information,
|
||||
finished,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getDecodedInformation(&self) -> &Option<DecodedInformation> {
|
||||
&self.decodedInformation
|
||||
}
|
||||
|
||||
pub fn isFinished(&self) -> bool {
|
||||
self.finished
|
||||
}
|
||||
}
|
||||
@@ -23,61 +23,62 @@
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum State {
|
||||
NUMERIC,
|
||||
ALPHA,
|
||||
ISO_IEC_646,
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
*/
|
||||
final class CurrentParsingState {
|
||||
|
||||
private int position;
|
||||
private State encoding;
|
||||
|
||||
private enum State {
|
||||
NUMERIC,
|
||||
ALPHA,
|
||||
ISO_IEC_646
|
||||
}
|
||||
|
||||
CurrentParsingState() {
|
||||
this.position = 0;
|
||||
this.encoding = State.NUMERIC;
|
||||
}
|
||||
|
||||
int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
void incrementPosition(int delta) {
|
||||
position += delta;
|
||||
}
|
||||
|
||||
boolean isAlpha() {
|
||||
return this.encoding == State.ALPHA;
|
||||
}
|
||||
|
||||
boolean isNumeric() {
|
||||
return this.encoding == State.NUMERIC;
|
||||
}
|
||||
|
||||
boolean isIsoIec646() {
|
||||
return this.encoding == State.ISO_IEC_646;
|
||||
}
|
||||
|
||||
void setNumeric() {
|
||||
this.encoding = State.NUMERIC;
|
||||
}
|
||||
|
||||
void setAlpha() {
|
||||
this.encoding = State.ALPHA;
|
||||
}
|
||||
|
||||
void setIsoIec646() {
|
||||
this.encoding = State.ISO_IEC_646;
|
||||
}
|
||||
pub struct CurrentParsingState {
|
||||
position: usize,
|
||||
encoding: State,
|
||||
}
|
||||
|
||||
impl CurrentParsingState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
position: 0,
|
||||
encoding: State::NUMERIC,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getPosition(&self) -> usize {
|
||||
self.position
|
||||
}
|
||||
|
||||
pub fn setPosition(&mut self, position: usize) {
|
||||
self.position = position
|
||||
}
|
||||
|
||||
pub fn incrementPosition(&mut self, delta: usize) {
|
||||
self.position += delta;
|
||||
}
|
||||
|
||||
pub fn isAlpha(&self) -> bool {
|
||||
self.encoding == State::ALPHA
|
||||
}
|
||||
|
||||
pub fn isNumeric(&self) -> bool {
|
||||
self.encoding == State::NUMERIC
|
||||
}
|
||||
|
||||
pub fn isIsoIec646(&self) -> bool {
|
||||
self.encoding == State::ISO_IEC_646
|
||||
}
|
||||
|
||||
pub fn setNumeric(&mut self) {
|
||||
self.encoding = State::NUMERIC;
|
||||
}
|
||||
|
||||
pub fn setAlpha(&mut self) {
|
||||
self.encoding = State::ALPHA;
|
||||
}
|
||||
|
||||
pub fn setIsoIec646(&mut self) {
|
||||
self.encoding = State::ISO_IEC_646;
|
||||
}
|
||||
}
|
||||
@@ -24,29 +24,33 @@
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
use super::DecodedObject;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
final class DecodedChar extends DecodedObject {
|
||||
|
||||
private final char value;
|
||||
|
||||
static final char FNC1 = '$'; // It's not in Alphanumeric neither in ISO/IEC 646 charset
|
||||
|
||||
DecodedChar(int newPosition, char value) {
|
||||
super(newPosition);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
char getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
boolean isFNC1() {
|
||||
return this.value == FNC1;
|
||||
}
|
||||
|
||||
pub struct DecodedChar {
|
||||
value: char,
|
||||
newPosition: usize,
|
||||
}
|
||||
impl DecodedObject for DecodedChar {
|
||||
fn getNewPosition(&self) -> usize {
|
||||
self.newPosition
|
||||
}
|
||||
}
|
||||
impl DecodedChar {
|
||||
pub const FNC1: char = '$'; // It's not in Alphanumeric neither in ISO/IEC 646 charset
|
||||
|
||||
pub fn new(newPosition: usize, value: char) -> Self {
|
||||
Self { value, newPosition }
|
||||
}
|
||||
|
||||
pub fn getValue(&self) -> char {
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn isFNC1(&self) -> bool {
|
||||
self.value == Self::FNC1
|
||||
}
|
||||
}
|
||||
@@ -24,50 +24,57 @@
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
|
||||
import com.google.zxing.FormatException;
|
||||
use super::DecodedObject;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
final class DecodedNumeric extends DecodedObject {
|
||||
#[derive(Clone)]
|
||||
pub struct DecodedInformation {
|
||||
newPosition: usize,
|
||||
newString: String,
|
||||
remainingValue: u32,
|
||||
remaining: bool,
|
||||
}
|
||||
|
||||
private final int firstDigit;
|
||||
private final int secondDigit;
|
||||
|
||||
static final int FNC1 = 10;
|
||||
|
||||
DecodedNumeric(int newPosition, int firstDigit, int secondDigit) throws FormatException {
|
||||
super(newPosition);
|
||||
|
||||
if (firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10) {
|
||||
throw FormatException.getFormatInstance();
|
||||
impl DecodedObject for DecodedInformation {
|
||||
fn getNewPosition(&self) -> usize {
|
||||
self.newPosition
|
||||
}
|
||||
}
|
||||
impl DecodedInformation {
|
||||
pub fn new(newPosition: usize, newString: String) -> Self {
|
||||
Self {
|
||||
newPosition,
|
||||
newString,
|
||||
remainingValue: 0,
|
||||
remaining: false,
|
||||
}
|
||||
}
|
||||
|
||||
this.firstDigit = firstDigit;
|
||||
this.secondDigit = secondDigit;
|
||||
}
|
||||
pub fn with_remaining_value(
|
||||
newPosition: usize,
|
||||
newString: String,
|
||||
remainingValue: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
newPosition,
|
||||
newString,
|
||||
remainingValue,
|
||||
remaining: true,
|
||||
}
|
||||
}
|
||||
|
||||
int getFirstDigit() {
|
||||
return this.firstDigit;
|
||||
}
|
||||
pub fn getNewString(&self) -> &str {
|
||||
&self.newString
|
||||
}
|
||||
|
||||
int getSecondDigit() {
|
||||
return this.secondDigit;
|
||||
}
|
||||
|
||||
int getValue() {
|
||||
return this.firstDigit * 10 + this.secondDigit;
|
||||
}
|
||||
|
||||
boolean isFirstDigitFNC1() {
|
||||
return this.firstDigit == FNC1;
|
||||
}
|
||||
|
||||
boolean isSecondDigitFNC1() {
|
||||
return this.secondDigit == FNC1;
|
||||
}
|
||||
pub fn isRemaining(&self) -> bool {
|
||||
self.remaining
|
||||
}
|
||||
|
||||
pub fn getRemainingValue(&self) -> u32 {
|
||||
self.remainingValue
|
||||
}
|
||||
}
|
||||
83
src/oned/rss/expanded/decoders/decoded_numeric.rs
Normal file
83
src/oned/rss/expanded/decoders/decoded_numeric.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
use crate::Exceptions;
|
||||
|
||||
use super::DecodedObject;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
pub struct DecodedNumeric {
|
||||
newPosition: usize,
|
||||
firstDigit: u32,
|
||||
secondDigit: u32,
|
||||
}
|
||||
impl DecodedObject for DecodedNumeric {
|
||||
fn getNewPosition(&self) -> usize {
|
||||
self.newPosition
|
||||
}
|
||||
}
|
||||
impl DecodedNumeric {
|
||||
pub const FNC1: u32 = 10;
|
||||
|
||||
pub fn new(newPosition: usize, firstDigit: u32, secondDigit: u32) -> Result<Self, Exceptions> {
|
||||
// super(newPosition);
|
||||
|
||||
if firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10 {
|
||||
return Err(Exceptions::FormatException(
|
||||
".getFormatInstance();".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
newPosition,
|
||||
firstDigit,
|
||||
secondDigit,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn getFirstDigit(&self) -> u32 {
|
||||
self.firstDigit
|
||||
}
|
||||
|
||||
pub fn getSecondDigit(&self) -> u32 {
|
||||
self.secondDigit
|
||||
}
|
||||
|
||||
pub fn getValue(&self) -> u32 {
|
||||
self.firstDigit * 10 + self.secondDigit
|
||||
}
|
||||
|
||||
pub fn isFirstDigitFNC1(&self) -> bool {
|
||||
self.firstDigit == Self::FNC1
|
||||
}
|
||||
|
||||
pub fn isSecondDigitFNC1(&self) -> bool {
|
||||
self.secondDigit == Self::FNC1
|
||||
}
|
||||
}
|
||||
@@ -24,21 +24,13 @@
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
package com.google.zxing.oned.rss.expanded.decoders;
|
||||
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
*/
|
||||
abstract class DecodedObject {
|
||||
pub trait DecodedObject {
|
||||
|
||||
private final int newPosition;
|
||||
|
||||
DecodedObject(int newPosition) {
|
||||
this.newPosition = newPosition;
|
||||
}
|
||||
|
||||
final int getNewPosition() {
|
||||
return this.newPosition;
|
||||
}
|
||||
fn getNewPosition(&self) -> usize;
|
||||
|
||||
}
|
||||
308
src/oned/rss/expanded/decoders/field_parser.rs
Normal file
308
src/oned/rss/expanded/decoders/field_parser.rs
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::Exceptions;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
|
||||
lazy_static! {
|
||||
|
||||
static ref TWO_DIGIT_DATA_LENGTH : HashMap<String,DataLength> = {
|
||||
let mut hm = HashMap::new();
|
||||
hm.insert("00".to_owned(), DataLength::fixed(18));
|
||||
hm.insert("01".to_owned(), DataLength::fixed(14));
|
||||
hm.insert("02".to_owned(), DataLength::fixed(14));
|
||||
hm.insert("10".to_owned(), DataLength::variable(20));
|
||||
hm.insert("11".to_owned(), DataLength::fixed(6));
|
||||
hm.insert("12".to_owned(), DataLength::fixed(6));
|
||||
hm.insert("13".to_owned(), DataLength::fixed(6));
|
||||
hm.insert("15".to_owned(), DataLength::fixed(6));
|
||||
hm.insert("17".to_owned(), DataLength::fixed(6));
|
||||
hm.insert("20".to_owned(), DataLength::fixed(2));
|
||||
hm.insert("21".to_owned(), DataLength::variable(20));
|
||||
hm.insert("22".to_owned(), DataLength::variable(29));
|
||||
hm.insert("30".to_owned(), DataLength::variable(8));
|
||||
hm.insert("37".to_owned(), DataLength::variable(8));
|
||||
//internal company codes
|
||||
for i in 90..=99 {
|
||||
// for (int i = 90; i <= 99; i++) {
|
||||
hm.insert(i.to_string(), DataLength::variable(30));
|
||||
}
|
||||
hm
|
||||
};
|
||||
|
||||
static ref THREE_DIGIT_DATA_LENGTH : HashMap<String,DataLength>=
|
||||
{
|
||||
let mut hm = HashMap::new();
|
||||
hm.insert("240".to_owned(), DataLength::variable(30));
|
||||
hm.insert("241".to_owned(), DataLength::variable(30));
|
||||
hm.insert("242".to_owned(), DataLength::variable(6));
|
||||
hm.insert("250".to_owned(), DataLength::variable(30));
|
||||
hm.insert("251".to_owned(), DataLength::variable(30));
|
||||
hm.insert("253".to_owned(), DataLength::variable(17));
|
||||
hm.insert("254".to_owned(), DataLength::variable(20));
|
||||
hm.insert("400".to_owned(), DataLength::variable(30));
|
||||
hm.insert("401".to_owned(), DataLength::variable(30));
|
||||
hm.insert("402".to_owned(), DataLength::fixed(17));
|
||||
hm.insert("403".to_owned(), DataLength::variable(30));
|
||||
hm.insert("410".to_owned(), DataLength::fixed(13));
|
||||
hm.insert("411".to_owned(), DataLength::fixed(13));
|
||||
hm.insert("412".to_owned(), DataLength::fixed(13));
|
||||
hm.insert("413".to_owned(), DataLength::fixed(13));
|
||||
hm.insert("414".to_owned(), DataLength::fixed(13));
|
||||
hm.insert("420".to_owned(), DataLength::variable(20));
|
||||
hm.insert("421".to_owned(), DataLength::variable(15));
|
||||
hm.insert("422".to_owned(), DataLength::fixed(3));
|
||||
hm.insert("423".to_owned(), DataLength::variable(15));
|
||||
hm.insert("424".to_owned(), DataLength::fixed(3));
|
||||
hm.insert("425".to_owned(), DataLength::fixed(3));
|
||||
hm.insert("426".to_owned(), DataLength::fixed(3));
|
||||
|
||||
hm
|
||||
};
|
||||
|
||||
static ref THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH:HashMap<String,DataLength> = {
|
||||
let mut hm = HashMap::new();
|
||||
for i in 310..=316 {
|
||||
// for (int i = 310; i <= 316; i++) {
|
||||
hm.insert(i.to_string(), DataLength::fixed(6));
|
||||
}
|
||||
for i in 320..=336 {
|
||||
// for (int i = 320; i <= 336; i++) {
|
||||
hm.insert(i.to_string(), DataLength::fixed(6));
|
||||
}
|
||||
for i in 340..=357 {
|
||||
// for (int i = 340; i <= 357; i++) {
|
||||
hm.insert(i.to_string(), DataLength::fixed(6));
|
||||
}
|
||||
for i in 360..=369 {
|
||||
// for (int i = 360; i <= 369; i++) {
|
||||
hm.insert(i.to_string(), DataLength::fixed(6));
|
||||
}
|
||||
hm.insert("390".to_owned(), DataLength::variable(15));
|
||||
hm.insert("391".to_owned(), DataLength::variable(18));
|
||||
hm.insert("392".to_owned(), DataLength::variable(15));
|
||||
hm.insert("393".to_owned(), DataLength::variable(18));
|
||||
hm.insert("703".to_owned(), DataLength::variable(30));
|
||||
|
||||
hm
|
||||
};
|
||||
|
||||
static ref FOUR_DIGIT_DATA_LENGTH : HashMap<String,DataLength>={
|
||||
let mut hm = HashMap::new();
|
||||
hm.insert("7001".to_owned(), DataLength::fixed(13));
|
||||
hm.insert("7002".to_owned(), DataLength::variable(30));
|
||||
hm.insert("7003".to_owned(), DataLength::fixed(10));
|
||||
hm.insert("8001".to_owned(), DataLength::fixed(14));
|
||||
hm.insert("8002".to_owned(), DataLength::variable(20));
|
||||
hm.insert("8003".to_owned(), DataLength::variable(30));
|
||||
hm.insert("8004".to_owned(), DataLength::variable(30));
|
||||
hm.insert("8005".to_owned(), DataLength::fixed(6));
|
||||
hm.insert("8006".to_owned(), DataLength::fixed(18));
|
||||
hm.insert("8007".to_owned(), DataLength::variable(30));
|
||||
hm.insert("8008".to_owned(), DataLength::variable(12));
|
||||
hm.insert("8018".to_owned(), DataLength::fixed(18));
|
||||
hm.insert("8020".to_owned(), DataLength::variable(25));
|
||||
hm.insert("8100".to_owned(), DataLength::fixed(6));
|
||||
hm.insert("8101".to_owned(), DataLength::fixed(10));
|
||||
hm.insert("8102".to_owned(), DataLength::fixed(2));
|
||||
hm.insert("8110".to_owned(), DataLength::variable(70));
|
||||
hm.insert("8200".to_owned(), DataLength::variable(70));
|
||||
|
||||
hm
|
||||
};
|
||||
}
|
||||
|
||||
pub fn parseFieldsInGeneralPurpose(rawInformation: &str) -> Result<String, Exceptions> {
|
||||
if rawInformation.is_empty() {
|
||||
return Ok("".to_owned());
|
||||
}
|
||||
|
||||
// Processing 2-digit AIs
|
||||
|
||||
if rawInformation.chars().count() < 2 {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
|
||||
let lookup: String = rawInformation.chars().take(2).collect();
|
||||
let twoDigitDataLength = TWO_DIGIT_DATA_LENGTH.get(&lookup);
|
||||
if let Some(tddl) = twoDigitDataLength {
|
||||
if tddl.variable {
|
||||
return processVariableAI(2, tddl.length, rawInformation);
|
||||
}
|
||||
return processFixedAI(2, tddl.length, rawInformation);
|
||||
}
|
||||
|
||||
if rawInformation.chars().count() < 3 {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
|
||||
let firstThreeDigits: String = rawInformation.chars().take(3).collect(); //rawInformation.substring(0, 3);
|
||||
let threeDigitDataLength = THREE_DIGIT_DATA_LENGTH.get(&firstThreeDigits);
|
||||
if let Some(tddl) = threeDigitDataLength {
|
||||
if tddl.variable {
|
||||
return processVariableAI(3, tddl.length, rawInformation);
|
||||
}
|
||||
return processFixedAI(3, tddl.length, rawInformation);
|
||||
}
|
||||
|
||||
if rawInformation.chars().count() < 4 {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
|
||||
let threeDigitPlusDigitDataLength = THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.get(&firstThreeDigits);
|
||||
if let Some(tdpddl) = threeDigitPlusDigitDataLength {
|
||||
if tdpddl.variable {
|
||||
return processVariableAI(4, tdpddl.length, rawInformation);
|
||||
}
|
||||
return processFixedAI(4, tdpddl.length, rawInformation);
|
||||
}
|
||||
|
||||
let lookup: String = rawInformation.chars().take(4).collect();
|
||||
let firstFourDigitLength = FOUR_DIGIT_DATA_LENGTH.get(&lookup /*(0, 4)*/);
|
||||
if let Some(ffdl) = firstFourDigitLength {
|
||||
if ffdl.variable {
|
||||
return processVariableAI(4, ffdl.length, rawInformation);
|
||||
}
|
||||
return processFixedAI(4, ffdl.length, rawInformation);
|
||||
}
|
||||
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
|
||||
fn processFixedAI(
|
||||
aiSize: usize,
|
||||
fieldSize: usize,
|
||||
rawInformation: &str,
|
||||
) -> Result<String, Exceptions> {
|
||||
if rawInformation.chars().count() < aiSize {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
|
||||
let ai: String = rawInformation.chars().take(aiSize).collect();
|
||||
|
||||
if rawInformation.chars().count() < aiSize + fieldSize {
|
||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||
}
|
||||
|
||||
let field: String = rawInformation
|
||||
.chars()
|
||||
.skip(aiSize)
|
||||
.take(fieldSize)
|
||||
.collect(); //rawInformation.substring(aiSize, aiSize + fieldSize);
|
||||
let remaining: String = rawInformation.chars().skip(aiSize + fieldSize).collect(); // rawInformation.substring(aiSize + fieldSize);
|
||||
let result = format!("({}){}", ai, field);
|
||||
let parsedAI = parseFieldsInGeneralPurpose(&remaining)?;
|
||||
|
||||
Ok(if parsedAI.is_empty() {
|
||||
result
|
||||
} else {
|
||||
format!("{}{}", result, parsedAI)
|
||||
})
|
||||
}
|
||||
|
||||
fn processVariableAI(
|
||||
aiSize: usize,
|
||||
variableFieldSize: usize,
|
||||
rawInformation: &str,
|
||||
) -> Result<String, Exceptions> {
|
||||
let ai: String = rawInformation.chars().take(aiSize as usize).collect(); //rawInformation.substring(0, aiSize);
|
||||
let maxSize = rawInformation
|
||||
.chars()
|
||||
.count()
|
||||
.min(aiSize + variableFieldSize);
|
||||
let field: String = rawInformation
|
||||
.chars()
|
||||
.skip(aiSize as usize)
|
||||
.take(maxSize)
|
||||
.collect(); // (aiSize, maxSize);
|
||||
let remaining: String = rawInformation.chars().skip(maxSize).collect();
|
||||
let result = format!("({}){}", ai, field); //'(' + ai + ')' + field;
|
||||
let parsedAI = parseFieldsInGeneralPurpose(&remaining)?;
|
||||
|
||||
Ok(if parsedAI.is_empty() {
|
||||
result
|
||||
} else {
|
||||
format!("{}{}", result, parsedAI)
|
||||
})
|
||||
}
|
||||
|
||||
struct DataLength {
|
||||
pub variable: bool,
|
||||
pub length: usize,
|
||||
}
|
||||
impl DataLength {
|
||||
// fn new( variable:bool, length:u32) -> Self{
|
||||
// Self(variable,length)
|
||||
// }
|
||||
|
||||
pub fn fixed(length: usize) -> Self {
|
||||
Self {
|
||||
variable: false,
|
||||
length,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn variable(length: usize) -> Self {
|
||||
Self {
|
||||
variable: true,
|
||||
length,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
#[cfg(test)]
|
||||
mod FieldParserTest {
|
||||
|
||||
fn checkFields( expected:&str) {
|
||||
let field = expected.replace("(", "").replace(")","");
|
||||
let actual = super::parseFieldsInGeneralPurpose(&field).expect("parse");
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testParseField() {
|
||||
checkFields("(15)991231(3103)001750(10)12A");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testParseField2() {
|
||||
checkFields("(15)991231(15)991231(3103)001750(10)12A");
|
||||
}
|
||||
}
|
||||
469
src/oned/rss/expanded/decoders/general_app_id_decoder.rs
Normal file
469
src/oned/rss/expanded/decoders/general_app_id_decoder.rs
Normal file
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
use crate::{common::BitArray, Exceptions};
|
||||
|
||||
use super::{CurrentParsingState, DecodedChar, DecodedNumeric, DecodedInformation, BlockParsedRXingResult, DecodedObject, field_parser};
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
pub struct GeneralAppIdDecoder<'a> {
|
||||
|
||||
information:&'a BitArray,
|
||||
current : CurrentParsingState, //= new CurrentParsingState();
|
||||
buffer :String, //= new StringBuilder();
|
||||
}
|
||||
|
||||
impl<'a> GeneralAppIdDecoder<'_> {
|
||||
pub fn new( information:&'a BitArray) -> GeneralAppIdDecoder<'a>{
|
||||
GeneralAppIdDecoder{
|
||||
information,
|
||||
current: CurrentParsingState::new(),
|
||||
buffer: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decodeAllCodes(&mut self, buff:String, initialPosition:usize) -> Result<String,Exceptions> {
|
||||
let mut buff = buff;
|
||||
let mut currentPosition = initialPosition;
|
||||
let mut remaining = "".to_owned();
|
||||
loop {
|
||||
let info = self.decodeGeneralPurposeField(currentPosition, &remaining)?;
|
||||
let parsedFields =field_parser::parseFieldsInGeneralPurpose(info.getNewString())?;
|
||||
if !parsedFields.is_empty() {
|
||||
buff.push_str(&parsedFields);
|
||||
}
|
||||
if info.isRemaining() {
|
||||
remaining = info.getRemainingValue().to_string();
|
||||
} else {
|
||||
remaining = "".to_owned();
|
||||
}
|
||||
|
||||
if currentPosition == info.getNewPosition() { // No step forward!
|
||||
break;
|
||||
}
|
||||
currentPosition = info.getNewPosition();
|
||||
}
|
||||
|
||||
Ok(buff)
|
||||
}
|
||||
|
||||
fn isStillNumeric(&self, pos:usize) -> bool{
|
||||
// It's numeric if it still has 7 positions
|
||||
// and one of the first 4 bits is "1".
|
||||
if pos + 7 > self.information.getSize() {
|
||||
return pos + 4 <= self.information.getSize();
|
||||
}
|
||||
|
||||
for i in pos..pos+3 {
|
||||
// for (int i = pos; i < pos + 3; ++i) {
|
||||
if self.information.get(i) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
self.information.get(pos + 3)
|
||||
}
|
||||
|
||||
fn decodeNumeric(&self, pos:usize) -> Result<DecodedNumeric,Exceptions> {
|
||||
if pos + 7 > self.information.getSize() {
|
||||
let numeric = self.extractNumericValueFromBitArray(pos, 4);
|
||||
if numeric == 0 {
|
||||
return DecodedNumeric::new(self.information.getSize(), DecodedNumeric::FNC1, DecodedNumeric::FNC1);
|
||||
}
|
||||
return DecodedNumeric::new(self.information.getSize(), numeric - 1, DecodedNumeric::FNC1);
|
||||
}
|
||||
let numeric = self.extractNumericValueFromBitArray(pos, 7);
|
||||
|
||||
let digit1 = (numeric - 8) / 11;
|
||||
let digit2 = (numeric - 8) % 11;
|
||||
|
||||
DecodedNumeric::new(pos + 7, digit1, digit2)
|
||||
}
|
||||
|
||||
pub fn extractNumericValueFromBitArray(&self, pos:usize, bits:u32) -> u32{
|
||||
Self::extractNumericValueFromBitArrayWithInformation(&self.information, pos, bits)
|
||||
}
|
||||
|
||||
pub fn extractNumericValueFromBitArrayWithInformation( information:&BitArray, pos:usize, bits:u32) ->u32{
|
||||
let mut value = 0;
|
||||
for i in 0..bits {
|
||||
// for (int i = 0; i < bits; ++i) {
|
||||
if information.get(pos + i as usize) {
|
||||
value |= 1 << (bits - i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
pub fn decodeGeneralPurposeField(&mut self, pos:usize, remaining:&str) -> Result<DecodedInformation,Exceptions> {
|
||||
self.buffer.clear();
|
||||
|
||||
if !remaining.is_empty() {
|
||||
self.buffer.push_str(remaining);
|
||||
}
|
||||
|
||||
self.current.setPosition(pos);
|
||||
|
||||
if let Ok(lastDecoded) = self.parseBlocks(){
|
||||
if lastDecoded.isRemaining() {
|
||||
return Ok(DecodedInformation::with_remaining_value(self.current.getPosition(),
|
||||
self.buffer.clone(), lastDecoded.getRemainingValue()));
|
||||
}}
|
||||
Ok(DecodedInformation::new(self.current.getPosition(), self.buffer.clone()))
|
||||
}
|
||||
|
||||
fn parseBlocks(&mut self) -> Result<DecodedInformation,Exceptions> {
|
||||
let mut isFinished;
|
||||
let mut result:BlockParsedRXingResult;
|
||||
loop {
|
||||
let initialPosition = self.current.getPosition();
|
||||
|
||||
if self.current.isAlpha() {
|
||||
result =self. parseAlphaBlock()?;
|
||||
isFinished = result.isFinished();
|
||||
} else if self.current.isIsoIec646() {
|
||||
result = self.parseIsoIec646Block()?;
|
||||
isFinished = result.isFinished();
|
||||
} else { // it must be numeric
|
||||
result = self.parseNumericBlock()?;
|
||||
isFinished = result.isFinished();
|
||||
}
|
||||
|
||||
let positionChanged = initialPosition != self.current.getPosition();
|
||||
if !positionChanged && !isFinished {
|
||||
break;
|
||||
}
|
||||
|
||||
if !(!isFinished) { break; }
|
||||
} //while (!isFinished);
|
||||
|
||||
Ok(result.getDecodedInformation().as_ref().unwrap().clone())
|
||||
}
|
||||
|
||||
fn parseNumericBlock(&mut self) -> Result<BlockParsedRXingResult,Exceptions> {
|
||||
while self.isStillNumeric(self.current.getPosition()) {
|
||||
let numeric = self.decodeNumeric(self.current.getPosition())?;
|
||||
self.current.setPosition(numeric.getNewPosition());
|
||||
|
||||
if numeric.isFirstDigitFNC1() {
|
||||
let information=
|
||||
if numeric.isSecondDigitFNC1() {
|
||||
DecodedInformation::new(self.current.getPosition(), self.buffer.clone())
|
||||
} else {
|
||||
DecodedInformation::with_remaining_value(self.current.getPosition(), self.buffer.clone(), numeric.getSecondDigit())
|
||||
};
|
||||
return Ok(BlockParsedRXingResult::with_information(Some(information), true));
|
||||
}
|
||||
self.buffer.push_str(&numeric.getFirstDigit().to_string());
|
||||
|
||||
if numeric.isSecondDigitFNC1() {
|
||||
let information = DecodedInformation::new(self.current.getPosition(), self.buffer.clone());
|
||||
return Ok(BlockParsedRXingResult::with_information(Some(information), true));
|
||||
}
|
||||
self.buffer.push_str(&numeric.getSecondDigit().to_string());
|
||||
}
|
||||
|
||||
if self.isNumericToAlphaNumericLatch(self.current.getPosition()) {
|
||||
self.current.setAlpha();
|
||||
self.current.incrementPosition(4);
|
||||
}
|
||||
|
||||
Ok(BlockParsedRXingResult::new())
|
||||
}
|
||||
|
||||
fn parseIsoIec646Block(&mut self) -> Result<BlockParsedRXingResult,Exceptions> {
|
||||
while self.isStillIsoIec646(self.current.getPosition()) {
|
||||
let iso = self.decodeIsoIec646(self.current.getPosition())?;
|
||||
self.current.setPosition(iso.getNewPosition());
|
||||
|
||||
if iso.isFNC1() {
|
||||
let information = DecodedInformation::new(self.current.getPosition(), self.buffer.clone());
|
||||
return Ok(BlockParsedRXingResult::with_information(Some(information), true));
|
||||
}
|
||||
self.buffer.push_str(&iso.getValue().to_string());
|
||||
}
|
||||
|
||||
if self.isAlphaOr646ToNumericLatch(self.current.getPosition()) {
|
||||
self.current.incrementPosition(3);
|
||||
self.current.setNumeric();
|
||||
} else if self.isAlphaTo646ToAlphaLatch(self.current.getPosition()) {
|
||||
if self.current.getPosition() + 5 < self.information.getSize() {
|
||||
self. current.incrementPosition(5);
|
||||
} else {
|
||||
self.current.setPosition(self.information.getSize());
|
||||
}
|
||||
|
||||
self.current.setAlpha();
|
||||
}
|
||||
Ok(BlockParsedRXingResult::new())
|
||||
}
|
||||
|
||||
fn parseAlphaBlock(&mut self) -> Result<BlockParsedRXingResult,Exceptions> {
|
||||
while self.isStillAlpha(self.current.getPosition()) {
|
||||
let alpha = self.decodeAlphanumeric(self.current.getPosition())?;
|
||||
self.current.setPosition(alpha.getNewPosition());
|
||||
|
||||
if alpha.isFNC1() {
|
||||
let information = DecodedInformation::new(self.current.getPosition(), self.buffer.clone());
|
||||
return Ok(BlockParsedRXingResult::with_information(Some(information), true)); //end of the char block
|
||||
}
|
||||
|
||||
self.buffer.push_str(&alpha.getValue().to_string());
|
||||
}
|
||||
|
||||
if self.isAlphaOr646ToNumericLatch(self.current.getPosition()) {
|
||||
self.current.incrementPosition(3);
|
||||
self.current.setNumeric();
|
||||
} else if self.isAlphaTo646ToAlphaLatch(self.current.getPosition()) {
|
||||
if self.current.getPosition() + 5 < self.information.getSize() {
|
||||
self.current.incrementPosition(5);
|
||||
} else {
|
||||
self.current.setPosition(self.information.getSize());
|
||||
}
|
||||
|
||||
self.current.setIsoIec646();
|
||||
}
|
||||
|
||||
Ok(BlockParsedRXingResult::new())
|
||||
}
|
||||
|
||||
fn isStillIsoIec646(&self, pos:usize) -> bool{
|
||||
if pos + 5 > self.information.getSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let fiveBitValue =self. extractNumericValueFromBitArray(pos, 5);
|
||||
if fiveBitValue >= 5 && fiveBitValue < 16 {
|
||||
return true;
|
||||
}
|
||||
|
||||
if pos + 7 > self.information.getSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let sevenBitValue = self.extractNumericValueFromBitArray(pos, 7);
|
||||
if sevenBitValue >= 64 && sevenBitValue < 116 {
|
||||
return true;
|
||||
}
|
||||
|
||||
if pos + 8 > self.information.getSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let eightBitValue = self.extractNumericValueFromBitArray(pos, 8);
|
||||
|
||||
eightBitValue >= 232 && eightBitValue < 253
|
||||
|
||||
}
|
||||
|
||||
fn decodeIsoIec646(&self, pos:usize) -> Result<DecodedChar,Exceptions> {
|
||||
let fiveBitValue = self.extractNumericValueFromBitArray(pos, 5);
|
||||
if fiveBitValue == 15 {
|
||||
return Ok(DecodedChar::new(pos + 5, DecodedChar::FNC1));
|
||||
}
|
||||
|
||||
if fiveBitValue >= 5 && fiveBitValue < 15 {
|
||||
return Ok(DecodedChar::new(pos + 5, char::from_u32 ('0' as u32 + fiveBitValue - 5).unwrap()));
|
||||
}
|
||||
|
||||
let sevenBitValue = self.extractNumericValueFromBitArray(pos, 7);
|
||||
|
||||
if sevenBitValue >= 64 && sevenBitValue < 90 {
|
||||
return Ok(DecodedChar::new(pos + 7, char::from_u32 (sevenBitValue + 1).unwrap()));
|
||||
}
|
||||
|
||||
if sevenBitValue >= 90 && sevenBitValue < 116 {
|
||||
return Ok(DecodedChar::new(pos + 7, char::from_u32 (sevenBitValue + 7).unwrap()));
|
||||
}
|
||||
|
||||
let eightBitValue = self.extractNumericValueFromBitArray(pos, 8);
|
||||
let c=
|
||||
match eightBitValue {
|
||||
232=>
|
||||
'!',
|
||||
233=>
|
||||
'"',
|
||||
234=>
|
||||
'%',
|
||||
235=>
|
||||
'&',
|
||||
236=>
|
||||
'\'',
|
||||
237=>
|
||||
'(',
|
||||
238=>
|
||||
')',
|
||||
239=>
|
||||
'*',
|
||||
240=>
|
||||
'+',
|
||||
241=>
|
||||
',',
|
||||
242=>
|
||||
'-',
|
||||
243=>
|
||||
'.',
|
||||
244=>
|
||||
'/',
|
||||
245=>
|
||||
':',
|
||||
246=>
|
||||
';',
|
||||
247=>
|
||||
'<',
|
||||
248=>
|
||||
'=',
|
||||
249=>
|
||||
'>',
|
||||
250=>
|
||||
'?',
|
||||
251=>
|
||||
'_',
|
||||
252=>
|
||||
' ',
|
||||
_=>
|
||||
return Err(Exceptions::FormatException("".to_owned())),
|
||||
};
|
||||
|
||||
Ok(DecodedChar::new(pos + 8, c))
|
||||
}
|
||||
|
||||
fn isStillAlpha(&self, pos:usize) -> bool{
|
||||
if pos + 5 > self.information.getSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We now check if it's a valid 5-bit value (0..9 and FNC1)
|
||||
let fiveBitValue = self.extractNumericValueFromBitArray(pos, 5);
|
||||
if fiveBitValue >= 5 && fiveBitValue < 16 {
|
||||
return true;
|
||||
}
|
||||
|
||||
if pos + 6 > self.information.getSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let sixBitValue = self.extractNumericValueFromBitArray(pos, 6);
|
||||
|
||||
sixBitValue >= 16 && sixBitValue < 63 // 63 not included
|
||||
}
|
||||
|
||||
fn decodeAlphanumeric(&self, pos:usize) -> Result<DecodedChar,Exceptions> {
|
||||
let fiveBitValue = self.extractNumericValueFromBitArray(pos, 5);
|
||||
if fiveBitValue == 15 {
|
||||
return Ok(DecodedChar::new(pos + 5, DecodedChar::FNC1));
|
||||
}
|
||||
|
||||
if fiveBitValue >= 5 && fiveBitValue < 15 {
|
||||
return Ok(DecodedChar::new(pos + 5, char::from_u32 ('0' as u32 + fiveBitValue - 5).unwrap()));
|
||||
}
|
||||
|
||||
let sixBitValue = self.extractNumericValueFromBitArray(pos, 6);
|
||||
|
||||
if sixBitValue >= 32 && sixBitValue < 58 {
|
||||
return Ok(DecodedChar::new(pos + 6, char::from_u32 (sixBitValue + 33).unwrap()));
|
||||
}
|
||||
|
||||
let c =
|
||||
match sixBitValue {
|
||||
58=>
|
||||
'*',
|
||||
59=>
|
||||
',',
|
||||
60=>
|
||||
'-',
|
||||
61=>
|
||||
'.',
|
||||
62=>
|
||||
'/',
|
||||
_=>
|
||||
return Err(Exceptions::IllegalStateException(format!("Decoding invalid alphanumeric value: {}" , sixBitValue))),
|
||||
};
|
||||
|
||||
Ok(DecodedChar::new(pos + 6, c))
|
||||
}
|
||||
|
||||
fn isAlphaTo646ToAlphaLatch(&self, pos:usize)-> bool {
|
||||
if pos + 1 > self.information.getSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
while i < 5 && i + pos < self.information.getSize() {
|
||||
// for (int i = 0; i < 5 && i + pos < this.information.getSize(); ++i) {
|
||||
if i == 2 {
|
||||
if !self.information.get(pos + 2) {
|
||||
return false;
|
||||
}
|
||||
} else if self.information.get(pos + i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i+=1;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn isAlphaOr646ToNumericLatch(&self, pos:usize) -> bool{
|
||||
// Next is alphanumeric if there are 3 positions and they are all zeros
|
||||
if pos + 3 > self.information.getSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
for i in pos..pos+3 {
|
||||
// for (int i = pos; i < pos + 3; ++i) {
|
||||
if self.information.get(i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn isNumericToAlphaNumericLatch(&self, pos:usize) -> bool{
|
||||
// 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.getSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
while i < 4 && pos < self.information.getSize() {
|
||||
// for (int i = 0; i < 4 && i + pos < this.information.getSize(); ++i) {
|
||||
if self.information.get(pos + i) {
|
||||
return false;
|
||||
}
|
||||
i+=1;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -1 +1,27 @@
|
||||
|
||||
|
||||
pub mod abstract_expanded_decoder;
|
||||
pub use abstract_expanded_decoder::AbstractExpandedDecoder;
|
||||
mod ai_01_and_other_ais;
|
||||
pub use ai_01_and_other_ais::*;
|
||||
mod ai_01_decoder;
|
||||
pub use ai_01_decoder::*;
|
||||
mod general_app_id_decoder;
|
||||
pub use general_app_id_decoder::*;
|
||||
mod current_parsing_state;
|
||||
pub use current_parsing_state::*;
|
||||
mod decoded_object;
|
||||
pub use decoded_object::*;
|
||||
mod decoded_char;
|
||||
pub use decoded_char::*;
|
||||
|
||||
mod decoded_information;
|
||||
pub use decoded_information::*;
|
||||
|
||||
mod decoded_numeric;
|
||||
pub use decoded_numeric::*;
|
||||
|
||||
mod block_parsed_result;
|
||||
pub use block_parsed_result::*;
|
||||
|
||||
pub mod field_parser;
|
||||
85
src/oned/rss/expanded/expanded_pair.rs
Normal file
85
src/oned/rss/expanded/expanded_pair.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These authors would like to acknowledge the Spanish Ministry of Industry,
|
||||
* Tourism and Trade, for the support in the project TSI020301-2008-2
|
||||
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
|
||||
* Mobile Dynamic Environments", led by Treelogic
|
||||
* ( http://www.treelogic.com/ ):
|
||||
*
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::oned::rss::{DataCharacter, FinderPattern};
|
||||
|
||||
/**
|
||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||
*/
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
pub struct ExpandedPair {
|
||||
leftChar: Option<DataCharacter>,
|
||||
rightChar: Option<DataCharacter>,
|
||||
finderPattern: Option<FinderPattern>,
|
||||
}
|
||||
|
||||
impl ExpandedPair {
|
||||
pub fn new(
|
||||
leftChar: Option<DataCharacter>,
|
||||
rightChar: Option<DataCharacter>,
|
||||
finderPattern: Option<FinderPattern>,
|
||||
) -> Self {
|
||||
Self {
|
||||
leftChar,
|
||||
rightChar,
|
||||
finderPattern,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getLeftChar(&self) -> &Option<DataCharacter> {
|
||||
&self.leftChar
|
||||
}
|
||||
|
||||
pub fn getRightChar(&self) -> &Option<DataCharacter> {
|
||||
&self.rightChar
|
||||
}
|
||||
|
||||
pub fn getFinderPattern(&self) -> &Option<FinderPattern> {
|
||||
&self.finderPattern
|
||||
}
|
||||
|
||||
pub fn mustBeLast(&self) -> bool {
|
||||
self.rightChar.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ExpandedPair {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"[ {:?} , {:?} : {} ]",
|
||||
self.leftChar,
|
||||
self.rightChar,
|
||||
if let Some(fp) = &self.finderPattern {
|
||||
fp.getValue().to_string()
|
||||
} else {
|
||||
"null".to_owned()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1 +1,7 @@
|
||||
pub mod decoders;
|
||||
|
||||
pub mod binary_util;
|
||||
pub mod bit_array_builder;
|
||||
|
||||
mod expanded_pair;
|
||||
pub use expanded_pair::*;
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::{detector::MathUtils, BitArray},
|
||||
oned::{OneDReader, one_d_reader},
|
||||
oned::{one_d_reader, OneDReader},
|
||||
BarcodeFormat, DecodeHintType, DecodingHintDictionary, Exceptions, RXingResult,
|
||||
RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint,
|
||||
};
|
||||
@@ -293,11 +293,10 @@ impl RSS14Reader {
|
||||
pattern: &FinderPattern,
|
||||
outsideChar: bool,
|
||||
) -> Result<DataCharacter, Exceptions> {
|
||||
let counters = &mut self.dataCharacterCounters; //[0_u32; 8]; //self.getDataCharacterCounters();
|
||||
//Arrays.fill(counters, 0);
|
||||
// counters.fill(0);
|
||||
counters.fill(0);
|
||||
|
||||
let counters = &mut self.dataCharacterCounters; //[0_u32; 8]; //self.getDataCharacterCounters();
|
||||
//Arrays.fill(counters, 0);
|
||||
// counters.fill(0);
|
||||
counters.fill(0);
|
||||
|
||||
if outsideChar {
|
||||
one_d_reader::recordPatternInReverse(row, pattern.getStartEnd()[0], &mut counters[..])?;
|
||||
@@ -305,7 +304,7 @@ impl RSS14Reader {
|
||||
one_d_reader::recordPattern(row, pattern.getStartEnd()[1], &mut counters[..])?;
|
||||
// reverse it
|
||||
let mut i = 0;
|
||||
let mut j = counters.len() -1;
|
||||
let mut j = counters.len() - 1;
|
||||
while i < j {
|
||||
// for (int i = 0, j = counters.length - 1; i < j; i++, j--) {
|
||||
let temp = counters[i];
|
||||
@@ -468,13 +467,13 @@ impl RSS14Reader {
|
||||
let firstCounter = startEnd[0] - firstElementStart as usize;
|
||||
let mut counters = &mut self.decodeFinderCounters;
|
||||
let counter_len = counters.len();
|
||||
let slc = counters[0..counter_len-1].to_vec();
|
||||
let slc = counters[0..counter_len - 1].to_vec();
|
||||
counters[1..counter_len].copy_from_slice(&slc);
|
||||
// Make 'counters' hold 1-4
|
||||
// let counters = self.getDecodeFinderCounters();
|
||||
// System.arraycopy(counters, 0, counters, 1, counters.length - 1);
|
||||
// counters.fill(0);
|
||||
|
||||
|
||||
counters[0] = firstCounter as u32;
|
||||
let value = Self::parseFinderValue(counters, &Self::FINDER_PATTERNS)?;
|
||||
let mut start = firstElementStart as usize;
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::{
|
||||
RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader,
|
||||
};
|
||||
|
||||
use super::{EANManufacturerOrgSupport, OneDReader, UPCEANExtensionSupport, one_d_reader};
|
||||
use super::{one_d_reader, EANManufacturerOrgSupport, OneDReader, UPCEANExtensionSupport};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
@@ -433,8 +433,11 @@ pub trait UPCEANReader: OneDReader {
|
||||
counters[counterPosition] += 1;
|
||||
} else {
|
||||
if counterPosition == patternLength - 1 {
|
||||
if one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE)
|
||||
< MAX_AVG_VARIANCE
|
||||
if one_d_reader::patternMatchVariance(
|
||||
counters,
|
||||
pattern,
|
||||
MAX_INDIVIDUAL_VARIANCE,
|
||||
) < MAX_AVG_VARIANCE
|
||||
{
|
||||
return Ok([patternStart, x]);
|
||||
}
|
||||
@@ -483,7 +486,7 @@ pub trait UPCEANReader: OneDReader {
|
||||
// for (int i = 0; i < max; i++) {
|
||||
let pattern = &patterns[i];
|
||||
let variance: f32 =
|
||||
one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
if variance < bestVariance {
|
||||
bestVariance = variance;
|
||||
bestMatch = i as isize;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* Copyright 2008 ZXing authors
|
||||
*
|
||||
@@ -15,15 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use rxing::{maxicode::MaxiCodeReader, BarcodeFormat, DecodeHintType, MultiFormatReader};
|
||||
use rxing::{maxicode::MaxiCodeReader, BarcodeFormat, DecodeHintType, MultiFormatReader};
|
||||
|
||||
mod common;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[test]
|
||||
fn rss14_black_box1_test_case() {
|
||||
mod common;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[test]
|
||||
fn rss14_black_box1_test_case() {
|
||||
let mut tester = common::AbstractBlackBoxTestCase::new(
|
||||
"test_resources/blackbox/rss14-1",
|
||||
MultiFormatReader::default(),
|
||||
@@ -31,15 +30,13 @@
|
||||
);
|
||||
|
||||
// super("src/test/resources/blackbox/rss14-1", new MultiFormatReader(), BarcodeFormat.RSS_14);
|
||||
tester.add_test(6, 6, 0.0);
|
||||
tester.add_test(6, 6, 180.0);
|
||||
tester.add_test(6, 6, 0.0);
|
||||
tester.add_test(6, 6, 180.0);
|
||||
|
||||
tester.test_black_box()
|
||||
}
|
||||
|
||||
|
||||
tester.test_black_box()
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[test]
|
||||
@@ -55,6 +52,4 @@ fn rss14_black_box2_test_case() {
|
||||
tester.add_test_complex(3, 8, 0, 1, 180.0);
|
||||
|
||||
tester.test_black_box()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user