11#include "reader.h"
22
33#include <assert.h>
4+ #include <Python.h>
45
56static void Reader_dealloc (hiredis_ReaderObject * self );
67static int Reader_traverse (hiredis_ReaderObject * self , visitproc visit , void * arg );
@@ -14,6 +15,10 @@ static PyObject *Reader_len(hiredis_ReaderObject *self);
1415static PyObject * Reader_has_data (hiredis_ReaderObject * self );
1516static PyObject * Reader_set_encoding (hiredis_ReaderObject * self , PyObject * args , PyObject * kwds );
1617
18+ static int PushNotificationType_init (PushNotificationObject * self , PyObject * args , PyObject * kwds );
19+ /* Create a new instance of PushNotificationType with preallocated number of elements */
20+ static PyObject * PushNotificationType_New (Py_ssize_t size );
21+
1722static PyMethodDef hiredis_ReaderMethods [] = {
1823 {"feed" , (PyCFunction )Reader_feed , METH_VARARGS , NULL },
1924 {"gets" , (PyCFunction )Reader_gets , METH_VARARGS , NULL },
@@ -66,6 +71,16 @@ PyTypeObject hiredis_ReaderType = {
6671 Reader_new , /*tp_new */
6772};
6873
74+ PyTypeObject PushNotificationType = {
75+ PyVarObject_HEAD_INIT (NULL , 0 )
76+ .tp_name = MOD_HIREDIS ".PushNotification" ,
77+ .tp_basicsize = sizeof (PushNotificationObject ),
78+ .tp_itemsize = 0 ,
79+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,
80+ .tp_doc = "Redis PUSH notification type" ,
81+ .tp_init = (initproc ) PushNotificationType_init ,
82+ };
83+
6984static void * tryParentize (const redisReadTask * task , PyObject * obj ) {
7085 PyObject * parent ;
7186 if (task && task -> parent ) {
@@ -165,6 +180,9 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
165180 case REDIS_REPLY_MAP :
166181 obj = PyDict_New ();
167182 break ;
183+ case REDIS_REPLY_PUSH :
184+ obj = PushNotificationType_New (elements );
185+ break ;
168186 default :
169187 obj = PyList_New (elements );
170188 }
@@ -199,6 +217,55 @@ static void freeObject(void *obj) {
199217 Py_XDECREF (obj );
200218}
201219
220+ static int PushNotificationType_init (PushNotificationObject * self , PyObject * args , PyObject * kwds ) {
221+ return PyList_Type .tp_init ((PyObject * )self , args , kwds );
222+ }
223+
224+ /* Create a new instance of PushNotificationType with preallocated number of elements */
225+ static PyObject * PushNotificationType_New (Py_ssize_t size ) {
226+ /* Check for negative size */
227+ if (size < 0 ) {
228+ PyErr_SetString (PyExc_SystemError , "negative list size" );
229+ return NULL ;
230+ }
231+
232+ /* Check for potential overflow */
233+ if ((size_t )size > PY_SSIZE_T_MAX / sizeof (PyObject * )) {
234+ return PyErr_NoMemory ();
235+ }
236+
237+ /* Create a new instance of PushNotificationType */
238+ PyObject * obj = PyType_GenericNew (& PushNotificationType , NULL , NULL );
239+ if (obj == NULL ) {
240+ return NULL ;
241+ }
242+
243+ /* Cast to PyListObject to access its fields */
244+ PyListObject * op = (PyListObject * )obj ;
245+
246+ /* Allocate memory for the list items if size > 0 */
247+ if (size > 0 ) {
248+ size_t nbytes = (size_t )size * sizeof (PyObject * );
249+ op -> ob_item = (PyObject * * )PyMem_Malloc (nbytes );
250+ if (op -> ob_item == NULL ) {
251+ Py_DECREF (obj );
252+ return PyErr_NoMemory ();
253+ }
254+ /* Initialize memory to zeros */
255+ memset (op -> ob_item , 0 , nbytes );
256+ }
257+
258+ /* Set the size and allocated fields */
259+ #if PY_VERSION_HEX >= 0x03090000
260+ Py_SET_SIZE (op , size );
261+ #else
262+ Py_SIZE (op ) = size ;
263+ #endif
264+ op -> allocated = size ;
265+
266+ return obj ;
267+ }
268+
202269redisReplyObjectFunctions hiredis_ObjectFunctions = {
203270 createStringObject , // void *(*createString)(const redisReadTask*, char*, size_t);
204271 createArrayObject , // void *(*createArray)(const redisReadTask*, size_t);
0 commit comments