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