blob: 68fed9e45facf8887858d69bad047b6e8b64df79 [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*/
Sjoerd Mullender615194a1993-11-01 13:46:50 +000037static tupleobject *free_tuples[MAXSAVESIZE];
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +000038#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
Sjoerd Mullender615194a1993-11-01 13:46:50 +000055 if (size == 0 && free_tuples[0]) {
56 op = free_tuples[0];
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +000057 INCREF(op);
58#ifdef COUNT_ALLOCS
59 tuple_zero_allocs++;
60#endif
61 return (object *) op;
62 }
Sjoerd Mullender615194a1993-11-01 13:46:50 +000063 if (0 < size && size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {
64 free_tuples[size] = (tupleobject *) op->ob_item[0];
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +000065#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) {
Sjoerd Mullender615194a1993-11-01 13:46:50 +000083 free_tuples[0] = op;
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +000084 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)) {
Guido van Rossum12d12c51993-10-26 17:58:25 +0000126 XDECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000127 err_badcall();
128 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000129 }
130 if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
Guido van Rossum12d12c51993-10-26 17:58:25 +0000131 XDECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000132 err_setstr(IndexError, "tuple assignment index out of range");
133 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000134 }
135 olditem = ((tupleobject *)op) -> ob_item[i];
136 ((tupleobject *)op) -> ob_item[i] = newitem;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000137 XDECREF(olditem);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000138 return 0;
139}
140
141/* Methods */
142
143static void
144tupledealloc(op)
145 register tupleobject *op;
146{
147 register int i;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000148 for (i = 0; i < op->ob_size; i++)
149 XDECREF(op->ob_item[i]);
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +0000150#if MAXSAVESIZE > 0
151 if (0 < op->ob_size && op->ob_size < MAXSAVESIZE) {
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000152 op->ob_item[0] = (object *) free_tuples[op->ob_size];
153 free_tuples[op->ob_size] = op;
Sjoerd Mullender842d2cc1993-10-15 16:18:48 +0000154 } else
155#endif
156 free((ANY *)op);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000157}
158
Guido van Rossum49e85141991-06-07 22:59:30 +0000159static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000160tupleprint(op, fp, flags)
161 tupleobject *op;
162 FILE *fp;
163 int flags;
164{
165 int i;
166 fprintf(fp, "(");
Guido van Rossum49e85141991-06-07 22:59:30 +0000167 for (i = 0; i < op->ob_size; i++) {
168 if (i > 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000169 fprintf(fp, ", ");
Guido van Rossum49e85141991-06-07 22:59:30 +0000170 if (printobject(op->ob_item[i], fp, flags) != 0)
171 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000172 }
173 if (op->ob_size == 1)
174 fprintf(fp, ",");
175 fprintf(fp, ")");
Guido van Rossum49e85141991-06-07 22:59:30 +0000176 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000177}
178
Guido van Rossum234f9421993-06-17 12:35:49 +0000179static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000180tuplerepr(v)
181 tupleobject *v;
182{
183 object *s, *t, *comma;
184 int i;
185 s = newstringobject("(");
186 comma = newstringobject(", ");
187 for (i = 0; i < v->ob_size && s != NULL; i++) {
188 if (i > 0)
189 joinstring(&s, comma);
190 t = reprobject(v->ob_item[i]);
191 joinstring(&s, t);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000192 XDECREF(t);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000193 }
194 DECREF(comma);
195 if (v->ob_size == 1) {
196 t = newstringobject(",");
197 joinstring(&s, t);
198 DECREF(t);
199 }
200 t = newstringobject(")");
201 joinstring(&s, t);
202 DECREF(t);
203 return s;
204}
205
206static int
207tuplecompare(v, w)
208 register tupleobject *v, *w;
209{
210 register int len =
211 (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
212 register int i;
213 for (i = 0; i < len; i++) {
214 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
215 if (cmp != 0)
216 return cmp;
217 }
218 return v->ob_size - w->ob_size;
219}
220
Guido van Rossum9bfef441993-03-29 10:43:31 +0000221static long
222tuplehash(v)
223 tupleobject *v;
224{
225 register long x, y;
226 register int len = v->ob_size;
227 register object **p;
228 x = 0x345678L;
229 p = v->ob_item;
230 while (--len >= 0) {
231 y = hashobject(*p++);
232 if (y == -1)
233 return -1;
234 x = (x + x + x) ^ y;
235 }
236 x ^= v->ob_size;
237 if (x == -1)
238 x = -2;
239 return x;
240}
241
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000242static int
243tuplelength(a)
244 tupleobject *a;
245{
246 return a->ob_size;
247}
248
249static object *
250tupleitem(a, i)
251 register tupleobject *a;
252 register int i;
253{
254 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000255 err_setstr(IndexError, "tuple index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000256 return NULL;
257 }
258 INCREF(a->ob_item[i]);
259 return a->ob_item[i];
260}
261
262static object *
263tupleslice(a, ilow, ihigh)
264 register tupleobject *a;
265 register int ilow, ihigh;
266{
267 register tupleobject *np;
268 register int i;
269 if (ilow < 0)
270 ilow = 0;
271 if (ihigh > a->ob_size)
272 ihigh = a->ob_size;
273 if (ihigh < ilow)
274 ihigh = ilow;
275 if (ilow == 0 && ihigh == a->ob_size) {
276 /* XXX can only do this if tuples are immutable! */
277 INCREF(a);
278 return (object *)a;
279 }
280 np = (tupleobject *)newtupleobject(ihigh - ilow);
281 if (np == NULL)
282 return NULL;
283 for (i = ilow; i < ihigh; i++) {
284 object *v = a->ob_item[i];
285 INCREF(v);
286 np->ob_item[i - ilow] = v;
287 }
288 return (object *)np;
289}
290
Guido van Rossum7c36ad71992-01-14 18:45:33 +0000291object *
292gettupleslice(op, i, j)
293 object *op;
294 int i, j;
295{
296 if (op == NULL || !is_tupleobject(op)) {
297 err_badcall();
298 return NULL;
299 }
300 return tupleslice((tupleobject *)op, i, j);
301}
302
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000303static object *
304tupleconcat(a, bb)
305 register tupleobject *a;
306 register object *bb;
307{
308 register int size;
309 register int i;
310 tupleobject *np;
311 if (!is_tupleobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000312 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000313 return NULL;
314 }
315#define b ((tupleobject *)bb)
316 size = a->ob_size + b->ob_size;
317 np = (tupleobject *) newtupleobject(size);
318 if (np == NULL) {
Guido van Rossum49e85141991-06-07 22:59:30 +0000319 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000320 }
321 for (i = 0; i < a->ob_size; i++) {
322 object *v = a->ob_item[i];
323 INCREF(v);
324 np->ob_item[i] = v;
325 }
326 for (i = 0; i < b->ob_size; i++) {
327 object *v = b->ob_item[i];
328 INCREF(v);
329 np->ob_item[i + a->ob_size] = v;
330 }
331 return (object *)np;
332#undef b
333}
334
Guido van Rossumb8393da1991-06-04 19:35:24 +0000335static object *
336tuplerepeat(a, n)
337 tupleobject *a;
338 int n;
339{
340 int i, j;
341 int size;
342 tupleobject *np;
343 object **p;
344 if (n < 0)
345 n = 0;
346 if (a->ob_size*n == a->ob_size) {
347 /* Since tuples are immutable, we can return a shared
348 copy in this case */
349 INCREF(a);
350 return (object *)a;
351 }
352 size = a->ob_size * n;
353 np = (tupleobject *) newtupleobject(size);
354 if (np == NULL)
355 return NULL;
356 p = np->ob_item;
357 for (i = 0; i < n; i++) {
358 for (j = 0; j < a->ob_size; j++) {
359 *p = a->ob_item[j];
360 INCREF(*p);
361 p++;
362 }
363 }
364 return (object *) np;
365}
366
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000367static sequence_methods tuple_as_sequence = {
368 tuplelength, /*sq_length*/
369 tupleconcat, /*sq_concat*/
Guido van Rossumb8393da1991-06-04 19:35:24 +0000370 tuplerepeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000371 tupleitem, /*sq_item*/
372 tupleslice, /*sq_slice*/
373 0, /*sq_ass_item*/
374 0, /*sq_ass_slice*/
375};
376
377typeobject Tupletype = {
378 OB_HEAD_INIT(&Typetype)
379 0,
380 "tuple",
381 sizeof(tupleobject) - sizeof(object *),
382 sizeof(object *),
383 tupledealloc, /*tp_dealloc*/
384 tupleprint, /*tp_print*/
385 0, /*tp_getattr*/
386 0, /*tp_setattr*/
387 tuplecompare, /*tp_compare*/
388 tuplerepr, /*tp_repr*/
389 0, /*tp_as_number*/
390 &tuple_as_sequence, /*tp_as_sequence*/
391 0, /*tp_as_mapping*/
Guido van Rossum9bfef441993-03-29 10:43:31 +0000392 tuplehash, /*tp_hash*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000393};
Guido van Rossum12d12c51993-10-26 17:58:25 +0000394
395/* The following function breaks the notion that tuples are immutable:
396 it changes the size of a tuple. We get away with this only if there
397 is only one module referencing the object. You can also think of it
398 as creating a new tuple object and destroying the old one, only
399 more efficiently. In any case, don't use this if the tuple may
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000400 already be known to some other part of the code...
401 If last_is_sticky is set, the tuple will grow or shrink at the
402 front, otherwise it will grow or shrink at the end. */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000403
404int
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000405resizetuple(pv, newsize, last_is_sticky)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000406 object **pv;
407 int newsize;
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000408 int last_is_sticky;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000409{
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000410 register tupleobject *v;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000411 register tupleobject *sv;
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000412 int i;
413 int sizediff;
414
415 v = (tupleobject *) *pv;
416 sizediff = newsize - v->ob_size;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000417 if (!is_tupleobject(v) || v->ob_refcnt != 1) {
418 *pv = 0;
419 DECREF(v);
420 err_badcall();
421 return -1;
422 }
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000423 if (sizediff == 0)
424 return 0;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000425 /* XXX UNREF/NEWREF interface should be more symmetrical */
426#ifdef REF_DEBUG
427 --ref_total;
428#endif
429 UNREF(v);
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000430 if (last_is_sticky && sizediff < 0) {
431 /* shrinking: move entries to the front and zero moved entries */
432 for (i = 0; i < newsize; i++) {
433 XDECREF(v->ob_item[i]);
434 v->ob_item[i] = v->ob_item[i - sizediff];
435 v->ob_item[i - sizediff] = NULL;
436 }
437 }
438 for (i = newsize; i < v->ob_size; i++) {
439 XDECREF(v->ob_item[i]);
440 v->ob_item[i] = NULL;
441 }
442 sv = (tupleobject *)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000443 realloc((char *)v,
444 sizeof(tupleobject) + newsize * sizeof(object *));
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000445 *pv = (object *) sv;
446 if (sv == NULL) {
Guido van Rossum12d12c51993-10-26 17:58:25 +0000447 DEL(v);
448 err_nomem();
449 return -1;
450 }
Sjoerd Mullender615194a1993-11-01 13:46:50 +0000451 NEWREF(sv);
452 for (i = sv->ob_size; i < newsize; i++)
453 sv->ob_item[i] = NULL;
454 if (last_is_sticky && sizediff > 0) {
455 /* growing: move entries to the end and zero moved entries */
456 for (i = newsize - 1; i >= sizediff; i--) {
457 sv->ob_item[i] = sv->ob_item[i - sizediff];
458 sv->ob_item[i - sizediff] = NULL;
459 }
460 }
461 sv->ob_size = newsize;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000462 return 0;
463}