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 : 15 : #include "vsikerchunk.h" 16 : #include "vsikerchunk_inline.hpp" 17 : 18 : /************************************************************************/ 19 : /* CheckExistenceOfOneZarrFile() */ 20 : /************************************************************************/ 21 : 22 1642 : static bool CheckExistenceOfOneZarrFile(const char *pszFilename) 23 : { 24 : 25 : CPLString osMDFilename = 26 3284 : CPLFormFilenameSafe(pszFilename, ".zarray", nullptr); 27 : 28 : VSIStatBufL sStat; 29 1642 : if (VSIStatL(osMDFilename, &sStat) == 0) 30 488 : return true; 31 : 32 1154 : osMDFilename = CPLFormFilenameSafe(pszFilename, ".zgroup", nullptr); 33 1154 : if (VSIStatL(osMDFilename, &sStat) == 0) 34 452 : return true; 35 : 36 : // Zarr V3 37 702 : osMDFilename = CPLFormFilenameSafe(pszFilename, "zarr.json", nullptr); 38 702 : if (VSIStatL(osMDFilename, &sStat) == 0) 39 424 : return true; 40 : 41 278 : return false; 42 : } 43 : 44 : /************************************************************************/ 45 : /* ZARRIsLikelyKerchunkJSONRef() */ 46 : /************************************************************************/ 47 : 48 55981 : bool ZARRIsLikelyKerchunkJSONRef(const GDALOpenInfo *poOpenInfo) 49 : { 50 57401 : if (poOpenInfo->nHeaderBytes > 0 && poOpenInfo->eAccess == GA_ReadOnly && 51 1420 : poOpenInfo->IsExtensionEqualToCI("json")) 52 : { 53 59 : const char *pszHeader = 54 : reinterpret_cast<const char *>(poOpenInfo->pabyHeader); 55 59 : if (ZARRIsLikelyStreamableKerchunkJSONRefContent( 56 118 : std::string_view(pszHeader, poOpenInfo->nHeaderBytes))) 57 : { 58 54 : return true; 59 : } 60 : } 61 55927 : return false; 62 : } 63 : 64 : /************************************************************************/ 65 : /* ZARRDriverIdentify() */ 66 : /************************************************************************/ 67 : 68 55320 : int ZARRDriverIdentify(GDALOpenInfo *poOpenInfo) 69 : 70 : { 71 55320 : if (STARTS_WITH(poOpenInfo->pszFilename, "ZARR:") || 72 55223 : STARTS_WITH(poOpenInfo->pszFilename, "ZARR_DUMMY:")) 73 : { 74 99 : return TRUE; 75 : } 76 : 77 55221 : if (ZARRIsLikelyKerchunkJSONRef(poOpenInfo)) 78 : { 79 36 : return TRUE; 80 : } 81 55184 : if (STARTS_WITH(poOpenInfo->pszFilename, JSON_REF_FS_PREFIX)) 82 : { 83 4 : return -1; 84 : } 85 : 86 55180 : if (!poOpenInfo->bIsDirectory) 87 : { 88 53539 : return FALSE; 89 : } 90 : 91 1641 : return CheckExistenceOfOneZarrFile(poOpenInfo->pszFilename); 92 : } 93 : 94 : /************************************************************************/ 95 : /* ZARRDriverSetCommonMetadata() */ 96 : /************************************************************************/ 97 : 98 1629 : void ZARRDriverSetCommonMetadata(GDALDriver *poDriver) 99 : { 100 1629 : poDriver->SetDescription(DRIVER_NAME); 101 1629 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); 102 1629 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES"); 103 1629 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Zarr"); 104 1629 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "zarr"); 105 1629 : poDriver->SetMetadataItem( 106 : GDAL_DMD_CREATIONDATATYPES, 107 : "Int8 Byte Int16 UInt16 Int32 UInt32 Int64 UInt64 " 108 1629 : "Float16 Float32 Float64 CFLoat16 CFloat32 CFloat64"); 109 1629 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 110 1629 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES"); 111 1629 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES"); 112 : 113 1629 : poDriver->SetMetadataItem( 114 : GDAL_DMD_OPENOPTIONLIST, 115 : "<OpenOptionList>" 116 : " <Option name='LIST_ALL_ARRAYS' type='boolean' " 117 : "description='Whether to list all arrays, and not only those whose " 118 : "dimension count is 2 or more' default='NO'/>" 119 : " <Option name='USE_ZMETADATA' type='boolean' description='Whether " 120 : "to use consolidated metadata from .zmetadata' default='YES'/>" 121 : " <Option name='CACHE_TILE_PRESENCE' type='boolean' " 122 : "description='Whether to establish an initial listing of present " 123 : "tiles' default='NO'/>" 124 : " <Option name='CACHE_KERCHUNK_JSON' type='boolean' " 125 : "description='Whether to transform Kerchunk JSON reference files into " 126 : "Kerchunk Parquet reference files in a local cache' default='NO'/>" 127 : " <Option name='MULTIBAND' type='boolean' default='YES' " 128 : "description='Whether to expose >= 3D arrays as GDAL multiband " 129 : "datasets " 130 : "(when using the classic 2D API)'/>" 131 : " <Option name='DIM_X' type='string' description=" 132 : "'Name or index of the X dimension (only used when MULTIBAND=YES)'/>" 133 : " <Option name='DIM_Y' type='string' description=" 134 : "'Name or index of the Y dimension (only used when MULTIBAND=YES)'/>" 135 : " <Option name='LOAD_EXTRA_DIM_METADATA_DELAY' type='string' " 136 : "description=" 137 : "'Maximum delay in seconds allowed to set the DIM_{dimname}_VALUE band " 138 : "metadata items'/>" 139 1629 : "</OpenOptionList>"); 140 : 141 1629 : poDriver->SetMetadataItem( 142 : GDAL_DMD_MULTIDIM_DATASET_CREATIONOPTIONLIST, 143 : "<MultiDimDatasetCreationOptionList>" 144 : " <Option name='FORMAT' type='string-select' default='ZARR_V2'>" 145 : " <Value>ZARR_V2</Value>" 146 : " <Value>ZARR_V3</Value>" 147 : " </Option>" 148 : " <Option name='CREATE_ZMETADATA' type='boolean' " 149 : "description='Whether to create consolidated metadata into .zmetadata " 150 : "(Zarr V2 only)' default='YES'/>" 151 1629 : "</MultiDimDatasetCreationOptionList>"); 152 : 153 1629 : poDriver->pfnIdentify = ZARRDriverIdentify; 154 1629 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); 155 1629 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES"); 156 1629 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES"); 157 1629 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_MULTIDIMENSIONAL, "YES"); 158 : 159 1629 : poDriver->SetMetadataItem(GDAL_DCAP_UPDATE, "YES"); 160 1629 : poDriver->SetMetadataItem(GDAL_DMD_UPDATE_ITEMS, 161 : "GeoTransform SRS NoData " 162 : "RasterValues " 163 1629 : "DatasetMetadata BandMetadata"); 164 1629 : } 165 : 166 : /************************************************************************/ 167 : /* DeclareDeferredZarrPlugin() */ 168 : /************************************************************************/ 169 : 170 : #ifdef PLUGIN_FILENAME 171 : void DeclareDeferredZarrPlugin() 172 : { 173 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 174 : { 175 : return; 176 : } 177 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME); 178 : #ifdef PLUGIN_INSTALLATION_MESSAGE 179 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE, 180 : PLUGIN_INSTALLATION_MESSAGE); 181 : #endif 182 : ZARRDriverSetCommonMetadata(poDriver); 183 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); 184 : } 185 : #endif