182
182
len = PyTuple_GET_SIZE(args);
183
if (len <= 0 || len > 256) {
183
if (len < 0 || len > 255) {
184
184
/* Too big or too small */
185
185
PyErr_SetString(PyExc_ValueError, "StaticTuple.__init__(...)"
186
" takes from 1 to 256 key bits");
186
" takes from 0 to 255 key bits");
189
189
self = (StaticTuple *)(type->tp_alloc(type, len));
200
200
for (i = 0; i < len; ++i) {
201
201
obj = PyTuple_GET_ITEM(args, i);
202
if (!PyString_CheckExact(obj)) {
202
if (!PyString_CheckExact(obj) && !StaticTuple_CheckExact(obj)) {
203
203
PyErr_SetString(PyExc_TypeError, "StaticTuple.__init__(...)"
204
" requires that all key bits are strings.");
204
" requires that all key bits are strings or StaticTuple.");
205
205
/* TODO: What is the proper way to dealloc ? */
206
206
type->tp_dealloc((PyObject *)self);
297
297
StaticTuple *vk, *wk;
298
298
Py_ssize_t vlen, wlen, min_len, i;
299
PyObject *v_obj, *w_obj;
299
300
richcmpfunc string_richcompare;
301
302
if (!StaticTuple_CheckExact(v)) {
302
/* This has never triggered */
303
/* This has never triggered, according to python-dev it seems this
304
* might trigger if '__op__' is defined but '__rop__' is not, sort of
305
* case. Such as "None == StaticTuple()"
303
307
fprintf(stderr, "self is tuple\n");
304
308
Py_INCREF(Py_NotImplemented);
305
309
return Py_NotImplemented;
316
320
return StaticTuple_richcompare_to_tuple(vk, w, op);
322
/* TODO: Py_None is one of the other common cases here, we should probably
323
* directly support it.
318
325
if (!StaticTuple_CheckExact(w)) {
319
326
/* Both are not StaticTuple objects, and they aren't Tuple objects or the
320
327
* previous path would have been taken. We don't support comparing with
327
334
/* Now we know that we have 2 StaticTuple objects, so let's compare them.
328
335
* This code is somewhat borrowed from tuplerichcompare, except we know our
329
* objects are strings, so we get to cheat a bit.
336
* objects are limited in scope, so we cheat a bit.
332
339
/* Identical pointers, we can shortcut this easily. */
349
356
min_len = (vlen < wlen) ? vlen : wlen;
350
357
string_richcompare = PyString_Type.tp_richcompare;
351
358
for (i = 0; i < min_len; i++) {
353
result = string_richcompare((PyObject *)vk->key_bits[i],
354
(PyObject *)wk->key_bits[i],
359
PyObject *result = NULL;
360
v_obj = StaticTuple_GET_ITEM(vk, i);
361
w_obj = StaticTuple_GET_ITEM(wk, i);
362
if (PyString_CheckExact(v_obj) && PyString_CheckExact(w_obj)) {
363
result = string_richcompare(v_obj, w_obj, Py_EQ);
364
} else if (StaticTuple_CheckExact(v_obj) &&
365
StaticTuple_CheckExact(w_obj))
367
/* Both are StaticTuple types, so recurse */
368
result = StaticTuple_richcompare(v_obj, w_obj, Py_EQ);
370
/* Not the same type, obviously they won't compare equal */
356
373
if (result == NULL) {
357
return NULL; /* Seems to be an error */
374
return NULL; /* There seems to be an error */
359
376
if (result == Py_NotImplemented) {
360
377
PyErr_BadInternalCall();
409
428
/* It is some other comparison, go ahead and do the real check. */
410
return string_richcompare((PyObject *)vk->key_bits[i],
411
(PyObject *)wk->key_bits[i],
429
if (PyString_CheckExact(v_obj) && PyString_CheckExact(w_obj))
431
return string_richcompare(v_obj, w_obj, op);
432
} else if (StaticTuple_CheckExact(v_obj) &&
433
StaticTuple_CheckExact(w_obj))
435
/* Both are StaticTuple types, so recurse */
436
return StaticTuple_richcompare(v_obj, w_obj, op);
438
Py_INCREF(Py_NotImplemented);
439
return Py_NotImplemented;
501
529
PyTypeObject StaticTuple_Type = {
502
530
PyObject_HEAD_INIT(NULL)
504
"StaticTuple", /* tp_name */
505
sizeof(StaticTuple) - sizeof(PyStringObject *), /* tp_basicsize */
532
"StaticTuple", /* tp_name */
533
sizeof(StaticTuple) - sizeof(PyObject *), /* tp_basicsize */
506
534
sizeof(PyObject *), /* tp_itemsize */
507
(destructor)StaticTuple_dealloc, /* tp_dealloc */
535
(destructor)StaticTuple_dealloc, /* tp_dealloc */
508
536
0, /* tp_print */
509
537
0, /* tp_getattr */
510
538
0, /* tp_setattr */
511
539
0, /* tp_compare */
512
(reprfunc)StaticTuple_repr, /* tp_repr */
540
(reprfunc)StaticTuple_repr, /* tp_repr */
513
541
0, /* tp_as_number */
514
&StaticTuple_as_sequence, /* tp_as_sequence */
542
&StaticTuple_as_sequence, /* tp_as_sequence */
515
543
0, /* tp_as_mapping */
516
(hashfunc)StaticTuple_hash, /* tp_hash */
544
(hashfunc)StaticTuple_hash, /* tp_hash */
519
547
PyObject_GenericGetAttr, /* tp_getattro */
520
548
0, /* tp_setattro */
521
549
0, /* tp_as_buffer */
522
550
Py_TPFLAGS_DEFAULT, /* tp_flags*/
523
StaticTuple_doc, /* tp_doc */
551
StaticTuple_doc, /* tp_doc */
524
552
/* gc.get_referents checks the IS_GC flag before it calls tp_traverse
525
553
* And we don't include this object in the garbage collector because we
526
554
* know it doesn't create cycles. However, 'meliae' will follow
527
555
* tp_traverse, even if the object isn't GC, and we want that.
529
(traverseproc)StaticTuple_traverse, /* tp_traverse */
557
(traverseproc)StaticTuple_traverse, /* tp_traverse */
530
558
0, /* tp_clear */
531
559
// TODO: implement richcompare, we should probably be able to compare vs an
532
560
// tuple, as well as versus another StaticTuples object.
533
StaticTuple_richcompare, /* tp_richcompare */
561
StaticTuple_richcompare, /* tp_richcompare */
534
562
0, /* tp_weaklistoffset */
535
563
// We could implement this as returning tuples of keys...
537
565
0, /* tp_iternext */
538
StaticTuple_methods, /* tp_methods */
566
StaticTuple_methods, /* tp_methods */
539
567
0, /* tp_members */
540
568
0, /* tp_getset */