1 /*------------------------------------------------------------------------
2 * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
3 *
4 * This file is part of the ZBar Bar Code Reader.
5 *
6 * The ZBar Bar Code Reader is free software; you can redistribute it
7 * and/or modify it under the terms of the GNU Lesser Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * The ZBar Bar Code Reader is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser Public License
17 * along with the ZBar Bar Code Reader; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301 USA
20 *
21 * http://sourceforge.net/projects/zbar
22 *------------------------------------------------------------------------*/
23
24 #include <config.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include <zbar.h>
30 #include "symbol.h"
31
zbar_get_symbol_name(zbar_symbol_type_t sym)32 const char *zbar_get_symbol_name (zbar_symbol_type_t sym)
33 {
34 switch(sym & ZBAR_SYMBOL) {
35 case ZBAR_EAN2: return("EAN-2");
36 case ZBAR_EAN5: return("EAN-5");
37 case ZBAR_EAN8: return("EAN-8");
38 case ZBAR_UPCE: return("UPC-E");
39 case ZBAR_ISBN10: return("ISBN-10");
40 case ZBAR_UPCA: return("UPC-A");
41 case ZBAR_EAN13: return("EAN-13");
42 case ZBAR_ISBN13: return("ISBN-13");
43 case ZBAR_COMPOSITE: return("COMPOSITE");
44 case ZBAR_I25: return("I2/5");
45 case ZBAR_DATABAR: return("DataBar");
46 case ZBAR_DATABAR_EXP: return("DataBar-Exp");
47 case ZBAR_CODABAR: return("Codabar");
48 case ZBAR_CODE39: return("CODE-39");
49 case ZBAR_CODE93: return("CODE-93");
50 case ZBAR_CODE128: return("CODE-128");
51 case ZBAR_PDF417: return("PDF417");
52 case ZBAR_QRCODE: return("QR-Code");
53 case ZBAR_SQCODE: return("SQ-Code");
54 default: return("UNKNOWN");
55 }
56 }
57
zbar_get_addon_name(zbar_symbol_type_t sym)58 const char *zbar_get_addon_name (zbar_symbol_type_t sym)
59 {
60 return("");
61 }
62
zbar_get_config_name(zbar_config_t cfg)63 const char *zbar_get_config_name (zbar_config_t cfg)
64 {
65 switch(cfg) {
66 case ZBAR_CFG_ENABLE: return("ENABLE");
67 case ZBAR_CFG_ADD_CHECK: return("ADD_CHECK");
68 case ZBAR_CFG_EMIT_CHECK: return("EMIT_CHECK");
69 case ZBAR_CFG_ASCII: return("ASCII");
70 case ZBAR_CFG_BINARY: return("BINARY");
71 case ZBAR_CFG_MIN_LEN: return("MIN_LEN");
72 case ZBAR_CFG_MAX_LEN: return("MAX_LEN");
73 case ZBAR_CFG_UNCERTAINTY: return("UNCERTAINTY");
74 case ZBAR_CFG_POSITION: return("POSITION");
75 case ZBAR_CFG_X_DENSITY: return("X_DENSITY");
76 case ZBAR_CFG_Y_DENSITY: return("Y_DENSITY");
77 default: return("");
78 }
79 }
80
zbar_get_modifier_name(zbar_modifier_t mod)81 const char *zbar_get_modifier_name (zbar_modifier_t mod)
82 {
83 switch(mod) {
84 case ZBAR_MOD_GS1: return("GS1");
85 case ZBAR_MOD_AIM: return("AIM");
86 default: return("");
87 }
88 }
89
zbar_get_orientation_name(zbar_orientation_t orient)90 const char *zbar_get_orientation_name (zbar_orientation_t orient)
91 {
92 switch(orient) {
93 case ZBAR_ORIENT_UP: return("UP");
94 case ZBAR_ORIENT_RIGHT: return("RIGHT");
95 case ZBAR_ORIENT_DOWN: return("DOWN");
96 case ZBAR_ORIENT_LEFT: return("LEFT");
97 default: return("UNKNOWN");
98 }
99 }
100
_zbar_get_symbol_hash(zbar_symbol_type_t sym)101 int _zbar_get_symbol_hash (zbar_symbol_type_t sym)
102 {
103 static const signed char hash[ZBAR_CODE128 + 1] = {
104 [0 ... ZBAR_CODE128] = -1,
105
106 /* [ZBAR_FOO] = 0, is empty */
107 [ZBAR_SQCODE] = 1,
108 [ZBAR_CODE128] = 2,
109 [ZBAR_EAN13] = 3,
110 [ZBAR_UPCA] = 4,
111 [ZBAR_EAN8] = 5,
112 [ZBAR_UPCE] = 6,
113 [ZBAR_ISBN13] = 7,
114 [ZBAR_ISBN10] = 8,
115 [ZBAR_CODE39] = 9,
116 [ZBAR_I25] = 10,
117 [ZBAR_PDF417] = 11,
118 [ZBAR_QRCODE] = 12,
119 [ZBAR_DATABAR] = 13,
120 [ZBAR_DATABAR_EXP] = 14,
121 [ZBAR_CODE93] = 15,
122 [ZBAR_EAN2] = 16,
123 [ZBAR_EAN5] = 17,
124 [ZBAR_COMPOSITE] = 18,
125 [ZBAR_CODABAR] = 19,
126
127 /* Please update NUM_SYMS accordingly */
128 };
129 int h;
130
131 assert (sym >= ZBAR_PARTIAL && sym <= ZBAR_CODE128);
132
133 h = hash[sym];
134 assert (h >= 0 && h < NUM_SYMS);
135
136 return h;
137 }
138
_zbar_symbol_free(zbar_symbol_t * sym)139 void _zbar_symbol_free (zbar_symbol_t *sym)
140 {
141 if(sym->syms) {
142 zbar_symbol_set_ref(sym->syms, -1);
143 sym->syms = NULL;
144 }
145 if(sym->pts)
146 free(sym->pts);
147 if(sym->data_alloc && sym->data)
148 free(sym->data);
149 free(sym);
150 }
151
zbar_symbol_ref(const zbar_symbol_t * sym,int refs)152 void zbar_symbol_ref (const zbar_symbol_t *sym,
153 int refs)
154 {
155 zbar_symbol_t *ncsym = (zbar_symbol_t*)sym;
156 _zbar_symbol_refcnt(ncsym, refs);
157 }
158
zbar_symbol_get_type(const zbar_symbol_t * sym)159 zbar_symbol_type_t zbar_symbol_get_type (const zbar_symbol_t *sym)
160 {
161 return(sym->type);
162 }
163
zbar_symbol_get_configs(const zbar_symbol_t * sym)164 unsigned int zbar_symbol_get_configs (const zbar_symbol_t *sym)
165 {
166 return(sym->configs);
167 }
168
zbar_symbol_get_modifiers(const zbar_symbol_t * sym)169 unsigned int zbar_symbol_get_modifiers (const zbar_symbol_t *sym)
170 {
171 return(sym->modifiers);
172 }
173
zbar_symbol_get_data(const zbar_symbol_t * sym)174 const char *zbar_symbol_get_data (const zbar_symbol_t *sym)
175 {
176 return(sym->data);
177 }
178
zbar_symbol_get_data_length(const zbar_symbol_t * sym)179 unsigned int zbar_symbol_get_data_length (const zbar_symbol_t *sym)
180 {
181 return(sym->datalen);
182 }
183
zbar_symbol_get_count(const zbar_symbol_t * sym)184 int zbar_symbol_get_count (const zbar_symbol_t *sym)
185 {
186 return(sym->cache_count);
187 }
188
zbar_symbol_get_quality(const zbar_symbol_t * sym)189 int zbar_symbol_get_quality (const zbar_symbol_t *sym)
190 {
191 return(sym->quality);
192 }
193
zbar_symbol_get_loc_size(const zbar_symbol_t * sym)194 unsigned zbar_symbol_get_loc_size (const zbar_symbol_t *sym)
195 {
196 return(sym->npts);
197 }
198
zbar_symbol_get_loc_x(const zbar_symbol_t * sym,unsigned idx)199 int zbar_symbol_get_loc_x (const zbar_symbol_t *sym,
200 unsigned idx)
201 {
202 if(idx < sym->npts)
203 return(sym->pts[idx].x);
204 else
205 return(-1);
206 }
207
zbar_symbol_get_loc_y(const zbar_symbol_t * sym,unsigned idx)208 int zbar_symbol_get_loc_y (const zbar_symbol_t *sym,
209 unsigned idx)
210 {
211 if(idx < sym->npts)
212 return(sym->pts[idx].y);
213 else
214 return(-1);
215 }
216
zbar_symbol_get_orientation(const zbar_symbol_t * sym)217 zbar_orientation_t zbar_symbol_get_orientation (const zbar_symbol_t *sym)
218 {
219 return(sym->orient);
220 }
221
zbar_symbol_next(const zbar_symbol_t * sym)222 const zbar_symbol_t *zbar_symbol_next (const zbar_symbol_t *sym)
223 {
224 return((sym) ? sym->next : NULL);
225 }
226
227 const zbar_symbol_set_t*
zbar_symbol_get_components(const zbar_symbol_t * sym)228 zbar_symbol_get_components (const zbar_symbol_t *sym)
229 {
230 return(sym->syms);
231 }
232
zbar_symbol_first_component(const zbar_symbol_t * sym)233 const zbar_symbol_t *zbar_symbol_first_component (const zbar_symbol_t *sym)
234 {
235 return((sym && sym->syms) ? sym->syms->head : NULL);
236 }
237
238
base64_encode(char * dst,const char * src,unsigned srclen)239 unsigned base64_encode (char *dst,
240 const char *src,
241 unsigned srclen)
242 {
243 static const char alphabet[] =
244 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
245 char *start = dst;
246 int nline = 19;
247 for(; srclen; srclen -= 3) {
248 unsigned int buf = *(src++) << 16;
249 if(srclen > 1) buf |= *(src++) << 8;
250 if(srclen > 2) buf |= *(src++);
251 *(dst++) = alphabet[(buf >> 18) & 0x3f];
252 *(dst++) = alphabet[(buf >> 12) & 0x3f];
253 *(dst++) = (srclen > 1) ? alphabet[(buf >> 6) & 0x3f] : '=';
254 *(dst++) = (srclen > 2) ? alphabet[buf & 0x3f] : '=';
255 if(srclen < 3) break;
256 if(!--nline) { *(dst++) = '\n'; nline = 19; }
257 }
258 *(dst++) = '\n';
259 *(dst++) = '\0';
260 return(dst - start - 1);
261 }
262
263 enum {
264 TMPL_START,
265 TMPL_MOD_START, TMPL_MOD_ITEM, TMPL_MOD_END,
266 TMPL_COUNT,
267 TMPL_DATA_START, TMPL_FORMAT, TMPL_CDATA,
268 TMPL_NL,
269 TMPL_END,
270 };
271
272 /* FIXME suspect... */
273 #define MAX_STATIC 256
274 #define MAX_MOD (5 * ZBAR_MOD_NUM)
275 #define MAX_CFG (10 * ZBAR_CFG_NUM)
276 #define MAX_INT_DIGITS 10
277
278 #define TMPL_COPY(t) do { \
279 static const char *_st = (t); \
280 i = strlen(_st); \
281 memcpy(*buf + n, _st, i + 1); \
282 n += i; \
283 assert(n <= maxlen); \
284 } while(0)
285
286 #define TMPL_FMT(t, ...) do { \
287 static const char *_st = (t); \
288 i = snprintf(*buf + n, maxlen - n, _st, __VA_ARGS__); \
289 assert(i > 0); \
290 n += i; \
291 assert(n <= maxlen); \
292 } while(0)
293
zbar_symbol_xml(const zbar_symbol_t * sym,char ** buf,unsigned * len)294 char *zbar_symbol_xml (const zbar_symbol_t *sym,
295 char **buf,
296 unsigned *len)
297 {
298 unsigned int datalen, maxlen;
299 int i, n = 0;
300
301 const char *type = zbar_get_symbol_name(sym->type);
302 const char *orient = zbar_get_orientation_name(sym->orient);
303
304 /* check for binary data */
305 unsigned char *data = (unsigned char*)sym->data;
306 char binary = ((data[0] == 0xff && data[1] == 0xfe) ||
307 (data[0] == 0xfe && data[1] == 0xff) ||
308 !strncmp(sym->data, "<?xml", 5));
309 for(i = 0; !binary && i < sym->datalen; i++) {
310 unsigned char c = sym->data[i];
311 binary = ((c < 0x20 && ((~0x00002600 >> c) & 1)) ||
312 (c >= 0x7f && c < 0xa0) ||
313 (c == ']' && i + 2 < sym->datalen &&
314 sym->data[i + 1] == ']' &&
315 sym->data[i + 2] == '>'));
316 }
317
318 datalen = strlen(sym->data);
319 if(binary)
320 datalen = (sym->datalen + 2) / 3 * 4 + sym->datalen / 57 + 3;
321
322 maxlen = (MAX_STATIC + strlen(type) + strlen(orient) +
323 datalen + MAX_INT_DIGITS + 1);
324 unsigned int mods = sym->modifiers;
325 if(mods)
326 maxlen += MAX_MOD;
327 unsigned int cfgs = sym->configs & ~(1 << ZBAR_CFG_ENABLE);
328 if(cfgs)
329 maxlen += MAX_CFG;
330 if(binary)
331 maxlen += MAX_INT_DIGITS;
332
333 if(!*buf || (*len < maxlen)) {
334 if(*buf)
335 free(*buf);
336 *buf = malloc(maxlen);
337 /* FIXME check OOM */
338 *len = maxlen;
339 }
340
341 TMPL_FMT("<symbol type='%s' quality='%d' orientation='%s'",
342 type, sym->quality, orient);
343
344 if(mods) {
345 int j;
346 TMPL_COPY(" modifiers='");
347 for(j = 0; mods && j < ZBAR_MOD_NUM; j++, mods >>= 1)
348 if(mods & 1)
349 TMPL_FMT("%s ", zbar_get_modifier_name(j));
350 /* cleanup trailing space */
351 n--;
352 TMPL_COPY("'");
353 }
354
355 if(cfgs) {
356 int j;
357 TMPL_COPY(" configs='");
358 for(j = 0; cfgs && j < ZBAR_CFG_NUM; j++, cfgs >>= 1)
359 if(cfgs & 1)
360 TMPL_FMT("%s ", zbar_get_config_name(j));
361 /* cleanup trailing space */
362 n--;
363 TMPL_COPY("'");
364 }
365
366 if(sym->cache_count)
367 TMPL_FMT(" count='%d'", sym->cache_count);
368
369 TMPL_COPY("><data");
370 if(binary)
371 TMPL_FMT(" format='base64' length='%d'", sym->datalen);
372 TMPL_COPY("><![CDATA[");
373
374 if(!binary) {
375 memcpy(*buf + n, sym->data, sym->datalen + 1);
376 n += sym->datalen;
377 }
378 else {
379 TMPL_COPY("\n");
380 n += base64_encode(*buf + n, sym->data, sym->datalen);
381 }
382 assert(n <= maxlen);
383
384 TMPL_COPY("]]></data></symbol>");
385
386 *len = n;
387 return(*buf);
388 }
389
390
_zbar_symbol_set_create()391 zbar_symbol_set_t *_zbar_symbol_set_create ()
392 {
393 zbar_symbol_set_t *syms = calloc(1, sizeof(*syms));
394 _zbar_refcnt(&syms->refcnt, 1);
395 return(syms);
396 }
397
_zbar_symbol_set_free(zbar_symbol_set_t * syms)398 inline void _zbar_symbol_set_free (zbar_symbol_set_t *syms)
399 {
400 zbar_symbol_t *sym, *next;
401 for(sym = syms->head; sym; sym = next) {
402 next = sym->next;
403 sym->next = NULL;
404 _zbar_symbol_refcnt(sym, -1);
405 }
406 syms->head = NULL;
407 free(syms);
408 }
409
zbar_symbol_set_ref(const zbar_symbol_set_t * syms,int delta)410 void zbar_symbol_set_ref (const zbar_symbol_set_t *syms,
411 int delta)
412 {
413 zbar_symbol_set_t *ncsyms = (zbar_symbol_set_t*)syms;
414 if(!_zbar_refcnt(&ncsyms->refcnt, delta) && delta <= 0)
415 _zbar_symbol_set_free(ncsyms);
416 }
417
zbar_symbol_set_get_size(const zbar_symbol_set_t * syms)418 int zbar_symbol_set_get_size (const zbar_symbol_set_t *syms)
419 {
420 return(syms->nsyms);
421 }
422
423 const zbar_symbol_t*
zbar_symbol_set_first_symbol(const zbar_symbol_set_t * syms)424 zbar_symbol_set_first_symbol (const zbar_symbol_set_t *syms)
425 {
426 zbar_symbol_t *sym = syms->tail;
427 if(sym)
428 return(sym->next);
429 return(syms->head);
430 }
431
432 const zbar_symbol_t*
zbar_symbol_set_first_unfiltered(const zbar_symbol_set_t * syms)433 zbar_symbol_set_first_unfiltered (const zbar_symbol_set_t *syms)
434 {
435 return(syms->head);
436 }
437