source: trunk/essentials/dev-lang/python/Objects/tupleobject.c@ 3393

Last change on this file since 3393 was 3225, checked in by bird, 19 years ago

Python 2.5

File size: 19.7 KB
Line 
1
2/* Tuple object implementation */
3
4#include "Python.h"
5
6/* Speed optimization to avoid frequent malloc/free of small tuples */
7#ifndef MAXSAVESIZE
8#define MAXSAVESIZE 20 /* Largest tuple to save on free list */
9#endif
10#ifndef MAXSAVEDTUPLES
11#define MAXSAVEDTUPLES 2000 /* Maximum number of tuples of each size to save */
12#endif
13
14#if MAXSAVESIZE > 0
15/* Entries 1 up to MAXSAVESIZE are free lists, entry 0 is the empty
16 tuple () of which at most one instance will be allocated.
17*/
18static PyTupleObject *free_tuples[MAXSAVESIZE];
19static int num_free_tuples[MAXSAVESIZE];
20#endif
21#ifdef COUNT_ALLOCS
22int fast_tuple_allocs;
23int tuple_zero_allocs;
24#endif
25
26PyObject *
27PyTuple_New(register Py_ssize_t size)
28{
29 register PyTupleObject *op;
30 Py_ssize_t i;
31 if (size < 0) {
32 PyErr_BadInternalCall();
33 return NULL;
34 }
35#if MAXSAVESIZE > 0
36 if (size == 0 && free_tuples[0]) {
37 op = free_tuples[0];
38 Py_INCREF(op);
39#ifdef COUNT_ALLOCS
40 tuple_zero_allocs++;
41#endif
42 return (PyObject *) op;
43 }
44 if (size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {
45 free_tuples[size] = (PyTupleObject *) op->ob_item[0];
46 num_free_tuples[size]--;
47#ifdef COUNT_ALLOCS
48 fast_tuple_allocs++;
49#endif
50 /* Inline PyObject_InitVar */
51#ifdef Py_TRACE_REFS
52 op->ob_size = size;
53 op->ob_type = &PyTuple_Type;
54#endif
55 _Py_NewReference((PyObject *)op);
56 }
57 else
58#endif
59 {
60 Py_ssize_t nbytes = size * sizeof(PyObject *);
61 /* Check for overflow */
62 if (nbytes / sizeof(PyObject *) != (size_t)size ||
63 (nbytes += sizeof(PyTupleObject) - sizeof(PyObject *))
64 <= 0)
65 {
66 return PyErr_NoMemory();
67 }
68 op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
69 if (op == NULL)
70 return NULL;
71 }
72 for (i=0; i < size; i++)
73 op->ob_item[i] = NULL;
74#if MAXSAVESIZE > 0
75 if (size == 0) {
76 free_tuples[0] = op;
77 ++num_free_tuples[0];
78 Py_INCREF(op); /* extra INCREF so that this is never freed */
79 }
80#endif
81 _PyObject_GC_TRACK(op);
82 return (PyObject *) op;
83}
84
85Py_ssize_t
86PyTuple_Size(register PyObject *op)
87{
88 if (!PyTuple_Check(op)) {
89 PyErr_BadInternalCall();
90 return -1;
91 }
92 else
93 return ((PyTupleObject *)op)->ob_size;
94}
95
96PyObject *
97PyTuple_GetItem(register PyObject *op, register Py_ssize_t i)
98{
99 if (!PyTuple_Check(op)) {
100 PyErr_BadInternalCall();
101 return NULL;
102 }
103 if (i < 0 || i >= ((PyTupleObject *)op) -> ob_size) {
104 PyErr_SetString(PyExc_IndexError, "tuple index out of range");
105 return NULL;
106 }
107 return ((PyTupleObject *)op) -> ob_item[i];
108}
109
110int
111PyTuple_SetItem(register PyObject *op, register Py_ssize_t i, PyObject *newitem)
112{
113 register PyObject *olditem;
114 register PyObject **p;
115 if (!PyTuple_Check(op) || op->ob_refcnt != 1) {
116 Py_XDECREF(newitem);
117 PyErr_BadInternalCall();
118 return -1;
119 }
120 if (i < 0 || i >= ((PyTupleObject *)op) -> ob_size) {
121 Py_XDECREF(newitem);
122 PyErr_SetString(PyExc_IndexError,
123 "tuple assignment index out of range");
124 return -1;
125 }
126 p = ((PyTupleObject *)op) -> ob_item + i;
127 olditem = *p;
128 *p = newitem;
129 Py_XDECREF(olditem);
130 return 0;
131}
132
133PyObject *
134PyTuple_Pack(Py_ssize_t n, ...)
135{
136 Py_ssize_t i;
137 PyObject *o;
138 PyObject *result;
139 PyObject **items;
140 va_list vargs;
141
142 va_start(vargs, n);
143 result = PyTuple_New(n);
144 if (result == NULL)
145 return NULL;
146 items = ((PyTupleObject *)result)->ob_item;
147 for (i = 0; i < n; i++) {
148 o = va_arg(vargs, PyObject *);
149 Py_INCREF(o);
150 items[i] = o;
151 }
152 va_end(vargs);
153 return result;
154}
155
156
157/* Methods */
158
159static void
160tupledealloc(register PyTupleObject *op)
161{
162 register Py_ssize_t i;
163 register Py_ssize_t len = op->ob_size;
164 PyObject_GC_UnTrack(op);
165 Py_TRASHCAN_SAFE_BEGIN(op)
166 if (len > 0) {
167 i = len;
168 while (--i >= 0)
169 Py_XDECREF(op->ob_item[i]);
170#if MAXSAVESIZE > 0
171 if (len < MAXSAVESIZE &&
172 num_free_tuples[len] < MAXSAVEDTUPLES &&
173 op->ob_type == &PyTuple_Type)
174 {
175 op->ob_item[0] = (PyObject *) free_tuples[len];
176 num_free_tuples[len]++;
177 free_tuples[len] = op;
178 goto done; /* return */
179 }
180#endif
181 }
182 op->ob_type->tp_free((PyObject *)op);
183done:
184 Py_TRASHCAN_SAFE_END(op)
185}
186
187static int
188tupleprint(PyTupleObject *op, FILE *fp, int flags)
189{
190 Py_ssize_t i;
191 fprintf(fp, "(");
192 for (i = 0; i < op->ob_size; i++) {
193 if (i > 0)
194 fprintf(fp, ", ");
195 if (PyObject_Print(op->ob_item[i], fp, 0) != 0)
196 return -1;
197 }
198 if (op->ob_size == 1)
199 fprintf(fp, ",");
200 fprintf(fp, ")");
201 return 0;
202}
203
204static PyObject *
205tuplerepr(PyTupleObject *v)