mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-28 05:12: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 crate::{common::BitArray, BarcodeFormat, Exceptions, RXingResult};
|
||||||
|
|
||||||
use super::{OneDReader, one_d_reader};
|
use super::{one_d_reader, OneDReader};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Decodes Code 128 barcodes.</p>
|
* <p>Decodes Code 128 barcodes.</p>
|
||||||
@@ -434,7 +434,8 @@ impl Code128Reader {
|
|||||||
for d in 0..CODE_PATTERNS.len() {
|
for d in 0..CODE_PATTERNS.len() {
|
||||||
// for (int d = 0; d < CODE_PATTERNS.len(); d++) {
|
// for (int d = 0; d < CODE_PATTERNS.len(); d++) {
|
||||||
let pattern = &CODE_PATTERNS[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 {
|
if variance < bestVariance {
|
||||||
bestVariance = variance;
|
bestVariance = variance;
|
||||||
bestMatch = d as isize;
|
bestMatch = d as isize;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use one_d_reader_derive::OneDReader;
|
|||||||
use crate::common::BitArray;
|
use crate::common::BitArray;
|
||||||
use crate::{BarcodeFormat, Exceptions, RXingResult};
|
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>
|
* <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 crate::{common::BitArray, BarcodeFormat, Exceptions, RXingResult};
|
||||||
|
|
||||||
use super::{OneDReader, one_d_reader};
|
use super::{one_d_reader, OneDReader};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Decodes Code 93 barcodes.</p>
|
* <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 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_AVG_VARIANCE: f32 = 0.38;
|
||||||
const MAX_INDIVIDUAL_VARIANCE: f32 = 0.5;
|
const MAX_INDIVIDUAL_VARIANCE: f32 = 0.5;
|
||||||
@@ -375,8 +375,11 @@ impl ITFReader {
|
|||||||
counters[counterPosition] += 1;
|
counters[counterPosition] += 1;
|
||||||
} else {
|
} else {
|
||||||
if counterPosition == patternLength - 1 {
|
if counterPosition == patternLength - 1 {
|
||||||
if one_d_reader::patternMatchVariance(&counters, pattern, MAX_INDIVIDUAL_VARIANCE)
|
if one_d_reader::patternMatchVariance(
|
||||||
< MAX_AVG_VARIANCE
|
&counters,
|
||||||
|
pattern,
|
||||||
|
MAX_INDIVIDUAL_VARIANCE,
|
||||||
|
) < MAX_AVG_VARIANCE
|
||||||
{
|
{
|
||||||
return Ok([patternStart, x]);
|
return Ok([patternStart, x]);
|
||||||
}
|
}
|
||||||
@@ -412,7 +415,8 @@ impl ITFReader {
|
|||||||
for i in 0..max {
|
for i in 0..max {
|
||||||
// for (int i = 0; i < max; i++) {
|
// for (int i = 0; i < max; i++) {
|
||||||
let pattern = &PATTERNS[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 {
|
if variance < bestVariance {
|
||||||
bestVariance = variance;
|
bestVariance = variance;
|
||||||
bestMatch = i as isize;
|
bestMatch = i as isize;
|
||||||
|
|||||||
@@ -166,7 +166,6 @@ pub trait OneDReader: Reader {
|
|||||||
) -> Result<RXingResult, Exceptions>;
|
) -> Result<RXingResult, Exceptions>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines how closely a set of observed counts of runs of black/white values matches a given
|
* 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
|
* 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
|
* @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
|
* @return ratio of total variance between counters and pattern compared to total pattern size
|
||||||
*/
|
*/
|
||||||
pub fn patternMatchVariance(
|
pub fn patternMatchVariance(counters: &[u32], pattern: &[u32], maxIndividualVariance: f32) -> f32 {
|
||||||
counters: &[u32],
|
|
||||||
pattern: &[u32],
|
|
||||||
maxIndividualVariance: f32,
|
|
||||||
) -> f32 {
|
|
||||||
let mut maxIndividualVariance = maxIndividualVariance;
|
let mut maxIndividualVariance = maxIndividualVariance;
|
||||||
let numCounters = counters.len();
|
let numCounters = counters.len();
|
||||||
let mut total = 0.0;
|
let mut total = 0.0;
|
||||||
@@ -218,7 +213,7 @@ pub fn patternMatchVariance(
|
|||||||
return totalVariance / total;
|
return totalVariance / total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records the size of successive runs of white and black pixels in a row, starting at a given point.
|
* 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
|
* 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
|
* of the array. If the row starts on a white pixel at the given start point, then the first count
|
||||||
@@ -231,11 +226,7 @@ pub fn patternMatchVariance(
|
|||||||
* @throws NotFoundException if counters cannot be filled entirely from row before running out
|
* @throws NotFoundException if counters cannot be filled entirely from row before running out
|
||||||
* of pixels
|
* of pixels
|
||||||
*/
|
*/
|
||||||
pub fn recordPattern(
|
pub fn recordPattern(row: &BitArray, start: usize, counters: &mut [u32]) -> Result<(), Exceptions> {
|
||||||
row: &BitArray,
|
|
||||||
start: usize,
|
|
||||||
counters: &mut [u32],
|
|
||||||
) -> Result<(), Exceptions> {
|
|
||||||
let numCounters = counters.len();
|
let numCounters = counters.len();
|
||||||
// Arrays.fill(counters, 0, numCounters, 0);
|
// Arrays.fill(counters, 0, numCounters, 0);
|
||||||
counters.fill(0);
|
counters.fill(0);
|
||||||
@@ -266,13 +257,13 @@ pub fn patternMatchVariance(
|
|||||||
return Err(Exceptions::NotFoundException("".to_owned()));
|
return Err(Exceptions::NotFoundException("".to_owned()));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recordPatternInReverse(
|
pub fn recordPatternInReverse(
|
||||||
row: &BitArray,
|
row: &BitArray,
|
||||||
start: usize,
|
start: usize,
|
||||||
counters: &mut [u32],
|
counters: &mut [u32],
|
||||||
) -> Result<(), Exceptions> {
|
) -> Result<(), Exceptions> {
|
||||||
let mut start = start;
|
let mut start = start;
|
||||||
// This could be more efficient I guess
|
// This could be more efficient I guess
|
||||||
let mut numTransitionsLeft = counters.len() as isize;
|
let mut numTransitionsLeft = counters.len() as isize;
|
||||||
@@ -290,4 +281,4 @@ pub fn patternMatchVariance(
|
|||||||
recordPattern(row, start + 1, counters)?;
|
recordPattern(row, start + 1, counters)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,10 @@
|
|||||||
* limitations under the License.
|
* 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
|
* Superclass of {@link OneDReader} implementations that read barcodes in the RSS family
|
||||||
@@ -97,7 +100,7 @@ pub trait AbstractRSSReaderTrait: OneDReader {
|
|||||||
array[index] -= 1;
|
array[index] -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isFinderPattern( counters: &[u32]) -> bool {
|
fn isFinderPattern(counters: &[u32]) -> bool {
|
||||||
let firstTwoSum = counters[0] + counters[1];
|
let firstTwoSum = counters[0] + counters[1];
|
||||||
let sum = firstTwoSum + counters[2] + counters[3];
|
let sum = firstTwoSum + counters[2] + counters[3];
|
||||||
let ratio: f32 = (firstTwoSum as f32) / (sum as f32);
|
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.
|
* 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 {
|
pub struct DataCharacter {
|
||||||
value: u32,
|
value: u32,
|
||||||
checksumPortion: 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/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.zxing.oned.rss.expanded.decoders;
|
use crate::common::BitArray;
|
||||||
|
|
||||||
import com.google.zxing.FormatException;
|
use super::{AI01decoder, AbstractExpandedDecoder, GeneralAppIdDecoder};
|
||||||
import com.google.zxing.NotFoundException;
|
|
||||||
import com.google.zxing.common.BitArray;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@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,
|
buff.push_str("(01)");
|
||||||
//the second one is the encodation method, and the other two are for the variable length
|
let initialGtinPosition = buff.chars().count();
|
||||||
AI01AndOtherAIs(BitArray information) {
|
let firstGtinDigit = self.getGeneralDecoder().extractNumericValueFromBitArray(Self::HEADER_SIZE, 4);
|
||||||
super(information);
|
buff.push_str(&firstGtinDigit.to_string());
|
||||||
|
|
||||||
|
self.encodeCompressedGtinWithoutAI(&mut buff, Self::HEADER_SIZE + 4, initialGtinPosition);
|
||||||
|
|
||||||
|
self.1.decodeAllCodes(buff, Self::HEADER_SIZE + 44)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
fn getGeneralDecoder(&self) -> &super::GeneralAppIdDecoder {
|
||||||
public String parseInformation() throws NotFoundException, FormatException {
|
&self.1
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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/
|
* 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 Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@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) {
|
fn encodeCompressedGtin(&self, buf:&mut String, currentPos:usize) {
|
||||||
super(information);
|
buf.push_str("(01)");
|
||||||
|
let initialPosition = buf.chars().count();
|
||||||
|
buf.push('9');
|
||||||
|
|
||||||
|
self.encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
final void encodeCompressedGtin(StringBuilder buf, int currentPos) {
|
fn encodeCompressedGtinWithoutAI(&self, buf:&mut String, currentPos:usize, initialBufferPosition:usize) {
|
||||||
buf.append("(01)");
|
for i in 0..4 {
|
||||||
int initialPosition = buf.length();
|
// for (int i = 0; i < 4; ++i) {
|
||||||
buf.append('9');
|
let currentBlock = self.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10);
|
||||||
|
if currentBlock / 100 == 0 {
|
||||||
encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);
|
buf.push('0');
|
||||||
}
|
}
|
||||||
|
if currentBlock / 10 == 0 {
|
||||||
final void encodeCompressedGtinWithoutAI(StringBuilder buf, int currentPos, int initialBufferPosition) {
|
buf.push('0');
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
int currentBlock = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10);
|
|
||||||
if (currentBlock / 100 == 0) {
|
|
||||||
buf.append('0');
|
|
||||||
}
|
}
|
||||||
if (currentBlock / 10 == 0) {
|
buf.push_str(¤tBlock.to_string());
|
||||||
buf.append('0');
|
|
||||||
}
|
|
||||||
buf.append(currentBlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
appendCheckDigit(buf, initialBufferPosition);
|
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;
|
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);
|
checkDigit = 10 - (checkDigit % 10);
|
||||||
if (checkDigit == 10) {
|
if checkDigit == 10 {
|
||||||
checkDigit = 0;
|
checkDigit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append(checkDigit);
|
buf.push_str(&checkDigit.to_string());
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -24,31 +24,33 @@
|
|||||||
* http://www.piramidepse.com/
|
* 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 Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||||
*/
|
*/
|
||||||
final class BlockParsedRXingResult {
|
pub struct BlockParsedRXingResult {
|
||||||
|
decodedInformation: Option<DecodedInformation>,
|
||||||
private final DecodedInformation decodedInformation;
|
finished: bool,
|
||||||
private final boolean finished;
|
}
|
||||||
|
impl BlockParsedRXingResult {
|
||||||
BlockParsedRXingResult() {
|
pub fn new() -> Self {
|
||||||
this(null, false);
|
Self::with_information(None, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockParsedRXingResult(DecodedInformation information, boolean finished) {
|
pub fn with_information(information: Option<DecodedInformation>, finished: bool) -> Self {
|
||||||
this.finished = finished;
|
Self {
|
||||||
this.decodedInformation = information;
|
decodedInformation: information,
|
||||||
|
finished,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DecodedInformation getDecodedInformation() {
|
pub fn getDecodedInformation(&self) -> &Option<DecodedInformation> {
|
||||||
return this.decodedInformation;
|
&self.decodedInformation
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isFinished() {
|
pub fn isFinished(&self) -> bool {
|
||||||
return this.finished;
|
self.finished
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,61 +23,62 @@
|
|||||||
*
|
*
|
||||||
* http://www.piramidepse.com/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
package com.google.zxing.oned.rss.expanded.decoders;
|
enum State {
|
||||||
|
NUMERIC,
|
||||||
|
ALPHA,
|
||||||
|
ISO_IEC_646,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
*/
|
*/
|
||||||
final class CurrentParsingState {
|
pub struct CurrentParsingState {
|
||||||
|
position: usize,
|
||||||
|
encoding: State,
|
||||||
|
}
|
||||||
|
|
||||||
private int position;
|
impl CurrentParsingState {
|
||||||
private State encoding;
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
private enum State {
|
position: 0,
|
||||||
NUMERIC,
|
encoding: State::NUMERIC,
|
||||||
ALPHA,
|
}
|
||||||
ISO_IEC_646
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentParsingState() {
|
pub fn getPosition(&self) -> usize {
|
||||||
this.position = 0;
|
self.position
|
||||||
this.encoding = State.NUMERIC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int getPosition() {
|
pub fn setPosition(&mut self, position: usize) {
|
||||||
return position;
|
self.position = position
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPosition(int position) {
|
pub fn incrementPosition(&mut self, delta: usize) {
|
||||||
this.position = position;
|
self.position += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
void incrementPosition(int delta) {
|
pub fn isAlpha(&self) -> bool {
|
||||||
position += delta;
|
self.encoding == State::ALPHA
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isAlpha() {
|
pub fn isNumeric(&self) -> bool {
|
||||||
return this.encoding == State.ALPHA;
|
self.encoding == State::NUMERIC
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isNumeric() {
|
pub fn isIsoIec646(&self) -> bool {
|
||||||
return this.encoding == State.NUMERIC;
|
self.encoding == State::ISO_IEC_646
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isIsoIec646() {
|
pub fn setNumeric(&mut self) {
|
||||||
return this.encoding == State.ISO_IEC_646;
|
self.encoding = State::NUMERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNumeric() {
|
pub fn setAlpha(&mut self) {
|
||||||
this.encoding = State.NUMERIC;
|
self.encoding = State::ALPHA;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAlpha() {
|
pub fn setIsoIec646(&mut self) {
|
||||||
this.encoding = State.ALPHA;
|
self.encoding = State::ISO_IEC_646;
|
||||||
}
|
|
||||||
|
|
||||||
void setIsoIec646() {
|
|
||||||
this.encoding = State.ISO_IEC_646;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,29 +24,33 @@
|
|||||||
* http://www.piramidepse.com/
|
* 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 Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||||
*/
|
*/
|
||||||
final class DecodedChar extends DecodedObject {
|
pub struct DecodedChar {
|
||||||
|
value: char,
|
||||||
private final char value;
|
newPosition: usize,
|
||||||
|
}
|
||||||
static final char FNC1 = '$'; // It's not in Alphanumeric neither in ISO/IEC 646 charset
|
impl DecodedObject for DecodedChar {
|
||||||
|
fn getNewPosition(&self) -> usize {
|
||||||
DecodedChar(int newPosition, char value) {
|
self.newPosition
|
||||||
super(newPosition);
|
}
|
||||||
this.value = value;
|
}
|
||||||
}
|
impl DecodedChar {
|
||||||
|
pub const FNC1: char = '$'; // It's not in Alphanumeric neither in ISO/IEC 646 charset
|
||||||
char getValue() {
|
|
||||||
return this.value;
|
pub fn new(newPosition: usize, value: char) -> Self {
|
||||||
}
|
Self { value, newPosition }
|
||||||
|
}
|
||||||
boolean isFNC1() {
|
|
||||||
return this.value == FNC1;
|
pub fn getValue(&self) -> char {
|
||||||
}
|
self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn isFNC1(&self) -> bool {
|
||||||
|
self.value == Self::FNC1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -24,50 +24,57 @@
|
|||||||
* http://www.piramidepse.com/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.zxing.oned.rss.expanded.decoders;
|
use super::DecodedObject;
|
||||||
|
|
||||||
import com.google.zxing.FormatException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||||
*/
|
*/
|
||||||
final class DecodedNumeric extends DecodedObject {
|
#[derive(Clone)]
|
||||||
|
pub struct DecodedInformation {
|
||||||
private final int firstDigit;
|
newPosition: usize,
|
||||||
private final int secondDigit;
|
newString: String,
|
||||||
|
remainingValue: u32,
|
||||||
static final int FNC1 = 10;
|
remaining: bool,
|
||||||
|
}
|
||||||
DecodedNumeric(int newPosition, int firstDigit, int secondDigit) throws FormatException {
|
|
||||||
super(newPosition);
|
impl DecodedObject for DecodedInformation {
|
||||||
|
fn getNewPosition(&self) -> usize {
|
||||||
if (firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10) {
|
self.newPosition
|
||||||
throw FormatException.getFormatInstance();
|
}
|
||||||
}
|
}
|
||||||
|
impl DecodedInformation {
|
||||||
this.firstDigit = firstDigit;
|
pub fn new(newPosition: usize, newString: String) -> Self {
|
||||||
this.secondDigit = secondDigit;
|
Self {
|
||||||
}
|
newPosition,
|
||||||
|
newString,
|
||||||
int getFirstDigit() {
|
remainingValue: 0,
|
||||||
return this.firstDigit;
|
remaining: false,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
int getSecondDigit() {
|
|
||||||
return this.secondDigit;
|
pub fn with_remaining_value(
|
||||||
}
|
newPosition: usize,
|
||||||
|
newString: String,
|
||||||
int getValue() {
|
remainingValue: u32,
|
||||||
return this.firstDigit * 10 + this.secondDigit;
|
) -> Self {
|
||||||
}
|
Self {
|
||||||
|
newPosition,
|
||||||
boolean isFirstDigitFNC1() {
|
newString,
|
||||||
return this.firstDigit == FNC1;
|
remainingValue,
|
||||||
}
|
remaining: true,
|
||||||
|
}
|
||||||
boolean isSecondDigitFNC1() {
|
}
|
||||||
return this.secondDigit == FNC1;
|
|
||||||
}
|
pub fn getNewString(&self) -> &str {
|
||||||
|
&self.newString
|
||||||
|
}
|
||||||
|
|
||||||
|
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/
|
* http://www.piramidepse.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.zxing.oned.rss.expanded.decoders;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
*/
|
*/
|
||||||
abstract class DecodedObject {
|
pub trait DecodedObject {
|
||||||
|
|
||||||
private final int newPosition;
|
fn getNewPosition(&self) -> usize;
|
||||||
|
|
||||||
DecodedObject(int newPosition) {
|
|
||||||
this.newPosition = newPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int getNewPosition() {
|
|
||||||
return this.newPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
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 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::{
|
use crate::{
|
||||||
common::{detector::MathUtils, BitArray},
|
common::{detector::MathUtils, BitArray},
|
||||||
oned::{OneDReader, one_d_reader},
|
oned::{one_d_reader, OneDReader},
|
||||||
BarcodeFormat, DecodeHintType, DecodingHintDictionary, Exceptions, RXingResult,
|
BarcodeFormat, DecodeHintType, DecodingHintDictionary, Exceptions, RXingResult,
|
||||||
RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint,
|
RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint,
|
||||||
};
|
};
|
||||||
@@ -298,14 +298,13 @@ impl RSS14Reader {
|
|||||||
// counters.fill(0);
|
// counters.fill(0);
|
||||||
counters.fill(0);
|
counters.fill(0);
|
||||||
|
|
||||||
|
|
||||||
if outsideChar {
|
if outsideChar {
|
||||||
one_d_reader::recordPatternInReverse(row, pattern.getStartEnd()[0], &mut counters[..])?;
|
one_d_reader::recordPatternInReverse(row, pattern.getStartEnd()[0], &mut counters[..])?;
|
||||||
} else {
|
} else {
|
||||||
one_d_reader::recordPattern(row, pattern.getStartEnd()[1], &mut counters[..])?;
|
one_d_reader::recordPattern(row, pattern.getStartEnd()[1], &mut counters[..])?;
|
||||||
// reverse it
|
// reverse it
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut j = counters.len() -1;
|
let mut j = counters.len() - 1;
|
||||||
while i < j {
|
while i < j {
|
||||||
// for (int i = 0, j = counters.length - 1; i < j; i++, j--) {
|
// for (int i = 0, j = counters.length - 1; i < j; i++, j--) {
|
||||||
let temp = counters[i];
|
let temp = counters[i];
|
||||||
@@ -468,7 +467,7 @@ impl RSS14Reader {
|
|||||||
let firstCounter = startEnd[0] - firstElementStart as usize;
|
let firstCounter = startEnd[0] - firstElementStart as usize;
|
||||||
let mut counters = &mut self.decodeFinderCounters;
|
let mut counters = &mut self.decodeFinderCounters;
|
||||||
let counter_len = counters.len();
|
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);
|
counters[1..counter_len].copy_from_slice(&slc);
|
||||||
// Make 'counters' hold 1-4
|
// Make 'counters' hold 1-4
|
||||||
// let counters = self.getDecodeFinderCounters();
|
// let counters = self.getDecodeFinderCounters();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use crate::{
|
|||||||
RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader,
|
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;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
@@ -433,8 +433,11 @@ pub trait UPCEANReader: OneDReader {
|
|||||||
counters[counterPosition] += 1;
|
counters[counterPosition] += 1;
|
||||||
} else {
|
} else {
|
||||||
if counterPosition == patternLength - 1 {
|
if counterPosition == patternLength - 1 {
|
||||||
if one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE)
|
if one_d_reader::patternMatchVariance(
|
||||||
< MAX_AVG_VARIANCE
|
counters,
|
||||||
|
pattern,
|
||||||
|
MAX_INDIVIDUAL_VARIANCE,
|
||||||
|
) < MAX_AVG_VARIANCE
|
||||||
{
|
{
|
||||||
return Ok([patternStart, x]);
|
return Ok([patternStart, x]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 ZXing authors
|
* Copyright 2008 ZXing authors
|
||||||
*
|
*
|
||||||
@@ -15,15 +14,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use rxing::{maxicode::MaxiCodeReader, BarcodeFormat, DecodeHintType, MultiFormatReader};
|
use rxing::{maxicode::MaxiCodeReader, BarcodeFormat, DecodeHintType, MultiFormatReader};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
#[test]
|
#[test]
|
||||||
fn rss14_black_box1_test_case() {
|
fn rss14_black_box1_test_case() {
|
||||||
let mut tester = common::AbstractBlackBoxTestCase::new(
|
let mut tester = common::AbstractBlackBoxTestCase::new(
|
||||||
"test_resources/blackbox/rss14-1",
|
"test_resources/blackbox/rss14-1",
|
||||||
MultiFormatReader::default(),
|
MultiFormatReader::default(),
|
||||||
@@ -35,11 +34,9 @@
|
|||||||
tester.add_test(6, 6, 180.0);
|
tester.add_test(6, 6, 180.0);
|
||||||
|
|
||||||
tester.test_black_box()
|
tester.test_black_box()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
#[test]
|
#[test]
|
||||||
@@ -55,6 +52,4 @@ fn rss14_black_box2_test_case() {
|
|||||||
tester.add_test_complex(3, 8, 0, 1, 180.0);
|
tester.add_test_complex(3, 8, 0, 1, 180.0);
|
||||||
|
|
||||||
tester.test_black_box()
|
tester.test_black_box()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user