/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
/* Copyright (C) 2009, 2010 Canonical Ltd
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
2
 * 
3
 * This program is free software; you can redistribute it and/or modify
4
 * it under the terms of the GNU General Public License as published by
5
 * the Free Software Foundation; either version 2 of the License, or
6
 * (at your option) any later version.
7
 *
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 * GNU General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU General Public License
14
 * along with this program; if not, write to the Free Software
15
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4679.3.5 by John Arbash Meinel
Have a pure-python implementation that works as tuples of tuples of strings,
16
 */
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
17
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
18
/* Must be defined before importing _static_tuple_c.h so that we get the right
19
 * linkage.
20
 */
21
#define STATIC_TUPLE_MODULE
22
4736.1.1 by John Arbash Meinel
Py_ssize_t and its associated function typedefs are not available w/ python 2.4
23
#include <Python.h>
24
#include "python-compat.h"
25
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
26
#include "_static_tuple_c.h"
27
#include "_export_c_api.h"
4679.5.11 by John Arbash Meinel
add a hack-around to handle differences between pyrex 0.9.6 and 0.9.8
28
4679.3.76 by John Arbash Meinel
Rename StaticTupleInterner => SimpleSet.
29
#include "_simple_set_pyx_api.h"
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
30
31
#if defined(__GNUC__)
32
#   define inline __inline__
33
#elif defined(_MSC_VER)
34
#   define inline __inline
35
#else
36
#   define inline
37
#endif
38
39
4679.3.44 by John Arbash Meinel
Special case the empty tuple as a singleton.
40
/* The one and only StaticTuple with no values */
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
41
static StaticTuple *_empty_tuple = NULL;
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
42
static PyObject *_interned_tuples = NULL;
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
43
44
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
45
static inline int
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
46
_StaticTuple_is_interned(StaticTuple *self)
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
47
{
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
48
    return self->flags & STATIC_TUPLE_INTERNED_FLAG;
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
49
}
50
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
51
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
52
53
static PyObject *
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
54
StaticTuple_as_tuple(StaticTuple *self)
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
55
{
56
    PyObject *tpl = NULL, *obj = NULL;
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
57
    int i, len;
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
58
4679.3.37 by John Arbash Meinel
Change the Key header a bit. It is simpler if you use unsigned char
59
    len = self->size;
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
60
    tpl = PyTuple_New(len);
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
61
    if (!tpl) {
62
        /* Malloc failure */
63
        return NULL;
64
    }
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
65
    for (i = 0; i < len; ++i) {
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
66
        obj = (PyObject *)self->items[i];
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
67
        Py_INCREF(obj);
68
        PyTuple_SET_ITEM(tpl, i, obj);
69
    }
70
    return tpl;
71
}
72
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
73
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
74
static char StaticTuple_as_tuple_doc[] = "as_tuple() => tuple";
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
75
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
76
static StaticTuple *
77
StaticTuple_Intern(StaticTuple *self)
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
78
{
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
79
    PyObject *canonical_tuple = NULL;
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
80
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
81
    if (_interned_tuples == NULL || _StaticTuple_is_interned(self)) {
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
82
        Py_INCREF(self);
83
        return self;
84
    }
4679.3.76 by John Arbash Meinel
Rename StaticTupleInterner => SimpleSet.
85
    /* SimpleSet_Add returns whatever object is present at self
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
86
     * or the new object if it needs to add it.
87
     */
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
88
    canonical_tuple = SimpleSet_Add(_interned_tuples, (PyObject *)self);
89
    if (!canonical_tuple) {
90
        // Some sort of exception, propogate it.
91
        return NULL;
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
92
    }
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
93
    if (canonical_tuple != (PyObject *)self) {
94
        // There was already a tuple with that value
95
        return (StaticTuple *)canonical_tuple;
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
96
    }
97
    self->flags |= STATIC_TUPLE_INTERNED_FLAG;
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
98
    // The two references in the dict do not count, so that the StaticTuple
99
    // object does not become immortal just because it was interned.
7490.147.1 by Victor Stinner
Port to Python 3.10
100
    Py_SET_REFCNT(self, Py_REFCNT(self) - 1);
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
101
    return self;
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
102
}
103
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
104
static char StaticTuple_Intern_doc[] = "intern() => unique StaticTuple\n"
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
105
    "Return a 'canonical' StaticTuple object.\n"
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
106
    "Similar to intern() for strings, this makes sure there\n"
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
107
    "is only one StaticTuple object for a given value\n."
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
108
    "Common usage is:\n"
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
109
    "  key = StaticTuple('foo', 'bar').intern()\n";
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
110
111
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
112
static void
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
113
StaticTuple_dealloc(StaticTuple *self)
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
114
{
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
115
    int i, len;
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
116
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
117
    if (_StaticTuple_is_interned(self)) {
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
118
        /* revive dead object temporarily for Discard */
7490.147.1 by Victor Stinner
Port to Python 3.10
119
        Py_SET_REFCNT(self, 2);
4679.3.76 by John Arbash Meinel
Rename StaticTupleInterner => SimpleSet.
120
        if (SimpleSet_Discard(_interned_tuples, (PyObject*)self) != 1)
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
121
            Py_FatalError("deletion of interned StaticTuple failed");
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
122
        self->flags &= ~STATIC_TUPLE_INTERNED_FLAG;
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
123
    }
4679.3.37 by John Arbash Meinel
Change the Key header a bit. It is simpler if you use unsigned char
124
    len = self->size;
4679.3.33 by John Arbash Meinel
Change Key away from being a PyVarObject.
125
    for (i = 0; i < len; ++i) {
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
126
        Py_XDECREF(self->items[i]);
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
127
    }
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
128
    Py_TYPE(self)->tp_free((PyObject *)self);
129
}
130
131
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
132
/* Similar to PyTuple_New() */
133
static StaticTuple *
134
StaticTuple_New(Py_ssize_t size)
135
{
136
    StaticTuple *stuple;
137
4759.2.7 by John Arbash Meinel
Re-implement StaticTuple_add() inline, rather that thunking over to tuples.
138
    if (size < 0 || size > 255) {
139
        /* Too big or too small */
140
        PyErr_SetString(PyExc_ValueError, "StaticTuple(...)"
141
            " takes from 0 to 255 items");
142
        return NULL;
143
    }
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
144
    if (size == 0 && _empty_tuple != NULL) {
145
        Py_INCREF(_empty_tuple);
146
        return _empty_tuple;
147
    }
148
    /* Note that we use PyObject_NewVar because we want to allocate a variable
149
     * width entry. However we *aren't* truly a PyVarObject because we don't
150
     * use a long for ob_size. Instead we use a plain 'size' that is an int,
151
     * and will be overloaded with flags in the future.
152
     * As such we do the alloc, and then have to clean up anything it does
153
     * incorrectly.
154
     */
155
    stuple = PyObject_NewVar(StaticTuple, &StaticTuple_Type, size);
156
    if (stuple == NULL) {
157
        return NULL;
158
    }
159
    stuple->size = size;
160
    stuple->flags = 0;
161
    stuple->_unused0 = 0;
162
    stuple->_unused1 = 0;
163
    if (size > 0) {
164
        memset(stuple->items, 0, sizeof(PyObject *) * size);
165
    }
166
#if STATIC_TUPLE_HAS_HASH
167
    stuple->hash = -1;
168
#endif
169
    return stuple;
170
}
171
172
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
173
static StaticTuple *
174
StaticTuple_FromSequence(PyObject *sequence)
175
{
4771.2.2 by John Arbash Meinel
Clean up the C code a bit, using a goto.
176
    StaticTuple *new = NULL;
4771.2.1 by Matt Nordhoff
_static_tuple_c.StaticTuple.from_sequence() now supports arbitrary iterables (by converting them to tuples first).
177
    PyObject *as_tuple = NULL;
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
178
    PyObject *item;
179
    Py_ssize_t i, size;
180
181
    if (StaticTuple_CheckExact(sequence)) {
182
        Py_INCREF(sequence);
183
        return (StaticTuple *)sequence;
184
    }
185
    if (!PySequence_Check(sequence)) {
4771.2.1 by Matt Nordhoff
_static_tuple_c.StaticTuple.from_sequence() now supports arbitrary iterables (by converting them to tuples first).
186
        as_tuple = PySequence_Tuple(sequence);
4771.2.2 by John Arbash Meinel
Clean up the C code a bit, using a goto.
187
        if (as_tuple == NULL)
188
            goto done;
4771.2.1 by Matt Nordhoff
_static_tuple_c.StaticTuple.from_sequence() now supports arbitrary iterables (by converting them to tuples first).
189
        sequence = as_tuple;
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
190
    }
191
    size = PySequence_Size(sequence);
4771.2.1 by Matt Nordhoff
_static_tuple_c.StaticTuple.from_sequence() now supports arbitrary iterables (by converting them to tuples first).
192
    if (size == -1) {
4771.2.2 by John Arbash Meinel
Clean up the C code a bit, using a goto.
193
        goto done;
4771.2.1 by Matt Nordhoff
_static_tuple_c.StaticTuple.from_sequence() now supports arbitrary iterables (by converting them to tuples first).
194
    }
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
195
    new = StaticTuple_New(size);
196
    if (new == NULL) {
4771.2.2 by John Arbash Meinel
Clean up the C code a bit, using a goto.
197
        goto done;
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
198
    }
199
    for (i = 0; i < size; ++i) {
200
        // This returns a new reference, which we then 'steal' with 
201
        // StaticTuple_SET_ITEM
202
        item = PySequence_GetItem(sequence, i);
203
        if (item == NULL) {
204
            Py_DECREF(new);
4771.2.2 by John Arbash Meinel
Clean up the C code a bit, using a goto.
205
            new = NULL;
206
            goto done;
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
207
        }
208
        StaticTuple_SET_ITEM(new, i, item);
209
    }
4771.2.2 by John Arbash Meinel
Clean up the C code a bit, using a goto.
210
done:
4771.2.1 by Matt Nordhoff
_static_tuple_c.StaticTuple.from_sequence() now supports arbitrary iterables (by converting them to tuples first).
211
    Py_XDECREF(as_tuple);
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
212
    return (StaticTuple *)new;
213
}
214
215
static StaticTuple *
216
StaticTuple_from_sequence(PyObject *self, PyObject *args, PyObject *kwargs)
217
{
218
    PyObject *sequence;
219
    if (!PyArg_ParseTuple(args, "O", &sequence))
220
        return NULL;
221
    return StaticTuple_FromSequence(sequence);
222
}
223
224
4759.2.6 by John Arbash Meinel
factor out the check of each internal item.
225
/* Check that all items we point to are 'valid' */
226
static int
227
StaticTuple_check_items(StaticTuple *self)
228
{
229
    int i;
230
    PyObject *obj;
231
232
    for (i = 0; i < self->size; ++i) {
233
        obj = self->items[i];
234
        if (obj == NULL) {
235
            PyErr_SetString(PyExc_RuntimeError, "StaticTuple(...)"
236
                " should not have a NULL entry.");
237
            return 0;
238
        }
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
239
        if (PyBytes_CheckExact(obj)
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
240
            || StaticTuple_CheckExact(obj)
241
            || obj == Py_None
242
            || PyBool_Check(obj)
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
243
#if PY_MAJOR_VERSION >= 3
244
#else
4759.2.11 by John Arbash Meinel
Review feedback from Andrew.
245
            || PyInt_CheckExact(obj)
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
246
#endif
4759.2.11 by John Arbash Meinel
Review feedback from Andrew.
247
            || PyLong_CheckExact(obj)
248
            || PyFloat_CheckExact(obj)
249
            || PyUnicode_CheckExact(obj)
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
250
            ) continue;
251
        PyErr_Format(PyExc_TypeError, "StaticTuple(...)"
252
            " requires that all items are one of"
253
            " str, StaticTuple, None, bool, int, long, float, or unicode"
254
            " not %s.", Py_TYPE(obj)->tp_name);
255
        return 0;
4759.2.6 by John Arbash Meinel
factor out the check of each internal item.
256
    }
257
    return 1;
258
}
259
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
260
static PyObject *
4679.5.9 by John Arbash Meinel
NEWS entry for StaticTuple class.
261
StaticTuple_new_constructor(PyTypeObject *type, PyObject *args, PyObject *kwds)
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
262
{
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
263
    StaticTuple *self;
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
264
    PyObject *obj = NULL;
265
    Py_ssize_t i, len = 0;
266
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
267
    if (type != &StaticTuple_Type) {
268
        PyErr_SetString(PyExc_TypeError, "we only support creating StaticTuple");
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
269
        return NULL;
270
    }
271
    if (!PyTuple_CheckExact(args)) {
272
        PyErr_SetString(PyExc_TypeError, "args must be a tuple");
273
        return NULL;
274
    }
275
    len = PyTuple_GET_SIZE(args);
4763.2.3 by Matt Nordhoff
Make StaticTuple_New always raise a ValueError, and StaticTuple_new_constructor always raise a TypeError.
276
    if (len < 0 || len > 255) {
277
        /* Check the length here so we can raise a TypeError instead of
278
         * StaticTuple_New's ValueError.
279
         */
280
        PyErr_SetString(PyExc_TypeError, "StaticTuple(...)"
281
            " takes from 0 to 255 items");
282
        return NULL;
283
    }
4679.3.44 by John Arbash Meinel
Special case the empty tuple as a singleton.
284
    self = (StaticTuple *)StaticTuple_New(len);
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
285
    if (self == NULL) {
286
        return NULL;
287
    }
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
288
    for (i = 0; i < len; ++i) {
289
        obj = PyTuple_GET_ITEM(args, i);
290
        Py_INCREF(obj);
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
291
        self->items[i] = obj;
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
292
    }
4759.2.6 by John Arbash Meinel
factor out the check of each internal item.
293
    if (!StaticTuple_check_items(self)) {
294
        type->tp_dealloc((PyObject *)self);
295
        return NULL;
296
    }
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
297
    return (PyObject *)self;
298
}
299
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
300
static PyObject *
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
301
StaticTuple_repr(StaticTuple *self)
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
302
{
4679.3.79 by John Arbash Meinel
Change the repr to print out 'StaticTuple'
303
    PyObject *as_tuple, *tuple_repr, *result;
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
304
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
305
    as_tuple = StaticTuple_as_tuple(self);
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
306
    if (as_tuple == NULL) {
307
        return NULL;
308
    }
4679.3.79 by John Arbash Meinel
Change the repr to print out 'StaticTuple'
309
    tuple_repr = PyObject_Repr(as_tuple);
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
310
    Py_DECREF(as_tuple);
4679.3.79 by John Arbash Meinel
Change the repr to print out 'StaticTuple'
311
    if (tuple_repr == NULL) {
312
        return NULL;
313
    }
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
314
#if PY_MAJOR_VERSION >= 3
315
    result = PyUnicode_FromFormat("StaticTuple%U", tuple_repr);
316
#else
4759.2.14 by Matt Nordhoff
Hardcode "StaticTuple" in repr instead of using tp_name, since that includes the module now.
317
    result = PyString_FromFormat("StaticTuple%s",
318
                                 PyString_AsString(tuple_repr));
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
319
#endif
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
320
    return result;
321
}
322
7290.38.1 by Jelmer Vernooij
Backport python3.8 support patch to breezy 3.0.
323
/* adapted from tuplehash(), is the specific hash value considered
324
 * 'stable'?
325
 */
