@@ -45,98 +45,105 @@ typedef struct {
4545#include "clinic/compressor.c.h"
4646
4747static int
48- _zstd_set_c_parameters (ZstdCompressor * self , PyObject * level_or_options ,
49- const char * arg_name , const char * arg_type )
48+ _zstd_set_c_level (ZstdCompressor * self , const Py_ssize_t level )
5049{
51- size_t zstd_ret ;
50+ /* Set integer compression level */
5251 _zstd_state * const mod_state = PyType_GetModuleState (Py_TYPE (self ));
5352 if (mod_state == NULL ) {
5453 return -1 ;
5554 }
5655
57- /* Integer compression level */
58- if (PyLong_Check (level_or_options )) {
59- int level = PyLong_AsInt (level_or_options );
60- if (level == -1 && PyErr_Occurred ()) {
61- PyErr_Format (PyExc_ValueError ,
62- "Compression level should be an int value between %d and %d." ,
63- ZSTD_minCLevel (), ZSTD_maxCLevel ());
64- return -1 ;
65- }
56+ const int min_level = ZSTD_minCLevel ();
57+ const int max_level = ZSTD_maxCLevel ();
58+ if (level < min_level || level > max_level ) {
59+ PyErr_Format (PyExc_ValueError ,
60+ "compression level %zd not in valid range %d <= level <= %d." ,
61+ level , min_level , max_level );
62+ return -1 ;
63+ }
6664
67- /* Save for generating ZSTD_CDICT */
68- self -> compression_level = level ;
65+ /* Save for generating ZSTD_CDICT */
66+ self -> compression_level = ( int ) level ;
6967
70- /* Set compressionLevel to compression context */
71- zstd_ret = ZSTD_CCtx_setParameter (self -> cctx ,
72- ZSTD_c_compressionLevel ,
73- level );
68+ /* Set compressionLevel to compression context */
69+ size_t zstd_ret = ZSTD_CCtx_setParameter (
70+ self -> cctx , ZSTD_c_compressionLevel , (int )level );
7471
75- /* Check error */
76- if (ZSTD_isError (zstd_ret )) {
77- set_zstd_error (mod_state , ERR_SET_C_LEVEL , zstd_ret );
78- return -1 ;
79- }
80- return 0 ;
72+ /* Check error */
73+ if (ZSTD_isError (zstd_ret )) {
74+ set_zstd_error (mod_state , ERR_SET_C_LEVEL , zstd_ret );
75+ return -1 ;
76+ }
77+ return 0 ;
78+ }
79+
80+ static int
81+ _zstd_set_c_parameters (ZstdCompressor * self , PyObject * options )
82+ {
83+ /* Set options dict */
84+ size_t zstd_ret ;
85+ _zstd_state * const mod_state = PyType_GetModuleState (Py_TYPE (self ));
86+ if (mod_state == NULL ) {
87+ return -1 ;
8188 }
8289
83- /* Options dict */
84- if ( PyDict_Check ( level_or_options )) {
85- PyObject * key , * value ;
86- Py_ssize_t pos = 0 ;
90+ if (! PyDict_Check ( options )) {
91+ PyErr_Format ( PyExc_TypeError , "Invalid type for options, expected dict" );
92+ return -1 ;
93+ }
8794
88- while (PyDict_Next (level_or_options , & pos , & key , & value )) {
89- /* Check key type */
90- if (Py_TYPE (key ) == mod_state -> DParameter_type ) {
91- PyErr_SetString (PyExc_TypeError ,
92- "Key of compression option dict should "
93- "NOT be DecompressionParameter." );
94- return -1 ;
95- }
95+ PyObject * key , * value ;
96+ Py_ssize_t pos = 0 ;
9697
97- int key_v = PyLong_AsInt (key );
98- if (key_v == -1 && PyErr_Occurred ()) {
99- PyErr_SetString (PyExc_ValueError ,
100- "Key of options dict should be a CompressionParameter attribute." );
101- return -1 ;
102- }
98+ while (PyDict_Next (options , & pos , & key , & value )) {
99+ /* Check key type */
100+ if (Py_TYPE (key ) == mod_state -> DParameter_type ) {
101+ PyErr_SetString (PyExc_TypeError ,
102+ "Key of compression option dict should "
103+ "NOT be DecompressionParameter." );
104+ return -1 ;
105+ }
103106
104- // TODO(emmatyping): check bounds when there is a value error here for better
105- // error message?
106- int value_v = PyLong_AsInt (value );
107- if (value_v == -1 && PyErr_Occurred ()) {
108- PyErr_SetString (PyExc_ValueError ,
109- "Value of option dict should be an int." );
110- return -1 ;
111- }
107+ int key_v = PyLong_AsInt (key );
108+ if (key_v == -1 && PyErr_Occurred ()) {
109+ PyErr_SetString (PyExc_ValueError ,
110+ "Key of options dict should be a CompressionParameter attribute." );
111+ return -1 ;
112+ }
112113
113- if (key_v == ZSTD_c_compressionLevel ) {
114- /* Save for generating ZSTD_CDICT */
115- self -> compression_level = value_v ;
116- }
117- else if (key_v == ZSTD_c_nbWorkers ) {
118- /* From the zstd library docs:
119- 1. When nbWorkers >= 1, triggers asynchronous mode when
120- used with ZSTD_compressStream2().
121- 2, Default value is `0`, aka "single-threaded mode" : no
122- worker is spawned, compression is performed inside
123- caller's thread, all invocations are blocking. */
124- if (value_v != 0 ) {
125- self -> use_multithread = 1 ;
126- }
127- }
114+ // TODO(emmatyping): check bounds when there is a value error here for better
115+ // error message?
116+ int value_v = PyLong_AsInt (value );
117+ if (value_v == -1 && PyErr_Occurred ()) {
118+ PyErr_SetString (PyExc_ValueError ,
119+ "Value of option dict should be an int." );
120+ return -1 ;
121+ }
128122
129- /* Set parameter to compression context */
130- zstd_ret = ZSTD_CCtx_setParameter (self -> cctx , key_v , value_v );
131- if (ZSTD_isError (zstd_ret )) {
132- set_parameter_error (mod_state , 1 , key_v , value_v );
133- return -1 ;
123+ if (key_v == ZSTD_c_compressionLevel ) {
124+ /* Save for generating ZSTD_CDICT */
125+ self -> compression_level = value_v ;
126+ }
127+ else if (key_v == ZSTD_c_nbWorkers ) {
128+ /* From the zstd library docs:
129+ 1. When nbWorkers >= 1, triggers asynchronous mode when
130+ used with ZSTD_compressStream2().
131+ 2, Default value is `0`, aka "single-threaded mode" : no
132+ worker is spawned, compression is performed inside
133+ caller's thread, all invocations are blocking. */
134+ if (value_v != 0 ) {
135+ self -> use_multithread = 1 ;
134136 }
135137 }
136- return 0 ;
138+
139+ /* Set parameter to compression context */
140+ zstd_ret = ZSTD_CCtx_setParameter (self -> cctx , key_v , value_v );
141+ if (ZSTD_isError (zstd_ret )) {
142+ set_parameter_error (mod_state , 1 , key_v , value_v );
143+ return -1 ;
144+ }
137145 }
138- PyErr_Format (PyExc_TypeError , "Invalid type for %s. Expected %s" , arg_name , arg_type );
139- return -1 ;
146+ return 0 ;
140147}
141148
142149static void
@@ -314,7 +321,7 @@ _zstd_load_c_dict(ZstdCompressor *self, PyObject *dict)
314321/*[clinic input]
315322@classmethod
316323_zstd.ZstdCompressor.__new__ as _zstd_ZstdCompressor_new
317- level: object = None
324+ level: Py_ssize_t(c_default='PY_SSIZE_T_MIN', accept={int, NoneType}) = None
318325 The compression level to use. Defaults to COMPRESSION_LEVEL_DEFAULT.
319326 options: object = None
320327 A dict object that contains advanced compression parameters.
@@ -328,9 +335,9 @@ function instead.
328335[clinic start generated code]*/
329336
330337static PyObject *
331- _zstd_ZstdCompressor_new_impl (PyTypeObject * type , PyObject * level ,
338+ _zstd_ZstdCompressor_new_impl (PyTypeObject * type , Py_ssize_t level ,
332339 PyObject * options , PyObject * zstd_dict )
333- /*[clinic end generated code: output=cdef61eafecac3d7 input=92de0211ae20ffdc ]*/
340+ /*[clinic end generated code: output=a857ec0dc29fc5e2 input=9899740b24d11319 ]*/
334341{
335342 ZstdCompressor * self = PyObject_GC_New (ZstdCompressor , type );
336343 if (self == NULL ) {
@@ -353,20 +360,20 @@ _zstd_ZstdCompressor_new_impl(PyTypeObject *type, PyObject *level,
353360 /* Last mode */
354361 self -> last_mode = ZSTD_e_end ;
355362
356- if (level != Py_None && options != Py_None ) {
363+ if (level != PY_SSIZE_T_MIN && options != Py_None ) {
357364 PyErr_SetString (PyExc_RuntimeError , "Only one of level or options should be used." );
358365 goto error ;
359366 }
360367
361368 /* Set compressLevel/options to compression context */
362- if (level != Py_None ) {
363- if (_zstd_set_c_parameters (self , level , "level" , "int" ) < 0 ) {
369+ if (level != PY_SSIZE_T_MIN ) {
370+ if (_zstd_set_c_level (self , level ) < 0 ) {
364371 goto error ;
365372 }
366373 }
367374
368375 if (options != Py_None ) {
369- if (_zstd_set_c_parameters (self , options , "options" , "dict" ) < 0 ) {
376+ if (_zstd_set_c_parameters (self , options ) < 0 ) {
370377 goto error ;
371378 }
372379 }
0 commit comments