Don't unconditionally define _GNU_SOURCE
[jimtcl.git] / jim-array.c
blob39cd168bed9dd7ef490501fb1d08642156173439
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 (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 return JIM_ERR;
121 /* Create a new object with the values which don't match */
122 resultObj = Jim_NewDictObj(interp, NULL, 0);
124 for (i = 0; i < len; i += 2) {
125 if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) {
126 Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]);
129 Jim_Free(dictValuesObj);
131 Jim_SetVariable(interp, argv[0], resultObj);
132 return JIM_OK;
135 static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
137 Jim_Obj *objPtr;
138 int len = 0;
140 /* Not found means zero length */
141 objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
142 if (objPtr) {
143 len = Jim_DictSize(interp, objPtr);
144 if (len < 0) {
145 return JIM_ERR;
149 Jim_SetResultInt(interp, len);
151 return JIM_OK;
154 static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
156 Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE);
157 if (objPtr) {
158 return Jim_DictInfo(interp, objPtr);
160 Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL);
161 return JIM_ERR;
164 static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
166 int i;
167 int len;
168 Jim_Obj *listObj = argv[1];
169 Jim_Obj *dictObj;
171 len = Jim_ListLength(interp, listObj);
172 if (len % 2) {
173 Jim_SetResultString(interp, "list must have an even number of elements", -1);
174 return JIM_ERR;
177 dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
178 if (!dictObj) {
179 /* Doesn't exist, so just set the list directly */
180 return Jim_SetVariable(interp, argv[0], listObj);
182 else if (Jim_DictSize(interp, dictObj) < 0) {
183 return JIM_ERR;
186 if (Jim_IsShared(dictObj)) {
187 dictObj = Jim_DuplicateObj(interp, dictObj);
190 for (i = 0; i < len; i += 2) {
191 Jim_Obj *nameObj;
192 Jim_Obj *valueObj;
194 Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE);
195 Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE);
197 Jim_DictAddElement(interp, dictObj, nameObj, valueObj);
199 return Jim_SetVariable(interp, argv[0], dictObj);
202 static const jim_subcmd_type array_command_table[] = {
203 { "exists",
204 "arrayName",
205 array_cmd_exists,
208 /* Description: Does array exist? */
210 { "get",
211 "arrayName ?pattern?",
212 array_cmd_get,
215 /* Description: Array contents as name value list */
217 { "names",
218 "arrayName ?pattern?",
219 array_cmd_names,
222 /* Description: Array keys as a list */
224 { "set",
225 "arrayName list",
226 array_cmd_set,
229 /* Description: Set array from list */
231 { "size",
232 "arrayName",
233 array_cmd_size,
236 /* Description: Number of elements in array */
238 { "stat",
239 "arrayName",
240 array_cmd_stat,
243 /* Description: Print statistics about an array */
245 { "unset",
246 "arrayName ?pattern?",
247 array_cmd_unset,
250 /* Description: Unset elements of an array */
252 { NULL
256 int Jim_arrayInit(Jim_Interp *interp)
258 if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG))
259 return JIM_ERR;
261 Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
262 return JIM_OK;