Skip to content

Commit

Permalink
DMDecoder: keep on decoding if a format error occurs
Browse files Browse the repository at this point in the history
This is inspired by the discussion in zxing-cpp#774. The idea is to "get as much
information out of the barcode as possible", even if a format error (like
an invalid code word) or readerInit flag at the wrong position occurs. This
still results in an error condition but the user might still find value in
interpreting the (completely) decoded message.
  • Loading branch information
axxel committed Apr 28, 2024
1 parent e3672fd commit 9d3b765
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 10 deletions.
17 changes: 12 additions & 5 deletions core/src/datamatrix/DMDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,18 @@ DecoderResult Decode(ByteArray&& bytes, const bool isDMRE)
int firstFNC1Position = 1;
Shift128 upperShift;

auto setError = [&error](Error&& e) {
// return only the first error but keep on decoding if possible
if (!error)
error = std::move(e);
};

// See ISO 16022:2006, 5.2.3 and Annex C, Table C.2
try {
while (!done && bits.available() >= 8) {
int oneByte = bits.readBits(8);
switch (oneByte) {
case 0: throw FormatError("invalid 0 code word");
case 0: setError(FormatError("invalid 0 code word")); break;
case 129: done = true; break; // Pad -> we are done, ignore the rest of the bits
case 230: DecodeC40OrTextSegment(bits, result, Mode::C40); break;
case 231: DecodeBase256Segment(bits, result); break;
Expand All @@ -307,13 +313,13 @@ DecoderResult Decode(ByteArray&& bytes, const bool isDMRE)
break;
case 233: // Structured Append
if (!firstCodeword) // Must be first ISO 16022:2006 5.6.1
throw FormatError("structured append tag must be first code word");
setError(FormatError("structured append tag must be first code word"));
ParseStructuredAppend(bits, sai);
firstFNC1Position = 5;
break;
case 234: // Reader Programming
if (!firstCodeword) // Must be first ISO 16022:2006 5.2.4.9
throw FormatError("reader programming tag must be first code word");
setError(FormatError("reader programming tag must be first code word"));
readerInit = true;
break;
case 235: upperShift.set = true; break; // Upper Shift (shift to Extended ASCII)
Expand All @@ -338,13 +344,14 @@ DecoderResult Decode(ByteArray&& bytes, const bool isDMRE)
// work around encoders that use unlatch to ASCII as last code word (ask upstream)
if (oneByte == 254 && bits.available() == 0)
break;
throw FormatError("invalid code word");
setError(FormatError("invalid code word"));
break;
}
}
firstCodeword = false;
}
} catch (Error e) {
error = std::move(e);
setError(std::move(e));
}

result.append(resultTrailer);
Expand Down
7 changes: 2 additions & 5 deletions test/unit/datamatrix/DMDecodedBitStreamParserTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ TEST(DMDecodeTest, StructuredAppend)

// Structured Append "233" must be first ISO 16022:2006 5.6.1
EXPECT_FALSE(parse({50, 233, 42, 1, 1}).isValid());
EXPECT_EQ(info({50, 233, 42, 1, 1}).index, -1);

// ISO/IEC 16022:2006 5.6.2 sequence indicator example
EXPECT_TRUE(parse({233, 42, 1, 1, 50}).isValid());
EXPECT_EQ(info({233, 42, 1, 1, 50}).index, 2); // 1-based position 3 == index 2
EXPECT_EQ(info({233, 42, 1, 1, 50}).count, 7);
EXPECT_EQ(info({233, 42, 1, 1, 50}).id, "257");
Expand Down Expand Up @@ -247,18 +247,15 @@ TEST(DMDecodeTest, ReaderInit)
EXPECT_TRUE(parse({50}).isValid());

// Reader Programming "234" must be first ISO 16022:2006 5.2.4.9
EXPECT_FALSE(parse({50, 234}).readerInit());
EXPECT_FALSE(parse({50, 234}).isValid());

// Set
EXPECT_TRUE(parse({234, 50}).readerInit());
EXPECT_TRUE(parse({234, 50}).isValid());
EXPECT_TRUE(parse({234, 50}).readerInit());

EXPECT_FALSE(parse({235, 234, 50}).readerInit()); // Upper Shift first
EXPECT_FALSE(parse({235, 234, 50}).isValid());

// Can't be used with Structured Append "233"
EXPECT_TRUE(parse({233, 42, 1, 1, 50}).isValid()); // Null
EXPECT_FALSE(parse({233, 42, 1, 1, 234, 50}).readerInit());
EXPECT_FALSE(parse({233, 42, 1, 1, 234, 50}).isValid());
}

0 comments on commit 9d3b765

Please sign in to comment.