LCOV - code coverage report
Current view: top level - frmts/zarr - zarr_v3_codec_blosc.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 50 77 64.9 %
Date: 2026-02-11 08:43:47 Functions: 3 4 75.0 %

          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             : }

Generated by: LCOV version 1.14