You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

238 lines
6.6 KiB

#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;
}