blob: ab2cf181cc2dae24e90f45d5041d0b34c718130f [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
Guido van Rossum7c36ad71992-01-14 18:45:33 +0000231object *
232gettupleslice(op, i, j)
233 object *op;
234 int i, j;
235{
236 if (op == NULL || !is_tupleobject(op)) {
237 err_badcall();
238 return NULL;
239 }
240 return tupleslice((tupleobject *)op, i, j);
241}
242
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000243static object *
244tupleconcat(a, bb)
245 register tupleobject *a;
246 register object *bb;
247{
248 register int size;
249 register int i;
250 tupleobject *np;
251 if (!is_tupleobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000252 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000253 return NULL;
254 }
255#define b ((tupleobject *)bb)
256 size = a->ob_size + b->ob_size;
257 np = (tupleobject *) newtupleobject(size);
258 if (np == NULL) {
Guido van Rossum49e85141991-06-07 22:59:30 +0000259 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000260 }
261 for (i = 0; i < a->ob_size; i++) {
262 object *v = a->ob_item[i];
263 INCREF(v);
264 np->ob_item[i] = v;
265 }
266 for (i = 0; i < b->ob_size; i++) {
267 object *v = b->ob_item[i];
268 INCREF(v);
269 np->ob_item[i + a->ob_size] = v;
270 }
271 return (object *)np;
272#undef b
273}
274
Guido van Rossumb8393da1991-06-04 19:35:24 +0000275static object *
276tuplerepeat(a, n)
277 tupleobject *a;
278 int n;
279{
280 int i, j;
281 int size;
282 tupleobject *np;
283 object **p;
284 if (n < 0)
285 n = 0;
286 if (a->ob_size*n == a->ob_size) {
287 /* Since tuples are immutable, we can return a shared
288 copy in this case */
289 INCREF(a);
290 return (object *)a;
291 }
292 size = a->ob_size * n;
293 np = (tupleobject *) newtupleobject(size);
294 if (np == NULL)
295 return NULL;
296 p = np->ob_item;
297 for (i = 0; i < n; i++) {
298 for (j = 0; j < a->ob_size; j++) {
299 *p = a->ob_item[j];
300 INCREF(*p);
301 p++;
302 }
303 }
304 return (object *) np;
305}
306
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000307static sequence_methods tuple_as_sequence = {
308 tuplelength, /*sq_length*/
309 tupleconcat, /*sq_concat*/
Guido van Rossumb8393da1991-06-04 19:35:24 +0000310 tuplerepeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000311 tupleitem, /*sq_item*/
312 tupleslice, /*sq_slice*/
313 0, /*sq_ass_item*/
314 0, /*sq_ass_slice*/
315};
316
317typeobject Tupletype = {
318 OB_HEAD_INIT(&Typetype)
319 0,
320 "tuple",
321 sizeof(tupleobject) - sizeof(object *),
322 sizeof(object *),
323 tupledealloc, /*tp_dealloc*/
324 tupleprint, /*tp_print*/
325 0, /*tp_getattr*/
326 0, /*tp_setattr*/
327 tuplecompare, /*tp_compare*/
328 tuplerepr, /*tp_repr*/
329 0, /*tp_as_number*/
330 &tuple_as_sequence, /*tp_as_sequence*/
331 0, /*tp_as_mapping*/
332};