blob: bce7fdf8da01a6c5740f920f137cd7361ded6858 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Tuple object implementation */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000028
29object *
30newtupleobject(size)
31 register int size;
32{
33 register int i;
34 register tupleobject *op;
35 if (size < 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000036 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000037 return NULL;
38 }
39 op = (tupleobject *)
40 malloc(sizeof(tupleobject) + size * sizeof(object *));
Guido van Rossum2a9096b1990-10-21 22:15:08 +000041 if (op == NULL)
42 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000043 NEWREF(op);
44 op->ob_type = &Tupletype;
45 op->ob_size = size;
46 for (i = 0; i < size; i++)
47 op->ob_item[i] = NULL;
48 return (object *) op;
49}
50
51int
52gettuplesize(op)
53 register object *op;
54{
55 if (!is_tupleobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000056 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000057 return -1;
58 }
59 else
60 return ((tupleobject *)op)->ob_size;
61}
62
63object *
64gettupleitem(op, i)
65 register object *op;
66 register int i;
67{
68 if (!is_tupleobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000069 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000070 return NULL;
71 }
72 if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000073 err_setstr(IndexError, "tuple index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000074 return NULL;
75 }
76 return ((tupleobject *)op) -> ob_item[i];
77}
78
79int
80settupleitem(op, i, newitem)
81 register object *op;
82 register int i;
83 register object *newitem;
84{
85 register object *olditem;
86 if (!is_tupleobject(op)) {
87 if (newitem != NULL)
88 DECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000089 err_badcall();
90 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000091 }
92 if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
93 if (newitem != NULL)
94 DECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000095 err_setstr(IndexError, "tuple assignment index out of range");
96 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000097 }
98 olditem = ((tupleobject *)op) -> ob_item[i];
99 ((tupleobject *)op) -> ob_item[i] = newitem;
100 if (olditem != NULL)
101 DECREF(olditem);
102 return 0;
103}
104
105/* Methods */
106
107static void
108tupledealloc(op)
109 register tupleobject *op;
110{
111 register int i;
112 for (i = 0; i < op->ob_size; i++) {
113 if (op->ob_item[i] != NULL)
114 DECREF(op->ob_item[i]);
115 }
116 free((ANY *)op);
117}
118
Guido van Rossum49e85141991-06-07 22:59:30 +0000119static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000120tupleprint(op, fp, flags)
121 tupleobject *op;
122 FILE *fp;
123 int flags;
124{
125 int i;
126 fprintf(fp, "(");
Guido van Rossum49e85141991-06-07 22:59:30 +0000127 for (i = 0; i < op->ob_size; i++) {
128 if (i > 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000129 fprintf(fp, ", ");
Guido van Rossum49e85141991-06-07 22:59:30 +0000130 if (printobject(op->ob_item[i], fp, flags) != 0)
131 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000132 }
133 if (op->ob_size == 1)
134 fprintf(fp, ",");
135 fprintf(fp, ")");
Guido van Rossum49e85141991-06-07 22:59:30 +0000136 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000137}
138
139object *
140tuplerepr(v)
141 tupleobject *v;
142{
143 object *s, *t, *comma;
144 int i;
145 s = newstringobject("(");
146 comma = newstringobject(", ");
147 for (i = 0; i < v->ob_size && s != NULL; i++) {
148 if (i > 0)
149 joinstring(&s, comma);
150 t = reprobject(v->ob_item[i]);
151 joinstring(&s, t);
152 if (t != NULL)
153 DECREF(t);
154 }
155 DECREF(comma);
156 if (v->ob_size == 1) {
157 t = newstringobject(",");
158 joinstring(&s, t);
159 DECREF(t);
160 }
161 t = newstringobject(")");
162 joinstring(&s, t);
163 DECREF(t);
164 return s;
165}
166
167static int
168tuplecompare(v, w)
169 register tupleobject *v, *w;
170{
171 register int len =
172 (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
173 register int i;
174 for (i = 0; i < len; i++) {
175 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
176 if (cmp != 0)
177 return cmp;
178 }
179 return v->ob_size - w->ob_size;
180}
181
182static int
183tuplelength(a)
184 tupleobject *a;
185{
186 return a->ob_size;
187}
188
189static object *
190tupleitem(a, i)
191 register tupleobject *a;
192 register int i;
193{
194 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000195 err_setstr(IndexError, "tuple index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000196 return NULL;
197 }
198 INCREF(a->ob_item[i]);
199 return a->ob_item[i];
200}
201
202static object *
203tupleslice(a, ilow, ihigh)
204 register tupleobject *a;
205 register int ilow, ihigh;
206{
207 register tupleobject *np;
208 register int i;
209 if (ilow < 0)
210 ilow = 0;
211 if (ihigh > a->ob_size)
212 ihigh = a->ob_size;
213 if (ihigh < ilow)
214 ihigh = ilow;
215 if (ilow == 0 && ihigh == a->ob_size) {
216 /* XXX can only do this if tuples are immutable! */
217 INCREF(a);
218 return (object *)a;
219 }
220 np = (tupleobject *)newtupleobject(ihigh - ilow);
221 if (np == NULL)
222 return NULL;
223 for (i = ilow; i < ihigh; i++) {
224 object *v = a->ob_item[i];
225 INCREF(v);
226 np->ob_item[i - ilow] = v;
227 }
228 return (object *)np;
229}
230
231static object *
232tupleconcat(a, bb)
233 register tupleobject *a;
234 register object *bb;
235{
236 register int size;
237 register int i;
238 tupleobject *np;
239 if (!is_tupleobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000240 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000241 return NULL;
242 }
243#define b ((tupleobject *)bb)
244 size = a->ob_size + b->ob_size;
245 np = (tupleobject *) newtupleobject(size);
246 if (np == NULL) {
Guido van Rossum49e85141991-06-07 22:59:30 +0000247 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000248 }
249 for (i = 0; i < a->ob_size; i++) {
250 object *v = a->ob_item[i];
251 INCREF(v);
252 np->ob_item[i] = v;
253 }
254 for (i = 0; i < b->ob_size; i++) {
255 object *v = b->ob_item[i];
256 INCREF(v);
257 np->ob_item[i + a->ob_size] = v;
258 }
259 return (object *)np;
260#undef b
261}
262
Guido van Rossumb8393da1991-06-04 19:35:24 +0000263static object *
264tuplerepeat(a, n)
265 tupleobject *a;
266 int n;
267{
268 int i, j;
269 int size;
270 tupleobject *np;
271 object **p;
272 if (n < 0)
273 n = 0;
274 if (a->ob_size*n == a->ob_size) {
275 /* Since tuples are immutable, we can return a shared
276 copy in this case */
277 INCREF(a);
278 return (object *)a;
279 }
280 size = a->ob_size * n;
281 np = (tupleobject *) newtupleobject(size);
282 if (np == NULL)
283 return NULL;
284 p = np->ob_item;
285 for (i = 0; i < n; i++) {
286 for (j = 0; j < a->ob_size; j++) {
287 *p = a->ob_item[j];
288 INCREF(*p);
289 p++;
290 }
291 }
292 return (object *) np;
293}
294
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000295static sequence_methods tuple_as_sequence = {
296 tuplelength, /*sq_length*/
297 tupleconcat, /*sq_concat*/
Guido van Rossumb8393da1991-06-04 19:35:24 +0000298 tuplerepeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000299 tupleitem, /*sq_item*/
300 tupleslice, /*sq_slice*/
301 0, /*sq_ass_item*/
302 0, /*sq_ass_slice*/
303};
304
305typeobject Tupletype = {
306 OB_HEAD_INIT(&Typetype)
307 0,
308 "tuple",
309 sizeof(tupleobject) - sizeof(object *),
310 sizeof(object *),
311 tupledealloc, /*tp_dealloc*/
312 tupleprint, /*tp_print*/
313 0, /*tp_getattr*/
314 0, /*tp_setattr*/
315 tuplecompare, /*tp_compare*/
316 tuplerepr, /*tp_repr*/
317 0, /*tp_as_number*/
318 &tuple_as_sequence, /*tp_as_sequence*/
319 0, /*tp_as_mapping*/
320};