forked from JuliaIO/HDF5.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathH5Zzstd.jl
More file actions
128 lines (109 loc) · 4.01 KB
/
H5Zzstd.jl
File metadata and controls
128 lines (109 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#=
Derived from https://github.com/aparamon/HDF5Plugin-Zstandard, zstd_h5plugin.c
Licensed under Apache License Version 2.0, see licenses/H5Zzstd_LICENSE.txt
The following license applies to the Julia port.
Copyright (c) 2021 Mark Kittisopikul and Howard Hughes Medical Institute. License MIT, see LICENSE.txt
=#
module H5Zzstd
using CodecZstd
import CodecZstd.LibZstd
using HDF5.API
import HDF5.Filters:
Filter, filterid, register_filter, filterid, filtername, filter_func, filter_cfunc
const H5Z_FILTER_ZSTD = API.H5Z_filter_t(32015)
const zstd_name = "Zstandard compression: http://www.zstd.net"
export H5Z_filter_zstd, H5Z_FILTER_ZSTD, ZstdFilter
# cd_values First optional value is the compressor aggression
# Default is CodecZstd.LibZstd.ZSTD_CLEVEL_DEFAULT
function H5Z_filter_zstd(
flags::Cuint,
cd_nelmts::Csize_t,
cd_values::Ptr{Cuint},
nbytes::Csize_t,
buf_size::Ptr{Csize_t},
buf::Ptr{Ptr{Cvoid}}
)::Csize_t
inbuf = unsafe_load(buf)
outbuf = C_NULL
origSize = nbytes
ret_value = Csize_t(0)
try
if flags & API.H5Z_FLAG_REVERSE != 0
#decompresssion
decompSize = LibZstd.ZSTD_getDecompressedSize(inbuf, origSize)
if decompSize == 0
error("zstd_h5plugin: Cannot retrieve decompressed chunk size")
end
outbuf = Libc.malloc(decompSize)
if outbuf == C_NULL
error(
"zstd_h5plugin: Cannot allocate memory for outbuf during decompression."
)
end
decompSize = LibZstd.ZSTD_decompress(outbuf, decompSize, inbuf, origSize)
Libc.free(inbuf)
unsafe_store!(buf, outbuf)
outbuf = C_NULL
ret_value = Csize_t(decompSize)
else
# compression
if cd_nelmts > 0
aggression = Cint(unsafe_load(cd_values))
else
aggression = CodecZstd.LibZstd.ZSTD_CLEVEL_DEFAULT
end
if aggression < 1
aggression = 1 # ZSTD_minCLevel()
elseif aggression > LibZstd.ZSTD_maxCLevel()
aggression = LibZstd.ZSTD_maxCLevel()
end
compSize = LibZstd.ZSTD_compressBound(origSize)
outbuf = Libc.malloc(compSize)
if outbuf == C_NULL
error(
"zstd_h5plugin: Cannot allocate memory for outbuf during compression."
)
end
compSize = LibZstd.ZSTD_compress(outbuf, compSize, inbuf, origSize, aggression)
Libc.free(unsafe_load(buf))
unsafe_store!(buf, outbuf)
unsafe_store!(buf_size, compSize)
outbuf = C_NULL
ret_value = compSize
end
catch e
# "In the case of failure, the return value is 0 (zero) and all pointer arguments are left unchanged."
ret_value = Csize_t(0)
# Output Julia error via async so we do not task switch during callback
@async @error "H5Zzstd Non-Fatal ERROR: " exception = (e, catch_backtrace())
finally
if outbuf != C_NULL
Libc.free(outbuf)
end
end # try catch finally
return Csize_t(ret_value)
end
# Filters Module
"""
ZstdFilter(clevel)
Zstandard compression filter. `clevel` determines the compression level.
# External Links
* [Zstandard HDF5 Filter ID 32015](https://portal.hdfgroup.org/display/support/Filters#Filters-32015)
* [Zstandard HDF5 Plugin Repository (C code)](https://github.com/aparamon/HDF5Plugin-Zstandard)
"""
struct ZstdFilter <: Filter
clevel::Cuint
end
ZstdFilter() = ZstdFilter(CodecZstd.LibZstd.ZSTD_CLEVEL_DEFAULT)
filterid(::Type{ZstdFilter}) = H5Z_FILTER_ZSTD
filtername(::Type{ZstdFilter}) = zstd_name
filter_func(::Type{ZstdFilter}) = H5Z_filter_zstd
filter_cfunc(::Type{ZstdFilter}) = @cfunction(
H5Z_filter_zstd,
Csize_t,
(Cuint, Csize_t, Ptr{Cuint}, Csize_t, Ptr{Csize_t}, Ptr{Ptr{Cvoid}})
)
function __init__()
register_filter(ZstdFilter)
end
end # module H5Zzstd