aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Modules/_zstd/decompressor.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_zstd/decompressor.c')
-rw-r--r--Modules/_zstd/decompressor.c133
1 files changed, 75 insertions, 58 deletions
diff --git a/Modules/_zstd/decompressor.c b/Modules/_zstd/decompressor.c
index a4be180c008..a654a9540e1 100644
--- a/Modules/_zstd/decompressor.c
+++ b/Modules/_zstd/decompressor.c
@@ -7,22 +7,65 @@ Python module.
/*[clinic input]
module _zstd
-class _zstd.ZstdDecompressor "ZstdDecompressor *" "clinic_state()->ZstdDecompressor_type"
+class _zstd.ZstdDecompressor "ZstdDecompressor *" "&zstd_decompressor_type_spec"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4e6eae327c0c0c76]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2969ddf48a203e0]*/
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
-#include "_zstdmodule.h"
+#include "Python.h"
+#include "_zstdmodule.h"
#include "buffer.h"
+#include "zstddict.h"
+#include <stdbool.h> // bool
#include <stddef.h> // offsetof()
+#include <zstd.h> // ZSTD_*()
+
+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. */
+ bool initialized;
+} ZstdDecompressor;
#define ZstdDecompressor_CAST(op) ((ZstdDecompressor *)op)
+#include "clinic/decompressor.c.h"
+
static inline ZSTD_DDict *
_get_DDict(ZstdDict *self)
{
@@ -61,8 +104,8 @@ _get_DDict(ZstdDict *self)
}
/* Set decompression parameters to decompression context */
-int
-_PyZstd_set_d_parameters(ZstdDecompressor *self, PyObject *options)
+static int
+_zstd_set_d_parameters(ZstdDecompressor *self, PyObject *options)
{
size_t zstd_ret;
PyObject *key, *value;
@@ -120,8 +163,8 @@ _PyZstd_set_d_parameters(ZstdDecompressor *self, PyObject *options)
}
/* Load dictionary or prefix to decompression context */
-int
-_PyZstd_load_d_dict(ZstdDecompressor *self, PyObject *dict)
+static int
+_zstd_load_d_dict(ZstdDecompressor *self, PyObject *dict)
{
size_t zstd_ret;
_zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
@@ -215,17 +258,14 @@ load:
return 0;
}
-
+typedef enum {
+ TYPE_DECOMPRESSOR, // <D>, ZstdDecompressor class
+ TYPE_ENDLESS_DECOMPRESSOR, // <E>, decompress() function
+} decompress_type;
/*
- Given the two types of decompressors (defined in _zstdmodule.h):
-
- typedef enum {
- TYPE_DECOMPRESSOR, // <D>, ZstdDecompressor class
- TYPE_ENDLESS_DECOMPRESSOR, // <E>, decompress() function
- } decompress_type;
-
- Decompress implementation for <D>, <E>, pseudo code:
+ Given the two types of decompressors (defined above),
+ decompress implementation for <D>, <E>, pseudo code:
initialize_output_buffer
while True:
@@ -276,7 +316,7 @@ load:
output stream: ====================|
^
*/
-PyObject *
+static PyObject *
decompress_impl(ZstdDecompressor *self, ZSTD_inBuffer *in,
Py_ssize_t max_length,
Py_ssize_t initial_size,
@@ -290,13 +330,7 @@ decompress_impl(ZstdDecompressor *self, ZSTD_inBuffer *in,
/* The first AFE check for setting .at_frame_edge flag */
if (type == TYPE_ENDLESS_DECOMPRESSOR) {
if (self->at_frame_edge && in->pos == in->size) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
- if (mod_state == NULL) {
- return NULL;
- }
- ret = mod_state->empty_bytes;
- Py_INCREF(ret);
- return ret;
+ return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
}
}
@@ -380,7 +414,7 @@ error:
return NULL;
}
-void
+static void
decompressor_reset_session(ZstdDecompressor *self,
decompress_type type)
{
@@ -405,7 +439,7 @@ decompressor_reset_session(ZstdDecompressor *self,
ZSTD_DCtx_reset(self->dctx, ZSTD_reset_session_only);
}
-PyObject *
+static PyObject *
stream_decompress(ZstdDecompressor *self, Py_buffer *data, Py_ssize_t max_length,
decompress_type type)
{
@@ -622,7 +656,7 @@ _zstd_ZstdDecompressor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
goto error;
}
- self->inited = 0;
+ self->initialized = 0;
self->dict = NULL;
self->input_buffer = NULL;
self->input_buffer_size = 0;
@@ -701,15 +735,15 @@ _zstd_ZstdDecompressor___init___impl(ZstdDecompressor *self,
/*[clinic end generated code: output=703af2f1ec226642 input=8fd72999acc1a146]*/
{
/* Only called once */
- if (self->inited) {
- PyErr_SetString(PyExc_RuntimeError, init_twice_msg);
+ if (self->initialized) {
+ PyErr_SetString(PyExc_RuntimeError, "reinitialization not supported");
return -1;
}
- self->inited = 1;
+ self->initialized = 1;
/* Load dictionary to decompression context */
if (zstd_dict != Py_None) {
- if (_PyZstd_load_d_dict(self, zstd_dict) < 0) {
+ if (_zstd_load_d_dict(self, zstd_dict) < 0) {
return -1;
}
@@ -720,7 +754,7 @@ _zstd_ZstdDecompressor___init___impl(ZstdDecompressor *self,
/* Set option to decompression context */
if (options != Py_None) {
- if (_PyZstd_set_d_parameters(self, options) < 0) {
+ if (_zstd_set_d_parameters(self, options) < 0) {
return -1;
}
}
@@ -747,16 +781,8 @@ _zstd_ZstdDecompressor_unused_data_get_impl(ZstdDecompressor *self)
{
PyObject *ret;
- /* Thread-safe code */
- Py_BEGIN_CRITICAL_SECTION(self);
-
if (!self->eof) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
- if (mod_state == NULL) {
- return NULL;
- }
- ret = mod_state->empty_bytes;
- Py_INCREF(ret);
+ return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
}
else {
if (self->unused_data == NULL) {
@@ -772,8 +798,6 @@ _zstd_ZstdDecompressor_unused_data_get_impl(ZstdDecompressor *self)
}
}
- Py_END_CRITICAL_SECTION();
-
return ret;
}
@@ -818,14 +842,9 @@ _zstd_ZstdDecompressor_decompress_impl(ZstdDecompressor *self,
return ret;
}
-#define clinic_state() (get_zstd_state_from_type(type))
-#include "clinic/decompressor.c.h"
-#undef clinic_state
-
static PyMethodDef ZstdDecompressor_methods[] = {
_ZSTD_ZSTDDECOMPRESSOR_DECOMPRESS_METHODDEF
-
- {0}
+ {NULL, NULL}
};
PyDoc_STRVAR(ZstdDecompressor_eof_doc,
@@ -840,17 +859,14 @@ PyDoc_STRVAR(ZstdDecompressor_needs_input_doc,
static PyMemberDef ZstdDecompressor_members[] = {
{"eof", Py_T_BOOL, offsetof(ZstdDecompressor, eof),
Py_READONLY, ZstdDecompressor_eof_doc},
-
{"needs_input", Py_T_BOOL, offsetof(ZstdDecompressor, needs_input),
Py_READONLY, ZstdDecompressor_needs_input_doc},
-
- {0}
+ {NULL}
};
static PyGetSetDef ZstdDecompressor_getset[] = {
_ZSTD_ZSTDDECOMPRESSOR_UNUSED_DATA_GETSETDEF
-
- {0}
+ {NULL}
};
static int
@@ -880,12 +896,13 @@ static PyType_Slot ZstdDecompressor_slots[] = {
{Py_tp_doc, (char*)_zstd_ZstdDecompressor___init____doc__},
{Py_tp_traverse, ZstdDecompressor_traverse},
{Py_tp_clear, ZstdDecompressor_clear},
- {0}
+ {0, 0}
};
-PyType_Spec ZstdDecompressor_type_spec = {
- .name = "_zstd.ZstdDecompressor",
+PyType_Spec zstd_decompressor_type_spec = {
+ .name = "compression.zstd.ZstdDecompressor",
.basicsize = sizeof(ZstdDecompressor),
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE
+ | Py_TPFLAGS_HAVE_GC,
.slots = ZstdDecompressor_slots,
};