Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: Zarr driver, "blosc" codec
5 : * Author: Even Rouault <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2023, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "zarr_v3_codec.h"
14 :
15 : #include "cpl_compressor.h"
16 :
17 : // Implements https://zarr-specs.readthedocs.io/en/latest/v3/codecs/blosc/index.html
18 :
19 : /************************************************************************/
20 : /* ZarrV3CodecBlosc() */
21 : /************************************************************************/
22 :
23 4 : ZarrV3CodecBlosc::ZarrV3CodecBlosc() : ZarrV3CodecAbstractCompressor(NAME)
24 : {
25 4 : }
26 :
27 : /************************************************************************/
28 : /* GetConfiguration() */
29 : /************************************************************************/
30 :
31 : /* static */ CPLJSONObject
32 2 : ZarrV3CodecBlosc::GetConfiguration(const char *cname, int clevel,
33 : const char *shuffle, int typesize,
34 : int blocksize)
35 : {
36 2 : CPLJSONObject oConfig;
37 2 : oConfig.Add("cname", cname);
38 2 : oConfig.Add("clevel", clevel);
39 2 : oConfig.Add("shuffle", shuffle);
40 2 : if (strcmp(shuffle, "noshuffle") != 0)
41 1 : oConfig.Add("typesize", typesize);
42 2 : oConfig.Add("blocksize", blocksize);
43 2 : return oConfig;
44 : }
45 :
46 : /************************************************************************/
47 : /* ZarrV3CodecBlosc::InitFromConfiguration() */
48 : /************************************************************************/
49 :
50 4 : bool ZarrV3CodecBlosc::InitFromConfiguration(
51 : const CPLJSONObject &configuration,
52 : const ZarrArrayMetadata &oInputArrayMetadata,
53 : ZarrArrayMetadata &oOutputArrayMetadata, bool /* bEmitWarnings */)
54 : {
55 4 : m_pCompressor = CPLGetCompressor("blosc");
56 4 : m_pDecompressor = CPLGetDecompressor("blosc");
57 4 : if (!m_pCompressor || !m_pDecompressor)
58 : {
59 0 : CPLError(CE_Failure, CPLE_AppDefined, "blosc compressor not available");
60 0 : return false;
61 : }
62 :
63 4 : m_oConfiguration = configuration.Clone();
64 4 : m_oInputArrayMetadata = oInputArrayMetadata;
65 : // byte->byte codec
66 4 : oOutputArrayMetadata = oInputArrayMetadata;
67 :
68 8 : if (!configuration.IsValid() ||
69 4 : configuration.GetType() != CPLJSONObject::Type::Object)
70 : {
71 0 : CPLError(CE_Failure, CPLE_AppDefined,
72 : "Codec blosc: configuration missing or not an object");
73 0 : return false;
74 : }
75 :
76 22 : for (const auto &oChild : configuration.GetChildren())
77 : {
78 18 : const auto osName = oChild.GetName();
79 32 : if (osName != "cname" && osName != "clevel" && osName != "shuffle" &&
80 32 : osName != "typesize" && osName != "blocksize")
81 : {
82 0 : CPLError(
83 : CE_Failure, CPLE_AppDefined,
84 : "Codec blosc: configuration contains a unhandled member: %s",
85 : osName.c_str());
86 0 : return false;
87 : }
88 : }
89 :
90 12 : const auto oCname = configuration.GetObj("cname");
91 4 : if (oCname.GetType() != CPLJSONObject::Type::String)
92 : {
93 0 : CPLError(CE_Failure, CPLE_AppDefined,
94 : "Codec blosc: cname is missing or not a string");
95 0 : return false;
96 : }
97 4 : m_aosCompressorOptions.SetNameValue("CNAME", oCname.ToString().c_str());
98 :
99 12 : const auto oLevel = configuration.GetObj("clevel");
100 4 : if (oLevel.IsValid())
101 : {
102 4 : if (oLevel.GetType() != CPLJSONObject::Type::Integer)
103 : {
104 0 : CPLError(CE_Failure, CPLE_AppDefined,
105 : "Codec blosc: clevel is not an integer");
106 0 : return false;
107 : }
108 4 : const int nLevel = oLevel.ToInteger();
109 4 : if (nLevel < 0 || nLevel > 9)
110 : {
111 0 : CPLError(CE_Failure, CPLE_AppDefined,
112 : "Codec blosc: invalid clevel value for level: %d", nLevel);
113 0 : return false;
114 : }
115 4 : m_aosCompressorOptions.SetNameValue("CLEVEL", CPLSPrintf("%d", nLevel));
116 : }
117 :
118 12 : const auto oShuffle = configuration.GetObj("shuffle");
119 4 : if (oShuffle.GetType() != CPLJSONObject::Type::String)
120 : {
121 0 : CPLError(CE_Failure, CPLE_AppDefined,
122 : "Codec blosc: shuffle is missing or not a string");
123 0 : return false;
124 : }
125 4 : if (oShuffle.ToString() == "noshuffle")
126 2 : m_aosCompressorOptions.SetNameValue("SHUFFLE", "NONE");
127 2 : else if (oShuffle.ToString() == "shuffle")
128 2 : m_aosCompressorOptions.SetNameValue("SHUFFLE", "BYTE");
129 0 : else if (oShuffle.ToString() == "bitshuffle")
130 0 : m_aosCompressorOptions.SetNameValue("SHUFFLE", "BIT");
131 : else
132 : {
133 0 : CPLError(CE_Failure, CPLE_AppDefined,
134 : "Codec blosc: Invalid value for shuffle");
135 0 : return false;
136 : }
137 :
138 12 : const auto oTypesize = configuration.GetObj("typesize");
139 4 : if (oTypesize.IsValid())
140 : {
141 2 : if (oTypesize.GetType() != CPLJSONObject::Type::Integer)
142 : {
143 0 : CPLError(CE_Failure, CPLE_AppDefined,
144 : "Codec blosc: typesize is not an integer");
145 0 : return false;
146 : }
147 2 : const int nTypeSize = oTypesize.ToInteger();
148 : m_aosCompressorOptions.SetNameValue("TYPESIZE",
149 2 : CPLSPrintf("%d", nTypeSize));
150 : }
151 :
152 12 : const auto oBlocksize = configuration.GetObj("blocksize");
153 4 : if (oBlocksize.IsValid())
154 : {
155 4 : if (oBlocksize.GetType() != CPLJSONObject::Type::Integer)
156 : {
157 0 : CPLError(CE_Failure, CPLE_AppDefined,
158 : "Codec blosc: blocksize is not an integer");
159 0 : return false;
160 : }
161 4 : const int nBlocksize = oBlocksize.ToInteger();
162 : m_aosCompressorOptions.SetNameValue("BLOCKSIZE",
163 4 : CPLSPrintf("%d", nBlocksize));
164 : }
165 :
166 4 : return true;
167 : }
168 :
169 : /************************************************************************/
170 : /* ZarrV3CodecBlosc::Clone() */
171 : /************************************************************************/
172 :
173 0 : std::unique_ptr<ZarrV3Codec> ZarrV3CodecBlosc::Clone() const
174 : {
175 0 : auto psClone = std::make_unique<ZarrV3CodecBlosc>();
176 0 : ZarrArrayMetadata oOutputArrayMetadata;
177 0 : psClone->InitFromConfiguration(m_oConfiguration, m_oInputArrayMetadata,
178 : oOutputArrayMetadata,
179 : /* bEmitWarnings = */ false);
180 0 : return psClone;
181 : }
|