Add pkg-config support: jimtcl.pc
[jimtcl.git] / jim-array.c
blobcd3e784aa6f14cf3174246eca8cfd0e5a71db6d4
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 a list of keys and values where the keys match the pattern */
83 return Jim_DictValues(interp, objPtr, patternObj);
86 static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
88 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
90 if (!objPtr) {
91 return JIM_OK;
94 return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]);
97 static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
99 int i;
100 int len;
101 Jim_Obj *resultObj;
102 Jim_Obj *objPtr;
103 Jim_Obj **dictValuesObj;
105 if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) {
106 /* Unset the whole array */
107 Jim_UnsetVariable(interp, argv[0], JIM_NONE);
108 return JIM_OK;
111 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
113 if (objPtr == NULL) {
114 /* Doesn't exist, so nothing to do */
115 return JIM_OK;
118 if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
119 /* Variable is not an array - tclsh ignores this and returns nothing - be compatible */
120 Jim_SetResultString(interp, "", -1);
121 return JIM_OK;
124 /* Create a new object with the values which don't match */
125 resultObj = Jim_NewDictObj(interp, NULL, 0);
127 for (i = 0; i < len; i += 2) {
128 if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
129 Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
132 Jim_Free(dictValuesObj);
134 Jim_SetVariable(interp, argv[0], resultObj);
135 return JIM_OK;
138 static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
140 Jim_Obj *objPtr;
141 int len = 0;
143 /* Not found means zero length */
144 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
145 if (objPtr) {
146 len = Jim_DictSize(interp, objPtr);
147 if (len < 0) {
148 /* Variable is not an array - tclsh ignores this and returns 0 - be compatible */
149 Jim_SetResultInt(interp, 0);
150 return JIM_OK;
154 Jim_SetResultInt(interp, len);
156 return JIM_OK;
159 static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
161 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
162 if (objPtr) {
163 return Jim_DictInfo(interp, objPtr);
165 Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
166 return JIM_ERR;
169 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
171 int i;
172 int len;
173 Jim_Obj *listObj = argv[1];
174 Jim_Obj *dictObj;
176 len = Jim_ListLength(interp, listObj);
177 if (len % 2) {
178 Jim_SetResultString(interp, "list must have an even number of elements", -1);
179 return JIM_ERR;
182 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
183 if (!dictObj) {
184 /* Doesn't exist, so just set the list directly */
185 return Jim_SetVariable(interp, argv[0], listObj);
187 else if (Jim_DictSize(interp, dictObj) < 0) {
188 return JIM_ERR;
191 if (Jim_IsShared(dictObj)) {
192 dictObj = Jim_DuplicateObj(interp, dictObj);
195 for (i = 0; i < len; i += 2) {
196 Jim_Obj *nameObj;
197 Jim_Obj *valueObj;
199 Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE);
200 Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE);
202 Jim_DictAddElement(interp, dictObj, nameObj, valueObj);
204 return Jim_SetVariable(interp, argv[0], dictObj);
207 static const jim_subcmd_type array_command_table[] = {
208 { "exists",
209 "arrayName",
210 array_cmd_exists,
213 /* Description: Does array exist? */
215 { "get",
216 "arrayName ?pattern?",
217 array_cmd_get,
220 /* Description: Array contents as name value list */
222 { "names",
223 "arrayName ?pattern?",
224 array_cmd_names,
227 /* Description: Array keys as a list */
229 { "set",
230 "arrayName list",
231 array_cmd_set,
234 /* Description: Set array from list */
236 { "size",
237 "arrayName",
238 array_cmd_size,
241 /* Description: Number of elements in array */
243 { "stat",
244 "arrayName",
245 array_cmd_stat,
248 /* Description: Print statistics about an array */
250 { "unset",
251 "arrayName ?pattern?",
252 array_cmd_unset,
255 /* Description: Unset elements of an array */
257 { NULL
261 int Jim_arrayInit(Jim_Interp *interp)
263 if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG))
264 return JIM_ERR;
266 Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
267 return JIM_OK;