blob: bc6874445d642848d8719850a49a62645ef436e4 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum9bfef441993-03-29 10:43:31 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
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
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +000029#ifndef MAXSAVESIZE
30#define MAXSAVESIZE 20
31#endif
32
33#if MAXSAVESIZE > 0
34/* Entries 1 upto MAXSAVESIZE are free lists, entry 0 is the empty
35 tuple () of which at most one instance will be allocated.
36*/
37static tupleobject *free_list[MAXSAVESIZE];
38#endif
39#ifdef COUNT_ALLOCS
40int fast_tuple_allocs;
41int tuple_zero_allocs;
42#endif
43
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000044object *
45newtupleobject(size)
46 register int size;
47{
48 register int i;
49 register tupleobject *op;
50 if (size < 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000051 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000052 return NULL;
53 }
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +000054#if MAXSAVESIZE > 0
55 if (size == 0 && free_list[0]) {
56 op = free_list[0];
57 INCREF(op);
58#ifdef COUNT_ALLOCS
59 tuple_zero_allocs++;
60#endif
61 return (object *) op;
62 }
63 if (0 < size && size < MAXSAVESIZE && (op = free_list[size]) != NULL) {
64 free_list[size] = (tupleobject *) op->ob_item[0];
65#ifdef COUNT_ALLOCS
66 fast_tuple_allocs++;
67#endif
68 } else
69#endif
70 {
71 op = (tupleobject *)
72 malloc(sizeof(tupleobject) + size * sizeof(object *));
73 if (op == NULL)
74 return err_nomem();
75 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000076 op->ob_type = &Tupletype;
77 op->ob_size = size;
78 for (i = 0; i < size; i++)
79 op->ob_item[i] = NULL;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +000080 NEWREF(op);
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +000081#if MAXSAVESIZE > 0
82 if (size == 0) {
83 free_list[0] = op;
84 INCREF(op); /* extra INCREF so that this is never freed */
85 }
86#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000087 return (object *) op;
88}
89
90int
91gettuplesize(op)
92 register object *op;
93{
94 if (!is_tupleobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000095 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000096 return -1;
97 }
98 else
99 return ((tupleobject *)op)->ob_size;
100}
101
102object *
103gettupleitem(op, i)
104 register object *op;
105 register int i;
106{
107 if (!is_tupleobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000108 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000109 return NULL;
110 }
111 if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000112 err_setstr(IndexError, "tuple index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000113 return NULL;
114 }
115 return ((tupleobject *)op) -> ob_item[i];
116}
117
118int
119settupleitem(op, i, newitem)
120 register object *op;
121 register int i;
122 register object *newitem;
123{
124 register object *olditem;
125 if (!is_tupleobject(op)) {
126 if (newitem != NULL)
127 DECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000128 err_badcall();
129 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000130 }
131 if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
132 if (newitem != NULL)
133 DECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000134 err_setstr(IndexError, "tuple assignment index out of range");
135 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000136 }
137 olditem = ((tupleobject *)op) -> ob_item[i];
138 ((tupleobject *)op) -> ob_item[i] = newitem;
139 if (olditem != NULL)
140 DECREF(olditem);
141 return 0;
142}
143
144/* Methods */
145
146static void
147tupledealloc(op)
148 register tupleobject *op;
149{
150 register int i;
151 for (i = 0; i < op->ob_size; i++) {
152 if (op->ob_item[i] != NULL)
153 DECREF(op->ob_item[i]);
154 }
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +0000155#if MAXSAVESIZE > 0
156 if (0 < op->ob_size && op->ob_size < MAXSAVESIZE) {
157 op->ob_item[0] = (object *) free_list[op->ob_size];
158 free_list[op->ob_size] = op;
159 } else
160#endif
161 free((ANY *)op);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000162}
163
Guido van Rossum49e85141991-06-07 22:59:30 +0000164static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000165tupleprint(op, fp, flags)
166 tupleobject *op;
167 FILE *fp;
168 int flags;
169{
170 int i;
171 fprintf(fp, "(");
Guido van Rossum49e85141991-06-07 22:59:30 +0000172 for (i = 0; i < op->ob_size; i++) {
173 if (i > 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000174 fprintf(fp, ", ");
Guido van Rossum49e85141991-06-07 22:59:30 +0000175 if (printobject(op->ob_item[i], fp, flags) != 0)
176 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000177 }
178 if (op->ob_size == 1)
179 fprintf(fp, ",");
180 fprintf(fp, ")");
Guido van Rossum49e85141991-06-07 22:59:30 +0000181 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000182}
183
Guido van Rossum234f9421993-06-17 12:35:49 +0000184static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000185tuplerepr(v)
186 tupleobject *v;
187{
188 object *s, *t, *comma;
189 int i;
190 s = newstringobject("(");
191 comma = newstringobject(", ");
192 for (i = 0; i < v->ob_size && s != NULL; i++) {
193 if (i > 0)
194 joinstring(&s, comma);
195 t = reprobject(v->ob_item[i]);
196 joinstring(&s, t);
197 if (t != NULL)
198 DECREF(t);
199 }
200 DECREF(comma);
201 if (v->ob_size == 1) {
202 t = newstringobject(",");
203 joinstring(&s, t);
204 DECREF(t);
205 }
206 t = newstringobject(")");
207 joinstring(&s, t);
208 DECREF(t);
209 return s;
210}
211
212static int
213tuplecompare(v, w)
214 register tupleobject *v, *w;
215{
216 register int len =
217 (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
218 register int i;
219 for (i = 0; i < len; i++) {
220 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
221 if (cmp != 0)
222 return cmp;
223 }
224 return v->ob_size - w->ob_size;
225}
226
Guido van Rossum9bfef441993-03-29 10:43:31 +0000227static long
228tuplehash(v)
229 tupleobject *v;
230{
231 register long x, y;
232 register int len = v->ob_size;
233 register object **p;
234 x = 0x345678L;
235 p = v->ob_item;
236 while (--len >= 0) {
237 y = hashobject(*p++);
238 if (y == -1)
239 return -1;
240 x = (x + x + x) ^ y;
241 }
242 x ^= v->ob_size;
243 if (x == -1)
244 x = -2;
245 return x;
246}
247
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000248static int
249tuplelength(a)
250 tupleobject *a;
251{
252 return a->ob_size;
253}
254
255static object *
256tupleitem(a, i)
257 register tupleobject *a;
258 register int i;
259{
260 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000261 err_setstr(IndexError, "tuple index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000262 return NULL;
263 }
264 INCREF(a->ob_item[i]);
265 return a->ob_item[i];
266}
267
268static object *
269tupleslice(a, ilow, ihigh)
270 register tupleobject *a;
271 register int ilow, ihigh;
272{
273 register tupleobject *np;
274 register int i;
275 if (ilow < 0)
276 ilow = 0;
277 if (ihigh > a->ob_size)
278 ihigh = a->ob_size;
279 if (ihigh < ilow)
280 ihigh = ilow;
281 if (ilow == 0 && ihigh == a->ob_size) {
282 /* XXX can only do this if tuples are immutable! */
283 INCREF(a);
284 return (object *)a;
285 }
286 np = (tupleobject *)newtupleobject(ihigh - ilow);
287 if (np == NULL)
288 return NULL;
289 for (i = ilow; i < ihigh; i++) {
290 object *v = a->ob_item[i];
291 INCREF(v);
292 np->ob_item[i - ilow] = v;
293 }
294 return (object *)np;
295}
296
Guido van Rossum7c36ad71992-01-14 18:45:33 +0000297object *
298gettupleslice(op, i, j)
299 object *op;
300 int i, j;
301{
302 if (op == NULL || !is_tupleobject(op)) {
303 err_badcall();
304 return NULL;
305 }
306 return tupleslice((tupleobject *)op, i, j);
307}
308
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000309static object *
310tupleconcat(a, bb)
311 register tupleobject *a;
312 register object *bb;
313{
314 register int size;
315 register int i;
316 tupleobject *np;
317 if (!is_tupleobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000318 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000319 return NULL;
320 }
321#define b ((tupleobject *)bb)
322 size = a->ob_size + b->ob_size;
323 np = (tupleobject *) newtupleobject(size);
324 if (np == NULL) {
Guido van Rossum49e85141991-06-07 22:59:30 +0000325 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000326 }
327 for (i = 0; i < a->ob_size; i++) {
328 object *v = a->ob_item[i];
329 INCREF(v);
330 np->ob_item[i] = v;
331 }
332 for (i = 0; i < b->ob_size; i++) {
333 object *v = b->ob_item[i];
334 INCREF(v);
335 np->ob_item[i + a->ob_size] = v;
336 }
337 return (object *)np;
338#undef b
339}
340
Guido van Rossumb8393da1991-06-04 19:35:24 +0000341static object *
342tuplerepeat(a, n)
343 tupleobject *a;
344 int n;
345{
346 int i, j;
347 int size;
348 tupleobject *np;
349 object **p;
350 if (n < 0)
351 n = 0;
352 if (a->ob_size*n == a->ob_size) {
353 /* Since tuples are immutable, we can return a shared
354 copy in this case */
355 INCREF(a);
356 return (object *)a;
357 }
358 size = a->ob_size * n;
359 np = (tupleobject *) newtupleobject(size);
360 if (np == NULL)
361 return NULL;
362 p = np->ob_item;
363 for (i = 0; i < n; i++) {
364 for (j = 0; j < a->ob_size; j++) {
365 *p = a->ob_item[j];
366 INCREF(*p);
367 p++;
368 }
369 }
370 return (object *) np;
371}
372
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000373static sequence_methods tuple_as_sequence = {
374 tuplelength, /*sq_length*/
375 tupleconcat, /*sq_concat*/
Guido van Rossumb8393da1991-06-04 19:35:24 +0000376 tuplerepeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000377 tupleitem, /*sq_item*/
378 tupleslice, /*sq_slice*/
379 0, /*sq_ass_item*/
380 0, /*sq_ass_slice*/
381};
382
383typeobject Tupletype = {
384 OB_HEAD_INIT(&Typetype)
385 0,
386 "tuple",
387 sizeof(tupleobject) - sizeof(object *),
388 sizeof(object *),
389 tupledealloc, /*tp_dealloc*/
390 tupleprint, /*tp_print*/
391 0, /*tp_getattr*/
392 0, /*tp_setattr*/
393 tuplecompare, /*tp_compare*/
394 tuplerepr, /*tp_repr*/
395 0, /*tp_as_number*/
396 &tuple_as_sequence, /*tp_as_sequence*/
397 0, /*tp_as_mapping*/
Guido van Rossum9bfef441993-03-29 10:43:31 +0000398 tuplehash, /*tp_hash*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000399};