/*------------------------------------------------------------------------
 *  Copyright 2008-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 <stdlib.h>     /* strtol */
#include <string.h>     /* strchr, strncmp, strlen */
#ifdef HAVE_ERRNO_H
# include <errno.h>
#endif

#include <zbar.h>

int zbar_parse_config (const char *cfgstr,
                       zbar_symbol_type_t *sym,
                       zbar_config_t *cfg,
                       int *val)
{
    const char *dot, *eq;
    int len;
    char negate;
    if(!cfgstr)
        return(1);

    dot = strchr(cfgstr, '.');
    if(dot) {
        int len = dot - cfgstr;
        if(!len || (len == 1 && !strncmp(cfgstr, "*", len)))
            *sym = 0;
        else if(len < 2)
            return(1);
        else if(!strncmp(cfgstr, "qrcode", len))
            *sym = ZBAR_QRCODE;
        else if(!strncmp(cfgstr, "sqcode", len))
            *sym = ZBAR_SQCODE;
        else if(!strncmp(cfgstr, "db", len))
            *sym = ZBAR_DATABAR;
        else if(len < 3)
            return(1);
        else if(!strncmp(cfgstr, "upca", len))
            *sym = ZBAR_UPCA;
        else if(!strncmp(cfgstr, "upce", len))
            *sym = ZBAR_UPCE;
        else if(!strncmp(cfgstr, "ean13", len))
            *sym = ZBAR_EAN13;
        else if(!strncmp(cfgstr, "ean8", len))
            *sym = ZBAR_EAN8;
        else if(!strncmp(cfgstr, "ean5", len))
            *sym = ZBAR_EAN5;
        else if(!strncmp(cfgstr, "ean2", len))
            *sym = ZBAR_EAN2;
        else if(!strncmp(cfgstr, "composite", len))
            *sym = ZBAR_COMPOSITE;
        else if(!strncmp(cfgstr, "i25", len))
            *sym = ZBAR_I25;
        else if(len < 4)
            return(1);
        else if(!strncmp(cfgstr, "scanner", len))
            *sym = ZBAR_PARTIAL; /* FIXME lame */
        else if(!strncmp(cfgstr, "isbn13", len))
            *sym = ZBAR_ISBN13;
        else if(!strncmp(cfgstr, "isbn10", len))
            *sym = ZBAR_ISBN10;
        else if(!strncmp(cfgstr, "db-exp", len))
            *sym = ZBAR_DATABAR_EXP;
        else if(!strncmp(cfgstr, "codabar", len))
            *sym = ZBAR_CODABAR;
        else if(len < 6)
            return(1);
        else if(!strncmp(cfgstr, "code93", len))
            *sym = ZBAR_CODE93;
        else if(!strncmp(cfgstr, "code39", len))
            *sym = ZBAR_CODE39;
        else if(!strncmp(cfgstr, "pdf417", len))
            *sym = ZBAR_PDF417;
        else if(len < 7)
            return(1);
        else if(!strncmp(cfgstr, "code128", len))
            *sym = ZBAR_CODE128;
        else if(!strncmp(cfgstr, "databar", len))
            *sym = ZBAR_DATABAR;
        else if(!strncmp(cfgstr, "databar-exp", len))
            *sym = ZBAR_DATABAR_EXP;
        else
            return(1);
        cfgstr = dot + 1;
    }
    else
        *sym = 0;

    len = strlen(cfgstr);
    eq = strchr(cfgstr, '=');
    if(eq)
        len = eq - cfgstr;
    else
        *val = 1;  /* handle this here so we can override later */
    negate = 0;

    if(len > 3 && !strncmp(cfgstr, "no-", 3)) {
        negate = 1;
        cfgstr += 3;
        len -= 3;
    }

    if(len < 1)
        return(1);
    else if(!strncmp(cfgstr, "y-density", len))
        *cfg = ZBAR_CFG_Y_DENSITY;
    else if(!strncmp(cfgstr, "x-density", len))
        *cfg = ZBAR_CFG_X_DENSITY;
    else if(len < 2)
        return(1);
    else if(!strncmp(cfgstr, "enable", len))
        *cfg = ZBAR_CFG_ENABLE;
    else if(len < 3)
        return(1);
    else if(!strncmp(cfgstr, "disable", len)) {
        *cfg = ZBAR_CFG_ENABLE;
        negate = !negate; /* no-disable ?!? */
    }
    else if(!strncmp(cfgstr, "min-length", len))
        *cfg = ZBAR_CFG_MIN_LEN;
    else if(!strncmp(cfgstr, "max-length", len))
        *cfg = ZBAR_CFG_MAX_LEN;
    else if(!strncmp(cfgstr, "ascii", len))
        *cfg = ZBAR_CFG_ASCII;
    else if(!strncmp(cfgstr, "binary", len))
        *cfg = ZBAR_CFG_BINARY;
    else if(!strncmp(cfgstr, "add-check", len))
        *cfg = ZBAR_CFG_ADD_CHECK;
    else if(!strncmp(cfgstr, "emit-check", len))
        *cfg = ZBAR_CFG_EMIT_CHECK;
    else if(!strncmp(cfgstr, "uncertainty", len))
        *cfg = ZBAR_CFG_UNCERTAINTY;
    else if(!strncmp(cfgstr, "test-inverted", len))
        *cfg = ZBAR_CFG_TEST_INVERTED;
    else if(!strncmp(cfgstr, "position", len))
        *cfg = ZBAR_CFG_POSITION;
    else 
        return(1);

    if(eq) {
#ifdef HAVE_ERRNO_H
        errno = 0;
#endif
        *val = strtol(eq + 1, NULL, 0);
#ifdef HAVE_ERRNO_H
        if(errno)
            return(1);
#endif
    }
    if(negate)
        *val = !*val;

    return(0);
}
