aboutsummaryrefslogtreecommitdiff
path: root/jim-array.c
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2010-01-24 10:58:31 +1000
committerSteve Bennett <steveb@workware.net.au>2010-10-15 11:02:40 +1000
commitd7bcbc515647b1d6897c16e5b3ef314a10ccd02e (patch)
treea25ae6757a3a9e6309cfba18e07e6494baee8f69 /jim-array.c
parentf32ada62c0567ce439868b04f5de0ebe2a504e79 (diff)
downloadjimtcl-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.c277
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;
+}