tessl install tessl/github-zxing-cpp--zxing-cpp@2.3.0Open-source, multi-format linear/matrix barcode image processing library implemented in C++
ZXing-C++ uses a value-based error handling approach through the Error class. Instead of throwing exceptions for barcode decoding failures, errors are returned as part of the Barcode result.
class Error {
public:
enum class Type : uint8_t {
None = 0, // No error
Format = 1, // Format/decoding error
Checksum = 2, // Checksum validation failed
Unsupported = 3 // Unsupported feature
};
// Constructors
Error(); // Default no-error state
Error(Type type, std::string msg = {});
Error(const char* file, short line, Type type, std::string msg = {});
// Accessors
Type type() const;
const std::string& msg() const;
std::string location() const;
// Conversion
explicit operator bool() const; // True if error exists
// Comparison
bool operator==(const Error& other) const;
bool operator!=(const Error& other) const;
// Static convenience constants
static constexpr auto Format = Type::Format;
static constexpr auto Checksum = Type::Checksum;
static constexpr auto Unsupported = Type::Unsupported;
};
// Utility function
std::string ToString(const Error& e);No error occurred - the operation was successful:
auto barcode = ZXing::ReadBarcode(image);
if (barcode.error().type() == ZXing::Error::Type::None) {
std::cout << "Success: " << barcode.text() << "\n";
}
// More concise - check validity
if (barcode.isValid()) {
std::cout << "Success: " << barcode.text() << "\n";
}Format or decoding error - the barcode was detected but could not be decoded:
if (barcode.error().type() == ZXing::Error::Type::Format) {
std::cerr << "Format error: " << barcode.error().msg() << "\n";
}
// Or using static constant
if (barcode.error().type() == ZXing::Error::Format) {
std::cerr << "Decoding failed\n";
}Common format errors:
Checksum validation failed - the barcode was decoded but data integrity check failed:
if (barcode.error().type() == ZXing::Error::Type::Checksum) {
std::cerr << "Checksum error: " << barcode.error().msg() << "\n";
}
// Or using static constant
if (barcode.error().type() == ZXing::Error::Checksum) {
std::cerr << "Data integrity check failed\n";
}Checksum errors indicate:
returnErrors is enabledUnsupported feature encountered:
if (barcode.error().type() == ZXing::Error::Type::Unsupported) {
std::cerr << "Unsupported: " << barcode.error().msg() << "\n";
}Examples:
The simplest way to check for errors:
auto barcode = ZXing::ReadBarcode(image);
if (barcode.isValid()) {
// No error - safe to use barcode
std::cout << barcode.text() << "\n";
} else {
// Error occurred
std::cerr << "Error: " << barcode.error().msg() << "\n";
}The Error class converts to bool:
const ZXing::Error& error = barcode.error();
if (error) {
// Error exists
std::cerr << "Error type: " << (int)error.type() << "\n";
std::cerr << "Message: " << error.msg() << "\n";
} else {
// No error
std::cout << "Success\n";
}switch (barcode.error().type()) {
case ZXing::Error::Type::None:
std::cout << "Success: " << barcode.text() << "\n";
break;
case ZXing::Error::Type::Format:
std::cerr << "Decoding failed: " << barcode.error().msg() << "\n";
break;
case ZXing::Error::Type::Checksum:
std::cerr << "Checksum failed: " << barcode.error().msg() << "\n";
// Might still be usable depending on requirements
break;
case ZXing::Error::Type::Unsupported:
std::cerr << "Unsupported: " << barcode.error().msg() << "\n";
break;
}Error objects include descriptive messages:
const ZXing::Error& error = barcode.error();
if (error) {
std::string message = error.msg();
std::cout << "Error message: " << message << "\n";
// Convert entire error to string
std::string fullError = ZXing::ToString(error);
std::cout << "Full error: " << fullError << "\n";
}Messages typically include:
Errors can include source location information for debugging:
const ZXing::Error& error = barcode.error();
if (error) {
std::string location = error.location();
if (!location.empty()) {
std::cout << "Error at: " << location << "\n";
}
}Location format: "file:line"
By default, ReadBarcode() and ReadBarcodes() do not return barcodes with errors. Configure ReaderOptions to get partial results:
// Return barcodes even if they have errors
auto options = ZXing::ReaderOptions()
.setReturnErrors(true);
auto barcodes = ZXing::ReadBarcodes(image, options);
for (const auto& bc : barcodes) {
if (bc.isValid()) {
std::cout << "Valid: " << bc.text() << "\n";
} else {
// Error barcode returned
std::cerr << "Error: " << ZXing::ToString(bc.error()) << "\n";
// Might still have partial data
if (bc.error().type() == ZXing::Error::Type::Checksum) {
// Checksum failed but data was decoded
std::cout << "Unchecked content: " << bc.text() << "\n";
}
}
}Use cases for returnErrors:
Error creation is typically internal, but you can create errors for testing or extension:
// Create error with type and message
ZXing::Error err1(ZXing::Error::Type::Format, "Invalid barcode structure");
// Create error with location information
ZXing::Error err2(__FILE__, __LINE__, ZXing::Error::Type::Checksum,
"Checksum validation failed");
// No-error state
ZXing::Error noError; // Type::NoneFor internal use, macros are provided to automatically capture location:
// These macros are for library implementation, not public API
// FormatError("message")
// ChecksumError("message")
// UnsupportedError("message")ZXing::Error err1(ZXing::Error::Type::Format, "Error 1");
ZXing::Error err2(ZXing::Error::Type::Format, "Error 1");
ZXing::Error err3(ZXing::Error::Type::Checksum, "Error 2");
if (err1 == err2) {
std::cout << "Errors are equal\n"; // True - same type and message
}
if (err1 != err3) {
std::cout << "Errors are different\n"; // True - different types
}Comparison considers:
ZXing-C++ does not throw exceptions for normal barcode reading failures:
// This never throws for "no barcode found" or decoding failures
auto barcode = ZXing::ReadBarcode(image);
// Always safe to call
if (!barcode.isValid()) {
// Handle error gracefully
}Exceptions may be thrown for:
BarcodeFormatsFromString)auto barcode = ZXing::ReadBarcode(image);
// Always check before using
if (barcode.isValid()) {
processBarcode(barcode);
}auto barcode = ZXing::ReadBarcode(image);
if (!barcode.isValid()) {
switch (barcode.error().type()) {
case ZXing::Error::Format:
showMessage("Could not decode barcode. Please ensure it's not damaged.");
break;
case ZXing::Error::Checksum:
showMessage("Barcode appears corrupted. Please try again.");
break;
case ZXing::Error::Unsupported:
showMessage("This barcode format is not supported.");
break;
default:
showMessage("No barcode detected in image.");
break;
}
}void logBarcode(const ZXing::Barcode& barcode) {
if (barcode.isValid()) {
LOG_INFO << "Decoded: " << ZXing::ToString(barcode.format())
<< " - " << barcode.text();
} else {
LOG_ERROR << "Failed to decode barcode: "
<< "Type=" << (int)barcode.error().type()
<< " Message=" << barcode.error().msg()
<< " Location=" << barcode.error().location();
}
}Checksum errors mean data was decoded but may be corrupted:
if (barcode.error().type() == ZXing::Error::Type::Checksum) {
// Data is available but unverified
std::string data = barcode.text();
// Decide based on application requirements
if (isLowRiskOperation()) {
// Use data anyway
processData(data);
warnUser("Checksum failed - data may be incorrect");
} else {
// Reject data
showError("Data integrity check failed - please scan again");
}
}auto barcodes = ZXing::ReadBarcodes(image);
int validCount = 0;
int errorCount = 0;
for (const auto& bc : barcodes) {
if (bc.isValid()) {
++validCount;
processBarcode(bc);
} else {
++errorCount;
logError(bc.error());
}
}
std::cout << "Valid: " << validCount << ", Errors: " << errorCount << "\n";