diff options
Diffstat (limited to 'zbar/symbol.c')
-rw-r--r-- | zbar/symbol.c | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/zbar/symbol.c b/zbar/symbol.c new file mode 100644 index 0000000..a518435 --- /dev/null +++ b/zbar/symbol.c @@ -0,0 +1,520 @@ +/*------------------------------------------------------------------------ + * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net> + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +#include "config.h" +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include <zbar.h> +#include "symbol.h" + +const char *zbar_get_symbol_name(zbar_symbol_type_t sym) +{ + switch (sym & ZBAR_SYMBOL) { + case ZBAR_EAN2: + return ("EAN-2"); + case ZBAR_EAN5: + return ("EAN-5"); + case ZBAR_EAN8: + return ("EAN-8"); + case ZBAR_UPCE: + return ("UPC-E"); + case ZBAR_ISBN10: + return ("ISBN-10"); + case ZBAR_UPCA: + return ("UPC-A"); + case ZBAR_EAN13: + return ("EAN-13"); + case ZBAR_ISBN13: + return ("ISBN-13"); + case ZBAR_COMPOSITE: + return ("COMPOSITE"); + case ZBAR_I25: + return ("I2/5"); + case ZBAR_DATABAR: + return ("DataBar"); + case ZBAR_DATABAR_EXP: + return ("DataBar-Exp"); + case ZBAR_CODABAR: + return ("Codabar"); + case ZBAR_CODE39: + return ("CODE-39"); + case ZBAR_CODE93: + return ("CODE-93"); + case ZBAR_CODE128: + return ("CODE-128"); + case ZBAR_PDF417: + return ("PDF417"); + case ZBAR_QRCODE: + return ("QR-Code"); + case ZBAR_SQCODE: + return ("SQ-Code"); + default: + return ("UNKNOWN"); + } +} + +const char *zbar_get_addon_name(zbar_symbol_type_t sym) +{ + return (""); +} + +const char *zbar_get_config_name(zbar_config_t cfg) +{ + switch (cfg) { + case ZBAR_CFG_ENABLE: + return ("ENABLE"); + case ZBAR_CFG_ADD_CHECK: + return ("ADD_CHECK"); + case ZBAR_CFG_EMIT_CHECK: + return ("EMIT_CHECK"); + case ZBAR_CFG_ASCII: + return ("ASCII"); + case ZBAR_CFG_BINARY: + return ("BINARY"); + case ZBAR_CFG_MIN_LEN: + return ("MIN_LEN"); + case ZBAR_CFG_MAX_LEN: + return ("MAX_LEN"); + case ZBAR_CFG_UNCERTAINTY: + return ("UNCERTAINTY"); + case ZBAR_CFG_POSITION: + return ("POSITION"); + case ZBAR_CFG_X_DENSITY: + return ("X_DENSITY"); + case ZBAR_CFG_Y_DENSITY: + return ("Y_DENSITY"); + default: + return (""); + } +} + +const char *zbar_get_modifier_name(zbar_modifier_t mod) +{ + switch (mod) { + case ZBAR_MOD_GS1: + return ("GS1"); + case ZBAR_MOD_AIM: + return ("AIM"); + default: + return (""); + } +} + +const char *zbar_get_orientation_name(zbar_orientation_t orient) +{ + switch (orient) { + case ZBAR_ORIENT_UP: + return ("UP"); + case ZBAR_ORIENT_RIGHT: + return ("RIGHT"); + case ZBAR_ORIENT_DOWN: + return ("DOWN"); + case ZBAR_ORIENT_LEFT: + return ("LEFT"); + default: + return ("UNKNOWN"); + } +} + +#ifndef _MSC_VER +static const signed char _zbar_symbol_hash[ZBAR_CODE128 + 1] = { + [0 ... ZBAR_CODE128] = -1, + + /* [ZBAR_FOO] = 0, is empty */ + [ZBAR_SQCODE] = 1, + [ZBAR_CODE128] = 2, + [ZBAR_EAN13] = 3, + [ZBAR_UPCA] = 4, + [ZBAR_EAN8] = 5, + [ZBAR_UPCE] = 6, + [ZBAR_ISBN13] = 7, + [ZBAR_ISBN10] = 8, + [ZBAR_CODE39] = 9, + [ZBAR_I25] = 10, + [ZBAR_PDF417] = 11, + [ZBAR_QRCODE] = 12, + [ZBAR_DATABAR] = 13, + [ZBAR_DATABAR_EXP] = 14, + [ZBAR_CODE93] = 15, + [ZBAR_EAN2] = 16, + [ZBAR_EAN5] = 17, + [ZBAR_COMPOSITE] = 18, + [ZBAR_CODABAR] = 19, + + /* Please update NUM_SYMS accordingly */ +}; + +static const signed char *_init_hash() +{ + return _zbar_symbol_hash; +}; +#else +/* + * Needed By Microsoft C. Even on Visual Studio 2019, C99 designated + * identifiers aren't supported! So, we need this hack. + */ +static const signed char *_init_hash() +{ + static signed char hash[ZBAR_CODE128 + 1] = { -1 }; + static int was_initialized = 0; + + if (was_initialized) + return (const signed char *)hash; + + memset(hash, -1, sizeof(hash)); + + /* Keep in sync with the C99 implementation */ + hash[ZBAR_SQCODE] = 1, hash[ZBAR_CODE128] = 2, hash[ZBAR_EAN13] = 3, + hash[ZBAR_UPCA] = 4, hash[ZBAR_EAN8] = 5, hash[ZBAR_UPCE] = 6, + hash[ZBAR_ISBN13] = 7, hash[ZBAR_ISBN10] = 8, hash[ZBAR_CODE39] = 9, + hash[ZBAR_I25] = 10, hash[ZBAR_PDF417] = 11, hash[ZBAR_QRCODE] = 12, + hash[ZBAR_DATABAR] = 13, hash[ZBAR_DATABAR_EXP] = 14, + hash[ZBAR_CODE93] = 15, hash[ZBAR_EAN2] = 16, hash[ZBAR_EAN5] = 17, + hash[ZBAR_COMPOSITE] = 18, hash[ZBAR_CODABAR] = 19; + + was_initialized = 1; + + return (const signed char *)hash; +}; +#endif + +int _zbar_get_symbol_hash(zbar_symbol_type_t sym) +{ + int h; + const signed char *hash = _init_hash(); + + assert(sym >= ZBAR_PARTIAL && sym <= ZBAR_CODE128); + + h = hash[sym]; + assert(h >= 0 && h < NUM_SYMS); + + return h; +} + +void _zbar_symbol_free(zbar_symbol_t *sym) +{ + if (sym->syms) { + zbar_symbol_set_ref(sym->syms, -1); + sym->syms = NULL; + } + if (sym->pts) + free(sym->pts); + if (sym->data_alloc && sym->data) + free(sym->data); + free(sym); +} + +void zbar_symbol_ref(const zbar_symbol_t *sym, int refs) +{ + zbar_symbol_t *ncsym = (zbar_symbol_t *)sym; + _zbar_symbol_refcnt(ncsym, refs); +} + +zbar_symbol_type_t zbar_symbol_get_type(const zbar_symbol_t *sym) +{ + return (sym->type); +} + +unsigned int zbar_symbol_get_configs(const zbar_symbol_t *sym) +{ + return (sym->configs); +} + +unsigned int zbar_symbol_get_modifiers(const zbar_symbol_t *sym) +{ + return (sym->modifiers); +} + +const char *zbar_symbol_get_data(const zbar_symbol_t *sym) +{ + return (sym->data); +} + +unsigned int zbar_symbol_get_data_length(const zbar_symbol_t *sym) +{ + return (sym->datalen); +} + +int zbar_symbol_get_count(const zbar_symbol_t *sym) +{ + return (sym->cache_count); +} + +int zbar_symbol_get_quality(const zbar_symbol_t *sym) +{ + return (sym->quality); +} + +unsigned zbar_symbol_get_loc_size(const zbar_symbol_t *sym) +{ + return (sym->npts); +} + +int zbar_symbol_get_loc_x(const zbar_symbol_t *sym, unsigned idx) +{ + if (idx < sym->npts) + return (sym->pts[idx].x); + else + return (-1); +} + +int zbar_symbol_get_loc_y(const zbar_symbol_t *sym, unsigned idx) +{ + if (idx < sym->npts) + return (sym->pts[idx].y); + else + return (-1); +} + +zbar_orientation_t zbar_symbol_get_orientation(const zbar_symbol_t *sym) +{ + return (sym->orient); +} + +const zbar_symbol_t *zbar_symbol_next(const zbar_symbol_t *sym) +{ + return ((sym) ? sym->next : NULL); +} + +const zbar_symbol_set_t *zbar_symbol_get_components(const zbar_symbol_t *sym) +{ + return (sym->syms); +} + +const zbar_symbol_t *zbar_symbol_first_component(const zbar_symbol_t *sym) +{ + return ((sym && sym->syms) ? sym->syms->head : NULL); +} + +unsigned base64_encode(char *dst, const char *src, unsigned srclen) +{ + static const char alphabet[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + char *start = dst; + int nline = 19; + for (; srclen; srclen -= 3) { + unsigned int buf = *(src++) << 16; + if (srclen > 1) + buf |= *(src++) << 8; + if (srclen > 2) + buf |= *(src++); + *(dst++) = alphabet[(buf >> 18) & 0x3f]; + *(dst++) = alphabet[(buf >> 12) & 0x3f]; + *(dst++) = (srclen > 1) ? alphabet[(buf >> 6) & 0x3f] : '='; + *(dst++) = (srclen > 2) ? alphabet[buf & 0x3f] : '='; + if (srclen < 3) + break; + if (!--nline) { + *(dst++) = '\n'; + nline = 19; + } + } + *(dst++) = '\n'; + *(dst++) = '\0'; + return (dst - start - 1); +} + +enum +{ + TMPL_START, + TMPL_MOD_START, + TMPL_MOD_ITEM, + TMPL_MOD_END, + TMPL_COUNT, + TMPL_DATA_START, + TMPL_FORMAT, + TMPL_CDATA, + TMPL_NL, + TMPL_END, +}; + +/* FIXME should be big enough to store XML extra data */ +#define MAX_STATIC (1 << 16) + +#define MAX_MOD (5 * ZBAR_MOD_NUM) +#define MAX_CFG (10 * ZBAR_CFG_NUM) +#define MAX_INT_DIGITS 10 + +#define TMPL_COPY(t) \ + do { \ + static const char *_st = (t); \ + i = strlen(_st); \ + memcpy(*buf + n, _st, i + 1); \ + n += i; \ + assert(n <= maxlen); \ + } while (0) + +#define TMPL_FMT(t, ...) \ + do { \ + static const char *_st = (t); \ + i = snprintf(*buf + n, maxlen - n, _st, __VA_ARGS__); \ + assert(i > 0); \ + n += i; \ + assert(n <= maxlen); \ + } while (0) + +char *zbar_symbol_xml(const zbar_symbol_t *sym, char **buf, unsigned *len) +{ + unsigned int mods, cfgs; + unsigned int datalen, maxlen; + int i, n = 0, p; + + const char *type = zbar_get_symbol_name(sym->type); + const char *orient = zbar_get_orientation_name(sym->orient); + + /* check for binary data */ + unsigned char *data = (unsigned char *)sym->data; + char binary = ((data[0] == 0xff && data[1] == 0xfe) || + (data[0] == 0xfe && data[1] == 0xff) || + !strncmp(sym->data, "<?xml", 5)); + for (i = 0; !binary && i < sym->datalen; i++) { + unsigned char c = sym->data[i]; + binary = ((c < 0x20 && ((~0x00002600 >> c) & 1)) || + (c >= 0x7f && c < 0xa0) || + (c == ']' && i + 2 < sym->datalen && + sym->data[i + 1] == ']' && sym->data[i + 2] == '>')); + } + + datalen = strlen(sym->data); + if (binary) + datalen = (sym->datalen + 2) / 3 * 4 + sym->datalen / 57 + 3; + + maxlen = (MAX_STATIC + strlen(type) + strlen(orient) + datalen + + MAX_INT_DIGITS + 1); + mods = sym->modifiers; + if (mods) + maxlen += MAX_MOD; + cfgs = sym->configs & ~(1 << ZBAR_CFG_ENABLE); + if (cfgs) + maxlen += MAX_CFG; + if (binary) + maxlen += MAX_INT_DIGITS; + + if (!*buf || (*len < maxlen)) { + if (*buf) + free(*buf); + *buf = malloc(maxlen); + /* FIXME check OOM */ + *len = maxlen; + } + + TMPL_FMT("<symbol type='%s' quality='%d' orientation='%s'", type, + sym->quality, orient); + + if (mods) { + int j; + TMPL_COPY(" modifiers='"); + for (j = 0; mods && j < ZBAR_MOD_NUM; j++, mods >>= 1) + if (mods & 1) + TMPL_FMT("%s ", zbar_get_modifier_name(j)); + /* cleanup trailing space */ + n--; + TMPL_COPY("'"); + } + + if (cfgs) { + int j; + TMPL_COPY(" configs='"); + for (j = 0; cfgs && j < ZBAR_CFG_NUM; j++, cfgs >>= 1) + if (cfgs & 1) + TMPL_FMT("%s ", zbar_get_config_name(j)); + /* cleanup trailing space */ + n--; + TMPL_COPY("'"); + } + + if (sym->cache_count) + TMPL_FMT(" count='%d'", sym->cache_count); + + TMPL_COPY("><polygon points='"); + if (sym->npts > 0 ) + TMPL_FMT("%+d,%+d", sym->pts[0].x, sym->pts[0].y); + for(p = 1; p < sym->npts; p++) + TMPL_FMT(" %+d,%+d", sym->pts[p].x, sym->pts[p].y); + + TMPL_COPY("'/><data"); + if (binary) + TMPL_FMT(" format='base64' length='%d'", sym->datalen); + TMPL_COPY("><![CDATA["); + + if (!binary) { + memcpy(*buf + n, sym->data, sym->datalen + 1); + n += sym->datalen; + } else { + TMPL_COPY("\n"); + n += base64_encode(*buf + n, sym->data, sym->datalen); + } + assert(n <= maxlen); + + TMPL_COPY("]]></data></symbol>"); + + *len = n; + return (*buf); +} + +zbar_symbol_set_t *_zbar_symbol_set_create() +{ + zbar_symbol_set_t *syms = calloc(1, sizeof(*syms)); + _zbar_refcnt(&syms->refcnt, 1); + return (syms); +} + +inline void _zbar_symbol_set_free(zbar_symbol_set_t *syms) +{ + zbar_symbol_t *sym, *next; + for (sym = syms->head; sym; sym = next) { + next = sym->next; + sym->next = NULL; + _zbar_symbol_refcnt(sym, -1); + } + syms->head = NULL; + free(syms); +} + +void zbar_symbol_set_ref(const zbar_symbol_set_t *syms, int delta) +{ + zbar_symbol_set_t *ncsyms = (zbar_symbol_set_t *)syms; + if (!_zbar_refcnt(&ncsyms->refcnt, delta) && delta <= 0) + _zbar_symbol_set_free(ncsyms); +} + +int zbar_symbol_set_get_size(const zbar_symbol_set_t *syms) +{ + return (syms->nsyms); +} + +const zbar_symbol_t *zbar_symbol_set_first_symbol(const zbar_symbol_set_t *syms) +{ + zbar_symbol_t *sym = syms->tail; + if (sym) + return (sym->next); + return (syms->head); +} + +const zbar_symbol_t * +zbar_symbol_set_first_unfiltered(const zbar_symbol_set_t *syms) +{ + return (syms->head); +} |