326
327
#if PY_MAJOR_VERSION > 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 8)
328
/* Hash for tuples. This is a slightly simplified version of the xxHash
329
   non-cryptographic hash:
330
   - we do not use any parallellism, there is only 1 accumulator.
331
   - we drop the final mixing since this is just a permutation of the
332
     output space: it does not help against collisions.
333
   - at the end, we mangle the length with a single constant.
334
   For the xxHash specification, see
335
   https://github.com/Cyan4973/xxHash/blob/master/doc/xxhash_spec.md
336
337
   Below are the official constants from the xxHash specification. Optimizing
338
   compilers should emit a single "rotate" instruction for the
339
   _PyHASH_XXROTATE() expansion. If that doesn't happen for some important
340
   platform, the macro could be changed to expand to a platform-specific rotate
341
   spelling instead.
342
*/
343
#if SIZEOF_PY_UHASH_T > 4
344
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
345
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
346
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
347
#define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33))  /* Rotate left 31 bits */
348
#else
349
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
350
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
351
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
352
#define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19))  /* Rotate left 13 bits */
353
#endif
354
355
/* Tests have shown that it's not worth to cache the hash value, see
356
   https://bugs.python.org/issue9685 */
357
static Py_hash_t
358
StaticTuple_hash(StaticTuple *self)
359
{
360
    Py_ssize_t i, len = self->size;
361
    PyObject **item = self->items;
362
363
#if STATIC_TUPLE_HAS_HASH
364
    if (self->hash != -1) {
365
        return self->hash;
366
    }
367
#endif
368
369
    Py_uhash_t acc = _PyHASH_XXPRIME_5;
370
    for (i = 0; i < len; i++) {
371
        Py_uhash_t lane = PyObject_Hash(item[i]);
372
        if (lane == (Py_uhash_t)-1) {
373
            return -1;
374
        }
375
        acc += lane * _PyHASH_XXPRIME_2;
376
        acc = _PyHASH_XXROTATE(acc);
377
        acc *= _PyHASH_XXPRIME_1;
378
    }
379
380
    /* Add input length, mangled to keep the historical value of hash(()). */
381
    acc += len ^ (_PyHASH_XXPRIME_5 ^ 3527539UL);
382
383
    if (acc == (Py_uhash_t)-1) {
384
        acc = 1546275796;
385
    }
386
387
#if STATIC_TUPLE_HAS_HASH
388
    self->hash = acc;
389
#endif
390
    return acc;
391
}
392
393
394
#else
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
395
static long
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
396
StaticTuple_hash(StaticTuple *self)
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
397
{
4679.3.22 by John Arbash Meinel
It seems that optimizing Keys_hash is not the way to go for 'bzr log' performance.
398
    /* adapted from tuplehash(), is the specific hash value considered
399
     * 'stable'?
400
     */
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
401
    register long x, y;
402
    Py_ssize_t len = self->size;
403
    PyObject **p;
404
    long mult = 1000003L;
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
405
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
406
#if STATIC_TUPLE_HAS_HASH
4679.3.22 by John Arbash Meinel
It seems that optimizing Keys_hash is not the way to go for 'bzr log' performance.
407
    if (self->hash != -1) {
408
        return self->hash;
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
409
    }
4679.3.28 by John Arbash Meinel
Add a KEY_HAS_HASH define.
410
#endif
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
411
    x = 0x345678L;
412
    p = self->items;
4679.3.77 by John Arbash Meinel
Some code cleanup passes.
413
    // TODO: We could set specific flags if we know that, for example, all the
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
414
    //       items are strings. I haven't seen a real-world benefit to that
415
    //       yet, though.
4679.3.77 by John Arbash Meinel
Some code cleanup passes.
416
    while (--len >= 0) {
417
        y = PyObject_Hash(*p++);
418
        if (y == -1) /* failure */
419
            return -1;
420
        x = (x ^ y) * mult;
421
        /* the cast might truncate len; that doesn't change hash stability */
422
        mult += (long)(82520L + len + len);
4679.3.46 by John Arbash Meinel
Play around a bit with changing the hash function.
423
    }
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
424
    x += 97531L;
425
    if (x == -1)
426
        x = -2;
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
427
#if STATIC_TUPLE_HAS_HASH
4679.3.22 by John Arbash Meinel
It seems that optimizing Keys_hash is not the way to go for 'bzr log' performance.
428
    self->hash = x;
4679.3.28 by John Arbash Meinel
Add a KEY_HAS_HASH define.
429
#endif
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
430
    return x;
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
431
}
7290.38.1 by Jelmer Vernooij
Backport python3.8 support patch to breezy 3.0.
432
#endif
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
433
434
static PyObject *
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
435
StaticTuple_richcompare_to_tuple(StaticTuple *v, PyObject *wt, int op)
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
436
{
4679.3.23 by John Arbash Meinel
A bit more testing shows that we are comparing Key to tuples fairly often.
437
    PyObject *vt;
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
438
    PyObject *result = NULL;
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
439
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
440
    vt = StaticTuple_as_tuple((StaticTuple *)v);
4679.3.23 by John Arbash Meinel
A bit more testing shows that we are comparing Key to tuples fairly often.
441
    if (vt == NULL) {
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
442
        goto done;
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
443
    }
4679.3.23 by John Arbash Meinel
A bit more testing shows that we are comparing Key to tuples fairly often.
444
    if (!PyTuple_Check(wt)) {
445
        PyErr_BadInternalCall();
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
446
        goto done;
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
447
    }
448
    /* Now we have 2 tuples to compare, do it */
449
    result = PyTuple_Type.tp_richcompare(vt, wt, op);
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
450
done:
4679.3.23 by John Arbash Meinel
A bit more testing shows that we are comparing Key to tuples fairly often.
451
    Py_XDECREF(vt);
4679.3.18 by John Arbash Meinel
Copy the hash and richcompare implementations, and add some tests.
452
    return result;
453
}
454
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
455
/** Compare two objects to determine if they are equivalent.
456
 * The basic flow is as follows
457
 *  1) First make sure that both objects are StaticTuple instances. If they
458
 *     aren't then cast self to a tuple, and have the tuple do the comparison.
459
 *  2) Special case comparison to Py_None, because it happens to occur fairly
460
 *     often in the test suite.
461
 *  3) Special case when v and w are the same pointer. As we know the answer to
462
 *     all queries without walking individual items.
463
 *  4) For all operations, we then walk the items to find the first paired
464
 *     items that are not equal.
465
 *  5) If all items found are equal, we then check the length of self and
466
 *     other to determine equality.
467
 *  6) If an item differs, then we apply "op" to those last two items. (eg.
468
 *     StaticTuple(A, B) > StaticTuple(A, C) iff B > C)
469
 */
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
470
471
static PyObject *
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
472
StaticTuple_richcompare(PyObject *v, PyObject *w, int op)
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
473
{
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
474
    StaticTuple *v_st, *w_st;
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
475
    Py_ssize_t vlen, wlen, min_len, i;
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
476
    PyObject *v_obj, *w_obj;
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
477
    richcmpfunc string_richcompare;
478
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
479
    if (!StaticTuple_CheckExact(v)) {
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
480
        /* This has never triggered, according to python-dev it seems this
481
         * might trigger if '__op__' is defined but '__rop__' is not, sort of
482
         * case. Such as "None == StaticTuple()"
483
         */
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
484
        fprintf(stderr, "self is not StaticTuple\n");
4679.3.23 by John Arbash Meinel
A bit more testing shows that we are comparing Key to tuples fairly often.
485
        Py_INCREF(Py_NotImplemented);
486
        return Py_NotImplemented;
487
    }
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
488
    v_st = (StaticTuple *)v;
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
489
    if (StaticTuple_CheckExact(w)) {
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
490
        /* The most common case */
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
491
        w_st = (StaticTuple*)w;
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
492
    } else if (PyTuple_Check(w)) {
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
493
        /* One of v or w is a tuple, so we go the 'slow' route and cast up to
494
         * tuples to compare.
495
         */
4679.3.23 by John Arbash Meinel
A bit more testing shows that we are comparing Key to tuples fairly often.
496
        /* TODO: This seems to be triggering more than I thought it would...
497
         *       We probably want to optimize comparing self to other when
498
         *       other is a tuple.
499
         */
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
500
        return StaticTuple_richcompare_to_tuple(v_st, w, op);
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
501
    } else if (w == Py_None) {
502
        // None is always less than the object
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
503
        switch (op) {
6715.1.8 by Martin
Make StaticTuple None comparison semantics consistent with tuple on Python 3
504
        case Py_NE:
505
#if PY_MAJOR_VERSION >= 3
506
#else
507
        case Py_GT:case Py_GE:
508
#endif
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
509
            Py_INCREF(Py_True);
510
            return Py_True;
6715.1.8 by Martin
Make StaticTuple None comparison semantics consistent with tuple on Python 3
511
        case Py_EQ:
512
#if PY_MAJOR_VERSION >= 3
513
#else
514
        case Py_LT:case Py_LE:
515
#endif
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
516
            Py_INCREF(Py_False);
517
            return Py_False;
6715.1.8 by Martin
Make StaticTuple None comparison semantics consistent with tuple on Python 3
518
        default: // Should only happen on Python 3
519
            return Py_NotImplemented;
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
520
        }
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
521
    } else {
522
        /* We don't special case this comparison, we just let python handle
523
         * it.
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
524
         */
525
         Py_INCREF(Py_NotImplemented);
526
         return Py_NotImplemented;
527
    }
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
528
    /* Now we know that we have 2 StaticTuple objects, so let's compare them.
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
529
     * This code is inspired from tuplerichcompare, except we know our
4679.3.45 by John Arbash Meinel
Do some work to handle comparison to object that aren't tuples or strings.
530
     * objects are limited in scope, so we can inline some comparisons.
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
531
     */
532
    if (v == w) {
533
        /* Identical pointers, we can shortcut this easily. */
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
534
        switch (op) {
535
        case Py_EQ:case Py_LE:case Py_GE:
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
536
            Py_INCREF(Py_True);
537
            return Py_True;
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
538
        case Py_NE:case Py_LT:case Py_GT:
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
539
            Py_INCREF(Py_False);
540
            return Py_False;
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
541
        }
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
542
    }
4679.5.6 by John Arbash Meinel
Some comment cleanup, implement a special case for Py_EQ when both objects are intrened.
543
    if (op == Py_EQ
544
        && _StaticTuple_is_interned(v_st)
545
        && _StaticTuple_is_interned(w_st))
546
    {
547
        /* If both objects are interned, we know they are different if the
548
         * pointer is not the same, which would have been handled by the
549
         * previous if. No need to compare the entries.
550
         */
551
        Py_INCREF(Py_False);
552
        return Py_False;
553
    }
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
554
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
555
    /* The only time we are likely to compare items of different lengths is in
556
     * something like the interned_keys set. However, the hash is good enough
557
     * that it is rare. Note that 'tuple_richcompare' also does not compare
558
     * lengths here.
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
559
     */
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
560
    vlen = v_st->size;
561
    wlen = w_st->size;
562
    min_len = (vlen < wlen) ? vlen : wlen;
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
563
    string_richcompare = PyBytes_Type.tp_richcompare;
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
564
    for (i = 0; i < min_len; i++) {
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
565
        PyObject *result = NULL;
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
566
        v_obj = StaticTuple_GET_ITEM(v_st, i);
567
        w_obj = StaticTuple_GET_ITEM(w_st, i);
4679.5.7 by John Arbash Meinel
Add a quick shortcut when comparing item-by-item.
568
        if (v_obj == w_obj) {
569
            /* Shortcut case, these must be identical */
570
            continue;
571
        }
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
572
        if (PyBytes_CheckExact(v_obj) && PyBytes_CheckExact(w_obj)) {
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
573
            result = string_richcompare(v_obj, w_obj, Py_EQ);
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
574
        } else if (StaticTuple_CheckExact(v_obj) &&
575
                   StaticTuple_CheckExact(w_obj))
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
576
        {
577
            /* Both are StaticTuple types, so recurse */
578
            result = StaticTuple_richcompare(v_obj, w_obj, Py_EQ);
579
        } else {
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
580
            /* Fall back to generic richcompare */
581
            result = PyObject_RichCompare(v_obj, w_obj, Py_EQ);
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
582
        }
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
583
        if (result == NULL) {
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
584
            return NULL; /* There seems to be an error */
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
585
        }
586
        if (result == Py_False) {
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
587
            // This entry is not identical, Shortcut for Py_EQ
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
588
            if (op == Py_EQ) {
589
                return result;
590
            }
591
            Py_DECREF(result);
592
            break;
593
        }
594
        if (result != Py_True) {
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
595
            /* We don't know *what* richcompare is returning, but it
596
             * isn't something we recognize
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
597
             */
598
            PyErr_BadInternalCall();
599
            Py_DECREF(result);
600
            return NULL;
601
        }
602
        Py_DECREF(result);
603
    }
4679.5.11 by John Arbash Meinel
add a hack-around to handle differences between pyrex 0.9.6 and 0.9.8
604
    if (i >= min_len) {
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
605
        /* We walked off one of the lists, but everything compared equal so
606
         * far. Just compare the size.
607
         */
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
608
        int cmp;
609
        PyObject *res;
610
        switch (op) {
611
        case Py_LT: cmp = vlen <  wlen; break;
612
        case Py_LE: cmp = vlen <= wlen; break;
613
        case Py_EQ: cmp = vlen == wlen; break;
614
        case Py_NE: cmp = vlen != wlen; break;
615
        case Py_GT: cmp = vlen >  wlen; break;
616
        case Py_GE: cmp = vlen >= wlen; break;
617
        default: return NULL; /* cannot happen */
618
        }
619
        if (cmp)
620
            res = Py_True;
621
        else
622
            res = Py_False;
623
        Py_INCREF(res);
624
        return res;
625
    }
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
626
    /* The last item differs, shortcut the Py_NE case */
627
    if (op == Py_NE) {
628
        Py_INCREF(Py_True);
629
        return Py_True;
630
    }
631
    /* It is some other comparison, go ahead and do the real check. */
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
632
    if (PyBytes_CheckExact(v_obj) && PyBytes_CheckExact(w_obj))
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
633
    {
634
        return string_richcompare(v_obj, w_obj, op);
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
635
    } else if (StaticTuple_CheckExact(v_obj) &&
636
               StaticTuple_CheckExact(w_obj))
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
637
    {
638
        /* Both are StaticTuple types, so recurse */
639
        return StaticTuple_richcompare(v_obj, w_obj, op);
640
    } else {
4759.2.9 by John Arbash Meinel
Implement support for lots of types.
641
        return PyObject_RichCompare(v_obj, w_obj, op);
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
642
    }
4679.3.21 by John Arbash Meinel
Implement Key_richcompare directly, rather than thunking to tuples.
643
}
644
645
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
646
static Py_ssize_t
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
647
StaticTuple_length(StaticTuple *self)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
648
{
4679.3.37 by John Arbash Meinel
Change the Key header a bit. It is simpler if you use unsigned char
649
    return self->size;
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
650
}
651
652
653
static PyObject *
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
654
StaticTuple__is_interned(StaticTuple *self)
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
655
{
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
656
    if (_StaticTuple_is_interned(self)) {
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
657
        Py_INCREF(Py_True);
658
        return Py_True;
659
    }
660
    Py_INCREF(Py_False);
661
    return Py_False;
662
}
663
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
664
static char StaticTuple__is_interned_doc[] = "_is_interned() => True/False\n"
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
665
    "Check to see if this tuple has been interned.\n";
