diff options
author | Steve Bennett <steveb@workware.net.au> | 2010-01-24 10:58:31 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2010-10-15 11:02:40 +1000 |
commit | d7bcbc515647b1d6897c16e5b3ef314a10ccd02e (patch) | |
tree | a25ae6757a3a9e6309cfba18e07e6494baee8f69 /jim-array.c | |
parent | f32ada62c0567ce439868b04f5de0ebe2a504e79 (diff) | |
download | jimtcl-d7bcbc515647b1d6897c16e5b3ef314a10ccd02e.zip jimtcl-d7bcbc515647b1d6897c16e5b3ef314a10ccd02e.tar.gz jimtcl-d7bcbc515647b1d6897c16e5b3ef314a10ccd02e.tar.bz2 |
Implement 'array' in C
Diffstat (limited to 'jim-array.c')
-rw-r--r-- | jim-array.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/jim-array.c b/jim-array.c new file mode 100644 index 0000000..903b157 --- /dev/null +++ b/jim-array.c @@ -0,0 +1,277 @@ +/* + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Implements the file command for jim + * + * The FreeBSD license + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 6.7: + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include "jim.h" +#include "jim-subcmd.h" + +static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* Just a regular [info exists] */ + Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0); + return JIM_OK; +} + +static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + Jim_Obj *resultObj; + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (!objPtr) { + return JIM_OK; + } + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { + /* Return the whole array */ + Jim_SetResult(interp, dictObj); + } + else { + /* REVISIT: We could create a dictionary rather than a list ...*/ + /* Only return the matching values */ + resultObj = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (Jim_StringMatchObj(argv[1], dictValuesObj[i], 0)) { + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i]); + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i + 1]); + } + } + + Jim_SetResult(interp, resultObj); + } + Jim_Free(dictValuesObj); + return JIM_OK; + +} + +static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + Jim_Obj *resultObj; + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (!objPtr) { + return JIM_OK; + } + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + /* Only return the matching values */ + resultObj = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (argc == 1 || Jim_StringMatchObj(argv[1], dictValuesObj[i], 0)) { + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i]); + } + } + Jim_Free(dictValuesObj); + + Jim_SetResult(interp, resultObj); + return JIM_OK; +} + +static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + Jim_Obj *resultObj; + Jim_Obj *objPtr; + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { + /* Unset the whole array */ + Jim_UnsetVariable(interp, argv[0], JIM_NONE); + return JIM_OK; + } + + objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + /* Create a new object with the values which don't match */ + resultObj = Jim_NewDictObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (!Jim_StringMatchObj(argv[1], dictValuesObj[i], 0)) { + Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); + } + } + Jim_Free(dictValuesObj); + + Jim_SetVariable(interp, argv[0], resultObj); + return JIM_OK; +} + +static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + int len = 0; + + /* Not found means zero length */ + objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + if (objPtr) { + Jim_ListLength(interp, objPtr, &len); + len /= 2; + } + + Jim_SetResultInt(interp, len); + + return JIM_OK; +} + +static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + Jim_Obj *listObj = argv[1]; + + Jim_ListLength(interp, listObj, &len); + if (len % 2) { + Jim_SetResultString(interp, "list must have an even number of elements", -1); + return JIM_ERR; + } + for (i = 0; i < len; i += 2) { + Jim_Obj *nameObj; + Jim_Obj *valueObj; + Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE); + Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE); + + Jim_SetDictKeysVector(interp, argv[0], &nameObj, 1, valueObj); + } + + return JIM_OK; +} + +static const jim_subcmd_type command_table[] = { + { .cmd = "exists", + .args = "arrayName", + .function = array_cmd_exists, + .minargs = 1, + .maxargs = 1, + .description = "Does array exist?" + }, + { .cmd = "get", + .args = "arrayName ?pattern?", + .function = array_cmd_get, + .minargs = 1, + .maxargs = 2, + .description = "Array contents as name value list" + }, + { .cmd = "names", + .args = "arrayName ?pattern?", + .function = array_cmd_names, + .minargs = 1, + .maxargs = 2, + .description = "Array keys as a list" + }, + { .cmd = "set", + .args = "arrayName list", + .function = array_cmd_set, + .minargs = 2, + .maxargs = 2, + .description = "Set array from list" + }, + { .cmd = "size", + .args = "arrayName", + .function = array_cmd_size, + .minargs = 1, + .maxargs = 1, + .description = "Number of elements in array" + }, + { .cmd = "unset", + .args = "arrayName ?pattern?", + .function = array_cmd_unset, + .minargs = 1, + .maxargs = 2, + .description = "Unset elements of an array" + }, + { .cmd = 0, + } +}; + +int Jim_arrayInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)command_table, NULL); + return JIM_OK; +} |