Skip to content

Commit

Permalink
C-API: drop ZXing_ReadBarcode() + new heap allocation optimization
Browse files Browse the repository at this point in the history
Use a trick from the C# playbook: return a static empty vector that
does not need to be allocated and deleted on every call.
  • Loading branch information
axxel committed Dec 28, 2024
1 parent 7bed1d8 commit a76ba53
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 24 deletions.
31 changes: 9 additions & 22 deletions core/src/ZXingC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using namespace ZXing;

static thread_local std::string lastErrorMsg;
static Barcodes emptyBarcodes{}; // used to prevent new heap allocation for each empty result

template<typename R, typename T> R transmute_cast(const T& v) noexcept
{
Expand Down Expand Up @@ -66,19 +67,6 @@ static uint8_t* copy(const ByteArray& ba, int* len) noexcept
ZX_CATCH({})


static std::tuple<Barcodes, bool> ReadBarcodesAndSetLastError(const ZXing_ImageView* iv, const ZXing_ReaderOptions* opts,
int maxSymbols)
{
ZX_CHECK(iv, "ImageView param is NULL")
try {
auto o = opts ? *opts : ReaderOptions{};
if (maxSymbols)
o.setMaxNumberOfSymbols(maxSymbols);
return {ReadBarcodes(*iv, o), true};
}
ZX_CATCH({Barcodes{}, false})
}

extern "C" {
/*
* ZXing/ImageView.h
Expand Down Expand Up @@ -238,7 +226,8 @@ void ZXing_Barcode_delete(ZXing_Barcode* barcode)

void ZXing_Barcodes_delete(ZXing_Barcodes* barcodes)
{
delete barcodes;
if (barcodes != &emptyBarcodes)
delete barcodes;
}

int ZXing_Barcodes_size(const ZXing_Barcodes* barcodes)
Expand Down Expand Up @@ -314,16 +303,14 @@ ZX_ENUM_PROPERTY(TextMode, textMode, TextMode)
* ZXing/ReadBarcode.h
*/

ZXing_Barcode* ZXing_ReadBarcode(const ZXing_ImageView* iv, const ZXing_ReaderOptions* opts)
{
auto [res, ok] = ReadBarcodesAndSetLastError(iv, opts, 1);
return !res.empty() ? new Barcode(std::move(res.front())) : NULL;
}

ZXing_Barcodes* ZXing_ReadBarcodes(const ZXing_ImageView* iv, const ZXing_ReaderOptions* opts)
{
auto [res, ok] = ReadBarcodesAndSetLastError(iv, opts, 0);
return !res.empty() || ok ? new Barcodes(std::move(res)) : NULL;
ZX_CHECK(iv, "ImageView param is NULL")
try {
auto res = ReadBarcodes(*iv, opts ? *opts : ReaderOptions{});
return res.empty() ? &emptyBarcodes : new Barcodes(std::move(res));
}
ZX_CATCH(NULL);
}


Expand Down
1 change: 0 additions & 1 deletion core/src/ZXingC.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ int ZXing_ReaderOptions_getMaxNumberOfSymbols(const ZXing_ReaderOptions* opts);
*/

/** Note: opts is optional, i.e. it can be NULL, which will imply default settings. */
ZXing_Barcode* ZXing_ReadBarcode(const ZXing_ImageView* iv, const ZXing_ReaderOptions* opts);
ZXing_Barcodes* ZXing_ReadBarcodes(const ZXing_ImageView* iv, const ZXing_ReaderOptions* opts);

#ifdef ZXING_EXPERIMENTAL_API
Expand Down
1 change: 0 additions & 1 deletion wrappers/rust/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ extern "C" {
pub fn ZXing_ReaderOptions_getTextMode(opts: *const ZXing_ReaderOptions) -> ZXing_TextMode;
pub fn ZXing_ReaderOptions_getMinLineCount(opts: *const ZXing_ReaderOptions) -> ::core::ffi::c_int;
pub fn ZXing_ReaderOptions_getMaxNumberOfSymbols(opts: *const ZXing_ReaderOptions) -> ::core::ffi::c_int;
pub fn ZXing_ReadBarcode(iv: *const ZXing_ImageView, opts: *const ZXing_ReaderOptions) -> *mut ZXing_Barcode;
pub fn ZXing_ReadBarcodes(iv: *const ZXing_ImageView, opts: *const ZXing_ReaderOptions) -> *mut ZXing_Barcodes;
pub fn ZXing_CreatorOptions_new(format: ZXing_BarcodeFormat) -> *mut ZXing_CreatorOptions;
pub fn ZXing_CreatorOptions_delete(opts: *mut ZXing_CreatorOptions);
Expand Down

0 comments on commit a76ba53

Please sign in to comment.