Coverage Report

Created: 2026-03-30 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/zarr/zarr_v3_codec_crc32c.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  Zarr driver, "crc32c" codec
5
 * Author:   Even Rouault <even dot rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2026, Development Seed
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "zarr_v3_codec.h"
14
15
#include "crc32c.h"
16
17
// Implements https://zarr-specs.readthedocs.io/en/latest/v3/codecs/crc32c/index.html
18
19
/************************************************************************/
20
/*                ZarrV3CodecCRC32C::ZarrV3CodecCRC32C()                */
21
/************************************************************************/
22
23
0
ZarrV3CodecCRC32C::ZarrV3CodecCRC32C() : ZarrV3Codec(NAME)
24
0
{
25
0
}
26
27
/************************************************************************/
28
/*                      ZarrV3CodecCRC32C::Clone()                      */
29
/************************************************************************/
30
31
std::unique_ptr<ZarrV3Codec> ZarrV3CodecCRC32C::Clone() const
32
0
{
33
0
    auto psClone = std::make_unique<ZarrV3CodecCRC32C>();
34
0
    ZarrArrayMetadata oOutputArrayMetadata;
35
0
    psClone->InitFromConfiguration(m_oConfiguration, m_oInputArrayMetadata,
36
0
                                   oOutputArrayMetadata,
37
0
                                   /* bEmitWarnings = */ false);
38
0
    return psClone;
39
0
}
40
41
/************************************************************************/
42
/*              ZarrV3CodecCRC32C::InitFromConfiguration()              */
43
/************************************************************************/
44
45
bool ZarrV3CodecCRC32C::InitFromConfiguration(
46
    const CPLJSONObject &configuration,
47
    const ZarrArrayMetadata &oInputArrayMetadata,
48
    ZarrArrayMetadata &oOutputArrayMetadata, bool /* bEmitWarnings */)
49
0
{
50
0
    m_oConfiguration = configuration.Clone();
51
0
    m_oInputArrayMetadata = oInputArrayMetadata;
52
0
    oOutputArrayMetadata = oInputArrayMetadata;
53
54
    // GDAL extension for tests !!!
55
0
    if (!m_oConfiguration.GetBool("check_crc", true))
56
0
        m_bCheckCRC = false;
57
58
0
    return true;
59
0
}
60
61
/************************************************************************/
62
/*                           ComputeCRC32C()                            */
63
/************************************************************************/
64
65
static uint32_t ComputeCRC32C(const GByte *pabyIn, size_t nLength)
66
0
{
67
0
    crc32c_init();
68
0
    return crc32c(0, pabyIn, nLength);
69
0
}
70
71
/************************************************************************/
72
/*                     ZarrV3CodecCRC32C::Encode()                      */
73
/************************************************************************/
74
75
bool ZarrV3CodecCRC32C::Encode(const ZarrByteVectorQuickResize &abySrc,
76
                               ZarrByteVectorQuickResize &abyDst) const
77
0
{
78
0
    abyDst.clear();
79
0
    abyDst.insert(abyDst.end(), abySrc.begin(), abySrc.end());
80
81
0
    const uint32_t nComputedCRC_le =
82
0
        CPL_LSBWORD32(ComputeCRC32C(abySrc.data(), abySrc.size()));
83
0
    const GByte *pabyCRC = reinterpret_cast<const GByte *>(&nComputedCRC_le);
84
0
    abyDst.insert(abyDst.end(), pabyCRC, pabyCRC + sizeof(uint32_t));
85
86
0
    return true;
87
0
}
88
89
/************************************************************************/
90
/*                     ZarrV3CodecCRC32C::Decode()                      */
91
/************************************************************************/
92
93
bool ZarrV3CodecCRC32C::Decode(const ZarrByteVectorQuickResize &abySrc,
94
                               ZarrByteVectorQuickResize &abyDst) const
95
0
{
96
0
    if (abySrc.size() < sizeof(uint32_t))
97
0
    {
98
0
        CPLError(CE_Failure, CPLE_AppDefined,
99
0
                 "CRC32C decoder: not enough input bytes");
100
0
        return false;
101
0
    }
102
103
0
    const size_t nSrcLen = abySrc.size() - sizeof(uint32_t);
104
0
    abyDst.clear();
105
0
    abyDst.insert(abyDst.end(), abySrc.begin(), abySrc.begin() + nSrcLen);
106
107
0
    if (m_bCheckCRC)
108
0
    {
109
0
        const uint32_t nComputedCRC =
110
0
            ComputeCRC32C(abyDst.data(), abyDst.size());
111
0
        const uint32_t nExpectedCRC = CPL_LSBUINT32PTR(abySrc.data() + nSrcLen);
112
0
        if (nComputedCRC != nExpectedCRC)
113
0
        {
114
0
            CPLError(
115
0
                CE_Failure, CPLE_AppDefined,
116
0
                "CRC32C decoder: computed CRC value is %08X whereas expected "
117
0
                "value is %08X",
118
0
                nComputedCRC, nExpectedCRC);
119
0
            return false;
120
0
        }
121
0
    }
122
123
0
    return true;
124
0
}