aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Modules/_zstd/_zstdmodule.h
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_zstd/_zstdmodule.h')
-rw-r--r--Modules/_zstd/_zstdmodule.h204
1 files changed, 204 insertions, 0 deletions
diff --git a/Modules/_zstd/_zstdmodule.h b/Modules/_zstd/_zstdmodule.h
new file mode 100644
index 00000000000..d50f1489e6f
--- /dev/null
+++ b/Modules/_zstd/_zstdmodule.h
@@ -0,0 +1,204 @@
+#pragma once
+/*
+Low level interface to Meta's zstd library for use in the compression.zstd
+Python module.
+*/
+
+/* Declarations shared between different parts of the _zstd module*/
+
+#include "Python.h"
+
+#include "zstd.h"
+#include "zdict.h"
+
+
+// if you update the minimum version, you should update the compile
+// check in configure.ac
+#define PYTHON_MINIMUM_SUPPORTED_ZSTD_VERSION 10405
+
+#if ZSTD_VERSION_NUMBER < PYTHON_MINIMUM_SUPPORTED_ZSTD_VERSION
+ #error "_zstd module requires zstd v1.4.5+"
+#endif
+
+/* Forward declaration of module state */
+typedef struct _zstd_state _zstd_state;
+
+/* Forward reference of module def */
+extern PyModuleDef _zstdmodule;
+
+/* For clinic type calculations */
+static inline _zstd_state *
+get_zstd_state_from_type(PyTypeObject *type) {
+ PyObject *module = PyType_GetModuleByDef(type, &_zstdmodule);
+ if (module == NULL) {
+ return NULL;
+ }
+ void *state = PyModule_GetState(module);
+ assert(state != NULL);
+ return (_zstd_state *)state;
+}
+
+extern PyType_Spec zstddict_type_spec;
+extern PyType_Spec zstdcompressor_type_spec;
+extern PyType_Spec ZstdDecompressor_type_spec;
+
+struct _zstd_state {
+ PyObject *empty_bytes;
+ PyObject *empty_readonly_memoryview;
+ PyObject *str_read;
+ PyObject *str_readinto;
+ PyObject *str_write;
+ PyObject *str_flush;
+
+ PyTypeObject *ZstdDict_type;
+ PyTypeObject *ZstdCompressor_type;
+ PyTypeObject *ZstdDecompressor_type;
+ PyObject *ZstdError;
+
+ PyTypeObject *CParameter_type;
+ PyTypeObject *DParameter_type;
+};
+
+typedef struct {
+ PyObject_HEAD
+
+ /* Reusable compress/decompress dictionary, they are created once and
+ can be shared by multiple threads concurrently, since its usage is
+ read-only.
+ c_dicts is a dict, int(compressionLevel):PyCapsule(ZSTD_CDict*) */
+ ZSTD_DDict *d_dict;
+ PyObject *c_dicts;
+
+ /* Content of the dictionary, bytes object. */
+ PyObject *dict_content;
+ /* Dictionary id */
+ uint32_t dict_id;
+
+ /* __init__ has been called, 0 or 1. */
+ int inited;
+} ZstdDict;
+
+typedef struct {
+ PyObject_HEAD
+
+ /* Compression context */
+ ZSTD_CCtx *cctx;
+
+ /* ZstdDict object in use */
+ PyObject *dict;
+
+ /* Last mode, initialized to ZSTD_e_end */
+ int last_mode;
+
+ /* (nbWorker >= 1) ? 1 : 0 */
+ int use_multithread;
+
+ /* Compression level */
+ int compression_level;
+
+ /* __init__ has been called, 0 or 1. */
+ int inited;
+} ZstdCompressor;
+
+typedef struct {
+ PyObject_HEAD
+
+ /* Decompression context */
+ ZSTD_DCtx *dctx;
+
+ /* ZstdDict object in use */
+ PyObject *dict;
+
+ /* Unconsumed input data */
+ char *input_buffer;
+ size_t input_buffer_size;
+ size_t in_begin, in_end;
+
+ /* Unused data */
+ PyObject *unused_data;
+
+ /* 0 if decompressor has (or may has) unconsumed input data, 0 or 1. */
+ char needs_input;
+
+ /* For decompress(), 0 or 1.
+ 1 when both input and output streams are at a frame edge, means a
+ frame is completely decoded and fully flushed, or the decompressor
+ just be initialized. */
+ char at_frame_edge;
+
+ /* For ZstdDecompressor, 0 or 1.
+ 1 means the end of the first frame has been reached. */
+ char eof;
+
+ /* Used for fast reset above three variables */
+ char _unused_char_for_align;
+
+ /* __init__ has been called, 0 or 1. */
+ int inited;
+} ZstdDecompressor;
+
+typedef enum {
+ TYPE_DECOMPRESSOR, // <D>, ZstdDecompressor class
+ TYPE_ENDLESS_DECOMPRESSOR, // <E>, decompress() function
+} decompress_type;
+
+typedef enum {
+ ERR_DECOMPRESS,
+ ERR_COMPRESS,
+ ERR_SET_PLEDGED_INPUT_SIZE,
+
+ ERR_LOAD_D_DICT,
+ ERR_LOAD_C_DICT,
+
+ ERR_GET_C_BOUNDS,
+ ERR_GET_D_BOUNDS,
+ ERR_SET_C_LEVEL,
+
+ ERR_TRAIN_DICT,
+ ERR_FINALIZE_DICT
+} error_type;
+
+typedef enum {
+ DICT_TYPE_DIGESTED = 0,
+ DICT_TYPE_UNDIGESTED = 1,
+ DICT_TYPE_PREFIX = 2
+} dictionary_type;
+
+static inline int
+mt_continue_should_break(ZSTD_inBuffer *in, ZSTD_outBuffer *out) {
+ return in->size == in->pos && out->size != out->pos;
+}
+
+/* Format error message and set ZstdError. */
+extern void
+set_zstd_error(const _zstd_state* const state,
+ const error_type type, size_t zstd_ret);
+
+extern void
+set_parameter_error(const _zstd_state* const state, int is_compress,
+ int key_v, int value_v);
+
+static const char init_twice_msg[] = "__init__ method is called twice.";
+
+extern int
+_PyZstd_load_c_dict(ZstdCompressor *self, PyObject *dict);
+
+extern int
+_PyZstd_load_d_dict(ZstdDecompressor *self, PyObject *dict);
+
+extern int
+_PyZstd_set_c_parameters(ZstdCompressor *self, PyObject *level_or_options,
+ const char *arg_name, const char *arg_type);
+
+extern int
+_PyZstd_set_d_parameters(ZstdDecompressor *self, PyObject *options);
+
+extern PyObject *
+decompress_impl(ZstdDecompressor *self, ZSTD_inBuffer *in,
+ Py_ssize_t max_length,
+ Py_ssize_t initial_size,
+ decompress_type type);
+
+extern PyObject *
+compress_impl(ZstdCompressor *self, Py_buffer *data,
+ ZSTD_EndDirective end_directive);