build-jim-ext: load using ./$filename
[jimtcl.git] / jim-array.c
blobbf07e078dbac053bd8c037ac49974b17a6b3bc52
1 /*
2 * Implements the array command for jim
4 * (c) 2008 Steve Bennett <steveb@workware.net.au>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and documentation
31 * are those of the authors and should not be interpreted as representing
32 * official policies, either expressed or implied, of the Jim Tcl Project.
34 * Based on code originally from Tcl 6.7:
36 * Copyright 1987-1991 Regents of the University of California
37 * Permission to use, copy, modify, and distribute this
38 * software and its documentation for any purpose and without
39 * fee is hereby granted, provided that the above copyright
40 * notice appear in all copies. The University of California
41 * makes no representations about the suitability of this
42 * software for any purpose. It is provided "as is" without
43 * express or implied warranty.
46 #include <limits.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <errno.h>
52 #include <jim-subcmd.h>
54 static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
56 /* Just a regular [info exists] */
57 Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
58 return JIM_OK;
61 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
63 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
64 Jim_Obj *patternObj;
66 if (!objPtr) {
67 return JIM_OK;
70 patternObj = (argc == 1) ? NULL : argv[1];
72 /* Optimise the "all" case */
73 if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
74 if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
75 /* A list with an even number of elements */
76 Jim_SetResult(interp, objPtr);
77 return JIM_OK;
81 /* Return a list of keys and values where the keys match the pattern */
82 return Jim_DictValues(interp, objPtr, patternObj);
85 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
87 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
89 if (!objPtr) {
90 return JIM_OK;
93 return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]);
96 static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
98 int i;
99 int len;
100 Jim_Obj *resultObj;
101 Jim_Obj *objPtr;
102 Jim_Obj **dictValuesObj;
104 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
105 /* Unset the whole array */
106 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
107 return JIM_OK;
110 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
112 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
113 return JIM_ERR;
116 /* Create a new object with the values which don't match */
117 resultObj = Jim_NewDictObj(interp, NULL, 0);
119 for (i = 0; i < len; i += 2) {
120 if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
121 Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
124 Jim_Free(dictValuesObj);
126 Jim_SetVariable(interp, argv[0], resultObj);
127 return JIM_OK;
130 static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
132 Jim_Obj *objPtr;
133 int len = 0;
135 /* Not found means zero length */
136 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
137 if (objPtr) {
138 len = Jim_DictSize(interp, objPtr);
139 if (len < 0) {
140 return JIM_ERR;
144 Jim_SetResultInt(interp, len);
146 return JIM_OK;
149 static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
151 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
152 if (objPtr) {
153 return Jim_DictInfo(interp, objPtr);
155 Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
156 return JIM_ERR;
159 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
161 int i;
162 int len;
163 Jim_Obj *listObj = argv[1];
164 Jim_Obj *dictObj;
166 len = Jim_ListLength(interp, listObj);
167 if (len % 2) {
168 Jim_SetResultString(interp, "list must have an even number of elements", -1);
169 return JIM_ERR;
172 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
173 if (!dictObj) {
174 /* Doesn't exist, so just set the list directly */
175 return Jim_SetVariable(interp, argv[0], listObj);
177 else if (Jim_DictSize(interp, dictObj) < 0) {
178 return JIM_ERR;
181 if (Jim_IsShared(dictObj)) {
182 dictObj = Jim_DuplicateObj(interp, dictObj);
185 for (i = 0; i < len; i += 2) {
186 Jim_Obj *nameObj;
187 Jim_Obj *valueObj;
189 Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE);
190 Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE);
192 Jim_DictAddElement(interp, dictObj, nameObj, valueObj);
194 return Jim_SetVariable(interp, argv[0], dictObj);
197 static const jim_subcmd_type array_command_table[] = {
198 { "exists",
199 "arrayName",
200 array_cmd_exists,
203 /* Description: Does array exist? */
205 { "get",
206 "arrayName ?pattern?",
207 array_cmd_get,
210 /* Description: Array contents as name value list */
212 { "names",
213 "arrayName ?pattern?",
214 array_cmd_names,
217 /* Description: Array keys as a list */
219 { "set",
220 "arrayName list",
221 array_cmd_set,
224 /* Description: Set array from list */
226 { "size",
227 "arrayName",
228 array_cmd_size,
231 /* Description: Number of elements in array */
233 { "stat",
234 "arrayName",
235 array_cmd_stat,
238 /* Description: Print statistics about an array */
240 { "unset",
241 "arrayName ?pattern?",
242 array_cmd_unset,
245 /* Description: Unset elements of an array */
247 { NULL
251 int Jim_arrayInit(Jim_Interp *interp)
253 if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG))
254 return JIM_ERR;
256 Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
257 return JIM_OK;