4679.3.35 by John Arbash Meinel
Work on making intern() not generate immortal Key objects.
666
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
667
4759.2.1 by Andrew Bennetts
Implement number.add and coerce to allow concatenation with tuples.
668
static PyObject *
4759.2.18 by Matt Nordhoff
Working C implemention.
669
StaticTuple_reduce(StaticTuple *self)
670
{
671
    PyObject *result = NULL, *as_tuple = NULL;
672
673
    result = PyTuple_New(2);
674
    if (!result) {
675
        return NULL;
676
    }
677
    as_tuple = StaticTuple_as_tuple(self);
678
    if (as_tuple == NULL) {
4759.2.19 by Matt Nordhoff
Throw in a Py_DECREF.
679
        Py_DECREF(result);
4759.2.18 by Matt Nordhoff
Working C implemention.
680
        return NULL;
681
    }
4759.2.20 by Matt Nordhoff
Review: Add a Py_INCREF, and test pickling a nested StaticTuple.
682
    Py_INCREF(&StaticTuple_Type);
4759.2.18 by Matt Nordhoff
Working C implemention.
683
    PyTuple_SET_ITEM(result, 0, (PyObject *)&StaticTuple_Type);
684
    PyTuple_SET_ITEM(result, 1, as_tuple);
685
    return result;
686
}
687
688
static char StaticTuple_reduce_doc[] = "__reduce__() => tuple\n";
689
690
691
static PyObject *
4759.2.1 by Andrew Bennetts
Implement number.add and coerce to allow concatenation with tuples.
692
StaticTuple_add(PyObject *v, PyObject *w)
693
{
4759.2.7 by John Arbash Meinel
Re-implement StaticTuple_add() inline, rather that thunking over to tuples.
694
    Py_ssize_t i, len_v, len_w;
695
    PyObject *item;
696
    StaticTuple *result;
4759.2.5 by John Arbash Meinel
Add a bit more tests.
697
     /* StaticTuples and plain tuples may be added (concatenated) to
698
      * StaticTuples.
699
      */
700
    if (StaticTuple_CheckExact(v)) {
4759.2.7 by John Arbash Meinel
Re-implement StaticTuple_add() inline, rather that thunking over to tuples.
701
        len_v = ((StaticTuple*)v)->size;
702
    } else if (PyTuple_Check(v)) {
703
        len_v = PyTuple_GET_SIZE(v);
704
    } else {
705
        Py_INCREF(Py_NotImplemented);
706
        return Py_NotImplemented;
707
    }
4759.2.5 by John Arbash Meinel
Add a bit more tests.
708
    if (StaticTuple_CheckExact(w)) {
4759.2.7 by John Arbash Meinel
Re-implement StaticTuple_add() inline, rather that thunking over to tuples.
709
        len_w = ((StaticTuple*)w)->size;
710
    } else if (PyTuple_Check(w)) {
711
        len_w = PyTuple_GET_SIZE(w);
712
    } else {
713
        Py_INCREF(Py_NotImplemented);
714
        return Py_NotImplemented;
715
    }
716
    result = StaticTuple_New(len_v + len_w);
717
    if (result == NULL)
718
        return NULL;
719
    for (i = 0; i < len_v; ++i) {
720
        // This returns a new reference, which we then 'steal' with 
721
        // StaticTuple_SET_ITEM
722
        item = PySequence_GetItem(v, i);
723
        if (item == NULL) {
724
            Py_DECREF(result);
725
            return NULL;
726
        }
727
        StaticTuple_SET_ITEM(result, i, item);
728
    }
729
    for (i = 0; i < len_w; ++i) {
730
        item = PySequence_GetItem(w, i);
731
        if (item == NULL) {
732
            Py_DECREF(result);
733
            return NULL;
734
        }
735
        StaticTuple_SET_ITEM(result, i+len_v, item);
736
    }
737
    if (!StaticTuple_check_items(result)) {
738
        Py_DECREF(result);
739
        return NULL;
740
    }
741
    return (PyObject *)result;
4759.2.1 by Andrew Bennetts
Implement number.add and coerce to allow concatenation with tuples.
742
}
743
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
744
static PyObject *
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
745
StaticTuple_item(StaticTuple *self, Py_ssize_t offset)
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
746
{
747
    PyObject *obj;
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
748
    /* We cast to (int) to avoid worrying about whether Py_ssize_t is a
749
     * long long, etc. offsets should never be >2**31 anyway.
750
     */
751
    if (offset < 0) {
752
        PyErr_Format(PyExc_IndexError, "StaticTuple_item does not support"
753
            " negative indices: %d\n", (int)offset);
754
    } else if (offset >= self->size) {
755
        PyErr_Format(PyExc_IndexError, "StaticTuple index out of range"
756
            " %d >= %d", (int)offset, (int)self->size);
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
757
        return NULL;
758
    }
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
759
    obj = (PyObject *)self->items[offset];
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
760
    Py_INCREF(obj);
761
    return obj;
762
}
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
763
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
764
#if PY_MAJOR_VERSION >= 3
765
#else
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
766
static PyObject *
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
767
StaticTuple_slice(StaticTuple *self, Py_ssize_t ilow, Py_ssize_t ihigh)
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
768
{
769
    PyObject *as_tuple, *result;
770
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
771
    as_tuple = StaticTuple_as_tuple(self);
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
772
    if (as_tuple == NULL) {
773
        return NULL;
774
    }
775
    result = PyTuple_Type.tp_as_sequence->sq_slice(as_tuple, ilow, ihigh);
776
    Py_DECREF(as_tuple);
777
    return result;
778
}
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
779
#endif
780
781
static PyObject *
782
StaticTuple_subscript(StaticTuple *self, PyObject *key)
783
{
784
    PyObject *as_tuple, *result;
785
786
    as_tuple = StaticTuple_as_tuple(self);
787
    if (as_tuple == NULL) {
788
        return NULL;
789
    }
790
    result = PyTuple_Type.tp_as_mapping->mp_subscript(as_tuple, key);
791
    Py_DECREF(as_tuple);
792
    return result;
793
}
4679.3.19 by John Arbash Meinel
implement slicing as a tuple thunk.
794
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
795
static int
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
796
StaticTuple_traverse(StaticTuple *self, visitproc visit, void *arg)
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
797
{
798
    Py_ssize_t i;
4679.3.46 by John Arbash Meinel
Play around a bit with changing the hash function.
799
    for (i = self->size; --i >= 0;) {
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
800
        Py_VISIT(self->items[i]);
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
801
    }
802
    return 0;
803
}
804
5320.1.1 by Andrew Bennetts
Implement __sizeof__ in StaticTuple.
805
806
static PyObject *
807
StaticTuple_sizeof(StaticTuple *self)
808
{
6715.1.7 by Martin
Expand some tabs in _static_tuple_c.c
809
    Py_ssize_t res;
5320.1.1 by Andrew Bennetts
Implement __sizeof__ in StaticTuple.
810
6715.1.7 by Martin
Expand some tabs in _static_tuple_c.c
811
    res = _PyObject_SIZE(&StaticTuple_Type) + (int)self->size * sizeof(void*);
812
    return PyInt_FromSsize_t(res);
5320.1.1 by Andrew Bennetts
Implement __sizeof__ in StaticTuple.
813
}
814
815
816
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
817
static char StaticTuple_doc[] =
818
    "C implementation of a StaticTuple structure."
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
819
    "\n This is used as StaticTuple(item1, item2, item3)"
