Skip to content

Commit c1be100

Browse files
authored
Compression/Decompression contexts hold reference to their dictionary (#5)
1 parent d2361b4 commit c1be100

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

c_src/ezstd_nif.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ struct ZSTDDCtxDeleter {
3838
struct ZstdCCtxWithBuffer {
3939
ZSTD_CCtx* cctx;
4040
ZSTD_outBuffer out;
41+
ZSTD_CDict** dict;
4142
};
4243

4344
struct ZstdDCtxWithBuffer {
4445
ZSTD_DCtx* dctx;
4546
ZSTD_outBuffer out;
47+
ZSTD_DDict** dict;
4648
};
4749

4850
void zstd_nif_compress_dictionary_destructor(ErlNifEnv *env, void *res) {
@@ -61,13 +63,19 @@ void zstd_nif_compression_context_destructor(ErlNifEnv *env, void *res) {
6163
UNUSED(env);
6264
ZstdCCtxWithBuffer* ctx_resource = static_cast<ZstdCCtxWithBuffer*>(res);
6365
ZSTD_freeCCtx(ctx_resource->cctx);
66+
if (ctx_resource->dict != nullptr) {
67+
enif_release_resource(ctx_resource->dict);
68+
}
6469
enif_free(ctx_resource->out.dst);
6570
}
6671

6772
void zstd_nif_decompression_context_destructor(ErlNifEnv *env, void *res) {
6873
UNUSED(env);
6974
ZstdDCtxWithBuffer* ctx_resource = static_cast<ZstdDCtxWithBuffer*>(res);
7075
ZSTD_freeDCtx(ctx_resource->dctx);
76+
if (ctx_resource->dict != nullptr) {
77+
enif_release_resource(ctx_resource->dict);
78+
}
7179
enif_free(ctx_resource->out.dst);
7280
}
7381

@@ -197,6 +205,7 @@ static ERL_NIF_TERM zstd_nif_create_compression_context(ErlNifEnv* env, int argc
197205
resource->out.dst = buffer;
198206
resource->out.pos = 0;
199207
resource->out.size = out_buffer_size;
208+
resource->dict = nullptr;
200209

201210
ERL_NIF_TERM result = enif_make_resource(env, resource);
202211

@@ -234,6 +243,7 @@ static ERL_NIF_TERM zstd_nif_create_decompression_context(ErlNifEnv* env, int ar
234243
resource->out.dst = buffer;
235244
resource->out.pos = 0;
236245
resource->out.size = out_buffer_size;
246+
resource->dict = nullptr;
237247

238248
ERL_NIF_TERM result = enif_make_resource(env, resource);
239249

@@ -253,6 +263,12 @@ static ERL_NIF_TERM zstd_nif_select_cdict(ErlNifEnv* env, int argc, const ERL_NI
253263
}
254264

255265
size_t result = ZSTD_CCtx_refCDict(ctx_resource->cctx, *dict_resource);
266+
if (ctx_resource->dict != nullptr) {
267+
// refCDict replaces the dictionary for this context, so we can't use the old one.
268+
enif_release_resource(ctx_resource->dict);
269+
}
270+
ctx_resource->dict = dict_resource;
271+
enif_keep_resource(dict_resource);
256272

257273
if (ZSTD_isError(result)) {
258274
return make_error(env, "failed to set dictionary");
@@ -273,6 +289,13 @@ static ERL_NIF_TERM zstd_nif_select_ddict(ErlNifEnv* env, int argc, const ERL_NI
273289
}
274290

275291
size_t result = ZSTD_DCtx_refDDict(ctx_resource->dctx, *dict_resource);
292+
if (ctx_resource->dict != nullptr) {
293+
// We do not support ZSTD_d_refMultipleDDicts so setting a new one means we no longer could want
294+
// to use the old dictionary.
295+
enif_release_resource(ctx_resource->dict);
296+
}
297+
ctx_resource->dict = dict_resource;
298+
enif_keep_resource(dict_resource);
276299

277300
if (ZSTD_isError(result)) {
278301
return make_error(env, "failed to set dictionary");

0 commit comments

Comments
 (0)