LCOV - code coverage report
Current view: top level - frmts/zarr - zarrdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 60 60 100.0 %
Date: 2025-10-22 21:46:17 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  Zarr driver
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2021, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "zarrdrivercore.h"
      14             : #include "gdal_frmts.h"
      15             : #include "gdalplugindriverproxy.h"
      16             : 
      17             : #include "cpl_string.h"
      18             : #include "vsikerchunk.h"
      19             : #include "vsikerchunk_inline.hpp"
      20             : 
      21             : /************************************************************************/
      22             : /*                    CheckExistenceOfOneZarrFile()                     */
      23             : /************************************************************************/
      24             : 
      25        1670 : static bool CheckExistenceOfOneZarrFile(const char *pszFilename)
      26             : {
      27             : 
      28             :     CPLString osMDFilename =
      29        3340 :         CPLFormFilenameSafe(pszFilename, ".zarray", nullptr);
      30             : 
      31             :     VSIStatBufL sStat;
      32        1670 :     if (VSIStatL(osMDFilename, &sStat) == 0)
      33         496 :         return true;
      34             : 
      35        1174 :     osMDFilename = CPLFormFilenameSafe(pszFilename, ".zgroup", nullptr);
      36        1174 :     if (VSIStatL(osMDFilename, &sStat) == 0)
      37         460 :         return true;
      38             : 
      39             :     // Zarr V3
      40         714 :     osMDFilename = CPLFormFilenameSafe(pszFilename, "zarr.json", nullptr);
      41         714 :     if (VSIStatL(osMDFilename, &sStat) == 0)
      42         436 :         return true;
      43             : 
      44         278 :     return false;
      45             : }
      46             : 
      47             : /************************************************************************/
      48             : /*                   ZARRIsLikelyKerchunkJSONRef()                      */
      49             : /************************************************************************/
      50             : 
      51       57952 : bool ZARRIsLikelyKerchunkJSONRef(const GDALOpenInfo *poOpenInfo)
      52             : {
      53       60840 :     if (poOpenInfo->nHeaderBytes > 0 && poOpenInfo->eAccess == GA_ReadOnly &&
      54        2888 :         (poOpenInfo->IsExtensionEqualToCI("json") ||
      55             :          // e.g. like in https://noaa-nodd-kerchunk-pds.s3.amazonaws.com/nos/cbofs/cbofs.fields.best.nc.zarr
      56        1416 :          poOpenInfo->IsExtensionEqualToCI("zarr")))
      57             :     {
      58          65 :         const char *pszHeader =
      59             :             reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
      60          65 :         if (ZARRIsLikelyStreamableKerchunkJSONRefContent(
      61         130 :                 std::string_view(pszHeader, poOpenInfo->nHeaderBytes)))
      62             :         {
      63          57 :             return true;
      64             :         }
      65             :     }
      66       57895 :     return false;
      67             : }
      68             : 
      69             : /************************************************************************/
      70             : /*                     ZARRDriverIdentify()                             */
      71             : /************************************************************************/
      72             : 
      73       57273 : int ZARRDriverIdentify(GDALOpenInfo *poOpenInfo)
      74             : 
      75             : {
      76       57273 :     const std::string_view osvFilename(poOpenInfo->pszFilename);
      77      114444 :     if (cpl::starts_with(osvFilename, "ZARR:") ||
      78       57171 :         cpl::starts_with(osvFilename, "ZARR_DUMMY:"))
      79             :     {
      80         104 :         return TRUE;
      81             :     }
      82             : 
      83       57169 :     if (ZARRIsLikelyKerchunkJSONRef(poOpenInfo))
      84             :     {
      85          38 :         return TRUE;
      86             :     }
      87       57131 :     if (cpl::starts_with(osvFilename, JSON_REF_FS_PREFIX))
      88             :     {
      89           4 :         return -1;
      90             :     }
      91      228486 :     for (const char *pszFile :
      92      285613 :          {".zarray", ".zgroup", ".zmetadata", "zarr.json"})
      93             :     {
      94      228493 :         if (cpl::ends_with(osvFilename, pszFile))
      95             :         {
      96           8 :             return TRUE;
      97             :         }
      98             :     }
      99       57119 :     if (!poOpenInfo->bIsDirectory)
     100             :     {
     101       55448 :         return FALSE;
     102             :     }
     103             : 
     104        1671 :     return CheckExistenceOfOneZarrFile(poOpenInfo->pszFilename);
     105             : }
     106             : 
     107             : /************************************************************************/
     108             : /*                     ZARRDriverSetCommonMetadata()                    */
     109             : /************************************************************************/
     110             : 
     111        1755 : void ZARRDriverSetCommonMetadata(GDALDriver *poDriver)
     112             : {
     113        1755 :     poDriver->SetDescription(DRIVER_NAME);
     114        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     115        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     116        1755 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Zarr");
     117        1755 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "zarr");
     118        1755 :     poDriver->SetMetadataItem(
     119             :         GDAL_DMD_CREATIONDATATYPES,
     120             :         "Int8 Byte Int16 UInt16 Int32 UInt32 Int64 UInt64 "
     121        1755 :         "Float16 Float32 Float64 CFLoat16 CFloat32 CFloat64");
     122        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     123        1755 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     124        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
     125             : 
     126        1755 :     poDriver->SetMetadataItem(
     127             :         GDAL_DMD_OPENOPTIONLIST,
     128             :         "<OpenOptionList>"
     129             :         "   <Option name='LIST_ALL_ARRAYS' type='boolean' "
     130             :         "description='Whether to list all arrays, and not only those whose "
     131             :         "dimension count is 2 or more' default='NO'/>"
     132             :         "   <Option name='USE_ZMETADATA' type='boolean' description='Whether "
     133             :         "to use consolidated metadata from .zmetadata' default='YES'/>"
     134             :         "   <Option name='CACHE_TILE_PRESENCE' type='boolean' "
     135             :         "description='Whether to establish an initial listing of present "
     136             :         "tiles' default='NO'/>"
     137             :         "   <Option name='CACHE_KERCHUNK_JSON' type='boolean' "
     138             :         "description='Whether to transform Kerchunk JSON reference files into "
     139             :         "Kerchunk Parquet reference files in a local cache' default='NO'/>"
     140             :         "   <Option name='MULTIBAND' type='boolean' default='YES' "
     141             :         "description='Whether to expose >= 3D arrays as GDAL multiband "
     142             :         "datasets "
     143             :         "(when using the classic 2D API)'/>"
     144             :         "   <Option name='DIM_X' type='string' description="
     145             :         "'Name or index of the X dimension (only used when MULTIBAND=YES)'/>"
     146             :         "   <Option name='DIM_Y' type='string' description="
     147             :         "'Name or index of the Y dimension (only used when MULTIBAND=YES)'/>"
     148             :         "   <Option name='LOAD_EXTRA_DIM_METADATA_DELAY' type='string' "
     149             :         "description="
     150             :         "'Maximum delay in seconds allowed to set the DIM_{dimname}_VALUE band "
     151             :         "metadata items'/>"
     152        1755 :         "</OpenOptionList>");
     153             : 
     154        1755 :     poDriver->SetMetadataItem(
     155             :         GDAL_DMD_MULTIDIM_DATASET_CREATIONOPTIONLIST,
     156             :         "<MultiDimDatasetCreationOptionList>"
     157             :         "   <Option name='FORMAT' type='string-select' default='ZARR_V2'>"
     158             :         "     <Value>ZARR_V2</Value>"
     159             :         "     <Value>ZARR_V3</Value>"
     160             :         "   </Option>"
     161             :         "   <Option name='CREATE_ZMETADATA' type='boolean' "
     162             :         "description='Whether to create consolidated metadata into .zmetadata "
     163             :         "(Zarr V2 only)' default='YES'/>"
     164        1755 :         "</MultiDimDatasetCreationOptionList>");
     165             : 
     166        1755 :     poDriver->pfnIdentify = ZARRDriverIdentify;
     167        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     168        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
     169        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     170        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_MULTIDIMENSIONAL, "YES");
     171             : 
     172        1755 :     poDriver->SetMetadataItem(GDAL_DCAP_UPDATE, "YES");
     173        1755 :     poDriver->SetMetadataItem(GDAL_DMD_UPDATE_ITEMS,
     174             :                               "GeoTransform SRS NoData "
     175             :                               "RasterValues "
     176        1755 :                               "DatasetMetadata BandMetadata");
     177        1755 : }
     178             : 
     179             : /************************************************************************/
     180             : /*                    DeclareDeferredZarrPlugin()                       */
     181             : /************************************************************************/
     182             : 
     183             : #ifdef PLUGIN_FILENAME
     184             : void DeclareDeferredZarrPlugin()
     185             : {
     186             :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     187             :     {
     188             :         return;
     189             :     }
     190             :     auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     191             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     192             :     poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     193             :                               PLUGIN_INSTALLATION_MESSAGE);
     194             : #endif
     195             :     ZARRDriverSetCommonMetadata(poDriver);
     196             :     GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     197             : }
     198             : #endif

Generated by: LCOV version 1.14