bpo-1635741: Convert _multibytecodec to multi-phase init (GH-24095)
Convert the _multibytecodec extension module (CJK codecs) to multi-phase initialization (PEP 489).
This commit is contained in:
parent
958acd2da0
commit
0b858cdd5d
|
@ -0,0 +1,2 @@
|
||||||
|
Convert the _multibytecodec extension module (CJK codecs) to multi-phase
|
||||||
|
initialization (:pep:`489`). Patch by Erlend E. Aasland.
|
|
@ -10,11 +10,44 @@
|
||||||
#include "multibytecodec.h"
|
#include "multibytecodec.h"
|
||||||
#include "clinic/multibytecodec.c.h"
|
#include "clinic/multibytecodec.c.h"
|
||||||
|
|
||||||
|
#define MODULE_NAME "_multibytecodec"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyTypeObject *encoder_type;
|
||||||
|
PyTypeObject *decoder_type;
|
||||||
|
PyTypeObject *reader_type;
|
||||||
|
PyTypeObject *writer_type;
|
||||||
|
PyTypeObject *multibytecodec_type;
|
||||||
|
} _multibytecodec_state;
|
||||||
|
|
||||||
|
static _multibytecodec_state *
|
||||||
|
_multibytecodec_get_state(PyObject *module)
|
||||||
|
{
|
||||||
|
_multibytecodec_state *state = PyModule_GetState(module);
|
||||||
|
assert(state != NULL);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct PyModuleDef _multibytecodecmodule;
|
||||||
|
static _multibytecodec_state *
|
||||||
|
_multibyte_codec_find_state_by_type(PyTypeObject *type)
|
||||||
|
{
|
||||||
|
PyObject *module = _PyType_GetModuleByDef(type, &_multibytecodecmodule);
|
||||||
|
assert(module != NULL);
|
||||||
|
return _multibytecodec_get_state(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define clinic_get_state() _multibyte_codec_find_state_by_type(type)
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
module _multibytecodec
|
module _multibytecodec
|
||||||
class _multibytecodec.MultibyteCodec "MultibyteCodecObject *" "&MultibyteCodec_Type"
|
class _multibytecodec.MultibyteCodec "MultibyteCodecObject *" "clinic_get_state()->multibytecodec_type"
|
||||||
|
class _multibytecodec.MultibyteIncrementalEncoder "MultibyteIncrementalEncoderObject *" "clinic_get_state()->encoder_type"
|
||||||
|
class _multibytecodec.MultibyteIncrementalDecoder "MultibyteIncrementalDecoderObject *" "clinic_get_state()->decoder_type"
|
||||||
|
class _multibytecodec.MultibyteStreamReader "MultibyteStreamReaderObject *" "clinic_get_state()->reader_type"
|
||||||
|
class _multibytecodec.MultibyteStreamWriter "MultibyteStreamWriterObject *" "clinic_get_state()->writer_type"
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6ad689546cbb5450]*/
|
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=305a76dfdd24b99c]*/
|
||||||
|
#undef clinic_get_state
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject *inobj;
|
PyObject *inobj;
|
||||||
|
@ -691,39 +724,23 @@ static struct PyMethodDef multibytecodec_methods[] = {
|
||||||
static void
|
static void
|
||||||
multibytecodec_dealloc(MultibyteCodecObject *self)
|
multibytecodec_dealloc(MultibyteCodecObject *self)
|
||||||
{
|
{
|
||||||
|
PyTypeObject *tp = Py_TYPE(self);
|
||||||
PyObject_Free(self);
|
PyObject_Free(self);
|
||||||
|
Py_DECREF(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyTypeObject MultibyteCodec_Type = {
|
static PyType_Slot multibytecodec_slots[] = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
{Py_tp_dealloc, multibytecodec_dealloc},
|
||||||
"MultibyteCodec", /* tp_name */
|
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||||
sizeof(MultibyteCodecObject), /* tp_basicsize */
|
{Py_tp_methods, multibytecodec_methods},
|
||||||
0, /* tp_itemsize */
|
{0, NULL},
|
||||||
/* methods */
|
};
|
||||||
(destructor)multibytecodec_dealloc, /* tp_dealloc */
|
|
||||||
0, /* tp_vectorcall_offset */
|
static PyType_Spec multibytecodec_spec = {
|
||||||
0, /* tp_getattr */
|
.name = MODULE_NAME ".MultibyteCodec",
|
||||||
0, /* tp_setattr */
|
.basicsize = sizeof(MultibyteCodecObject),
|
||||||
0, /* tp_as_async */
|
.flags = Py_TPFLAGS_DEFAULT,
|
||||||
0, /* tp_repr */
|
.slots = multibytecodec_slots,
|
||||||
0, /* tp_as_number */
|
|
||||||
0, /* tp_as_sequence */
|
|
||||||
0, /* tp_as_mapping */
|
|
||||||
0, /* tp_hash */
|
|
||||||
0, /* tp_call */
|
|
||||||
0, /* tp_str */
|
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
|
||||||
0, /* tp_setattro */
|
|
||||||
0, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
||||||
0, /* tp_doc */
|
|
||||||
0, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
0, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
0, /* tp_iter */
|
|
||||||
0, /* tp_iterext */
|
|
||||||
multibytecodec_methods, /* tp_methods */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -868,11 +885,6 @@ decoder_feed_buffer(MultibyteStatefulDecoderContext *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*[clinic input]
|
|
||||||
class _multibytecodec.MultibyteIncrementalEncoder "MultibyteIncrementalEncoderObject *" "&MultibyteIncrementalEncoder_Type"
|
|
||||||
[clinic start generated code]*/
|
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3be82909cd08924d]*/
|
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_multibytecodec.MultibyteIncrementalEncoder.encode
|
_multibytecodec.MultibyteIncrementalEncoder.encode
|
||||||
|
|
||||||
|
@ -1024,7 +1036,9 @@ mbiencoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
codec = PyObject_GetAttrString((PyObject *)type, "codec");
|
codec = PyObject_GetAttrString((PyObject *)type, "codec");
|
||||||
if (codec == NULL)
|
if (codec == NULL)
|
||||||
goto errorexit;
|
goto errorexit;
|
||||||
if (!MultibyteCodec_Check(codec)) {
|
|
||||||
|
_multibytecodec_state *state = _multibyte_codec_find_state_by_type(type);
|
||||||
|
if (!MultibyteCodec_Check(state, codec)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
|
PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
|
||||||
goto errorexit;
|
goto errorexit;
|
||||||
}
|
}
|
||||||
|
@ -1065,60 +1079,32 @@ mbiencoder_traverse(MultibyteIncrementalEncoderObject *self,
|
||||||
static void
|
static void
|
||||||
mbiencoder_dealloc(MultibyteIncrementalEncoderObject *self)
|
mbiencoder_dealloc(MultibyteIncrementalEncoderObject *self)
|
||||||
{
|
{
|
||||||
|
PyTypeObject *tp = Py_TYPE(self);
|
||||||
PyObject_GC_UnTrack(self);
|
PyObject_GC_UnTrack(self);
|
||||||
ERROR_DECREF(self->errors);
|
ERROR_DECREF(self->errors);
|
||||||
Py_CLEAR(self->pending);
|
Py_CLEAR(self->pending);
|
||||||
Py_TYPE(self)->tp_free(self);
|
tp->tp_free(self);
|
||||||
|
Py_DECREF(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyTypeObject MultibyteIncrementalEncoder_Type = {
|
static PyType_Slot encoder_slots[] = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
{Py_tp_dealloc, mbiencoder_dealloc},
|
||||||
"MultibyteIncrementalEncoder", /* tp_name */
|
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||||
sizeof(MultibyteIncrementalEncoderObject), /* tp_basicsize */
|
{Py_tp_traverse, mbiencoder_traverse},
|
||||||
0, /* tp_itemsize */
|
{Py_tp_methods, mbiencoder_methods},
|
||||||
/* methods */
|
{Py_tp_getset, codecctx_getsets},
|
||||||
(destructor)mbiencoder_dealloc, /* tp_dealloc */
|
{Py_tp_init, mbiencoder_init},
|
||||||
0, /* tp_vectorcall_offset */
|
{Py_tp_new, mbiencoder_new},
|
||||||
0, /* tp_getattr */
|
{0, NULL},
|
||||||
0, /* tp_setattr */
|
|
||||||
0, /* tp_as_async */
|
|
||||||
0, /* tp_repr */
|
|
||||||
0, /* tp_as_number */
|
|
||||||
0, /* tp_as_sequence */
|
|
||||||
0, /* tp_as_mapping */
|
|
||||||
0, /* tp_hash */
|
|
||||||
0, /* tp_call */
|
|
||||||
0, /* tp_str */
|
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
|
||||||
0, /* tp_setattro */
|
|
||||||
0, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
|
|
||||||
| Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
||||||
0, /* tp_doc */
|
|
||||||
(traverseproc)mbiencoder_traverse, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
0, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
0, /* tp_iter */
|
|
||||||
0, /* tp_iterext */
|
|
||||||
mbiencoder_methods, /* tp_methods */
|
|
||||||
0, /* tp_members */
|
|
||||||
codecctx_getsets, /* tp_getset */
|
|
||||||
0, /* tp_base */
|
|
||||||
0, /* tp_dict */
|
|
||||||
0, /* tp_descr_get */
|
|
||||||
0, /* tp_descr_set */
|
|
||||||
0, /* tp_dictoffset */
|
|
||||||
mbiencoder_init, /* tp_init */
|
|
||||||
0, /* tp_alloc */
|
|
||||||
mbiencoder_new, /* tp_new */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyType_Spec encoder_spec = {
|
||||||
|
.name = MODULE_NAME ".MultibyteIncrementalEncoder",
|
||||||
|
.basicsize = sizeof(MultibyteIncrementalEncoderObject),
|
||||||
|
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
|
.slots = encoder_slots,
|
||||||
|
};
|
||||||
|
|
||||||
/*[clinic input]
|
|
||||||
class _multibytecodec.MultibyteIncrementalDecoder "MultibyteIncrementalDecoderObject *" "&MultibyteIncrementalDecoder_Type"
|
|
||||||
[clinic start generated code]*/
|
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f6003faaf2cea692]*/
|
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_multibytecodec.MultibyteIncrementalDecoder.decode
|
_multibytecodec.MultibyteIncrementalDecoder.decode
|
||||||
|
@ -1324,7 +1310,9 @@ mbidecoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
codec = PyObject_GetAttrString((PyObject *)type, "codec");
|
codec = PyObject_GetAttrString((PyObject *)type, "codec");
|
||||||
if (codec == NULL)
|
if (codec == NULL)
|
||||||
goto errorexit;
|
goto errorexit;
|
||||||
if (!MultibyteCodec_Check(codec)) {
|
|
||||||
|
_multibytecodec_state *state = _multibyte_codec_find_state_by_type(type);
|
||||||
|
if (!MultibyteCodec_Check(state, codec)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
|
PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
|
||||||
goto errorexit;
|
goto errorexit;
|
||||||
}
|
}
|
||||||
|
@ -1365,59 +1353,30 @@ mbidecoder_traverse(MultibyteIncrementalDecoderObject *self,
|
||||||
static void
|
static void
|
||||||
mbidecoder_dealloc(MultibyteIncrementalDecoderObject *self)
|
mbidecoder_dealloc(MultibyteIncrementalDecoderObject *self)
|
||||||
{
|
{
|
||||||
|
PyTypeObject *tp = Py_TYPE(self);
|
||||||
PyObject_GC_UnTrack(self);
|
PyObject_GC_UnTrack(self);
|
||||||
ERROR_DECREF(self->errors);
|
ERROR_DECREF(self->errors);
|
||||||
Py_TYPE(self)->tp_free(self);
|
tp->tp_free(self);
|
||||||
|
Py_DECREF(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyTypeObject MultibyteIncrementalDecoder_Type = {
|
static PyType_Slot decoder_slots[] = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
{Py_tp_dealloc, mbidecoder_dealloc},
|
||||||
"MultibyteIncrementalDecoder", /* tp_name */
|
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||||
sizeof(MultibyteIncrementalDecoderObject), /* tp_basicsize */
|
{Py_tp_traverse, mbidecoder_traverse},
|
||||||
0, /* tp_itemsize */
|
{Py_tp_methods, mbidecoder_methods},
|
||||||
/* methods */
|
{Py_tp_getset, codecctx_getsets},
|
||||||
(destructor)mbidecoder_dealloc, /* tp_dealloc */
|
{Py_tp_init, mbidecoder_init},
|
||||||
0, /* tp_vectorcall_offset */
|
{Py_tp_new, mbidecoder_new},
|
||||||
0, /* tp_getattr */
|
{0, NULL},
|
||||||
0, /* tp_setattr */
|
|
||||||
0, /* tp_as_async */
|
|
||||||
0, /* tp_repr */
|
|
||||||
0, /* tp_as_number */
|
|
||||||
0, /* tp_as_sequence */
|
|
||||||
0, /* tp_as_mapping */
|
|
||||||
0, /* tp_hash */
|
|
||||||
0, /* tp_call */
|
|
||||||
0, /* tp_str */
|
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
|
||||||
0, /* tp_setattro */
|
|
||||||
0, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
|
|
||||||
| Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
||||||
0, /* tp_doc */
|
|
||||||
(traverseproc)mbidecoder_traverse, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
0, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
0, /* tp_iter */
|
|
||||||
0, /* tp_iterext */
|
|
||||||
mbidecoder_methods, /* tp_methods */
|
|
||||||
0, /* tp_members */
|
|
||||||
codecctx_getsets, /* tp_getset */
|
|
||||||
0, /* tp_base */
|
|
||||||
0, /* tp_dict */
|
|
||||||
0, /* tp_descr_get */
|
|
||||||
0, /* tp_descr_set */
|
|
||||||
0, /* tp_dictoffset */
|
|
||||||
mbidecoder_init, /* tp_init */
|
|
||||||
0, /* tp_alloc */
|
|
||||||
mbidecoder_new, /* tp_new */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyType_Spec decoder_spec = {
|
||||||
/*[clinic input]
|
.name = MODULE_NAME ".MultibyteIncrementalDecoder",
|
||||||
class _multibytecodec.MultibyteStreamReader "MultibyteStreamReaderObject *" "MultibyteStreamReader_Type"
|
.basicsize = sizeof(MultibyteIncrementalDecoderObject),
|
||||||
[clinic start generated code]*/
|
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d323634b74976f09]*/
|
.slots = decoder_slots,
|
||||||
|
};
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mbstreamreader_iread(MultibyteStreamReaderObject *self,
|
mbstreamreader_iread(MultibyteStreamReaderObject *self,
|
||||||
|
@ -1667,7 +1626,9 @@ mbstreamreader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
codec = PyObject_GetAttrString((PyObject *)type, "codec");
|
codec = PyObject_GetAttrString((PyObject *)type, "codec");
|
||||||
if (codec == NULL)
|
if (codec == NULL)
|
||||||
goto errorexit;
|
goto errorexit;
|
||||||
if (!MultibyteCodec_Check(codec)) {
|
|
||||||
|
_multibytecodec_state *state = _multibyte_codec_find_state_by_type(type);
|
||||||
|
if (!MultibyteCodec_Check(state, codec)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
|
PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
|
||||||
goto errorexit;
|
goto errorexit;
|
||||||
}
|
}
|
||||||
|
@ -1711,60 +1672,32 @@ mbstreamreader_traverse(MultibyteStreamReaderObject *self,
|
||||||
static void
|
static void
|
||||||
mbstreamreader_dealloc(MultibyteStreamReaderObject *self)
|
mbstreamreader_dealloc(MultibyteStreamReaderObject *self)
|
||||||
{
|
{
|
||||||
|
PyTypeObject *tp = Py_TYPE(self);
|
||||||
PyObject_GC_UnTrack(self);
|
PyObject_GC_UnTrack(self);
|
||||||
ERROR_DECREF(self->errors);
|
ERROR_DECREF(self->errors);
|
||||||
Py_XDECREF(self->stream);
|
Py_XDECREF(self->stream);
|
||||||
Py_TYPE(self)->tp_free(self);
|
tp->tp_free(self);
|
||||||
|
Py_DECREF(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyTypeObject MultibyteStreamReader_Type = {
|
static PyType_Slot reader_slots[] = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
{Py_tp_dealloc, mbstreamreader_dealloc},
|
||||||
"MultibyteStreamReader", /* tp_name */
|
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||||
sizeof(MultibyteStreamReaderObject), /* tp_basicsize */
|
{Py_tp_traverse, mbstreamreader_traverse},
|
||||||
0, /* tp_itemsize */
|
{Py_tp_methods, mbstreamreader_methods},
|
||||||
/* methods */
|
{Py_tp_members, mbstreamreader_members},
|
||||||
(destructor)mbstreamreader_dealloc, /* tp_dealloc */
|
{Py_tp_getset, codecctx_getsets},
|
||||||
0, /* tp_vectorcall_offset */
|
{Py_tp_init, mbstreamreader_init},
|
||||||
0, /* tp_getattr */
|
{Py_tp_new, mbstreamreader_new},
|
||||||
0, /* tp_setattr */
|
{0, NULL},
|
||||||
0, /* tp_as_async */
|
|
||||||
0, /* tp_repr */
|
|
||||||
0, /* tp_as_number */
|
|
||||||
0, /* tp_as_sequence */
|
|
||||||
0, /* tp_as_mapping */
|
|
||||||
0, /* tp_hash */
|
|
||||||
0, /* tp_call */
|
|
||||||
0, /* tp_str */
|
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
|
||||||
0, /* tp_setattro */
|
|
||||||
0, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
|
|
||||||
| Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
||||||
0, /* tp_doc */
|
|
||||||
(traverseproc)mbstreamreader_traverse, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
0, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
0, /* tp_iter */
|
|
||||||
0, /* tp_iterext */
|
|
||||||
mbstreamreader_methods, /* tp_methods */
|
|
||||||
mbstreamreader_members, /* tp_members */
|
|
||||||
codecctx_getsets, /* tp_getset */
|
|
||||||
0, /* tp_base */
|
|
||||||
0, /* tp_dict */
|
|
||||||
0, /* tp_descr_get */
|
|
||||||
0, /* tp_descr_set */
|
|
||||||
0, /* tp_dictoffset */
|
|
||||||
mbstreamreader_init, /* tp_init */
|
|
||||||
0, /* tp_alloc */
|
|
||||||
mbstreamreader_new, /* tp_new */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyType_Spec reader_spec = {
|
||||||
/*[clinic input]
|
.name = MODULE_NAME ".MultibyteStreamReader",
|
||||||
class _multibytecodec.MultibyteStreamWriter "MultibyteStreamWriterObject *" "&MultibyteStreamWriter_Type"
|
.basicsize = sizeof(MultibyteStreamReaderObject),
|
||||||
[clinic start generated code]*/
|
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cde22780a215d6ac]*/
|
.slots = reader_slots,
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mbstreamwriter_iwrite(MultibyteStreamWriterObject *self,
|
mbstreamwriter_iwrite(MultibyteStreamWriterObject *self,
|
||||||
|
@ -1899,7 +1832,9 @@ mbstreamwriter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
codec = PyObject_GetAttrString((PyObject *)type, "codec");
|
codec = PyObject_GetAttrString((PyObject *)type, "codec");
|
||||||
if (codec == NULL)
|
if (codec == NULL)
|
||||||
goto errorexit;
|
goto errorexit;
|
||||||
if (!MultibyteCodec_Check(codec)) {
|
|
||||||
|
_multibytecodec_state *state = _multibyte_codec_find_state_by_type(type);
|
||||||
|
if (!MultibyteCodec_Check(state, codec)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
|
PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
|
||||||
goto errorexit;
|
goto errorexit;
|
||||||
}
|
}
|
||||||
|
@ -1943,10 +1878,12 @@ mbstreamwriter_traverse(MultibyteStreamWriterObject *self,
|
||||||
static void
|
static void
|
||||||
mbstreamwriter_dealloc(MultibyteStreamWriterObject *self)
|
mbstreamwriter_dealloc(MultibyteStreamWriterObject *self)
|
||||||
{
|
{
|
||||||
|
PyTypeObject *tp = Py_TYPE(self);
|
||||||
PyObject_GC_UnTrack(self);
|
PyObject_GC_UnTrack(self);
|
||||||
ERROR_DECREF(self->errors);
|
ERROR_DECREF(self->errors);
|
||||||
Py_XDECREF(self->stream);
|
Py_XDECREF(self->stream);
|
||||||
Py_TYPE(self)->tp_free(self);
|
tp->tp_free(self);
|
||||||
|
Py_DECREF(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct PyMethodDef mbstreamwriter_methods[] = {
|
static struct PyMethodDef mbstreamwriter_methods[] = {
|
||||||
|
@ -1963,47 +1900,23 @@ static PyMemberDef mbstreamwriter_members[] = {
|
||||||
{NULL,}
|
{NULL,}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyTypeObject MultibyteStreamWriter_Type = {
|
static PyType_Slot writer_slots[] = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
{Py_tp_dealloc, mbstreamwriter_dealloc},
|
||||||
"MultibyteStreamWriter", /* tp_name */
|
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||||
sizeof(MultibyteStreamWriterObject), /* tp_basicsize */
|
{Py_tp_traverse, mbstreamwriter_traverse},
|
||||||
0, /* tp_itemsize */
|
{Py_tp_methods, mbstreamwriter_methods},
|
||||||
/* methods */
|
{Py_tp_members, mbstreamwriter_members},
|
||||||
(destructor)mbstreamwriter_dealloc, /* tp_dealloc */
|
{Py_tp_getset, codecctx_getsets},
|
||||||
0, /* tp_vectorcall_offset */
|
{Py_tp_init, mbstreamwriter_init},
|
||||||
0, /* tp_getattr */
|
{Py_tp_new, mbstreamwriter_new},
|
||||||
0, /* tp_setattr */
|
{0, NULL},
|
||||||
0, /* tp_as_async */
|
};
|
||||||
0, /* tp_repr */
|
|
||||||
0, /* tp_as_number */
|
static PyType_Spec writer_spec = {
|
||||||
0, /* tp_as_sequence */
|
.name = MODULE_NAME ".MultibyteStreamWriter",
|
||||||
0, /* tp_as_mapping */
|
.basicsize = sizeof(MultibyteStreamWriterObject),
|
||||||
0, /* tp_hash */
|
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
0, /* tp_call */
|
.slots = writer_slots,
|
||||||
0, /* tp_str */
|
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
|
||||||
0, /* tp_setattro */
|
|
||||||
0, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
|
|
||||||
| Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
||||||
0, /* tp_doc */
|
|
||||||
(traverseproc)mbstreamwriter_traverse, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
0, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
0, /* tp_iter */
|
|
||||||
0, /* tp_iterext */
|
|
||||||
mbstreamwriter_methods, /* tp_methods */
|
|
||||||
mbstreamwriter_members, /* tp_members */
|
|
||||||
codecctx_getsets, /* tp_getset */
|
|
||||||
0, /* tp_base */
|
|
||||||
0, /* tp_dict */
|
|
||||||
0, /* tp_descr_get */
|
|
||||||
0, /* tp_descr_set */
|
|
||||||
0, /* tp_dictoffset */
|
|
||||||
mbstreamwriter_init, /* tp_init */
|
|
||||||
0, /* tp_alloc */
|
|
||||||
mbstreamwriter_new, /* tp_new */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2030,7 +1943,8 @@ _multibytecodec___create_codec(PyObject *module, PyObject *arg)
|
||||||
if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0)
|
if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
self = PyObject_New(MultibyteCodecObject, &MultibyteCodec_Type);
|
_multibytecodec_state *state = _multibytecodec_get_state(module);
|
||||||
|
self = PyObject_New(MultibyteCodecObject, state->multibytecodec_type);
|
||||||
if (self == NULL)
|
if (self == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
self->codec = codec;
|
self->codec = codec;
|
||||||
|
@ -2038,51 +1952,94 @@ _multibytecodec___create_codec(PyObject *module, PyObject *arg)
|
||||||
return (PyObject *)self;
|
return (PyObject *)self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct PyMethodDef __methods[] = {
|
static int
|
||||||
|
_multibytecodec_traverse(PyObject *mod, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
_multibytecodec_state *state = _multibytecodec_get_state(mod);
|
||||||
|
Py_VISIT(state->multibytecodec_type);
|
||||||
|
Py_VISIT(state->encoder_type);
|
||||||
|
Py_VISIT(state->decoder_type);
|
||||||
|
Py_VISIT(state->reader_type);
|
||||||
|
Py_VISIT(state->writer_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_multibytecodec_clear(PyObject *mod)
|
||||||
|
{
|
||||||
|
_multibytecodec_state *state = _multibytecodec_get_state(mod);
|
||||||
|
Py_CLEAR(state->multibytecodec_type);
|
||||||
|
Py_CLEAR(state->encoder_type);
|
||||||
|
Py_CLEAR(state->decoder_type);
|
||||||
|
Py_CLEAR(state->reader_type);
|
||||||
|
Py_CLEAR(state->writer_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_multibytecodec_free(void *mod)
|
||||||
|
{
|
||||||
|
_multibytecodec_clear((PyObject *)mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CREATE_TYPE(module, type, spec) \
|
||||||
|
do { \
|
||||||
|
type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \
|
||||||
|
if (!type) { \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define ADD_TYPE(module, type) \
|
||||||
|
do { \
|
||||||
|
if (PyModule_AddType(module, type) < 0) { \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static int
|
||||||
|
_multibytecodec_exec(PyObject *mod)
|
||||||
|
{
|
||||||
|
_multibytecodec_state *state = _multibytecodec_get_state(mod);
|
||||||
|
CREATE_TYPE(mod, state->multibytecodec_type, &multibytecodec_spec);
|
||||||
|
CREATE_TYPE(mod, state->encoder_type, &encoder_spec);
|
||||||
|
CREATE_TYPE(mod, state->decoder_type, &decoder_spec);
|
||||||
|
CREATE_TYPE(mod, state->reader_type, &reader_spec);
|
||||||
|
CREATE_TYPE(mod, state->writer_type, &writer_spec);
|
||||||
|
|
||||||
|
ADD_TYPE(mod, state->encoder_type);
|
||||||
|
ADD_TYPE(mod, state->decoder_type);
|
||||||
|
ADD_TYPE(mod, state->reader_type);
|
||||||
|
ADD_TYPE(mod, state->writer_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CREATE_TYPE
|
||||||
|
#undef ADD_TYPE
|
||||||
|
|
||||||
|
static struct PyMethodDef _multibytecodec_methods[] = {
|
||||||
_MULTIBYTECODEC___CREATE_CODEC_METHODDEF
|
_MULTIBYTECODEC___CREATE_CODEC_METHODDEF
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyModuleDef_Slot _multibytecodec_slots[] = {
|
||||||
|
{Py_mod_exec, _multibytecodec_exec},
|
||||||
|
{0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
static struct PyModuleDef _multibytecodecmodule = {
|
static struct PyModuleDef _multibytecodecmodule = {
|
||||||
PyModuleDef_HEAD_INIT,
|
.m_base = PyModuleDef_HEAD_INIT,
|
||||||
"_multibytecodec",
|
.m_name = "_multibytecodec",
|
||||||
NULL,
|
.m_size = sizeof(_multibytecodec_state),
|
||||||
-1,
|
.m_methods = _multibytecodec_methods,
|
||||||
__methods,
|
.m_slots = _multibytecodec_slots,
|
||||||
NULL,
|
.m_traverse = _multibytecodec_traverse,
|
||||||
NULL,
|
.m_clear = _multibytecodec_clear,
|
||||||
NULL,
|
.m_free = _multibytecodec_free,
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PyMODINIT_FUNC
|
PyMODINIT_FUNC
|
||||||
PyInit__multibytecodec(void)
|
PyInit__multibytecodec(void)
|
||||||
{
|
{
|
||||||
PyObject *m;
|
return PyModuleDef_Init(&_multibytecodecmodule);
|
||||||
PyTypeObject *typelist[] = {
|
|
||||||
&MultibyteIncrementalEncoder_Type,
|
|
||||||
&MultibyteIncrementalDecoder_Type,
|
|
||||||
&MultibyteStreamReader_Type,
|
|
||||||
&MultibyteStreamWriter_Type
|
|
||||||
};
|
|
||||||
|
|
||||||
if (PyType_Ready(&MultibyteCodec_Type) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
m = PyModule_Create(&_multibytecodecmodule);
|
|
||||||
if (m == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
|
|
||||||
if (PyModule_AddType(m, typelist[i]) < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
Py_DECREF(m);
|
|
||||||
m = NULL;
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ typedef struct {
|
||||||
MultibyteCodec *codec;
|
MultibyteCodec *codec;
|
||||||
} MultibyteCodecObject;
|
} MultibyteCodecObject;
|
||||||
|
|
||||||
#define MultibyteCodec_Check(op) Py_IS_TYPE((op), &MultibyteCodec_Type)
|
#define MultibyteCodec_Check(state, op) Py_IS_TYPE((op), state->multibytecodec_type)
|
||||||
|
|
||||||
#define _MultibyteStatefulCodec_HEAD \
|
#define _MultibyteStatefulCodec_HEAD \
|
||||||
PyObject_HEAD \
|
PyObject_HEAD \
|
||||||
|
|
Loading…
Reference in New Issue