@@ -25,7 +25,7 @@ class _zstd.ZstdDict "ZstdDict *" "&zstd_dict_type_spec"
2525/*[clinic input]
2626@classmethod
2727_zstd.ZstdDict.__new__ as _zstd_ZstdDict_new
28- dict_content: object
28+ dict_content: Py_buffer
2929 The content of a Zstandard dictionary as a bytes-like object.
3030 /
3131 *
@@ -41,16 +41,15 @@ by multiple ZstdCompressor or ZstdDecompressor objects.
4141[clinic start generated code]*/
4242
4343static PyObject *
44- _zstd_ZstdDict_new_impl (PyTypeObject * type , PyObject * dict_content ,
44+ _zstd_ZstdDict_new_impl (PyTypeObject * type , Py_buffer * dict_content ,
4545 int is_raw )
46- /*[clinic end generated code: output=3ebff839cb3be6d7 input=6b5de413869ae878 ]*/
46+ /*[clinic end generated code: output=685b7406a48b0949 input=9e8c493e31c98383 ]*/
4747{
4848 ZstdDict * self = PyObject_GC_New (ZstdDict , type );
4949 if (self == NULL ) {
50- goto error ;
50+ return NULL ;
5151 }
5252
53- self -> dict_content = NULL ;
5453 self -> d_dict = NULL ;
5554
5655 /* ZSTD_CDict dict */
@@ -60,24 +59,28 @@ _zstd_ZstdDict_new_impl(PyTypeObject *type, PyObject *dict_content,
6059 }
6160
6261 /* Check dict_content's type */
63- self -> dict_content = PyBytes_FromObject (dict_content );
64- if (self -> dict_content == NULL ) {
62+ if (dict_content == NULL ) {
6563 PyErr_SetString (PyExc_TypeError ,
6664 "dict_content argument should be bytes-like object." );
6765 goto error ;
6866 }
6967
70- /* Both ordinary dictionary and "raw content" dictionary should
71- at least 8 bytes */
72- if (Py_SIZE (self -> dict_content ) < 8 ) {
68+ self -> dict_buffer = PyMem_RawMalloc (dict_content -> len );
69+ if (!self -> dict_buffer ) {
70+ return PyErr_NoMemory ();
71+ }
72+ memcpy (self -> dict_buffer , dict_content -> buf , dict_content -> len );
73+ self -> dict_len = dict_content -> len ;
74+
75+ /* Both ordinary and "raw content" dictionaries must be 8 bytes minimum */
76+ if (self -> dict_len < 8 ) {
7377 PyErr_SetString (PyExc_ValueError ,
7478 "Zstandard dictionary content should at least 8 bytes." );
7579 goto error ;
7680 }
7781
7882 /* Get dict_id, 0 means "raw content" dictionary. */
79- self -> dict_id = ZSTD_getDictID_fromDict (PyBytes_AS_STRING (self -> dict_content ),
80- Py_SIZE (self -> dict_content ));
83+ self -> dict_id = ZSTD_getDictID_fromDict (self -> dict_buffer , self -> dict_len );
8184
8285 /* Check validity for ordinary dictionary */
8386 if (!is_raw && self -> dict_id == 0 ) {
@@ -86,15 +89,12 @@ _zstd_ZstdDict_new_impl(PyTypeObject *type, PyObject *dict_content,
8689 goto error ;
8790 }
8891
89- // Can only track self once self->dict_content is included
9092 PyObject_GC_Track (self );
9193
9294 return (PyObject * )self ;
9395
9496error :
95- if (self != NULL ) {
96- PyObject_GC_Del (self );
97- }
97+ PyObject_GC_Del (self );
9898 return NULL ;
9999}
100100
@@ -108,12 +108,12 @@ ZstdDict_dealloc(PyObject *ob)
108108 /* Free ZSTD_DDict instance */
109109 ZSTD_freeDDict (self -> d_dict );
110110
111- /* Release dict_content after Free ZSTD_CDict/ZSTD_DDict instances */
112- Py_CLEAR (self -> dict_content );
111+ /* Release dict_buffer after Free ZSTD_CDict/ZSTD_DDict instances */
112+ PyMem_RawFree (self -> dict_buffer );
113113 Py_CLEAR (self -> c_dicts );
114114
115115 PyTypeObject * tp = Py_TYPE (self );
116- PyObject_GC_Del ( ob );
116+ tp -> tp_free ( self );
117117 Py_DECREF (tp );
118118}
119119
@@ -124,23 +124,33 @@ PyDoc_STRVAR(ZstdDict_dictid_doc,
124124"The special value '0' means a 'raw content' dictionary,"
125125"without any restrictions on format or content." );
126126
127- PyDoc_STRVAR (ZstdDict_dictcontent_doc ,
128- "The content of a Zstandard dictionary, as a bytes object." );
129-
130127static PyObject *
131128ZstdDict_str (PyObject * ob )
132129{
133130 ZstdDict * dict = ZstdDict_CAST (ob );
134131 return PyUnicode_FromFormat ("<ZstdDict dict_id=%u dict_size=%zd>" ,
135- dict -> dict_id , Py_SIZE ( dict -> dict_content ) );
132+ dict -> dict_id , dict -> dict_len );
136133}
137134
138135static PyMemberDef ZstdDict_members [] = {
139136 {"dict_id" , Py_T_UINT , offsetof(ZstdDict , dict_id ), Py_READONLY , ZstdDict_dictid_doc },
140- {"dict_content" , Py_T_OBJECT_EX , offsetof(ZstdDict , dict_content ), Py_READONLY , ZstdDict_dictcontent_doc },
141137 {NULL }
142138};
143139
140+ /*[clinic input]
141+ @getter
142+ _zstd.ZstdDict.dict_content
143+
144+ The content of a Zstandard dictionary, as a bytes object.
145+ [clinic start generated code]*/
146+
147+ static PyObject *
148+ _zstd_ZstdDict_dict_content_get_impl (ZstdDict * self )
149+ /*[clinic end generated code: output=0d05caa5b550eabb input=4ed526d1c151c596]*/
150+ {
151+ return PyBytes_FromStringAndSize (self -> dict_buffer , self -> dict_len );
152+ }
153+
144154/*[clinic input]
145155@critical_section
146156@getter
@@ -207,6 +217,7 @@ _zstd_ZstdDict_as_prefix_get_impl(ZstdDict *self)
207217}
208218
209219static PyGetSetDef ZstdDict_getset [] = {
220+ _ZSTD_ZSTDDICT_DICT_CONTENT_GETSETDEF
210221 _ZSTD_ZSTDDICT_AS_DIGESTED_DICT_GETSETDEF
211222 _ZSTD_ZSTDDICT_AS_UNDIGESTED_DICT_GETSETDEF
212223 _ZSTD_ZSTDDICT_AS_PREFIX_GETSETDEF
@@ -217,24 +228,14 @@ static Py_ssize_t
217228ZstdDict_length (PyObject * ob )
218229{
219230 ZstdDict * self = ZstdDict_CAST (ob );
220- assert (PyBytes_Check (self -> dict_content ));
221- return Py_SIZE (self -> dict_content );
231+ return self -> dict_len ;
222232}
223233
224234static int
225235ZstdDict_traverse (PyObject * ob , visitproc visit , void * arg )
226236{
227237 ZstdDict * self = ZstdDict_CAST (ob );
228238 Py_VISIT (self -> c_dicts );
229- Py_VISIT (self -> dict_content );
230- return 0 ;
231- }
232-
233- static int
234- ZstdDict_clear (PyObject * ob )
235- {
236- ZstdDict * self = ZstdDict_CAST (ob );
237- Py_CLEAR (self -> dict_content );
238239 return 0 ;
239240}
240241
@@ -247,7 +248,6 @@ static PyType_Slot zstddict_slots[] = {
247248 {Py_tp_doc , (void * )_zstd_ZstdDict_new__doc__ },
248249 {Py_sq_length , ZstdDict_length },
249250 {Py_tp_traverse , ZstdDict_traverse },
250- {Py_tp_clear , ZstdDict_clear },
251251 {0 , 0 }
252252};
253253
0 commit comments