diff options
author | Martin Poirier <theeth@yahoo.com> | 2010-02-01 04:43:31 +0300 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2010-02-01 04:43:31 +0300 |
commit | 678f68550ba96cf539bd50d197680537741b3c83 (patch) | |
tree | febf9ac567f0b98739a3d7556216a9809604b053 /source/blender/blenlib/intern | |
parent | 7379e75e12c5d5de2181802f5d2cd71f4c9c73f1 (diff) |
New argument parsing library supporting multiple passes, case sensitive and insensitive arguments, default handlers and other features that were hacked in the previous ugly switch system. Very simpler system for adding new arguments, easier to see conflicts and no more replication between BG and non BG mode arguments.
I've tested pretty much everything except GE options (-g options), but some small bugs could have sneaked in.
Diffstat (limited to 'source/blender/blenlib/intern')
-rw-r--r-- | source/blender/blenlib/intern/BLI_args.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/source/blender/blenlib/intern/BLI_args.c b/source/blender/blenlib/intern/BLI_args.c new file mode 100644 index 00000000000..9d67556a599 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_args.c @@ -0,0 +1,201 @@ +/** + * A general argument parsing module + * + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <ctype.h> /* for tolower */ + +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" +#include "BLI_args.h" +#include "BLI_ghash.h" + +typedef struct bAKey { + char *arg; + uintptr_t pass; /* cast easier */ + int case_str; /* case specific or not */ +} bAKey; + +typedef struct bArgument { + BA_ArgCallback func; + void *data; +} bArgument; + +struct bArgs { + GHash *items; + int argc; + char **argv; + int *passes; +}; + +unsigned int case_strhash(void *ptr) { + char *s= ptr; + unsigned int i= 0; + unsigned char c; + + while ( (c= tolower(*s++)) ) + i= i*37 + c; + + return i; +} + +static unsigned int keyhash(void *ptr) +{ + bAKey *k = ptr; + return case_strhash(k->arg) ^ BLI_ghashutil_inthash((void*)k->pass); +} + +static int keycmp(void *a, void *b) +{ + bAKey *ka = a; + bAKey *kb = b; + if (ka->pass == kb->pass || ka->pass == -1 || kb->pass == -1) { /* -1 is wildcard for pass */ + if (ka->case_str == 1 || kb->case_str == 1) + return BLI_strcasecmp(ka->arg, kb->arg); + else + return strcmp(ka->arg, kb->arg); + } else { + return BLI_ghashutil_intcmp((void*)ka->pass, (void*)kb->pass); + } +} + +bArgs *BLI_argsInit(int argc, char **argv) +{ + bArgs *ba = MEM_callocN(sizeof(bArgs), "bArgs"); + ba->passes = MEM_callocN(sizeof(int) * argc, "bArgs passes"); + ba->items = BLI_ghash_new(keyhash, keycmp); + ba->argc = argc; + ba->argv = argv; + + return ba; +} + +static void freeItem(void *val) +{ + MEM_freeN(val); +} + +void BLI_argsFree(struct bArgs *ba) +{ + BLI_ghash_free(ba->items, freeItem, freeItem); + MEM_freeN(ba->passes); + MEM_freeN(ba); +} + +void BLI_argsPrint(struct bArgs *ba) +{ + int i; + for (i = 0; i < ba->argc; i++) { + printf("argv[%d] = %s\n", i, ba->argv[i]); + } +} + +char **BLI_argsArgv(struct bArgs *ba) +{ + return ba->argv; +} + +void BLI_argsAdd(struct bArgs *ba, char *arg, int pass, BA_ArgCallback cb, void *data) +{ + bArgument *a = MEM_callocN(sizeof(bArgument), "bArgument"); + bAKey *key = MEM_callocN(sizeof(bAKey), "bAKey"); + + key->arg = arg; + key->pass = pass; + key->case_str = 1; + + a->func = cb; + a->data = data; + + BLI_ghash_insert(ba->items, key, a); +} + +void BLI_argsAddCase(struct bArgs *ba, char *arg, int pass, BA_ArgCallback cb, void *data) +{ + bArgument *a = MEM_callocN(sizeof(bArgument), "bArgument"); + bAKey *key = MEM_callocN(sizeof(bAKey), "bAKey"); + + key->arg = arg; + key->pass = pass; + key->case_str = 0; + + a->func = cb; + a->data = data; + + BLI_ghash_insert(ba->items, key, a); +} + + +void BLI_argsParse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void *default_data) +{ + bAKey key; + int i = 0; + + key.case_str = -1; /* signal what side of the comparison it is */ + key.pass = pass; + + for( i = 1; i < ba->argc; i++) { /* skip argv[0] */ + key.arg = ba->argv[i]; + if (ba->passes[i] == 0) { + bArgument *a = BLI_ghash_lookup(ba->items, &key); + BA_ArgCallback func = NULL; + void *data = NULL; + + if (a) { + func = a->func; + data = a->data; + } else { + func = default_cb; + data = default_data; + + if (func) { + printf("calling default on %s\n", ba->argv[i]); + } + } + + if (func) { + int retval = func(ba->argc - i, ba->argv + i, data); + + if (retval >= 0) { + int j; + + /* use extra arguments */ + for (j = 0; j <= retval; j++) { + ba->passes[i + j] = pass; + } + i += retval; + } else if (retval == -1){ + ba->passes[i] = pass; + break; + } + } + } + } +} |