comparison mupdf-source/thirdparty/zxing-cpp/core/src/ZXingC.cpp @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*
2 * Copyright 2023 siiky
3 * Copyright 2023 Axel Waggershauser
4 */
5 // SPDX-License-Identifier: Apache-2.0
6
7 #include "ZXingC.h"
8
9 #include "ZXingCpp.h"
10 #include "ZXConfig.h"
11
12 #if __has_include("Version.h")
13 #include "Version.h"
14 #else // this is mainly a workaround for a missing autogenerated Version.h in the XCode/CocoaPods corner
15 #define ZXING_VERSION_STR "undefined"
16 #endif
17
18 #include <cstdlib>
19 #include <exception>
20 #include <string>
21 #include <string_view>
22 #include <utility>
23
24 using namespace ZXing;
25
26 static ZX_THREAD_LOCAL std::string lastErrorMsg;
27 static Barcodes emptyBarcodes{}; // used to prevent new heap allocation for each empty result
28
29 template<typename R, typename T> R transmute_cast(const T& v) noexcept
30 {
31 static_assert(sizeof(T) == sizeof(R));
32 return *(const R*)(&v);
33 }
34
35 template<typename C, typename P = typename C::pointer>
36 P copy(const C& c) noexcept
37 {
38 auto ret = (P)malloc(c.size() + 1);
39 if (ret) {
40 memcpy(ret, c.data(), c.size());
41 ret[c.size()] = 0;
42 }
43 return ret;
44 }
45
46 static uint8_t* copy(const ByteArray& ba, int* len) noexcept
47 {
48 // for convencience and as a safety measure, we NULL terminate even byte arrays
49 auto ret = copy(ba);
50 if (len)
51 *len = ret ? Size(ba) : 0;
52 return ret;
53 }
54
55 #define ZX_CHECK( GOOD, MSG ) \
56 if (!(GOOD)) { \
57 lastErrorMsg = MSG; \
58 return {}; \
59 }
60
61 #define ZX_CATCH(...) \
62 catch (std::exception & e) { \
63 lastErrorMsg = e.what(); \
64 } catch (...) { \
65 lastErrorMsg = "Unknown error"; \
66 } \
67 return __VA_ARGS__;
68
69 #define ZX_TRY(...) \
70 try { \
71 return __VA_ARGS__; \
72 } \
73 ZX_CATCH({})
74
75
76 extern "C" {
77 /*
78 * ZXing/ImageView.h
79 */
80
81 ZXing_ImageView* ZXing_ImageView_new(const uint8_t* data, int width, int height, ZXing_ImageFormat format, int rowStride,
82 int pixStride)
83 {
84 ImageFormat cppformat = static_cast<ImageFormat>(format);
85 ZX_TRY(new ImageView(data, width, height, cppformat, rowStride, pixStride))
86 }
87
88 ZXing_ImageView* ZXing_ImageView_new_checked(const uint8_t* data, int size, int width, int height, ZXing_ImageFormat format,
89 int rowStride, int pixStride)
90 {
91 ImageFormat cppformat = static_cast<ImageFormat>(format);
92 ZX_TRY(new ImageView(data, size, width, height, cppformat, rowStride, pixStride))
93 }
94
95 void ZXing_ImageView_delete(ZXing_ImageView* iv)
96 {
97 delete iv;
98 }
99
100 void ZXing_ImageView_crop(ZXing_ImageView* iv, int left, int top, int width, int height)
101 {
102 *iv = iv->cropped(left, top, width, height);
103 }
104
105 void ZXing_ImageView_rotate(ZXing_ImageView* iv, int degree)
106 {
107 *iv = iv->rotated(degree);
108 }
109
110 void ZXing_Image_delete(ZXing_Image* img)
111 {
112 delete img;
113 }
114
115 const uint8_t* ZXing_Image_data(const ZXing_Image* img)
116 {
117 return img->data();
118 }
119
120 int ZXing_Image_width(const ZXing_Image* img)
121 {
122 return img->width();
123 }
124
125 int ZXing_Image_height(const ZXing_Image* img)
126 {
127 return img->height();
128 }
129
130 ZXing_ImageFormat ZXing_Image_format(const ZXing_Image* img)
131 {
132 return static_cast<ZXing_ImageFormat>(img->format());
133 }
134
135 /*
136 * ZXing/BarcodeFormat.h
137 */
138
139 ZXing_BarcodeFormats ZXing_BarcodeFormatsFromString(const char* str)
140 {
141 if (!str)
142 return {};
143 try {
144 return transmute_cast<ZXing_BarcodeFormats>(BarcodeFormatsFromString(str));
145 }
146 ZX_CATCH(ZXing_BarcodeFormat_Invalid)
147 }
148
149 ZXing_BarcodeFormat ZXing_BarcodeFormatFromString(const char* str)
150 {
151 ZXing_BarcodeFormat res = ZXing_BarcodeFormatsFromString(str);
152 return BitHacks::CountBitsSet(res) == 1 ? res : ZXing_BarcodeFormat_Invalid;
153 }
154
155 char* ZXing_BarcodeFormatToString(ZXing_BarcodeFormat format)
156 {
157 return copy(ToString(static_cast<BarcodeFormat>(format)));
158 }
159
160 /*
161 * ZXing/ZXingCpp.h
162 */
163
164
165 #ifdef ZXING_EXPERIMENTAL_API
166 ZXing_BarcodeFormats ZXing_SupportedBarcodeFormats(ZXing_Operation op)
167 {
168 return transmute_cast<ZXing_BarcodeFormats>(SupportedBarcodeFormats(static_cast<Operation>(op)));
169 }
170 #endif
171
172 /*
173 * ZXing/Barcode.h
174 */
175
176 char* ZXing_ContentTypeToString(ZXing_ContentType type)
177 {
178 return copy(ToString(static_cast<ContentType>(type)));
179 }
180
181 char* ZXing_PositionToString(ZXing_Position position)
182 {
183 return copy(ToString(transmute_cast<Position>(position)));
184 }
185
186
187 bool ZXing_Barcode_isValid(const ZXing_Barcode* barcode)
188 {
189 return barcode != NULL && barcode->isValid();
190 }
191
192 ZXing_ErrorType ZXing_Barcode_errorType(const ZXing_Barcode* barcode)
193 {
194 return static_cast<ZXing_ErrorType>(barcode->error().type());
195 }
196
197 char* ZXing_Barcode_errorMsg(const ZXing_Barcode* barcode)
198 {
199 return copy(ToString(barcode->error()));
200 }
201
202 uint8_t* ZXing_Barcode_bytes(const ZXing_Barcode* barcode, int* len)
203 {
204 return copy(barcode->bytes(), len);
205 }
206
207 uint8_t* ZXing_Barcode_bytesECI(const ZXing_Barcode* barcode, int* len)
208 {
209 return copy(barcode->bytesECI(), len);
210 }
211
212 #define ZX_GETTER(TYPE, GETTER, TRANS) \
213 TYPE ZXing_Barcode_##GETTER(const ZXing_Barcode* barcode) { return TRANS(barcode->GETTER()); }
214
215 ZX_GETTER(ZXing_BarcodeFormat, format, static_cast<ZXing_BarcodeFormat>)
216 ZX_GETTER(ZXing_ContentType, contentType, static_cast<ZXing_ContentType>)
217 ZX_GETTER(char*, text, copy)
218 ZX_GETTER(char*, ecLevel, copy)
219 ZX_GETTER(char*, symbologyIdentifier, copy)
220 ZX_GETTER(ZXing_Position, position, transmute_cast<ZXing_Position>)
221
222 ZX_GETTER(int, orientation,)
223 ZX_GETTER(bool, hasECI,)
224 ZX_GETTER(bool, isInverted,)
225 ZX_GETTER(bool, isMirrored,)
226 ZX_GETTER(int, lineCount,)
227
228 void ZXing_Barcode_delete(ZXing_Barcode* barcode)
229 {
230 delete barcode;
231 }
232
233 void ZXing_Barcodes_delete(ZXing_Barcodes* barcodes)
234 {
235 if (barcodes != &emptyBarcodes)
236 delete barcodes;
237 }
238
239 int ZXing_Barcodes_size(const ZXing_Barcodes* barcodes)
240 {
241 return barcodes ? Size(*barcodes) : 0;
242 }
243
244 const ZXing_Barcode* ZXing_Barcodes_at(const ZXing_Barcodes* barcodes, int i)
245 {
246 if (!barcodes || i < 0 || i >= Size(*barcodes))
247 return NULL;
248 return &(*barcodes)[i];
249 }
250
251 ZXing_Barcode* ZXing_Barcodes_move(ZXing_Barcodes* barcodes, int i)
252 {
253 if (!barcodes || i < 0 || i >= Size(*barcodes))
254 return NULL;
255
256 ZX_TRY(new Barcode(std::move((*barcodes)[i])));
257 }
258
259 /*
260 * ZXing/ReaderOptions.h
261 */
262
263 ZXing_ReaderOptions* ZXing_ReaderOptions_new()
264 {
265 ZX_TRY(new ReaderOptions());
266 }
267
268 void ZXing_ReaderOptions_delete(ZXing_ReaderOptions* opts)
269 {
270 delete opts;
271 }
272
273 #define ZX_PROPERTY(TYPE, GETTER, SETTER) \
274 TYPE ZXing_ReaderOptions_get##SETTER(const ZXing_ReaderOptions* opts) { return opts->GETTER(); } \
275 void ZXing_ReaderOptions_set##SETTER(ZXing_ReaderOptions* opts, TYPE val) { opts->set##SETTER(val); }
276
277 ZX_PROPERTY(bool, tryHarder, TryHarder)
278 ZX_PROPERTY(bool, tryRotate, TryRotate)
279 ZX_PROPERTY(bool, tryInvert, TryInvert)
280 ZX_PROPERTY(bool, tryDownscale, TryDownscale)
281 ZX_PROPERTY(bool, isPure, IsPure)
282 ZX_PROPERTY(bool, returnErrors, ReturnErrors)
283 ZX_PROPERTY(int, minLineCount, MinLineCount)
284 ZX_PROPERTY(int, maxNumberOfSymbols, MaxNumberOfSymbols)
285
286 #undef ZX_PROPERTY
287
288 void ZXing_ReaderOptions_setFormats(ZXing_ReaderOptions* opts, ZXing_BarcodeFormats formats)
289 {
290 opts->setFormats(static_cast<BarcodeFormat>(formats));
291 }
292
293 ZXing_BarcodeFormats ZXing_ReaderOptions_getFormats(const ZXing_ReaderOptions* opts)
294 {
295 auto v = opts->formats();
296 return transmute_cast<ZXing_BarcodeFormats>(v);
297 }
298
299 #define ZX_ENUM_PROPERTY(TYPE, GETTER, SETTER) \
300 ZXing_##TYPE ZXing_ReaderOptions_get##SETTER(const ZXing_ReaderOptions* opts) { return static_cast<ZXing_##TYPE>(opts->GETTER()); } \
301 void ZXing_ReaderOptions_set##SETTER(ZXing_ReaderOptions* opts, ZXing_##TYPE val) { opts->set##SETTER(static_cast<TYPE>(val)); }
302
303 ZX_ENUM_PROPERTY(Binarizer, binarizer, Binarizer)
304 ZX_ENUM_PROPERTY(EanAddOnSymbol, eanAddOnSymbol, EanAddOnSymbol)
305 ZX_ENUM_PROPERTY(TextMode, textMode, TextMode)
306
307
308 /*
309 * ZXing/ReadBarcode.h
310 */
311
312 ZXing_Barcodes* ZXing_ReadBarcodes(const ZXing_ImageView* iv, const ZXing_ReaderOptions* opts)
313 {
314 ZX_CHECK(iv, "ImageView param is NULL")
315 try {
316 auto res = ReadBarcodes(*iv, opts ? *opts : ReaderOptions{});
317 return res.empty() ? &emptyBarcodes : new Barcodes(std::move(res));
318 }
319 ZX_CATCH(NULL);
320 }
321
322
323 #ifdef ZXING_EXPERIMENTAL_API
324 /*
325 * ZXing/WriteBarcode.h
326 */
327
328 ZXing_CreatorOptions* ZXing_CreatorOptions_new(ZXing_BarcodeFormat format)
329 {
330 ZX_TRY(new CreatorOptions(static_cast<BarcodeFormat>(format)));
331 }
332
333 void ZXing_CreatorOptions_delete(ZXing_CreatorOptions* opts)
334 {
335 delete opts;
336 }
337
338 #define ZX_PROPERTY(TYPE, GETTER, SETTER) \
339 TYPE ZXing_CreatorOptions_get##SETTER(const ZXing_CreatorOptions* opts) { return opts->GETTER(); } \
340 void ZXing_CreatorOptions_set##SETTER(ZXing_CreatorOptions* opts, TYPE val) { opts->GETTER(val); }
341
342 ZX_PROPERTY(bool, readerInit, ReaderInit)
343 ZX_PROPERTY(bool, forceSquareDataMatrix, ForceSquareDataMatrix)
344
345 #undef ZX_PROPERTY
346
347 //ZX_PROPERTY(BarcodeFormat, format, Format)
348
349 char* ZXing_CreatorOptions_getEcLevel(const ZXing_CreatorOptions* opts)
350 {
351 return copy(opts->ecLevel());
352 }
353
354 void ZXing_CreatorOptions_setEcLevel(ZXing_CreatorOptions* opts, const char* val)
355 {
356 opts->ecLevel(val);
357 }
358
359
360 ZXing_WriterOptions* ZXing_WriterOptions_new()
361 {
362 ZX_TRY(new ZXing_WriterOptions());
363 }
364
365 void ZXing_WriterOptions_delete(ZXing_WriterOptions* opts)
366 {
367 delete opts;
368 }
369
370 #define ZX_PROPERTY(TYPE, GETTER, SETTER) \
371 TYPE ZXing_WriterOptions_get##SETTER(const ZXing_WriterOptions* opts) { return opts->GETTER(); } \
372 void ZXing_WriterOptions_set##SETTER(ZXing_WriterOptions* opts, TYPE val) { opts->GETTER(val); }
373
374 ZX_PROPERTY(int, scale, Scale)
375 ZX_PROPERTY(int, sizeHint, SizeHint)
376 ZX_PROPERTY(int, rotate, Rotate)
377 ZX_PROPERTY(bool, withHRT, WithHRT)
378 ZX_PROPERTY(bool, withQuietZones, WithQuietZones)
379
380 #undef ZX_PROPERTY
381
382 ZXing_Barcode* ZXing_CreateBarcodeFromText(const char* data, int size, const ZXing_CreatorOptions* opts)
383 {
384 ZX_CHECK(data && opts, "Data and/or options param in CreateBarcodeFromText is NULL")
385 ZX_TRY(new Barcode(CreateBarcodeFromText({data, size ? static_cast<size_t>(size) : strlen(data)}, *opts));)
386 }
387
388 ZXing_Barcode* ZXing_CreateBarcodeFromBytes(const void* data, int size, const ZXing_CreatorOptions* opts)
389 {
390 ZX_CHECK(data && size && opts, "Data and/or options param in CreateBarcodeFromBytes is NULL")
391 ZX_TRY(new Barcode(CreateBarcodeFromBytes(data, size, *opts)))
392 }
393
394 char* ZXing_WriteBarcodeToSVG(const ZXing_Barcode* barcode, const ZXing_WriterOptions* opts)
395 {
396 ZX_CHECK(barcode, "Barcode param in WriteBarcodeToSVG is NULL")
397 ZX_TRY(copy(opts ? WriteBarcodeToSVG(*barcode, *opts) : WriteBarcodeToSVG(*barcode)))
398 }
399
400 ZXing_Image* ZXing_WriteBarcodeToImage(const ZXing_Barcode* barcode, const ZXing_WriterOptions* opts)
401 {
402 ZX_CHECK(barcode, "Barcode param in WriteBarcodeToSVG is NULL")
403 ZX_TRY(new Image(opts ? WriteBarcodeToImage(*barcode, *opts) : WriteBarcodeToImage(*barcode)))
404 }
405
406 #endif
407
408 /*
409 * ZXingC.h
410 */
411
412 char* ZXing_LastErrorMsg()
413 {
414 if (lastErrorMsg.empty())
415 return NULL;
416
417 return copy(std::exchange(lastErrorMsg, {}));
418 }
419
420 const char* ZXing_Version()
421 {
422 return ZXING_VERSION_STR;
423 }
424
425 void ZXing_free(void* ptr)
426 {
427 if (ptr != ZXing_Version())
428 free(ptr);
429 }
430
431 } // extern "C"