@@ -26,7 +26,7 @@ class _zstd.ZstdDict "ZstdDict *" "&zstd_dict_type_spec"
2626/*[clinic input]
2727@classmethod
2828_zstd.ZstdDict.__new__ as _zstd_ZstdDict_new
29- dict_content: object
29+ dict_content: Py_buffer
3030 The content of a Zstandard dictionary as a bytes-like object.
3131 /
3232 *
@@ -42,16 +42,15 @@ by multiple ZstdCompressor or ZstdDecompressor objects.
4242[clinic start generated code]*/
4343
4444static PyObject *
45- _zstd_ZstdDict_new_impl (PyTypeObject * type , PyObject * dict_content ,
45+ _zstd_ZstdDict_new_impl (PyTypeObject * type , Py_buffer * dict_content ,
4646 int is_raw )
47- /*[clinic end generated code: output=3ebff839cb3be6d7 input=6b5de413869ae878 ]*/
47+ /*[clinic end generated code: output=685b7406a48b0949 input=9e8c493e31c98383 ]*/
4848{
4949 ZstdDict * self = PyObject_GC_New (ZstdDict , type );
5050 if (self == NULL ) {
51- goto error ;
51+ return NULL ;
5252 }
5353
54- self -> dict_content = NULL ;
5554 self -> d_dict = NULL ;
5655 self -> dict_id = 0 ;
5756 self -> lock = (PyMutex ){0 };
@@ -63,16 +62,21 @@ _zstd_ZstdDict_new_impl(PyTypeObject *type, PyObject *dict_content,
6362 }
6463
6564 /* Check dict_content's type */
66- self -> dict_content = PyBytes_FromObject (dict_content );
67- if (self -> dict_content == NULL ) {
65+ if (dict_content == NULL ) {
6866 PyErr_SetString (PyExc_TypeError ,
6967 "dict_content argument should be bytes-like object." );
7068 goto error ;
7169 }
7270
73- /* Both ordinary dictionary and "raw content" dictionary should
74- at least 8 bytes */
75- if (Py_SIZE (self -> dict_content ) < 8 ) {
71+ self -> dict_buffer = PyMem_RawMalloc (dict_content -> len );
72+ if (!self -> dict_buffer ) {
73+ return PyErr_NoMemory ();
74+ }
75+ memcpy (self -> dict_buffer , dict_content -> buf , dict_content -> len );
76+ self -> dict_len = dict_content -> len ;
77+
78+ /* Both ordinary and "raw content" dictionaries must be 8 bytes minimum */
79+ if (self -> dict_len < 8 ) {
7680 PyErr_SetString (PyExc_ValueError ,
7781 "Zstandard dictionary content should at least "
7882 "8 bytes." );
@@ -81,8 +85,7 @@ _zstd_ZstdDict_new_impl(PyTypeObject *type, PyObject *dict_content,
8185
8286 /* Get dict_id, 0 means "raw content" dictionary. */
8387 self -> dict_id = ZSTD_getDictID_fromDict (
84- PyBytes_AS_STRING (self -> dict_content ),
85- Py_SIZE (self -> dict_content ));
88+ self -> dict_buffer , self -> dict_len );
8689
8790 /* Check validity for ordinary dictionary */
8891 if (!is_raw && self -> dict_id == 0 ) {
@@ -91,13 +94,13 @@ _zstd_ZstdDict_new_impl(PyTypeObject *type, PyObject *dict_content,
9194 goto error ;
9295 }
9396
94- // Can only track self once self->dict_content is included
9597 PyObject_GC_Track (self );
9698
9799 return (PyObject * )self ;
98100
99101error :
100102 Py_XDECREF (self );
103+ PyObject_GC_Del (self );
101104 return NULL ;
102105}
103106
@@ -115,12 +118,12 @@ ZstdDict_dealloc(PyObject *ob)
115118
116119 assert (!PyMutex_IsLocked (& self -> lock ));
117120
118- /* Release dict_content after Free ZSTD_CDict/ZSTD_DDict instances */
119- Py_CLEAR (self -> dict_content );
121+ /* Release dict_buffer after Free ZSTD_CDict/ZSTD_DDict instances */
122+ PyMem_RawFree (self -> dict_buffer );
120123 Py_CLEAR (self -> c_dicts );
121124
122125 PyTypeObject * tp = Py_TYPE (self );
123- PyObject_GC_Del ( ob );
126+ tp -> tp_free ( self );
124127 Py_DECREF (tp );
125128}
126129
@@ -131,25 +134,33 @@ PyDoc_STRVAR(ZstdDict_dictid_doc,
131134"The special value '0' means a 'raw content' dictionary,"
132135"without any restrictions on format or content." );
133136
134- PyDoc_STRVAR (ZstdDict_dictcontent_doc ,
135- "The content of a Zstandard dictionary, as a bytes object." );
136-
137137static PyObject *
138138ZstdDict_str (PyObject * ob )
139139{
140140 ZstdDict * dict = ZstdDict_CAST (ob );
141141 return PyUnicode_FromFormat ("<ZstdDict dict_id=%u dict_size=%zd>" ,
142- dict -> dict_id , Py_SIZE ( dict -> dict_content ) );
142+ dict -> dict_id , dict -> dict_len );
143143}
144144
145145static PyMemberDef ZstdDict_members [] = {
146- {"dict_id" , Py_T_UINT , offsetof(ZstdDict , dict_id ), Py_READONLY ,
147- ZstdDict_dictid_doc },
148- {"dict_content" , Py_T_OBJECT_EX , offsetof(ZstdDict , dict_content ),
149- Py_READONLY , ZstdDict_dictcontent_doc },
146+ {"dict_id" , Py_T_UINT , offsetof(ZstdDict , dict_id ), Py_READONLY , ZstdDict_dictid_doc },
150147 {NULL }
151148};
152149
150+ /*[clinic input]
151+ @getter
152+ _zstd.ZstdDict.dict_content
153+
154+ The content of a Zstandard dictionary, as a bytes object.
155+ [clinic start generated code]*/
156+
157+ static PyObject *
158+ _zstd_ZstdDict_dict_content_get_impl (ZstdDict * self )
159+ /*[clinic end generated code: output=0d05caa5b550eabb input=4ed526d1c151c596]*/
160+ {
161+ return PyBytes_FromStringAndSize (self -> dict_buffer , self -> dict_len );
162+ }
163+
153164/*[clinic input]
154165@getter
155166_zstd.ZstdDict.as_digested_dict
@@ -219,6 +230,7 @@ _zstd_ZstdDict_as_prefix_get_impl(ZstdDict *self)
219230}
220231
221232static PyGetSetDef ZstdDict_getset [] = {
233+ _ZSTD_ZSTDDICT_DICT_CONTENT_GETSETDEF
222234 _ZSTD_ZSTDDICT_AS_DIGESTED_DICT_GETSETDEF
223235 _ZSTD_ZSTDDICT_AS_UNDIGESTED_DICT_GETSETDEF
224236 _ZSTD_ZSTDDICT_AS_PREFIX_GETSETDEF
@@ -229,24 +241,14 @@ static Py_ssize_t
229241ZstdDict_length (PyObject * ob )
230242{
231243 ZstdDict * self = ZstdDict_CAST (ob );
232- assert (PyBytes_Check (self -> dict_content ));
233- return Py_SIZE (self -> dict_content );
244+ return self -> dict_len ;
234245}
235246
236247static int
237248ZstdDict_traverse (PyObject * ob , visitproc visit , void * arg )
238249{
239250 ZstdDict * self = ZstdDict_CAST (ob );
240251 Py_VISIT (self -> c_dicts );
241- Py_VISIT (self -> dict_content );
242- return 0 ;
243- }
244-
245- static int
246- ZstdDict_clear (PyObject * ob )
247- {
248- ZstdDict * self = ZstdDict_CAST (ob );
249- Py_CLEAR (self -> dict_content );
250252 return 0 ;
251253}
252254
@@ -259,7 +261,6 @@ static PyType_Slot zstddict_slots[] = {
259261 {Py_tp_doc , (void * )_zstd_ZstdDict_new__doc__ },
260262 {Py_sq_length , ZstdDict_length },
261263 {Py_tp_traverse , ZstdDict_traverse },
262- {Py_tp_clear , ZstdDict_clear },
263264 {0 , 0 }
264265};
265266
0 commit comments