820
    "\n This is similar to tuple, less flexible in what it"
821
    "\n supports, but also lighter memory consumption."
822
    "\n Note that the constructor mimics the () form of tuples"
823
    "\n Rather than the 'tuple()' constructor."
824
    "\n  eg. StaticTuple(a, b) == (a, b) == tuple((a, b))";
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
825
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
826
static PyMethodDef StaticTuple_methods[] = {
827
    {"as_tuple", (PyCFunction)StaticTuple_as_tuple, METH_NOARGS, StaticTuple_as_tuple_doc},
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
828
    {"intern", (PyCFunction)StaticTuple_Intern, METH_NOARGS, StaticTuple_Intern_doc},
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
829
    {"_is_interned", (PyCFunction)StaticTuple__is_interned, METH_NOARGS,
830
     StaticTuple__is_interned_doc},
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
831
    {"from_sequence", (PyCFunction)StaticTuple_from_sequence,
832
     METH_STATIC | METH_VARARGS,
833
     "Create a StaticTuple from a given sequence. This functions"
834
     " the same as the tuple() constructor."},
4759.2.18 by Matt Nordhoff
Working C implemention.
835
    {"__reduce__", (PyCFunction)StaticTuple_reduce, METH_NOARGS, StaticTuple_reduce_doc},
5320.1.1 by Andrew Bennetts
Implement __sizeof__ in StaticTuple.
836
    {"__sizeof__",  (PyCFunction)StaticTuple_sizeof, METH_NOARGS}, 
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
837
    {NULL, NULL} /* sentinel */
838
};
839
4759.2.1 by Andrew Bennetts
Implement number.add and coerce to allow concatenation with tuples.
840
841
static PyNumberMethods StaticTuple_as_number = {
4759.2.5 by John Arbash Meinel
Add a bit more tests.
842
    (binaryfunc) StaticTuple_add,   /* nb_add */
843
    0,                              /* nb_subtract */
844
    0,                              /* nb_multiply */
845
    0,                              /* nb_divide */
846
    0,                              /* nb_remainder */
847
    0,                              /* nb_divmod */
848
    0,                              /* nb_power */
849
    0,                              /* nb_negative */
850
    0,                              /* nb_positive */
851
    0,                              /* nb_absolute */
852
    0,                              /* nb_nonzero */
853
    0,                              /* nb_invert */
854
    0,                              /* nb_lshift */
855
    0,                              /* nb_rshift */
856
    0,                              /* nb_and */
857
    0,                              /* nb_xor */
858
    0,                              /* nb_or */
859
    0,                              /* nb_coerce */
4759.2.1 by Andrew Bennetts
Implement number.add and coerce to allow concatenation with tuples.
860
};
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
861
4759.2.1 by Andrew Bennetts
Implement number.add and coerce to allow concatenation with tuples.
862
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
863
static PySequenceMethods StaticTuple_as_sequence = {
864
    (lenfunc)StaticTuple_length,            /* sq_length */
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
865
    0,                              /* sq_concat */
866
    0,                              /* sq_repeat */
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
867
    (ssizeargfunc)StaticTuple_item,         /* sq_item */
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
868
#if PY_MAJOR_VERSION >= 3
869
#else
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
870
    (ssizessizeargfunc)StaticTuple_slice,   /* sq_slice */
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
871
#endif
4679.3.17 by John Arbash Meinel
Implement some of the sequence items.
872
    0,                              /* sq_ass_item */
873
    0,                              /* sq_ass_slice */
874
    0,                              /* sq_contains */
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
875
#if PY_MAJOR_VERSION >= 3
876
    0,                              /* sq_inplace_concat */
877
    0,                              /* sq_inplace_repeat */
878
#endif
879
};
880
881
882
static PyMappingMethods StaticTuple_as_mapping = {
883
    (lenfunc)StaticTuple_length,            /* mp_length */
884
    (binaryfunc)StaticTuple_subscript,      /* mp_subscript */
885
    0,                                      /* mp_ass_subscript */
886
};
4679.5.5 by John Arbash Meinel
Review feedback from Andrew Bennetts.
887
4679.4.1 by John Arbash Meinel
Handle some issues with static/etc to get things to build on babune.
888
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
889
PyTypeObject StaticTuple_Type = {
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
890
    PyVarObject_HEAD_INIT(NULL, 0)
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
891
    "breezy._static_tuple_c.StaticTuple",        /* tp_name */
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
892
    sizeof(StaticTuple),                         /* tp_basicsize */
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
893
    sizeof(PyObject *),                          /* tp_itemsize */
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
894
    (destructor)StaticTuple_dealloc,             /* tp_dealloc */
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
895
    0,                                           /* tp_print */
896
    0,                                           /* tp_getattr */
897
    0,                                           /* tp_setattr */
898
    0,                                           /* tp_compare */
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
899
    (reprfunc)StaticTuple_repr,                  /* tp_repr */
4759.2.1 by Andrew Bennetts
Implement number.add and coerce to allow concatenation with tuples.
900
    &StaticTuple_as_number,                      /* tp_as_number */
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
901
    &StaticTuple_as_sequence,                    /* tp_as_sequence */
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
902
    &StaticTuple_as_mapping,                     /* tp_as_mapping */
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
903
    (hashfunc)StaticTuple_hash,                  /* tp_hash */
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
904
    0,                                           /* tp_call */
905
    0,                                           /* tp_str */
4747.1.1 by John Arbash Meinel
On Windows w/ Python2.5 PyObject_GenericGetAttr is an external DLL function,
906
    0,                                           /* tp_getattro */
4679.3.16 by John Arbash Meinel
Initial work for a Key class.
907
    0,                                           /* tp_setattro */
908
    0,                                           /* tp_as_buffer */
4759.2.5 by John Arbash Meinel
Add a bit more tests.
909
    /* Py_TPFLAGS_CHECKTYPES tells the number operations that they shouldn't
910
     * try to 'coerce' but instead stuff like 'add' will check it arguments.
911
     */
912
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,  /* tp_flags*/
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
913
    StaticTuple_doc,                             /* tp_doc */
4679.3.20 by John Arbash Meinel
Implement tp_traverse, and add a soft dependency on meliae to test it.
914
    /* gc.get_referents checks the IS_GC flag before it calls tp_traverse
915
     * And we don't include this object in the garbage collector because we
916
     * know it doesn't create cycles. However, 'meliae' will follow
917
     * tp_traverse, even if the object isn't GC, and we want that.
918
     */
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
919
    (traverseproc)StaticTuple_traverse,          /* tp_traverse */
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
920
    0,                                           /* tp_clear */
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
921
    StaticTuple_richcompare,                     /* tp_richcompare */
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
922
    0,                                           /* tp_weaklistoffset */
4679.3.76 by John Arbash Meinel
Rename StaticTupleInterner => SimpleSet.
923
    // without implementing tp_iter, Python will fall back to PySequence*
924
    // which seems to work ok, we may need something faster/lighter in the
925
    // future.
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
926
    0,                                           /* tp_iter */
927
    0,                                           /* tp_iternext */
4679.3.42 by John Arbash Meinel
Implement comparison support when using nested StaticTuple objects.
928
    StaticTuple_methods,                         /* tp_methods */
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
929
    0,                                           /* tp_members */
930
    0,                                           /* tp_getset */
931
    0,                                           /* tp_base */
932
    0,                                           /* tp_dict */
933
    0,                                           /* tp_descr_get */
934
    0,                                           /* tp_descr_set */
935
    0,                                           /* tp_dictoffset */
936
    0,                                           /* tp_init */
937
    0,                                           /* tp_alloc */
4679.5.9 by John Arbash Meinel
NEWS entry for StaticTuple class.
938
    StaticTuple_new_constructor,                 /* tp_new */
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
939
};
940
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
941
4679.3.41 by John Arbash Meinel
Finish switching the naming to StaticTuple.
942
static PyMethodDef static_tuple_c_methods[] = {
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
943
    {NULL, NULL}
944
};
945
946
4679.3.47 by John Arbash Meinel
Work out how to expose the C api using the Python PyCObject interface.
947
static void
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
948
setup_interned_tuples(PyObject *m)
4679.3.1 by John Arbash Meinel
Start working on a Keys type.
949
{
4679.3.76 by John Arbash Meinel
Rename StaticTupleInterner => SimpleSet.
950
    _interned_tuples = (PyObject *)SimpleSet_New();
4679.3.51 by John Arbash Meinel
Add a _static_tuple_c.pxd file to define the C api to pyrex code.
951
    if (_interned_tuples != NULL) {
952
        Py_INCREF(_interned_tuples);
953
        PyModule_AddObject(m, "_interned_tuples", _interned_tuples);
4679.3.29 by John Arbash Meinel
Start work on implementing a Key.intern() function.
954
    }
4679.3.47 by John Arbash Meinel
Work out how to expose the C api using the Python PyCObject interface.
955
}
956
957
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
958
static void
959
setup_empty_tuple(PyObject *m)
960
{
961
    StaticTuple *stuple;
962
    if (_interned_tuples == NULL) {
963
        fprintf(stderr, "You need to call setup_interned_tuples() before"
964
                " setup_empty_tuple, because we intern it.\n");
965
    }
966
    // We need to create the empty tuple
967
    stuple = (StaticTuple *)StaticTuple_New(0);
968
    _empty_tuple = StaticTuple_Intern(stuple);
969
    assert(_empty_tuple == stuple);
970
    // At this point, refcnt is 2: 1 from New(), and 1 from the return from
971
    // intern(). We will keep 1 for the _empty_tuple global, and use the other
972
    // for the module reference.
973
    PyModule_AddObject(m, "_empty_tuple", (PyObject *)_empty_tuple);
974
}
975
976
static int
977
_StaticTuple_CheckExact(PyObject *obj)
978
{
979
    return StaticTuple_CheckExact(obj);
980
}
981
982
static void
983
setup_c_api(PyObject *m)
984
{
985
    _export_function(m, "StaticTuple_New", StaticTuple_New,
986
        "StaticTuple *(Py_ssize_t)");
987
    _export_function(m, "StaticTuple_Intern", StaticTuple_Intern,
988
        "StaticTuple *(StaticTuple *)");
4739.4.1 by John Arbash Meinel
Implement StaticTuple.from_sequence()
989
    _export_function(m, "StaticTuple_FromSequence", StaticTuple_FromSequence,
990
        "StaticTuple *(PyObject *)");
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
991
    _export_function(m, "_StaticTuple_CheckExact", _StaticTuple_CheckExact,
992
        "int(PyObject *)");
993
}
994
995
6715.1.4 by Martin
Correct name for init func
996
PYMOD_INIT_FUNC(_static_tuple_c)
4679.3.47 by John Arbash Meinel
Work out how to expose the C api using the Python PyCObject interface.
997
{
998
    PyObject* m;
999
4747.1.1 by John Arbash Meinel
On Windows w/ Python2.5 PyObject_GenericGetAttr is an external DLL function,
1000
    StaticTuple_Type.tp_getattro = PyObject_GenericGetAttr;
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
1001
    if (PyType_Ready(&StaticTuple_Type) < 0) {
1002
        return PYMOD_ERROR;
1003
    }
4679.3.47 by John Arbash Meinel
Work out how to expose the C api using the Python PyCObject interface.
1004
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
1005
    PYMOD_CREATE(m, "_static_tuple_c",
1006
                 "C implementation of a StaticTuple structure",
1007
                 static_tuple_c_methods);
1008
    if (m == NULL) {
1009
      return PYMOD_ERROR;
1010
    }
4679.3.47 by John Arbash Meinel
Work out how to expose the C api using the Python PyCObject interface.
1011
1012
    Py_INCREF(&StaticTuple_Type);
1013
    PyModule_AddObject(m, "StaticTuple", (PyObject *)&StaticTuple_Type);
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
1014
    if (import_breezy___simple_set_pyx() == -1) {
1015
        return PYMOD_ERROR;
4679.3.81 by John Arbash Meinel
Fix up _simple_set_pyx.pyx to be compatible with pyrex again.
1016
    }
4679.3.74 by John Arbash Meinel
Revert back to before I started trying to move to pyrex/cython code.
1017
    setup_interned_tuples(m);
1018
    setup_empty_tuple(m);
1019
    setup_c_api(m);
6715.1.1 by Martin
Make _static_tuple_c compile on Python 3
1020
1021
    return PYMOD_SUCCESS(m);
4679.3.47 by John Arbash Meinel
Work out how to expose the C api using the Python PyCObject interface.
1022
}
4759.2.5 by John Arbash Meinel
Add a bit more tests.
1023
1024
// vim: tabstop=4 sw=4 expandtab