15
15
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
#include "_static_tuple_type_c.h"
20
#include "_static_tuple_pyx_api.h"
18
/* Must be defined before importing _static_tuple_c.h so that we get the right
21
#define STATIC_TUPLE_MODULE
23
#include "_static_tuple_c.h"
24
#include "_export_c_api.h"
25
#include "_static_tuple_interned_pyx_api.h"
22
27
#include "python-compat.h"
66
72
static char StaticTuple_as_tuple_doc[] = "as_tuple() => tuple";
69
_StaticTuple_intern(StaticTuple *self)
75
StaticTuple_Intern(StaticTuple *self)
71
return (PyObject *)StaticTuple_Intern(self);
77
PyObject *unique_key = NULL;
79
if (_interned_tuples == NULL) {
83
if (_StaticTuple_is_interned(self)) {
88
/* StaticTupleInterner_Add returns whatever object is present at self
89
* or the new object if it needs to add it.
91
unique_key = StaticTupleInterner_Add(_interned_tuples, (PyObject *)self);
93
// Suppress any error and just return the object
97
if (unique_key != (PyObject *)self) {
98
// There was already a key at that location
99
return (StaticTuple *)unique_key;
101
self->flags |= STATIC_TUPLE_INTERNED_FLAG;
102
// The two references in the dict do not count, so that the StaticTuple object
103
// does not become immortal just because it was interned.
104
Py_REFCNT(self) -= 1;
74
static char StaticTuple_intern_doc[] = "intern() => unique StaticTuple\n"
108
static char StaticTuple_Intern_doc[] = "intern() => unique StaticTuple\n"
75
109
"Return a 'canonical' StaticTuple object.\n"
76
110
"Similar to intern() for strings, this makes sure there\n"
77
111
"is only one StaticTuple object for a given value\n."
135
/* Similar to PyTuple_New() */
137
StaticTuple_New(Py_ssize_t size)
141
PyErr_BadInternalCall();
145
if (size == 0 && _empty_tuple != NULL) {
146
Py_INCREF(_empty_tuple);
149
/* Note that we use PyObject_NewVar because we want to allocate a variable
150
* width entry. However we *aren't* truly a PyVarObject because we don't
151
* use a long for ob_size. Instead we use a plain 'size' that is an int,
152
* and will be overloaded with flags in the future.
153
* As such we do the alloc, and then have to clean up anything it does
156
stuple = PyObject_NewVar(StaticTuple, &StaticTuple_Type, size);
157
if (stuple == NULL) {
162
stuple->_unused0 = 0;
163
stuple->_unused1 = 0;
165
memset(stuple->items, 0, sizeof(PyObject *) * size);
167
#if STATIC_TUPLE_HAS_HASH
101
174
static PyObject *
102
175
StaticTuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
323
396
w_obj = StaticTuple_GET_ITEM(wk, i);
324
397
if (PyString_CheckExact(v_obj) && PyString_CheckExact(w_obj)) {
325
398
result = string_richcompare(v_obj, w_obj, Py_EQ);
326
} else if (_StaticTuple_CheckExact(v_obj) &&
327
_StaticTuple_CheckExact(w_obj))
399
} else if (StaticTuple_CheckExact(v_obj) &&
400
StaticTuple_CheckExact(w_obj))
329
402
/* Both are StaticTuple types, so recurse */
330
403
result = StaticTuple_richcompare(v_obj, w_obj, Py_EQ);
391
464
if (PyString_CheckExact(v_obj) && PyString_CheckExact(w_obj))
393
466
return string_richcompare(v_obj, w_obj, op);
394
} else if (_StaticTuple_CheckExact(v_obj) &&
395
_StaticTuple_CheckExact(w_obj))
467
} else if (StaticTuple_CheckExact(v_obj) &&
468
StaticTuple_CheckExact(w_obj))
397
470
/* Both are StaticTuple types, so recurse */
398
471
return StaticTuple_richcompare(v_obj, w_obj, op);
471
544
static PyMethodDef StaticTuple_methods[] = {
472
545
{"as_tuple", (PyCFunction)StaticTuple_as_tuple, METH_NOARGS, StaticTuple_as_tuple_doc},
473
// set after loading _static_tuple_pyx
474
{"intern", (PyCFunction)_StaticTuple_intern, METH_NOARGS, StaticTuple_intern_doc},
546
{"intern", (PyCFunction)StaticTuple_Intern, METH_NOARGS, StaticTuple_Intern_doc},
475
547
{"_is_interned", (PyCFunction)StaticTuple__is_interned, METH_NOARGS,
476
548
StaticTuple__is_interned_doc},
477
549
{NULL, NULL} /* sentinel */
615
static char KeyIntern_doc[] = "";
617
static PyMethodDef KeyIntern_methods[] = {
618
// {"as_tuple", (PyCFunction)Keys_as_tuple, METH_NOARGS, Keys_as_tuple_doc},
619
{NULL, NULL} /* sentinel */
622
// static PySequenceMethods KeyIntern_as_sequence = {
623
// 0, //(lenfunc)Keys_length, /* sq_length */
624
// 0, /* sq_concat */
625
// 0, /* sq_repeat */
626
// 0, //(ssizeargfunc)Keys_item, /* sq_item */
628
// 0, /* sq_ass_item */
629
// 0, /* sq_ass_slice */
630
// 0, /* sq_contains */
633
// static PyTypeObject KeyIntern_Type = {
634
// PyObject_HEAD_INIT(NULL)
636
// "KeyIntern", /* tp_name */
637
// sizeof(KeyIntern) - sizeof(Key *), /* tp_basicsize */
638
// sizeof(Key *), /* tp_itemsize */
639
// 0, //(destructor)Keys_dealloc, /* tp_dealloc */
641
// 0, /* tp_getattr */
642
// 0, /* tp_setattr */
643
// 0, /* tp_compare */
644
// // TODO: implement repr() and possibly str()
645
// 0, //(reprfunc)Keys_repr, /* tp_repr */
646
// 0, /* tp_as_number */
647
// &KeyIntern_as_sequence, /* tp_as_sequence */
648
// 0, /* tp_as_mapping */
649
// 0, //(hashfunc)Keys_hash, /* tp_hash */
652
// PyObject_GenericGetAttr, /* tp_getattro */
653
// 0, /* tp_setattro */
654
// 0, /* tp_as_buffer */
655
// Py_TPFLAGS_DEFAULT, /* tp_flags*/
656
// 0, // Keys_doc, /* tp_doc */
657
// /* See Key_traverse for why we have this, even though we aren't GC */
658
// 0, //(traverseproc)Keys_traverse, /* tp_traverse */
660
// // TODO: implement richcompare, we should probably be able to compare vs an
661
// // tuple, as well as versus another Keys object.
662
// 0, //Keys_richcompare, /* tp_richcompare */
663
// 0, /* tp_weaklistoffset */
664
// // We could implement this as returning tuples of keys...
666
// 0, /* tp_iternext */
667
// KeyIntern_methods, /* tp_methods */
668
// 0, /* tp_members */
669
// 0, /* tp_getset */
672
// 0, /* tp_descr_get */
673
// 0, /* tp_descr_set */
674
// 0, /* tp_dictoffset */
677
// 0, //Keys_new, /* tp_new */
543
681
static PyMethodDef static_tuple_c_methods[] = {
544
682
// {"unique_lcs_c", py_unique_lcs, METH_VARARGS},
545
683
// {"recurse_matches_c", py_recurse_matches, METH_VARARGS},
700
setup_empty_tuple(PyObject *m)
703
if (_interned_tuples == NULL) {
704
fprintf(stderr, "You need to call setup_interned_tuples() before"
705
" setup_empty_tuple, because we intern it.\n");
707
// We need to create the empty tuple
708
stuple = (StaticTuple *)StaticTuple_New(0);
709
stuple->flags = STATIC_TUPLE_ALL_STRING;
710
_empty_tuple = StaticTuple_Intern(stuple);
711
assert(_empty_tuple == stuple);
712
// At this point, refcnt is 2: 1 from New(), and 1 from the return from
713
// intern(). We will keep 1 for the _empty_tuple global, and use the other
714
// for the module reference.
715
PyModule_AddObject(m, "_empty_tuple", (PyObject *)_empty_tuple);
719
_StaticTuple_CheckExact(PyObject *obj)
721
return StaticTuple_CheckExact(obj);
725
setup_c_api(PyObject *m)
727
_export_function(m, "StaticTuple_New", StaticTuple_New,
728
"StaticTuple *(Py_ssize_t)");
729
_export_function(m, "StaticTuple_Intern", StaticTuple_Intern,
730
"StaticTuple *(StaticTuple *)");
731
_export_function(m, "_StaticTuple_CheckExact", _StaticTuple_CheckExact,
562
init_static_tuple_type_c(void)
737
init_static_tuple_c(void)
565
fprintf(stderr, "init_static_tuple_type_c\n");
567
if (PyType_Ready(&StaticTuple_Type) < 0) {
568
fprintf(stderr, "StaticTuple_Type not ready\n");
741
if (PyType_Ready(&StaticTuple_Type) < 0)
571
fprintf(stderr, "StaticTuple_Type ready\n");
573
m = Py_InitModule3("_static_tuple_type_c", static_tuple_c_methods,
744
m = Py_InitModule3("_static_tuple_c", static_tuple_c_methods,
574
745
"C implementation of a StaticTuple structure");
578
749
Py_INCREF(&StaticTuple_Type);
579
750
PyModule_AddObject(m, "StaticTuple", (PyObject *)&StaticTuple_Type);
580
fprintf(stderr, "added the StaticTuple type, importing _static_tuple_pyx\n");
581
if (import_bzrlib___static_tuple_pyx() == -1) {
583
fprintf(stderr, "Failed to import_bzrlib___static_tuple_pyx.\n");
584
// PyErr_SetString(PyExc_ImportError,
585
// "Failed to import _static_tuple_pyx");
587
// m2 = PyImport_ImportModule("bzrlib._static_tuple_pyx");
589
// fprintf(stderr, "Failed to import bzrlib._static_tuple_pyx\n");
591
// Py_INCREF(&StaticTuple_Type);
592
// if (PyModule_AddObject(m2, "StaticTuple", (PyObject
593
// *)&StaticTuple_Type) == -1) {
594
// fprintf(stderr, "Failed to add StaticTuple to bzrlib._static_tuple_pyx\n");
598
if (PyErr_Occurred()) {
599
fprintf(stderr, "an exception has occurred\n");
601
fprintf(stderr, "imported successfully\n");
751
import_bzrlib___static_tuple_interned_pyx();
752
setup_interned_tuples(m);
753
setup_empty_tuple(m);