1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Tuple object implementation */
27 #include "allobjects.h"
30 #define MAXSAVESIZE 20
34 /* Entries 1 upto MAXSAVESIZE are free lists, entry 0 is the empty
35 tuple () of which at most one instance will be allocated.
37 static tupleobject
*free_tuples
[MAXSAVESIZE
];
40 int fast_tuple_allocs
;
41 int tuple_zero_allocs
;
49 register tupleobject
*op
;
55 if (size
== 0 && free_tuples
[0]) {
63 if (0 < size
&& size
< MAXSAVESIZE
&& (op
= free_tuples
[size
]) != NULL
) {
64 free_tuples
[size
] = (tupleobject
*) op
->ob_item
[0];
72 malloc(sizeof(tupleobject
) + size
* sizeof(object
*));
76 op
->ob_type
= &Tupletype
;
78 for (i
= 0; i
< size
; i
++)
79 op
->ob_item
[i
] = NULL
;
84 INCREF(op
); /* extra INCREF so that this is never freed */
94 if (!is_tupleobject(op
)) {
99 return ((tupleobject
*)op
)->ob_size
;
107 if (!is_tupleobject(op
)) {
111 if (i
< 0 || i
>= ((tupleobject
*)op
) -> ob_size
) {
112 err_setstr(IndexError
, "tuple index out of range");
115 return ((tupleobject
*)op
) -> ob_item
[i
];
119 settupleitem(op
, i
, newitem
)
124 register object
*olditem
;
126 if (!is_tupleobject(op
)) {
131 if (i
< 0 || i
>= ((tupleobject
*)op
) -> ob_size
) {
133 err_setstr(IndexError
, "tuple assignment index out of range");
136 p
= ((tupleobject
*)op
) -> ob_item
+ i
;
147 register tupleobject
*op
;
150 for (i
= 0; i
< op
->ob_size
; i
++)
151 XDECREF(op
->ob_item
[i
]);
153 if (0 < op
->ob_size
&& op
->ob_size
< MAXSAVESIZE
) {
154 op
->ob_item
[0] = (object
*) free_tuples
[op
->ob_size
];
155 free_tuples
[op
->ob_size
] = op
;
162 tupleprint(op
, fp
, flags
)
169 for (i
= 0; i
< op
->ob_size
; i
++) {
172 if (printobject(op
->ob_item
[i
], fp
, 0) != 0)
175 if (op
->ob_size
== 1)
187 s
= newstringobject("(");
188 comma
= newstringobject(", ");
189 for (i
= 0; i
< v
->ob_size
&& s
!= NULL
; i
++) {
191 joinstring(&s
, comma
);
192 joinstring_decref(&s
, reprobject(v
->ob_item
[i
]));
196 joinstring_decref(&s
, newstringobject(","));
197 joinstring_decref(&s
, newstringobject(")"));
203 register tupleobject
*v
, *w
;
206 (v
->ob_size
< w
->ob_size
) ? v
->ob_size
: w
->ob_size
;
208 for (i
= 0; i
< len
; i
++) {
209 int cmp
= cmpobject(v
->ob_item
[i
], w
->ob_item
[i
]);
213 return v
->ob_size
- w
->ob_size
;
221 register int len
= v
->ob_size
;
226 y
= hashobject(*p
++);
246 register tupleobject
*a
;
249 if (i
< 0 || i
>= a
->ob_size
) {
250 err_setstr(IndexError
, "tuple index out of range");
253 INCREF(a
->ob_item
[i
]);
254 return a
->ob_item
[i
];
258 tupleslice(a
, ilow
, ihigh
)
259 register tupleobject
*a
;
260 register int ilow
, ihigh
;
262 register tupleobject
*np
;
266 if (ihigh
> a
->ob_size
)
270 if (ilow
== 0 && ihigh
== a
->ob_size
) {
271 /* XXX can only do this if tuples are immutable! */
275 np
= (tupleobject
*)newtupleobject(ihigh
- ilow
);
278 for (i
= ilow
; i
< ihigh
; i
++) {
279 object
*v
= a
->ob_item
[i
];
281 np
->ob_item
[i
- ilow
] = v
;
287 gettupleslice(op
, i
, j
)
291 if (op
== NULL
|| !is_tupleobject(op
)) {
295 return tupleslice((tupleobject
*)op
, i
, j
);
300 register tupleobject
*a
;
306 if (!is_tupleobject(bb
)) {
310 #define b ((tupleobject *)bb)
311 size
= a
->ob_size
+ b
->ob_size
;
312 np
= (tupleobject
*) newtupleobject(size
);
316 for (i
= 0; i
< a
->ob_size
; i
++) {
317 object
*v
= a
->ob_item
[i
];
321 for (i
= 0; i
< b
->ob_size
; i
++) {
322 object
*v
= b
->ob_item
[i
];
324 np
->ob_item
[i
+ a
->ob_size
] = v
;
341 if (a
->ob_size
*n
== a
->ob_size
) {
342 /* Since tuples are immutable, we can return a shared
347 size
= a
->ob_size
* n
;
348 np
= (tupleobject
*) newtupleobject(size
);
352 for (i
= 0; i
< n
; i
++) {
353 for (j
= 0; j
< a
->ob_size
; j
++) {
359 return (object
*) np
;
362 static sequence_methods tuple_as_sequence
= {
363 (inquiry
)tuplelength
, /*sq_length*/
364 (binaryfunc
)tupleconcat
, /*sq_concat*/
365 (intargfunc
)tuplerepeat
, /*sq_repeat*/
366 (intargfunc
)tupleitem
, /*sq_item*/
367 (intintargfunc
)tupleslice
, /*sq_slice*/
372 typeobject Tupletype
= {
373 OB_HEAD_INIT(&Typetype
)
376 sizeof(tupleobject
) - sizeof(object
*),
378 (destructor
)tupledealloc
, /*tp_dealloc*/
379 (printfunc
)tupleprint
, /*tp_print*/
382 (cmpfunc
)tuplecompare
, /*tp_compare*/
383 (reprfunc
)tuplerepr
, /*tp_repr*/
385 &tuple_as_sequence
, /*tp_as_sequence*/
387 (hashfunc
)tuplehash
, /*tp_hash*/
390 /* The following function breaks the notion that tuples are immutable:
391 it changes the size of a tuple. We get away with this only if there
392 is only one module referencing the object. You can also think of it
393 as creating a new tuple object and destroying the old one, only
394 more efficiently. In any case, don't use this if the tuple may
395 already be known to some other part of the code...
396 If last_is_sticky is set, the tuple will grow or shrink at the
397 front, otherwise it will grow or shrink at the end. */
400 resizetuple(pv
, newsize
, last_is_sticky
)
405 register tupleobject
*v
;
406 register tupleobject
*sv
;
410 v
= (tupleobject
*) *pv
;
411 sizediff
= newsize
- v
->ob_size
;
412 if (!is_tupleobject(v
) || v
->ob_refcnt
!= 1) {
420 /* XXX UNREF/NEWREF interface should be more symmetrical */
425 if (last_is_sticky
&& sizediff
< 0) {
426 /* shrinking: move entries to the front and zero moved entries */
427 for (i
= 0; i
< newsize
; i
++) {
428 XDECREF(v
->ob_item
[i
]);
429 v
->ob_item
[i
] = v
->ob_item
[i
- sizediff
];
430 v
->ob_item
[i
- sizediff
] = NULL
;
433 for (i
= newsize
; i
< v
->ob_size
; i
++) {
434 XDECREF(v
->ob_item
[i
]);
435 v
->ob_item
[i
] = NULL
;
439 sizeof(tupleobject
) + newsize
* sizeof(object
*));
447 for (i
= sv
->ob_size
; i
< newsize
; i
++)
448 sv
->ob_item
[i
] = NULL
;
449 if (last_is_sticky
&& sizediff
> 0) {
450 /* growing: move entries to the end and zero moved entries */
451 for (i
= newsize
- 1; i
>= sizediff
; i
--) {
452 sv
->ob_item
[i
] = sv
->ob_item
[i
- sizediff
];
453 sv
->ob_item
[i
- sizediff
] = NULL
;
456 sv
->ob_size
= newsize
;