@@ -26,7 +26,7 @@ class _zstd.ZstdDict "ZstdDict *" "&zstd_dict_type_spec"
26
26
/*[clinic input]
27
27
@classmethod
28
28
_zstd.ZstdDict.__new__ as _zstd_ZstdDict_new
29
- dict_content: object
29
+ dict_content: Py_buffer
30
30
The content of a Zstandard dictionary as a bytes-like object.
31
31
/
32
32
*
@@ -42,17 +42,25 @@ by multiple ZstdCompressor or ZstdDecompressor objects.
42
42
[clinic start generated code]*/
43
43
44
44
static PyObject *
45
- _zstd_ZstdDict_new_impl (PyTypeObject * type , PyObject * dict_content ,
45
+ _zstd_ZstdDict_new_impl (PyTypeObject * type , Py_buffer * dict_content ,
46
46
int is_raw )
47
- /*[clinic end generated code: output=3ebff839cb3be6d7 input=6b5de413869ae878 ]*/
47
+ /*[clinic end generated code: output=685b7406a48b0949 input=9e8c493e31c98383 ]*/
48
48
{
49
+ /* All dictionaries must be at least 8 bytes */
50
+ if (dict_content -> len < 8 ) {
51
+ PyErr_SetString (PyExc_ValueError ,
52
+ "Zstandard dictionary content too short "
53
+ "(must have at least eight bytes)" );
54
+ return NULL ;
55
+ }
56
+
49
57
ZstdDict * self = PyObject_GC_New (ZstdDict , type );
50
58
if (self == NULL ) {
51
- goto error ;
59
+ return NULL ;
52
60
}
53
61
54
- self -> dict_content = NULL ;
55
62
self -> d_dict = NULL ;
63
+ self -> dict_buffer = NULL ;
56
64
self -> dict_id = 0 ;
57
65
self -> lock = (PyMutex ){0 };
58
66
@@ -62,39 +70,26 @@ _zstd_ZstdDict_new_impl(PyTypeObject *type, PyObject *dict_content,
62
70
goto error ;
63
71
}
64
72
65
- /* Check dict_content's type */
66
- self -> dict_content = PyBytes_FromObject (dict_content );
67
- if (self -> dict_content == NULL ) {
68
- PyErr_SetString (PyExc_TypeError ,
69
- "dict_content argument should be bytes-like object." );
70
- goto error ;
71
- }
72
-
73
- /* Both ordinary dictionary and "raw content" dictionary should
74
- at least 8 bytes */
75
- if (Py_SIZE (self -> dict_content ) < 8 ) {
76
- PyErr_SetString (PyExc_ValueError ,
77
- "Zstandard dictionary content should at least "
78
- "8 bytes." );
73
+ self -> dict_buffer = PyMem_Malloc (dict_content -> len );
74
+ if (!self -> dict_buffer ) {
75
+ PyErr_NoMemory ();
79
76
goto error ;
80
77
}
78
+ memcpy (self -> dict_buffer , dict_content -> buf , dict_content -> len );
79
+ self -> dict_len = dict_content -> len ;
81
80
82
81
/* Get dict_id, 0 means "raw content" dictionary. */
83
- self -> dict_id = ZSTD_getDictID_fromDict (
84
- PyBytes_AS_STRING (self -> dict_content ),
85
- Py_SIZE (self -> dict_content ));
82
+ self -> dict_id = ZSTD_getDictID_fromDict (self -> dict_buffer , self -> dict_len );
86
83
87
84
/* Check validity for ordinary dictionary */
88
85
if (!is_raw && self -> dict_id == 0 ) {
89
- char * msg = "Invalid Zstandard dictionary and is_raw not set.\n" ;
90
- PyErr_SetString (PyExc_ValueError , msg );
86
+ PyErr_SetString (PyExc_ValueError , "invalid Zstandard dictionary" );
91
87
goto error ;
92
88
}
93
89
94
- // Can only track self once self->dict_content is included
95
90
PyObject_GC_Track (self );
96
91
97
- return (PyObject * )self ;
92
+ return (PyObject * )self ;
98
93
99
94
error :
100
95
Py_XDECREF (self );
@@ -115,12 +110,12 @@ ZstdDict_dealloc(PyObject *ob)
115
110
116
111
assert (!PyMutex_IsLocked (& self -> lock ));
117
112
118
- /* Release dict_content after Free ZSTD_CDict/ZSTD_DDict instances */
119
- Py_CLEAR (self -> dict_content );
113
+ /* Release dict_buffer after freeing ZSTD_CDict/ZSTD_DDict instances */
114
+ PyMem_Free (self -> dict_buffer );
120
115
Py_CLEAR (self -> c_dicts );
121
116
122
117
PyTypeObject * tp = Py_TYPE (self );
123
- PyObject_GC_Del ( ob );
118
+ tp -> tp_free ( self );
124
119
Py_DECREF (tp );
125
120
}
126
121
@@ -131,25 +126,33 @@ PyDoc_STRVAR(ZstdDict_dictid_doc,
131
126
"The special value '0' means a 'raw content' dictionary,"
132
127
"without any restrictions on format or content." );
133
128
134
- PyDoc_STRVAR (ZstdDict_dictcontent_doc ,
135
- "The content of a Zstandard dictionary, as a bytes object." );
136
-
137
129
static PyObject *
138
- ZstdDict_str (PyObject * ob )
130
+ ZstdDict_repr (PyObject * ob )
139
131
{
140
132
ZstdDict * dict = ZstdDict_CAST (ob );
141
133
return PyUnicode_FromFormat ("<ZstdDict dict_id=%u dict_size=%zd>" ,
142
- dict -> dict_id , Py_SIZE ( dict -> dict_content ) );
134
+ ( unsigned int ) dict -> dict_id , dict -> dict_len );
143
135
}
144
136
145
137
static 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 },
138
+ {"dict_id" , Py_T_UINT , offsetof(ZstdDict , dict_id ), Py_READONLY , ZstdDict_dictid_doc },
150
139
{NULL }
151
140
};
152
141
142
+ /*[clinic input]
143
+ @getter
144
+ _zstd.ZstdDict.dict_content
145
+
146
+ The content of a Zstandard dictionary, as a bytes object.
147
+ [clinic start generated code]*/
148
+
149
+ static PyObject *
150
+ _zstd_ZstdDict_dict_content_get_impl (ZstdDict * self )
151
+ /*[clinic end generated code: output=0d05caa5b550eabb input=4ed526d1c151c596]*/
152
+ {
153
+ return PyBytes_FromStringAndSize (self -> dict_buffer , self -> dict_len );
154
+ }
155
+
153
156
/*[clinic input]
154
157
@getter
155
158
_zstd.ZstdDict.as_digested_dict
@@ -219,6 +222,7 @@ _zstd_ZstdDict_as_prefix_get_impl(ZstdDict *self)
219
222
}
220
223
221
224
static PyGetSetDef ZstdDict_getset [] = {
225
+ _ZSTD_ZSTDDICT_DICT_CONTENT_GETSETDEF
222
226
_ZSTD_ZSTDDICT_AS_DIGESTED_DICT_GETSETDEF
223
227
_ZSTD_ZSTDDICT_AS_UNDIGESTED_DICT_GETSETDEF
224
228
_ZSTD_ZSTDDICT_AS_PREFIX_GETSETDEF
@@ -229,24 +233,22 @@ static Py_ssize_t
229
233
ZstdDict_length (PyObject * ob )
230
234
{
231
235
ZstdDict * self = ZstdDict_CAST (ob );
232
- assert (PyBytes_Check (self -> dict_content ));
233
- return Py_SIZE (self -> dict_content );
236
+ return self -> dict_len ;
234
237
}
235
238
236
239
static int
237
240
ZstdDict_traverse (PyObject * ob , visitproc visit , void * arg )
238
241
{
239
242
ZstdDict * self = ZstdDict_CAST (ob );
240
243
Py_VISIT (self -> c_dicts );
241
- Py_VISIT (self -> dict_content );
242
244
return 0 ;
243
245
}
244
246
245
247
static int
246
248
ZstdDict_clear (PyObject * ob )
247
249
{
248
250
ZstdDict * self = ZstdDict_CAST (ob );
249
- Py_CLEAR (self -> dict_content );
251
+ Py_CLEAR (self -> c_dicts );
250
252
return 0 ;
251
253
}
252
254
@@ -255,7 +257,7 @@ static PyType_Slot zstddict_slots[] = {
255
257
{Py_tp_getset , ZstdDict_getset },
256
258
{Py_tp_new , _zstd_ZstdDict_new },
257
259
{Py_tp_dealloc , ZstdDict_dealloc },
258
- {Py_tp_str , ZstdDict_str },
260
+ {Py_tp_repr , ZstdDict_repr },
259
261
{Py_tp_doc , (void * )_zstd_ZstdDict_new__doc__ },
260
262
{Py_sq_length , ZstdDict_length },
261
263
{Py_tp_traverse , ZstdDict_traverse },
0 commit comments