LCOV - code coverage report
Current view: top level - frmts/zarr - zarr_v3_codec_bytes.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 49 74 66.2 %
Date: 2026-03-05 10:33:42 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  Zarr driver, "bytes" 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             : // Implements https://zarr-specs.readthedocs.io/en/latest/v3/codecs/bytes/index.html
      16             : 
      17             : /************************************************************************/
      18             : /*                          ZarrV3CodecBytes()                          */
      19             : /************************************************************************/
      20             : 
      21        1975 : ZarrV3CodecBytes::ZarrV3CodecBytes() : ZarrV3Codec(NAME)
      22             : {
      23        1975 : }
      24             : 
      25             : /************************************************************************/
      26             : /*                          GetConfiguration()                          */
      27             : /************************************************************************/
      28             : 
      29         203 : /* static */ CPLJSONObject ZarrV3CodecBytes::GetConfiguration(bool bLittle)
      30             : {
      31         203 :     CPLJSONObject oConfig;
      32         203 :     oConfig.Add("endian", bLittle ? "little" : "big");
      33         203 :     return oConfig;
      34             : }
      35             : 
      36             : /************************************************************************/
      37             : /*              ZarrV3CodecBytes::InitFromConfiguration()               */
      38             : /************************************************************************/
      39             : 
      40        1975 : bool ZarrV3CodecBytes::InitFromConfiguration(
      41             :     const CPLJSONObject &configuration,
      42             :     const ZarrArrayMetadata &oInputArrayMetadata,
      43             :     ZarrArrayMetadata &oOutputArrayMetadata, bool /* bEmitWarnings */)
      44             : {
      45        1975 :     m_oConfiguration = configuration.Clone();
      46        1975 :     m_bLittle = true;
      47        1975 :     m_oInputArrayMetadata = oInputArrayMetadata;
      48        1975 :     oOutputArrayMetadata = oInputArrayMetadata;
      49             : 
      50        1975 :     if (configuration.IsValid())
      51             :     {
      52        1950 :         if (configuration.GetType() != CPLJSONObject::Type::Object)
      53             :         {
      54           0 :             CPLError(CE_Failure, CPLE_AppDefined,
      55             :                      "Codec endian: configuration is not an object");
      56           0 :             return false;
      57             :         }
      58             : 
      59        3900 :         for (const auto &oChild : configuration.GetChildren())
      60             :         {
      61        1950 :             if (oChild.GetName() != "endian")
      62             :             {
      63           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
      64             :                          "Codec endian: configuration contains a unhandled "
      65             :                          "member: %s",
      66           0 :                          oChild.GetName().c_str());
      67           0 :                 return false;
      68             :             }
      69             :         }
      70             : 
      71        3900 :         const auto oEndian = configuration.GetObj("endian");
      72        1950 :         if (oEndian.IsValid())
      73             :         {
      74        1950 :             if (oEndian.GetType() != CPLJSONObject::Type::String)
      75             :             {
      76           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
      77             :                          "Codec gzip: endian is not a string");
      78           0 :                 return false;
      79             :             }
      80        1950 :             if (oEndian.ToString() == "little")
      81        1885 :                 m_bLittle = true;
      82          65 :             else if (oEndian.ToString() == "big")
      83          65 :                 m_bLittle = false;
      84             :             else
      85             :             {
      86           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
      87             :                          "Codec gzip: invalid value for endian");
      88           0 :                 return false;
      89             :             }
      90             :         }
      91             :     }
      92             : 
      93        1975 :     return true;
      94             : }
      95             : 
      96             : /************************************************************************/
      97             : /*                      ZarrV3CodecBytes::Clone()                       */
      98             : /************************************************************************/
      99             : 
     100           0 : std::unique_ptr<ZarrV3Codec> ZarrV3CodecBytes::Clone() const
     101             : {
     102           0 :     auto psClone = std::make_unique<ZarrV3CodecBytes>();
     103           0 :     ZarrArrayMetadata oOutputArrayMetadata;
     104           0 :     psClone->InitFromConfiguration(m_oConfiguration, m_oInputArrayMetadata,
     105             :                                    oOutputArrayMetadata,
     106             :                                    /* bEmitWarnings = */ false);
     107           0 :     return psClone;
     108             : }
     109             : 
     110             : /************************************************************************/
     111             : /*                      ZarrV3CodecBytes::Encode()                      */
     112             : /************************************************************************/
     113             : 
     114          53 : bool ZarrV3CodecBytes::Encode(const ZarrByteVectorQuickResize &abySrc,
     115             :                               ZarrByteVectorQuickResize &abyDst) const
     116             : {
     117          53 :     CPLAssert(!IsNoOp());
     118             : 
     119          53 :     size_t nEltCount = MultiplyElements(m_oInputArrayMetadata.anBlockSizes);
     120          53 :     size_t nNativeSize = m_oInputArrayMetadata.oElt.nativeSize;
     121          53 :     if (abySrc.size() < nEltCount * nNativeSize)
     122             :     {
     123           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     124             :                  "ZarrV3CodecBytes::Encode(): input buffer too small");
     125           0 :         return false;
     126             :     }
     127          53 :     CPLAssert(abySrc.size() >= nEltCount * nNativeSize);
     128          53 :     abyDst.resize(nEltCount * nNativeSize);
     129             : 
     130          53 :     const GByte *pabySrc = abySrc.data();
     131          53 :     GByte *pabyDst = abyDst.data();
     132             : 
     133          53 :     if (m_oInputArrayMetadata.oElt.nativeType ==
     134             :         DtypeElt::NativeType::STRING_UNICODE)
     135             :     {
     136             :         // Swap each 4-byte UCS-4 character individually
     137           0 :         const size_t nTotalBytes = nEltCount * nNativeSize;
     138           0 :         for (size_t i = 0; i < nTotalBytes; i += 4)
     139             :         {
     140           0 :             const uint32_t val =
     141           0 :                 CPL_SWAP32(*reinterpret_cast<const uint32_t *>(pabySrc + i));
     142           0 :             memcpy(pabyDst + i, &val, sizeof(val));
     143             :         }
     144           0 :         return true;
     145             :     }
     146          53 :     if (m_oInputArrayMetadata.oElt.nativeType ==
     147             :         DtypeElt::NativeType::COMPLEX_IEEEFP)
     148             :     {
     149           0 :         nEltCount *= 2;
     150           0 :         nNativeSize /= 2;
     151             :     }
     152          53 :     if (nNativeSize == 2)
     153             :     {
     154          36 :         for (size_t i = 0; i < nEltCount; ++i)
     155             :         {
     156          24 :             const uint16_t val = CPL_SWAP16(*reinterpret_cast<const uint16_t *>(
     157             :                 pabySrc + sizeof(uint16_t) * i));
     158          24 :             memcpy(pabyDst + sizeof(uint16_t) * i, &val, sizeof(val));
     159             :         }
     160             :     }
     161          41 :     else if (nNativeSize == 4)
     162             :     {
     163          54 :         for (size_t i = 0; i < nEltCount; ++i)
     164             :         {
     165          36 :             const uint32_t val = CPL_SWAP32(*reinterpret_cast<const uint32_t *>(
     166             :                 pabySrc + sizeof(uint32_t) * i));
     167          36 :             memcpy(pabyDst + sizeof(uint32_t) * i, &val, sizeof(val));
     168             :         }
     169             :     }
     170          23 :     else if (nNativeSize == 8)
     171             :     {
     172          75 :         for (size_t i = 0; i < nEltCount; ++i)
     173             :         {
     174          52 :             const uint64_t val = CPL_SWAP64(*reinterpret_cast<const uint64_t *>(
     175             :                 pabySrc + sizeof(uint64_t) * i));
     176          52 :             memcpy(pabyDst + sizeof(uint64_t) * i, &val, sizeof(val));
     177             :         }
     178             :     }
     179             :     else
     180             :     {
     181           0 :         CPLAssert(false);
     182             :     }
     183          53 :     return true;
     184             : }
     185             : 
     186             : /************************************************************************/
     187             : /*                      ZarrV3CodecBytes::Decode()                      */
     188             : /************************************************************************/
     189             : 
     190          29 : bool ZarrV3CodecBytes::Decode(const ZarrByteVectorQuickResize &abySrc,
     191             :                               ZarrByteVectorQuickResize &abyDst) const
     192             : {
     193          29 :     return Encode(abySrc, abyDst);
     194             : }

Generated by: LCOV version 1.14