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 1800 : ZarrV3CodecBytes::ZarrV3CodecBytes() : ZarrV3Codec(NAME) 22 : { 23 1800 : } 24 : 25 : /************************************************************************/ 26 : /* GetConfiguration() */ 27 : /************************************************************************/ 28 : 29 131 : /* static */ CPLJSONObject ZarrV3CodecBytes::GetConfiguration(bool bLittle) 30 : { 31 131 : CPLJSONObject oConfig; 32 131 : oConfig.Add("endian", bLittle ? "little" : "big"); 33 131 : return oConfig; 34 : } 35 : 36 : /************************************************************************/ 37 : /* ZarrV3CodecBytes::InitFromConfiguration() */ 38 : /************************************************************************/ 39 : 40 1800 : bool ZarrV3CodecBytes::InitFromConfiguration( 41 : const CPLJSONObject &configuration, 42 : const ZarrArrayMetadata &oInputArrayMetadata, 43 : ZarrArrayMetadata &oOutputArrayMetadata, bool /* bEmitWarnings */) 44 : { 45 1800 : m_oConfiguration = configuration.Clone(); 46 1800 : m_bLittle = true; 47 1800 : m_oInputArrayMetadata = oInputArrayMetadata; 48 1800 : oOutputArrayMetadata = oInputArrayMetadata; 49 : 50 1800 : if (configuration.IsValid()) 51 : { 52 1779 : 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 3558 : for (const auto &oChild : configuration.GetChildren()) 60 : { 61 1779 : 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 3558 : const auto oEndian = configuration.GetObj("endian"); 72 1779 : if (oEndian.IsValid()) 73 : { 74 1779 : 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 1779 : if (oEndian.ToString() == "little") 81 1714 : 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 1800 : 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::COMPLEX_IEEEFP) 135 : { 136 0 : nEltCount *= 2; 137 0 : nNativeSize /= 2; 138 : } 139 53 : if (nNativeSize == 2) 140 : { 141 36 : for (size_t i = 0; i < nEltCount; ++i) 142 : { 143 24 : const uint16_t val = CPL_SWAP16(*reinterpret_cast<const uint16_t *>( 144 : pabySrc + sizeof(uint16_t) * i)); 145 24 : memcpy(pabyDst + sizeof(uint16_t) * i, &val, sizeof(val)); 146 : } 147 : } 148 41 : else if (nNativeSize == 4) 149 : { 150 54 : for (size_t i = 0; i < nEltCount; ++i) 151 : { 152 36 : const uint32_t val = CPL_SWAP32(*reinterpret_cast<const uint32_t *>( 153 : pabySrc + sizeof(uint32_t) * i)); 154 36 : memcpy(pabyDst + sizeof(uint32_t) * i, &val, sizeof(val)); 155 : } 156 : } 157 23 : else if (nNativeSize == 8) 158 : { 159 75 : for (size_t i = 0; i < nEltCount; ++i) 160 : { 161 52 : const uint64_t val = CPL_SWAP64(*reinterpret_cast<const uint64_t *>( 162 : pabySrc + sizeof(uint64_t) * i)); 163 52 : memcpy(pabyDst + sizeof(uint64_t) * i, &val, sizeof(val)); 164 : } 165 : } 166 : else 167 : { 168 0 : CPLAssert(false); 169 : } 170 53 : return true; 171 : } 172 : 173 : /************************************************************************/ 174 : /* ZarrV3CodecBytes::Decode() */ 175 : /************************************************************************/ 176 : 177 29 : bool ZarrV3CodecBytes::Decode(const ZarrByteVectorQuickResize &abySrc, 178 : ZarrByteVectorQuickResize &abyDst) const 179 : { 180 29 : return Encode(abySrc, abyDst); 181 : }