contrib/python-zstandard/c-ext/compressionparams.c
changeset 37495 b1fb341d8a61
parent 31796 e0dc40530c5a
child 40121 73fef626dae3
equal deleted inserted replaced
37494:1ce7a55b09d1 37495:b1fb341d8a61
     6 * of the BSD license. See the LICENSE file for details.
     6 * of the BSD license. See the LICENSE file for details.
     7 */
     7 */
     8 
     8 
     9 #include "python-zstandard.h"
     9 #include "python-zstandard.h"
    10 
    10 
    11 void ztopy_compression_parameters(CompressionParametersObject* params, ZSTD_compressionParameters* zparams) {
    11 extern PyObject* ZstdError;
    12 	zparams->windowLog = params->windowLog;
    12 
    13 	zparams->chainLog = params->chainLog;
    13 int set_parameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned value) {
    14 	zparams->hashLog = params->hashLog;
    14 	size_t zresult = ZSTD_CCtxParam_setParameter(params, param, value);
    15 	zparams->searchLog = params->searchLog;
    15 	if (ZSTD_isError(zresult)) {
    16 	zparams->searchLength = params->searchLength;
    16 		PyErr_Format(ZstdError, "unable to set compression context parameter: %s",
    17 	zparams->targetLength = params->targetLength;
    17 			ZSTD_getErrorName(zresult));
    18 	zparams->strategy = params->strategy;
    18 		return 1;
    19 }
    19 	}
    20 
    20 
    21 CompressionParametersObject* get_compression_parameters(PyObject* self, PyObject* args) {
    21 	return 0;
    22 	int compressionLevel;
    22 }
    23 	unsigned PY_LONG_LONG sourceSize = 0;
    23 
    24 	Py_ssize_t dictSize = 0;
    24 #define TRY_SET_PARAMETER(params, param, value) if (set_parameter(params, param, value)) return -1;
    25 	ZSTD_compressionParameters params;
    25 
    26 	CompressionParametersObject* result;
    26 int set_parameters(ZSTD_CCtx_params* params, ZstdCompressionParametersObject* obj) {
    27 
    27 	TRY_SET_PARAMETER(params, ZSTD_p_format, obj->format);
    28 	if (!PyArg_ParseTuple(args, "i|Kn:get_compression_parameters",
    28 	TRY_SET_PARAMETER(params, ZSTD_p_compressionLevel, (unsigned)obj->compressionLevel);
    29 		&compressionLevel, &sourceSize, &dictSize)) {
    29 	TRY_SET_PARAMETER(params, ZSTD_p_windowLog, obj->windowLog);
    30 		return NULL;
    30 	TRY_SET_PARAMETER(params, ZSTD_p_hashLog, obj->hashLog);
    31 	}
    31 	TRY_SET_PARAMETER(params, ZSTD_p_chainLog, obj->chainLog);
    32 
    32 	TRY_SET_PARAMETER(params, ZSTD_p_searchLog, obj->searchLog);
    33 	params = ZSTD_getCParams(compressionLevel, sourceSize, dictSize);
    33 	TRY_SET_PARAMETER(params, ZSTD_p_minMatch, obj->minMatch);
    34 
    34 	TRY_SET_PARAMETER(params, ZSTD_p_targetLength, obj->targetLength);
    35 	result = PyObject_New(CompressionParametersObject, &CompressionParametersType);
    35 	TRY_SET_PARAMETER(params, ZSTD_p_compressionStrategy, obj->compressionStrategy);
    36 	if (!result) {
    36 	TRY_SET_PARAMETER(params, ZSTD_p_contentSizeFlag, obj->contentSizeFlag);
    37 		return NULL;
    37 	TRY_SET_PARAMETER(params, ZSTD_p_checksumFlag, obj->checksumFlag);
    38 	}
    38 	TRY_SET_PARAMETER(params, ZSTD_p_dictIDFlag, obj->dictIDFlag);
    39 
    39 	TRY_SET_PARAMETER(params, ZSTD_p_nbWorkers, obj->threads);
    40 	result->windowLog = params.windowLog;
    40 	TRY_SET_PARAMETER(params, ZSTD_p_jobSize, obj->jobSize);
    41 	result->chainLog = params.chainLog;
    41 	TRY_SET_PARAMETER(params, ZSTD_p_overlapSizeLog, obj->overlapSizeLog);
    42 	result->hashLog = params.hashLog;
    42 	TRY_SET_PARAMETER(params, ZSTD_p_compressLiterals, obj->compressLiterals);
    43 	result->searchLog = params.searchLog;
    43 	TRY_SET_PARAMETER(params, ZSTD_p_forceMaxWindow, obj->forceMaxWindow);
    44 	result->searchLength = params.searchLength;
    44 	TRY_SET_PARAMETER(params, ZSTD_p_enableLongDistanceMatching, obj->enableLongDistanceMatching);
    45 	result->targetLength = params.targetLength;
    45 	TRY_SET_PARAMETER(params, ZSTD_p_ldmHashLog, obj->ldmHashLog);
    46 	result->strategy = params.strategy;
    46 	TRY_SET_PARAMETER(params, ZSTD_p_ldmMinMatch, obj->ldmMinMatch);
    47 
    47 	TRY_SET_PARAMETER(params, ZSTD_p_ldmBucketSizeLog, obj->ldmBucketSizeLog);
    48 	return result;
    48 	TRY_SET_PARAMETER(params, ZSTD_p_ldmHashEveryLog, obj->ldmHashEveryLog);
    49 }
    49 
    50 
    50 	return 0;
    51 static int CompressionParameters_init(CompressionParametersObject* self, PyObject* args, PyObject* kwargs) {
    51 }
       
    52 
       
    53 int reset_params(ZstdCompressionParametersObject* params) {
       
    54 	if (params->params) {
       
    55 		ZSTD_CCtxParams_reset(params->params);
       
    56 	}
       
    57 	else {
       
    58 		params->params = ZSTD_createCCtxParams();
       
    59 		if (!params->params) {
       
    60 			PyErr_NoMemory();
       
    61 			return 1;
       
    62 		}
       
    63 	}
       
    64 
       
    65 	return set_parameters(params->params, params);
       
    66 }
       
    67 
       
    68 static int ZstdCompressionParameters_init(ZstdCompressionParametersObject* self, PyObject* args, PyObject* kwargs) {
    52 	static char* kwlist[] = {
    69 	static char* kwlist[] = {
       
    70 		"format",
       
    71 		"compression_level",
    53 		"window_log",
    72 		"window_log",
       
    73 		"hash_log",
    54 		"chain_log",
    74 		"chain_log",
    55 		"hash_log",
       
    56 		"search_log",
    75 		"search_log",
    57 		"search_length",
    76 		"min_match",
    58 		"target_length",
    77 		"target_length",
    59 		"strategy",
    78 		"compression_strategy",
       
    79 		"write_content_size",
       
    80 		"write_checksum",
       
    81 		"write_dict_id",
       
    82 		"job_size",
       
    83 		"overlap_size_log",
       
    84 		"force_max_window",
       
    85 		"enable_ldm",
       
    86 		"ldm_hash_log",
       
    87 		"ldm_min_match",
       
    88 		"ldm_bucket_size_log",
       
    89 		"ldm_hash_every_log",
       
    90 		"threads",
       
    91 		"compress_literals",
    60 		NULL
    92 		NULL
    61 	};
    93 	};
    62 
    94 
    63 	unsigned windowLog;
    95 	unsigned format = 0;
    64 	unsigned chainLog;
    96 	int compressionLevel = 0;
    65 	unsigned hashLog;
    97 	unsigned windowLog = 0;
    66 	unsigned searchLog;
    98 	unsigned hashLog = 0;
    67 	unsigned searchLength;
    99 	unsigned chainLog = 0;
    68 	unsigned targetLength;
   100 	unsigned searchLog = 0;
    69 	unsigned strategy;
   101 	unsigned minMatch = 0;
       
   102 	unsigned targetLength = 0;
       
   103 	unsigned compressionStrategy = 0;
       
   104 	unsigned contentSizeFlag = 1;
       
   105 	unsigned checksumFlag = 0;
       
   106 	unsigned dictIDFlag = 0;
       
   107 	unsigned jobSize = 0;
       
   108 	unsigned overlapSizeLog = 0;
       
   109 	unsigned forceMaxWindow = 0;
       
   110 	unsigned enableLDM = 0;
       
   111 	unsigned ldmHashLog = 0;
       
   112 	unsigned ldmMinMatch = 0;
       
   113 	unsigned ldmBucketSizeLog = 0;
       
   114 	unsigned ldmHashEveryLog = 0;
       
   115 	int threads = 0;
       
   116 
       
   117 	/* Setting value 0 has the effect of disabling. So we use -1 as a default
       
   118 	 * to detect whether to set. Then we automatically derive the expected value
       
   119 	 * based on the level, just like zstandard does itself. */
       
   120 	int compressLiterals = -1;
       
   121 
       
   122 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,
       
   123 		"|IiIIIIIIIIIIIIIIIIIIii:CompressionParameters",
       
   124 		kwlist, &format, &compressionLevel, &windowLog, &hashLog, &chainLog,
       
   125 		&searchLog, &minMatch, &targetLength, &compressionStrategy,
       
   126 		&contentSizeFlag, &checksumFlag, &dictIDFlag, &jobSize, &overlapSizeLog,
       
   127 		&forceMaxWindow, &enableLDM, &ldmHashLog, &ldmMinMatch, &ldmBucketSizeLog,
       
   128 		&ldmHashEveryLog, &threads, &compressLiterals)) {
       
   129 		return -1;
       
   130 	}
       
   131 
       
   132 	if (threads < 0) {
       
   133 		threads = cpu_count();
       
   134 	}
       
   135 
       
   136 	if (compressLiterals < 0) {
       
   137 		compressLiterals = compressionLevel >= 0;
       
   138 	}
       
   139 
       
   140 	self->format = format;
       
   141 	self->compressionLevel = compressionLevel;
       
   142 	self->windowLog = windowLog;
       
   143 	self->hashLog = hashLog;
       
   144 	self->chainLog = chainLog;
       
   145 	self->searchLog = searchLog;
       
   146 	self->minMatch = minMatch;
       
   147 	self->targetLength = targetLength;
       
   148 	self->compressionStrategy = compressionStrategy;
       
   149 	self->contentSizeFlag = contentSizeFlag;
       
   150 	self->checksumFlag = checksumFlag;
       
   151 	self->dictIDFlag = dictIDFlag;
       
   152 	self->threads = threads;
       
   153 	self->jobSize = jobSize;
       
   154 	self->overlapSizeLog = overlapSizeLog;
       
   155 	self->compressLiterals = compressLiterals;
       
   156 	self->forceMaxWindow = forceMaxWindow;
       
   157 	self->enableLongDistanceMatching = enableLDM;
       
   158 	self->ldmHashLog = ldmHashLog;
       
   159 	self->ldmMinMatch = ldmMinMatch;
       
   160 	self->ldmBucketSizeLog = ldmBucketSizeLog;
       
   161 	self->ldmHashEveryLog = ldmHashEveryLog;
       
   162 
       
   163 	if (reset_params(self)) {
       
   164 		return -1;
       
   165 	}
       
   166 
       
   167 	return 0;
       
   168 }
       
   169 
       
   170 PyDoc_STRVAR(ZstdCompressionParameters_from_level__doc__,
       
   171 "Create a CompressionParameters from a compression level and target sizes\n"
       
   172 );
       
   173 
       
   174 ZstdCompressionParametersObject* CompressionParameters_from_level(PyObject* undef, PyObject* args, PyObject* kwargs) {
       
   175 	int managedKwargs = 0;
       
   176 	int level;
       
   177 	PyObject* sourceSize = NULL;
       
   178 	PyObject* dictSize = NULL;
       
   179 	unsigned PY_LONG_LONG iSourceSize = 0;
       
   180 	Py_ssize_t iDictSize = 0;
       
   181 	PyObject* val;
    70 	ZSTD_compressionParameters params;
   182 	ZSTD_compressionParameters params;
    71 	size_t zresult;
   183 	ZstdCompressionParametersObject* result = NULL;
    72 
   184 	int res;
    73 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "IIIIIII:CompressionParameters",
   185 
    74 		kwlist, &windowLog, &chainLog, &hashLog, &searchLog, &searchLength,
   186 	if (!PyArg_ParseTuple(args, "i:from_level",
    75 		&targetLength, &strategy)) {
   187 		&level)) {
    76 		return -1;
   188 		return NULL;
    77 	}
   189 	}
    78 
   190 
    79 	if (windowLog < ZSTD_WINDOWLOG_MIN || windowLog > ZSTD_WINDOWLOG_MAX) {
   191 	if (!kwargs) {
    80 		PyErr_SetString(PyExc_ValueError, "invalid window log value");
   192 		kwargs = PyDict_New();
    81 		return -1;
   193 		if (!kwargs) {
    82 	}
   194 			return NULL;
    83 
   195 		}
    84 	if (chainLog < ZSTD_CHAINLOG_MIN || chainLog > ZSTD_CHAINLOG_MAX) {
   196 		managedKwargs = 1;
    85 		PyErr_SetString(PyExc_ValueError, "invalid chain log value");
   197 	}
    86 		return -1;
   198 
    87 	}
   199 	sourceSize = PyDict_GetItemString(kwargs, "source_size");
    88 
   200 	if (sourceSize) {
    89 	if (hashLog < ZSTD_HASHLOG_MIN || hashLog > ZSTD_HASHLOG_MAX) {
   201 #if PY_MAJOR_VERSION >= 3
    90 		PyErr_SetString(PyExc_ValueError, "invalid hash log value");
   202 		iSourceSize = PyLong_AsUnsignedLongLong(sourceSize);
    91 		return -1;
   203 		if (iSourceSize == (unsigned PY_LONG_LONG)(-1)) {
    92 	}
   204 			goto cleanup;
    93 
   205 		}
    94 	if (searchLog < ZSTD_SEARCHLOG_MIN || searchLog > ZSTD_SEARCHLOG_MAX) {
   206 #else
    95 		PyErr_SetString(PyExc_ValueError, "invalid search log value");
   207 		iSourceSize = PyInt_AsUnsignedLongLongMask(sourceSize);
    96 		return -1;
   208 #endif
    97 	}
   209 
    98 
   210 		PyDict_DelItemString(kwargs, "source_size");
    99 	if (searchLength < ZSTD_SEARCHLENGTH_MIN || searchLength > ZSTD_SEARCHLENGTH_MAX) {
   211 	}
   100 		PyErr_SetString(PyExc_ValueError, "invalid search length value");
   212 
   101 		return -1;
   213 	dictSize = PyDict_GetItemString(kwargs, "dict_size");
   102 	}
   214 	if (dictSize) {
   103 
   215 #if PY_MAJOR_VERSION >= 3
   104 	if (targetLength < ZSTD_TARGETLENGTH_MIN || targetLength > ZSTD_TARGETLENGTH_MAX) {
   216 		iDictSize = PyLong_AsSsize_t(dictSize);
   105 		PyErr_SetString(PyExc_ValueError, "invalid target length value");
   217 #else
   106 		return -1;
   218 		iDictSize = PyInt_AsSsize_t(dictSize);
   107 	}
   219 #endif
   108 
   220 		if (iDictSize == -1) {
   109 	if (strategy < ZSTD_fast || strategy > ZSTD_btopt) {
   221 			goto cleanup;
   110 		PyErr_SetString(PyExc_ValueError, "invalid strategy value");
   222 		}
   111 		return -1;
   223 
   112 	}
   224 		PyDict_DelItemString(kwargs, "dict_size");
   113 
   225 	}
   114 	self->windowLog = windowLog;
   226 
   115 	self->chainLog = chainLog;
   227 
   116 	self->hashLog = hashLog;
   228 	params = ZSTD_getCParams(level, iSourceSize, iDictSize);
   117 	self->searchLog = searchLog;
   229 
   118 	self->searchLength = searchLength;
   230 	/* Values derived from the input level and sizes are passed along to the
   119 	self->targetLength = targetLength;
   231 	   constructor. But only if a value doesn't already exist. */
   120 	self->strategy = strategy;
   232 	val = PyDict_GetItemString(kwargs, "window_log");
   121 
   233 	if (!val) {
   122 	ztopy_compression_parameters(self, &params);
   234 		val = PyLong_FromUnsignedLong(params.windowLog);
   123 	zresult = ZSTD_checkCParams(params);
   235 		if (!val) {
   124 
   236 			goto cleanup;
   125 	if (ZSTD_isError(zresult)) {
   237 		}
   126 		PyErr_Format(PyExc_ValueError, "invalid compression parameters: %s",
   238 		PyDict_SetItemString(kwargs, "window_log", val);
   127 			ZSTD_getErrorName(zresult));
   239 		Py_DECREF(val);
   128 		return -1;
   240 	}
   129 	}
   241 
   130 
   242 	val = PyDict_GetItemString(kwargs, "chain_log");
   131 	return 0;
   243 	if (!val) {
   132 }
   244 		val = PyLong_FromUnsignedLong(params.chainLog);
   133 
   245 		if (!val) {
   134 PyDoc_STRVAR(CompressionParameters_estimated_compression_context_size__doc__,
   246 			goto cleanup;
       
   247 		}
       
   248 		PyDict_SetItemString(kwargs, "chain_log", val);
       
   249 		Py_DECREF(val);
       
   250 	}
       
   251 
       
   252 	val = PyDict_GetItemString(kwargs, "hash_log");
       
   253 	if (!val) {
       
   254 		val = PyLong_FromUnsignedLong(params.hashLog);
       
   255 		if (!val) {
       
   256 			goto cleanup;
       
   257 		}
       
   258 		PyDict_SetItemString(kwargs, "hash_log", val);
       
   259 		Py_DECREF(val);
       
   260 	}
       
   261 
       
   262 	val = PyDict_GetItemString(kwargs, "search_log");
       
   263 	if (!val) {
       
   264 		val = PyLong_FromUnsignedLong(params.searchLog);
       
   265 		if (!val) {
       
   266 			goto cleanup;
       
   267 		}
       
   268 		PyDict_SetItemString(kwargs, "search_log", val);
       
   269 		Py_DECREF(val);
       
   270 	}
       
   271 
       
   272 	val = PyDict_GetItemString(kwargs, "min_match");
       
   273 	if (!val) {
       
   274 		val = PyLong_FromUnsignedLong(params.searchLength);
       
   275 		if (!val) {
       
   276 			goto cleanup;
       
   277 		}
       
   278 		PyDict_SetItemString(kwargs, "min_match", val);
       
   279 		Py_DECREF(val);
       
   280 	}
       
   281 
       
   282 	val = PyDict_GetItemString(kwargs, "target_length");
       
   283 	if (!val) {
       
   284 		val = PyLong_FromUnsignedLong(params.targetLength);
       
   285 		if (!val) {
       
   286 			goto cleanup;
       
   287 		}
       
   288 		PyDict_SetItemString(kwargs, "target_length", val);
       
   289 		Py_DECREF(val);
       
   290 	}
       
   291 
       
   292 	val = PyDict_GetItemString(kwargs, "compression_strategy");
       
   293 	if (!val) {
       
   294 		val = PyLong_FromUnsignedLong(params.strategy);
       
   295 		if (!val) {
       
   296 			goto cleanup;
       
   297 		}
       
   298 		PyDict_SetItemString(kwargs, "compression_strategy", val);
       
   299 		Py_DECREF(val);
       
   300 	}
       
   301 
       
   302 	val = PyDict_GetItemString(kwargs, "compress_literals");
       
   303 	if (!val) {
       
   304 		val = PyLong_FromLong(level >= 0 ? 1 : 0);
       
   305 		if (!val) {
       
   306 			goto cleanup;
       
   307 		}
       
   308 		PyDict_SetItemString(kwargs, "compress_literals", val);
       
   309 		Py_DECREF(val);
       
   310 	}
       
   311 
       
   312 	result = PyObject_New(ZstdCompressionParametersObject, &ZstdCompressionParametersType);
       
   313 	if (!result) {
       
   314 		goto cleanup;
       
   315 	}
       
   316 
       
   317 	result->params = NULL;
       
   318 
       
   319 	val = PyTuple_New(0);
       
   320 	if (!val) {
       
   321 		Py_CLEAR(result);
       
   322 		goto cleanup;
       
   323 	}
       
   324 
       
   325 	res = ZstdCompressionParameters_init(result, val, kwargs);
       
   326 	Py_DECREF(val);
       
   327 
       
   328 	if (res) {
       
   329 		Py_CLEAR(result);
       
   330 		goto cleanup;
       
   331 	}
       
   332 
       
   333 cleanup:
       
   334 	if (managedKwargs) {
       
   335 		Py_DECREF(kwargs);
       
   336 	}
       
   337 
       
   338 	return result;
       
   339 }
       
   340 
       
   341 PyDoc_STRVAR(ZstdCompressionParameters_estimated_compression_context_size__doc__,
   135 "Estimate the size in bytes of a compression context for compression parameters\n"
   342 "Estimate the size in bytes of a compression context for compression parameters\n"
   136 );
   343 );
   137 
   344 
   138 PyObject* CompressionParameters_estimated_compression_context_size(CompressionParametersObject* self) {
   345 PyObject* ZstdCompressionParameters_estimated_compression_context_size(ZstdCompressionParametersObject* self) {
   139 	ZSTD_compressionParameters params;
   346 	return PyLong_FromSize_t(ZSTD_estimateCCtxSize_usingCCtxParams(self->params));
   140 
   347 }
   141 	ztopy_compression_parameters(self, &params);
   348 
   142 
   349 PyDoc_STRVAR(ZstdCompressionParameters__doc__,
   143 	return PyLong_FromSize_t(ZSTD_estimateCCtxSize(params));
   350 "ZstdCompressionParameters: low-level control over zstd compression");
   144 }
   351 
   145 
   352 static void ZstdCompressionParameters_dealloc(ZstdCompressionParametersObject* self) {
   146 PyObject* estimate_compression_context_size(PyObject* self, PyObject* args) {
   353 	if (self->params) {
   147 	CompressionParametersObject* params;
   354 		ZSTD_freeCCtxParams(self->params);
   148 	ZSTD_compressionParameters zparams;
   355 		self->params = NULL;
   149 	PyObject* result;
   356 	}
   150 
   357 
   151 	if (!PyArg_ParseTuple(args, "O!:estimate_compression_context_size",
       
   152 		&CompressionParametersType, &params)) {
       
   153 		return NULL;
       
   154 	}
       
   155 
       
   156 	ztopy_compression_parameters(params, &zparams);
       
   157 	result = PyLong_FromSize_t(ZSTD_estimateCCtxSize(zparams));
       
   158 	return result;
       
   159 }
       
   160 
       
   161 PyDoc_STRVAR(CompressionParameters__doc__,
       
   162 "CompressionParameters: low-level control over zstd compression");
       
   163 
       
   164 static void CompressionParameters_dealloc(PyObject* self) {
       
   165 	PyObject_Del(self);
   358 	PyObject_Del(self);
   166 }
   359 }
   167 
   360 
   168 static PyMethodDef CompressionParameters_methods[] = {
   361 static PyMethodDef ZstdCompressionParameters_methods[] = {
       
   362 	{
       
   363 		"from_level",
       
   364 		(PyCFunction)CompressionParameters_from_level,
       
   365 		METH_VARARGS | METH_KEYWORDS | METH_STATIC,
       
   366 		ZstdCompressionParameters_from_level__doc__
       
   367 	},
   169 	{
   368 	{
   170 		"estimated_compression_context_size",
   369 		"estimated_compression_context_size",
   171 		(PyCFunction)CompressionParameters_estimated_compression_context_size,
   370 		(PyCFunction)ZstdCompressionParameters_estimated_compression_context_size,
   172 		METH_NOARGS,
   371 		METH_NOARGS,
   173 		CompressionParameters_estimated_compression_context_size__doc__
   372 		ZstdCompressionParameters_estimated_compression_context_size__doc__
   174 	},
   373 	},
   175 	{ NULL, NULL }
   374 	{ NULL, NULL }
   176 };
   375 };
   177 
   376 
   178 static PyMemberDef CompressionParameters_members[] = {
   377 static PyMemberDef ZstdCompressionParameters_members[] = {
       
   378 	{ "format", T_UINT,
       
   379 	  offsetof(ZstdCompressionParametersObject, format), READONLY,
       
   380 	  "compression format" },
       
   381 	{ "compression_level", T_INT,
       
   382 	  offsetof(ZstdCompressionParametersObject, compressionLevel), READONLY,
       
   383 	  "compression level" },
   179 	{ "window_log", T_UINT,
   384 	{ "window_log", T_UINT,
   180 	  offsetof(CompressionParametersObject, windowLog), READONLY,
   385 	  offsetof(ZstdCompressionParametersObject, windowLog), READONLY,
   181 	  "window log" },
   386 	  "window log" },
       
   387 	{ "hash_log", T_UINT,
       
   388 	  offsetof(ZstdCompressionParametersObject, hashLog), READONLY,
       
   389 	  "hash log" },
   182 	{ "chain_log", T_UINT,
   390 	{ "chain_log", T_UINT,
   183 	  offsetof(CompressionParametersObject, chainLog), READONLY,
   391 	  offsetof(ZstdCompressionParametersObject, chainLog), READONLY,
   184 	  "chain log" },
   392 	  "chain log" },
   185 	{ "hash_log", T_UINT,
       
   186 	  offsetof(CompressionParametersObject, hashLog), READONLY,
       
   187 	  "hash log" },
       
   188 	{ "search_log", T_UINT,
   393 	{ "search_log", T_UINT,
   189 	  offsetof(CompressionParametersObject, searchLog), READONLY,
   394 	  offsetof(ZstdCompressionParametersObject, searchLog), READONLY,
   190 	  "search log" },
   395 	  "search log" },
   191 	{ "search_length", T_UINT,
   396 	{ "min_match", T_UINT,
   192 	  offsetof(CompressionParametersObject, searchLength), READONLY,
   397 	  offsetof(ZstdCompressionParametersObject, minMatch), READONLY,
   193 	  "search length" },
   398 	  "search length" },
   194 	{ "target_length", T_UINT,
   399 	{ "target_length", T_UINT,
   195 	  offsetof(CompressionParametersObject, targetLength), READONLY,
   400 	  offsetof(ZstdCompressionParametersObject, targetLength), READONLY,
   196 	  "target length" },
   401 	  "target length" },
   197 	{ "strategy", T_INT,
   402 	{ "compression_strategy", T_UINT,
   198 	  offsetof(CompressionParametersObject, strategy), READONLY,
   403 	  offsetof(ZstdCompressionParametersObject, compressionStrategy), READONLY,
   199 	  "strategy" },
   404 	  "compression strategy" },
       
   405 	{ "write_content_size", T_UINT,
       
   406 	  offsetof(ZstdCompressionParametersObject, contentSizeFlag), READONLY,
       
   407 	  "whether to write content size in frames" },
       
   408 	{ "write_checksum", T_UINT,
       
   409 	  offsetof(ZstdCompressionParametersObject, checksumFlag), READONLY,
       
   410 	  "whether to write checksum in frames" },
       
   411 	{ "write_dict_id", T_UINT,
       
   412 	  offsetof(ZstdCompressionParametersObject, dictIDFlag), READONLY,
       
   413 	  "whether to write dictionary ID in frames" },
       
   414 	{ "threads", T_UINT,
       
   415 	  offsetof(ZstdCompressionParametersObject, threads), READONLY,
       
   416 	  "number of threads to use" },
       
   417 	{ "job_size", T_UINT,
       
   418 	  offsetof(ZstdCompressionParametersObject, jobSize), READONLY,
       
   419 	  "size of compression job when using multiple threads" },
       
   420 	{ "overlap_size_log", T_UINT,
       
   421 	  offsetof(ZstdCompressionParametersObject, overlapSizeLog), READONLY,
       
   422 	  "Size of previous input reloaded at the beginning of each job" },
       
   423 	{ "compress_literals", T_UINT,
       
   424 	  offsetof(ZstdCompressionParametersObject, compressLiterals), READONLY,
       
   425 	  "whether Huffman compression of literals is in use" },
       
   426 	{ "force_max_window", T_UINT,
       
   427 	  offsetof(ZstdCompressionParametersObject, forceMaxWindow), READONLY,
       
   428 	  "force back references to remain smaller than window size" },
       
   429 	{ "enable_ldm", T_UINT,
       
   430 	  offsetof(ZstdCompressionParametersObject, enableLongDistanceMatching), READONLY,
       
   431 	  "whether to enable long distance matching" },
       
   432 	{ "ldm_hash_log", T_UINT,
       
   433 	  offsetof(ZstdCompressionParametersObject, ldmHashLog), READONLY,
       
   434 	  "Size of the table for long distance matching, as a power of 2" },
       
   435 	{ "ldm_min_match", T_UINT,
       
   436 	  offsetof(ZstdCompressionParametersObject, ldmMinMatch), READONLY,
       
   437 	  "minimum size of searched matches for long distance matcher" },
       
   438 	{ "ldm_bucket_size_log", T_UINT,
       
   439 	  offsetof(ZstdCompressionParametersObject, ldmBucketSizeLog), READONLY,
       
   440 	  "log size of each bucket in the LDM hash table for collision resolution" },
       
   441 	{ "ldm_hash_every_log", T_UINT,
       
   442 	  offsetof(ZstdCompressionParametersObject, ldmHashEveryLog), READONLY,
       
   443 	  "frequency of inserting/looking up entries in the LDM hash table" },
   200 	{ NULL }
   444 	{ NULL }
   201 };
   445 };
   202 
   446 
   203 PyTypeObject CompressionParametersType = {
   447 PyTypeObject ZstdCompressionParametersType = {
   204 	PyVarObject_HEAD_INIT(NULL, 0)
   448 	PyVarObject_HEAD_INIT(NULL, 0)
   205 	"CompressionParameters", /* tp_name */
   449 	"ZstdCompressionParameters", /* tp_name */
   206 	sizeof(CompressionParametersObject), /* tp_basicsize */
   450 	sizeof(ZstdCompressionParametersObject), /* tp_basicsize */
   207 	0,                         /* tp_itemsize */
   451 	0,                         /* tp_itemsize */
   208 	(destructor)CompressionParameters_dealloc, /* tp_dealloc */
   452 	(destructor)ZstdCompressionParameters_dealloc, /* tp_dealloc */
   209 	0,                         /* tp_print */
   453 	0,                         /* tp_print */
   210 	0,                         /* tp_getattr */
   454 	0,                         /* tp_getattr */
   211 	0,                         /* tp_setattr */
   455 	0,                         /* tp_setattr */
   212 	0,                         /* tp_compare */
   456 	0,                         /* tp_compare */
   213 	0,                         /* tp_repr */
   457 	0,                         /* tp_repr */
   219 	0,                         /* tp_str */
   463 	0,                         /* tp_str */
   220 	0,                         /* tp_getattro */
   464 	0,                         /* tp_getattro */
   221 	0,                         /* tp_setattro */
   465 	0,                         /* tp_setattro */
   222 	0,                         /* tp_as_buffer */
   466 	0,                         /* tp_as_buffer */
   223 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
   467 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
   224 	CompressionParameters__doc__, /* tp_doc */
   468 	ZstdCompressionParameters__doc__, /* tp_doc */
   225 	0,                         /* tp_traverse */
   469 	0,                         /* tp_traverse */
   226 	0,                         /* tp_clear */
   470 	0,                         /* tp_clear */
   227 	0,                         /* tp_richcompare */
   471 	0,                         /* tp_richcompare */
   228 	0,                         /* tp_weaklistoffset */
   472 	0,                         /* tp_weaklistoffset */
   229 	0,                         /* tp_iter */
   473 	0,                         /* tp_iter */
   230 	0,                         /* tp_iternext */
   474 	0,                         /* tp_iternext */
   231 	CompressionParameters_methods, /* tp_methods */
   475 	ZstdCompressionParameters_methods, /* tp_methods */
   232 	CompressionParameters_members, /* tp_members */
   476 	ZstdCompressionParameters_members, /* tp_members */
   233 	0,                         /* tp_getset */
   477 	0,                         /* tp_getset */
   234 	0,                         /* tp_base */
   478 	0,                         /* tp_base */
   235 	0,                         /* tp_dict */
   479 	0,                         /* tp_dict */
   236 	0,                         /* tp_descr_get */
   480 	0,                         /* tp_descr_get */
   237 	0,                         /* tp_descr_set */
   481 	0,                         /* tp_descr_set */
   238 	0,                         /* tp_dictoffset */
   482 	0,                         /* tp_dictoffset */
   239 	(initproc)CompressionParameters_init, /* tp_init */
   483 	(initproc)ZstdCompressionParameters_init, /* tp_init */
   240 	0,                         /* tp_alloc */
   484 	0,                         /* tp_alloc */
   241 	PyType_GenericNew,         /* tp_new */
   485 	PyType_GenericNew,         /* tp_new */
   242 };
   486 };
   243 
   487 
   244 void compressionparams_module_init(PyObject* mod) {
   488 void compressionparams_module_init(PyObject* mod) {
   245 	Py_TYPE(&CompressionParametersType) = &PyType_Type;
   489 	Py_TYPE(&ZstdCompressionParametersType) = &PyType_Type;
   246 	if (PyType_Ready(&CompressionParametersType) < 0) {
   490 	if (PyType_Ready(&ZstdCompressionParametersType) < 0) {
   247 		return;
   491 		return;
   248 	}
   492 	}
   249 
   493 
   250 	Py_INCREF(&CompressionParametersType);
   494 	Py_INCREF(&ZstdCompressionParametersType);
       
   495 	PyModule_AddObject(mod, "ZstdCompressionParameters",
       
   496 		(PyObject*)&ZstdCompressionParametersType);
       
   497 
       
   498 	/* TODO remove deprecated alias. */
       
   499 	Py_INCREF(&ZstdCompressionParametersType);
   251 	PyModule_AddObject(mod, "CompressionParameters",
   500 	PyModule_AddObject(mod, "CompressionParameters",
   252 		(PyObject*)&CompressionParametersType);
   501 		(PyObject*)&ZstdCompressionParametersType);
   253 }
   502 }