clock: Fix test for platforms with no scan support
[jimtcl.git] / jim-array.c
blob4213bc3307ea2a3d5ab370876beac5c44f2b3f09
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_Obj *dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
58 Jim_SetResultInt(interp, dictObj && Jim_DictSize(interp, dictObj) != -1);
59 return JIM_OK;
62 static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
64 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
65 Jim_Obj *patternObj;
67 if (!objPtr) {
68 return JIM_OK;
71 patternObj = (argc == 1) ? NULL : argv[1];
73 /* Optimise the "all" case */
74 if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) {
75 if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) {
76 /* A list with an even number of elements */
77 Jim_SetResult(interp, objPtr);
78 return JIM_OK;
82 return Jim_DictMatchTypes(interp, objPtr, patternObj, JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS | JIM_DICTMATCH_VALUES);
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_DictMatchTypes(interp, objPtr, argc == 1 ? NULL : argv[1], JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS);
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 (objPtr == NULL) {
113 /* Doesn't exist, so nothing to do */
114 return JIM_OK;
117 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
118 /* Variable is not an array - tclsh ignores this and returns nothing - be compatible */
119 Jim_SetResultString(interp, "", -1);
120 return JIM_OK;
123 /* Create a new object with the values which don't match */
124 resultObj = Jim_NewDictObj(interp, NULL, 0);
126 for (i = 0; i < len; i += 2) {
127 if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
128 Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
131 Jim_Free(dictValuesObj);
133 Jim_SetVariable(interp, argv[0], resultObj);
134 return JIM_OK;
137 static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
139 Jim_Obj *objPtr;
140 int len = 0;
142 /* Not found means zero length */
143 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
144 if (objPtr) {
145 len = Jim_DictSize(interp, objPtr);
146 if (len < 0) {
147 /* Variable is not an array - tclsh ignores this and returns 0 - be compatible */
148 Jim_SetResultInt(interp, 0);
149 return JIM_OK;
153 Jim_SetResultInt(interp, len);
155 return JIM_OK;
158 static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
160 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
161 if (objPtr) {
162 return Jim_DictInfo(interp, objPtr);
164 Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
165 return JIM_ERR;
168 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
170 int i;
171 int len;
172 Jim_Obj *listObj = argv[1];
173 Jim_Obj *dictObj;
175 len = Jim_ListLength(interp, listObj);
176 if (len % 2) {
177 Jim_SetResultString(interp, "list must have an even number of elements", -1);
178 return JIM_ERR;
181 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
182 if (!dictObj) {
183 /* Doesn't exist, so just set the list directly */
184 return Jim_SetVariable(interp, argv[0], listObj);
186 else if (Jim_DictSize(interp, dictObj) < 0) {
187 return JIM_ERR;
190 if (Jim_IsShared(dictObj)) {
191 dictObj = Jim_DuplicateObj(interp, dictObj);
194 for (i = 0; i < len; i += 2) {
195 Jim_Obj *nameObj;
196 Jim_Obj *valueObj;
198 Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE);
199 Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE);
201 Jim_DictAddElement(interp, dictObj, nameObj, valueObj);
203 return Jim_SetVariable(interp, argv[0], dictObj);
206 static const jim_subcmd_type array_command_table[] = {
207 { "exists",
208 "arrayName",
209 array_cmd_exists,
212 /* Description: Does array exist? */
214 { "get",
215 "arrayName ?pattern?",
216 array_cmd_get,
219 /* Description: Array contents as name value list */
221 { "names",
222 "arrayName ?pattern?",
223 array_cmd_names,
226 /* Description: Array keys as a list */
228 { "set",
229 "arrayName list",
230 array_cmd_set,
233 /* Description: Set array from list */
235 { "size",
236 "arrayName",
237 array_cmd_size,
240 /* Description: Number of elements in array */
242 { "stat",
243 "arrayName",
244 array_cmd_stat,
247 /* Description: Print statistics about an array */
249 { "unset",
250 "arrayName ?pattern?",
251 array_cmd_unset,
254 /* Description: Unset elements of an array */
256 { NULL
260 int Jim_arrayInit(Jim_Interp *interp)
262 if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG))
263 return JIM_ERR;
265 Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
266 return JIM_OK;