#include "Python.h" #include "structmember.h" PyDoc_STRVAR(istr__doc__, "istr class implementation"); /* We link this module statically for convenience. If compiled as a shared library instead, some compilers don't allow addresses of Python objects defined in other libraries to be used in static initializers here. The DEFERRED_ADDRESS macro is used to tag the slots where such addresses appear; the module init function must fill in the tagged slots at runtime. The argument is for documentation -- the macro ignores it. */ #define DEFERRED_ADDRESS(ADDR) 0 typedef struct { PyUnicodeObject str; PyObject * canonical; } istrobject; typedef struct { PyObject *title; PyObject *emptystr; PyObject *emptydict; } ModData; static struct PyModuleDef _istrmodule; static PyTypeObject istr_type; static ModData * modstate(PyObject *mod) { return (ModData*)PyModule_GetState(mod); } static ModData * global_state(void) { return modstate(PyState_FindModule(&_istrmodule)); } static PyObject * istr_title(istrobject *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":title")) return NULL; Py_INCREF(self); return (PyObject*)self; } static PyObject * istr_str(istrobject *self) { Py_INCREF(self->canonical); return self->canonical; } static PyMethodDef istr_methods[] = { {"title", (PyCFunction)istr_title, METH_VARARGS, PyDoc_STR("title()")}, {NULL, NULL}, }; void istr_dealloc(istrobject *self) { Py_XDECREF(self->canonical); PyUnicode_Type.tp_dealloc((PyObject*)self); } static PyObject * istr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *x = NULL; static char *kwlist[] = {"object", "encoding", "errors", 0}; char *encoding = NULL; char *errors = NULL; PyObject *s = NULL; PyObject *tmp = NULL; PyObject * new_args = NULL; PyObject * ret = NULL; ModData * state = global_state(); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:str", kwlist, &x, &encoding, &errors)) return NULL; if (x == NULL) { s = state->emptystr; Py_INCREF(s); } else if (PyObject_IsInstance(x, (PyObject*)&istr_type)) { Py_INCREF(x); return x; } else { if (encoding == NULL && errors == NULL) { tmp = PyObject_Str(x); } else { tmp = PyUnicode_FromEncodedObject(x, encoding, errors); } if (!tmp) { goto finish; } s = PyObject_CallMethodObjArgs(tmp, state->title, NULL); } if (!s) goto finish; new_args = PyTuple_Pack(1, s); if (!new_args) { goto finish; } ret = PyUnicode_Type.tp_new(type, new_args, state->emptydict); if (!ret) { goto finish; } ((istrobject*)ret)->canonical = s; s = NULL; /* the reference is stollen by .canonical */ finish: Py_XDECREF(tmp); Py_XDECREF(s); Py_XDECREF(new_args); return ret; } static PyTypeObject istr_type = { PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "multidict._istr.istr", sizeof(istrobject), 0, (destructor)istr_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ (reprfunc)istr_str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_UNICODE_SUBCLASS, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ istr_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ DEFERRED_ADDRESS(&PyUnicode_Type), /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ (newfunc)istr_new, /* tp_new */ }; static int mod_clear(PyObject *m) { Py_CLEAR(modstate(m)->title); Py_CLEAR(modstate(m)->emptystr); Py_CLEAR(modstate(m)->emptydict); return 0; } static struct PyModuleDef _istrmodule = { PyModuleDef_HEAD_INIT, "multidict._istr", istr__doc__, sizeof(ModData), NULL, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ mod_clear, /* m_clear */ NULL /* m_free */ }; PyObject* PyInit__istr(void) { PyObject * tmp; PyObject *mod; mod = PyState_FindModule(&_istrmodule); if (mod) { Py_INCREF(mod); return mod; } istr_type.tp_base = &PyUnicode_Type; if (PyType_Ready(&istr_type) < 0) { return NULL; } mod = PyModule_Create(&_istrmodule); if (!mod) { return NULL; } tmp = PyUnicode_FromString("title"); if (!tmp) { goto err; } modstate(mod)->title = tmp; tmp = PyUnicode_New(0, 0); if (!tmp) { goto err; } modstate(mod)->emptystr = tmp; tmp = PyUnicode_FromString("title"); if(!tmp) { goto err; } modstate(mod)->title = tmp; Py_INCREF(&istr_type); if (PyModule_AddObject(mod, "istr", (PyObject *)&istr_type) < 0) goto err; return mod; err: Py_DECREF(mod); return NULL; }