LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfdataset.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 35 35 100.0 %
Date: 2026-08-22 15:37:05 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  netCDF read/write Driver
       4             :  * Purpose:  GDAL bindings over netCDF library.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2004, Frank Warmerdam
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef NETCDFDATASET_H_INCLUDED_
      14             : #define NETCDFDATASET_H_INCLUDED_
      15             : 
      16             : #include <array>
      17             : #include <ctime>
      18             : #include <cfloat>
      19             : #include <cstdlib>
      20             : #include <functional>
      21             : #include <map>
      22             : #include <memory>
      23             : #include <utility>
      24             : #include <vector>
      25             : 
      26             : #include "cpl_mem_cache.h"
      27             : #include "cpl_string.h"
      28             : #include "gdal_frmts.h"
      29             : #include "gdal_pam.h"
      30             : #include "gdal_priv.h"
      31             : #include "netcdf.h"
      32             : #include "netcdfformatenum.h"
      33             : #include "netcdfsg.h"
      34             : #include "netcdfsgwriterutil.h"
      35             : #include "ogr_spatialref.h"
      36             : #include "ogrsf_frmts.h"
      37             : #include "netcdfuffd.h"
      38             : #include "netcdf_cf_constants.h"
      39             : 
      40             : constexpr uint8_t PLATFORM_HEADER = CPL_IS_LSB;
      41             : 
      42             : /************************************************************************/
      43             : /* ==================================================================== */
      44             : /*                           defines                                    */
      45             : /* ==================================================================== */
      46             : /************************************************************************/
      47             : 
      48             : /* -------------------------------------------------------------------- */
      49             : /*      Creation and Configuration Options                              */
      50             : /* -------------------------------------------------------------------- */
      51             : 
      52             : /* Creation options
      53             : 
      54             :    FORMAT=NC/NC2/NC4/NC4C (COMPRESS=DEFLATE sets FORMAT=NC4C)
      55             :    COMPRESS=NONE/DEFLATE (default: NONE)
      56             :    ZLEVEL=[1-9] (default: 1)
      57             :    WRITE_BOTTOMUP=YES/NO (default: YES)
      58             :    WRITE_GDAL_TAGS=YES/NO (default: YES)
      59             :    WRITE_LONLAT=YES/NO/IF_NEEDED (default: YES for geographic, NO for projected)
      60             :    TYPE_LONLAT=float/double (default: double for geographic, float for
      61             :    projected) PIXELTYPE=DEFAULT/SIGNEDBYTE (use SIGNEDBYTE to get a signed Byte
      62             :    Band)
      63             : */
      64             : 
      65             : /* Config Options
      66             : 
      67             :    GDAL_NETCDF_BOTTOMUP=YES/NO overrides bottom-up value on import
      68             :    GDAL_NETCDF_VERIFY_DIMS=[YES/STRICT] : Try to guess which dimensions
      69             :    represent the latitude and longitude only by their attributes (STRICT) or
      70             :    also by guessing the name (YES), default is YES.
      71             :    GDAL_NETCDF_IGNORE_XY_AXIS_NAME_CHECKS=[YES/NO] Whether X/Y dimensions should
      72             :    be always considered as geospatial axis, even if the lack conventional
      73             :    attributes confirming it. Default is NO. GDAL_NETCDF_ASSUME_LONGLAT=[YES/NO]
      74             :    Whether when all else has failed for determining a CRS, a meaningful
      75             :    geotransform has been found, and is within the bounds -180,360 -90,90, if YES
      76             :    assume OGC:CRS84. Default is NO.
      77             : 
      78             :    // TODO: this unused and a few others occur in the source that are not
      79             :    documented, flush out unused opts and document the rest mdsumner@gmail.com
      80             :    GDAL_NETCDF_CONVERT_LAT_180=YES/NO convert longitude values from ]180,360] to
      81             :    [-180,180]
      82             : */
      83             : 
      84             : /* -------------------------------------------------------------------- */
      85             : /*      Driver-specific defines                                         */
      86             : /* -------------------------------------------------------------------- */
      87             : 
      88             : /* NETCDF driver defs */
      89             : static const size_t NCDF_MAX_STR_LEN = 8192;
      90             : #define NCDF_CONVENTIONS "Conventions"
      91             : #define NCDF_CONVENTIONS_CF_V1_5 "CF-1.5"
      92             : #define GDAL_DEFAULT_NCDF_CONVENTIONS NCDF_CONVENTIONS_CF_V1_5
      93             : #define NCDF_CONVENTIONS_CF_V1_6 "CF-1.6"
      94             : #define NCDF_CONVENTIONS_CF_V1_8 "CF-1.8"
      95             : #define NCDF_GEOTRANSFORM "GeoTransform"
      96             : #define NCDF_DIMNAME_X "x"
      97             : #define NCDF_DIMNAME_Y "y"
      98             : #define NCDF_DIMNAME_LON "lon"
      99             : #define NCDF_DIMNAME_LAT "lat"
     100             : #define NCDF_LONLAT "lon lat"
     101             : #define NCDF_DIMNAME_RLON "rlon"  // rotated longitude
     102             : #define NCDF_DIMNAME_RLAT "rlat"  // rotated latitude
     103             : 
     104             : /* compression parameters */
     105             : typedef enum
     106             : {
     107             :     NCDF_COMPRESS_NONE = 0,
     108             :     /* TODO */
     109             :     /* http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#Packed%20Data%20Values
     110             :      */
     111             :     NCDF_COMPRESS_PACKED = 1,
     112             :     NCDF_COMPRESS_DEFLATE = 2,
     113             :     NCDF_COMPRESS_SZIP = 3 /* no support for writing */
     114             : } NetCDFCompressEnum;
     115             : 
     116             : static const int NCDF_DEFLATE_LEVEL = 1; /* best time/size ratio */
     117             : 
     118             : /* helper for libnetcdf errors */
     119             : #define NCDF_ERR(status)                                                       \
     120             :     do                                                                         \
     121             :     {                                                                          \
     122             :         int NCDF_ERR_status_ = (status);                                       \
     123             :         if (NCDF_ERR_status_ != NC_NOERR)                                      \
     124             :         {                                                                      \
     125             :             CPLError(CE_Failure, CPLE_AppDefined,                              \
     126             :                      "netcdf error #%d : %s .\nat (%s,%s,%d)\n",               \
     127             :                      NCDF_ERR_status_, nc_strerror(NCDF_ERR_status_),          \
     128             :                      __FILE__, __FUNCTION__, __LINE__);                        \
     129             :         }                                                                      \
     130             :     } while (0)
     131             : 
     132             : #define NCDF_ERR_RET(status)                                                   \
     133             :     do                                                                         \
     134             :     {                                                                          \
     135             :         int NCDF_ERR_RET_status_ = (status);                                   \
     136             :         if (NCDF_ERR_RET_status_ != NC_NOERR)                                  \
     137             :         {                                                                      \
     138             :             NCDF_ERR(NCDF_ERR_RET_status_);                                    \
     139             :             return CE_Failure;                                                 \
     140             :         }                                                                      \
     141             :     } while (0)
     142             : 
     143             : #define ERR_RET(eErr)                                                          \
     144             :     do                                                                         \
     145             :     {                                                                          \
     146             :         CPLErr ERR_RET_eErr_ = (eErr);                                         \
     147             :         if (ERR_RET_eErr_ != CE_None)                                          \
     148             :             return ERR_RET_eErr_;                                              \
     149             :     } while (0)
     150             : 
     151             : /* Check for NC2 support in case it was not enabled at compile time. */
     152             : /* NC4 has to be detected at compile as it requires a special build of netcdf-4.
     153             :  */
     154             : #ifndef NETCDF_HAS_NC2
     155             : #ifdef NC_64BIT_OFFSET
     156             : #define NETCDF_HAS_NC2 1
     157             : #endif
     158             : #endif
     159             : 
     160             : /* Some additional metadata */
     161             : #define OGR_SG_ORIGINAL_LAYERNAME "ogr_layer_name"
     162             : 
     163             : /*
     164             :  * Starting `c26f7ea`, netcdf-c exposes the `NC_FillValue`[1] macro instead of
     165             :  * `_FillValue` to avoid collisions with C++ standard library[2]. However, the
     166             :  * previous macro, `_FillValue`, was fully removed causing netcdf-c consumers,
     167             :  * including GDAL, fail to build.
     168             :  *
     169             :  * It's unlikely that this naming change will be backported to the previous
     170             :  * netcdf-c releases, so we have to account for both macros variants. We do so
     171             :  * by introducing our own macro, `NCDF_FillValue`, and using that in places
     172             :  * where `_FillValue` was previously used. If `NC_FillValue` is defined by
     173             :  * `netcdf.h`, `NCDF_FillValue` expands to it and, if it's not, to `_FillValue`.
     174             :  *
     175             :  * References:
     176             :  * 1. https://github.com/Unidata/netcdf-c/commit/c26f7eabf4a1cd25353f22734f439505fe636a45
     177             :  * 2. https://github.com/Unidata/netcdf-c/issues/2858
     178             :  */
     179             : #if defined(NC_FillValue)
     180             : #define NCDF_FillValue NC_FillValue
     181             : #elif defined(_FillValue)
     182             : #define NCDF_FillValue _FillValue
     183             : #endif
     184             : 
     185             : /* -------------------------------------------------------------------- */
     186             : /*         CF-1 Coordinate Type Naming (Chapter 4.  Coordinate Types )  */
     187             : /* -------------------------------------------------------------------- */
     188             : static const char *const papszCFLongitudeVarNames[] = {CF_LONGITUDE_VAR_NAME,
     189             :                                                        "longitude", nullptr};
     190             : static const char *const papszCFLongitudeAttribNames[] = {
     191             :     CF_UNITS, CF_UNITS, CF_UNITS, CF_STD_NAME, CF_AXIS, CF_LNG_NAME, nullptr};
     192             : static const char *const papszCFLongitudeAttribValues[] = {
     193             :     CF_DEGREES_EAST,
     194             :     CF_DEGREE_EAST,
     195             :     CF_DEGREES_E,
     196             :     CF_LONGITUDE_STD_NAME,
     197             :     "X",
     198             :     CF_LONGITUDE_LNG_NAME,
     199             :     nullptr};
     200             : static const char *const papszCFLatitudeVarNames[] = {CF_LATITUDE_VAR_NAME,
     201             :                                                       "latitude", nullptr};
     202             : static const char *const papszCFLatitudeAttribNames[] = {
     203             :     CF_UNITS, CF_UNITS, CF_UNITS, CF_STD_NAME, CF_AXIS, CF_LNG_NAME, nullptr};
     204             : static const char *const papszCFLatitudeAttribValues[] = {CF_DEGREES_NORTH,
     205             :                                                           CF_DEGREE_NORTH,
     206             :                                                           CF_DEGREES_N,
     207             :                                                           CF_LATITUDE_STD_NAME,
     208             :                                                           "Y",
     209             :                                                           CF_LATITUDE_LNG_NAME,
     210             :                                                           nullptr};
     211             : 
     212             : static const char *const papszCFProjectionXVarNames[] = {CF_PROJ_X_VAR_NAME,
     213             :                                                          "xc", "rlon", nullptr};
     214             : static const char *const papszCFProjectionXAttribNames[] = {
     215             :     CF_STD_NAME, CF_AXIS, CF_STD_NAME, nullptr};
     216             : static const char *const papszCFProjectionXAttribValues[] = {
     217             :     CF_PROJ_X_COORD, "X", "grid_longitude", nullptr};
     218             : static const char *const papszCFProjectionYVarNames[] = {CF_PROJ_Y_VAR_NAME,
     219             :                                                          "yc", "rlat", nullptr};
     220             : static const char *const papszCFProjectionYAttribNames[] = {
     221             :     CF_STD_NAME, CF_AXIS, CF_STD_NAME, nullptr};
     222             : static const char *const papszCFProjectionYAttribValues[] = {
     223             :     CF_PROJ_Y_COORD, "Y", "grid_latitude", nullptr};
     224             : 
     225             : static const char *const papszCFVerticalAttribNames[] = {CF_AXIS, "positive",
     226             :                                                          "positive", nullptr};
     227             : static const char *const papszCFVerticalAttribValues[] = {"Z", "up", "down",
     228             :                                                           nullptr};
     229             : static const char *const papszCFVerticalUnitsValues[] = {
     230             :     /* units of pressure */
     231             :     "bar", "bars", "millibar", "millibars", "decibar", "decibars", "atmosphere",
     232             :     "atmospheres", "atm", "pascal", "pascals", "Pa", "hPa",
     233             :     /* units of length */
     234             :     "meter", "meters", "m", "kilometer", "kilometers", "km",
     235             :     /* dimensionless vertical coordinates */
     236             :     "level", "layer", "sigma_level", nullptr};
     237             : /* dimensionless vertical coordinates */
     238             : static const char *const papszCFVerticalStandardNameValues[] = {
     239             :     "atmosphere_ln_pressure_coordinate",
     240             :     "atmosphere_sigma_coordinate",
     241             :     "atmosphere_hybrid_sigma_pressure_coordinate",
     242             :     "atmosphere_hybrid_height_coordinate",
     243             :     "atmosphere_sleve_coordinate",
     244             :     "ocean_sigma_coordinate",
     245             :     "ocean_s_coordinate",
     246             :     "ocean_sigma_z_coordinate",
     247             :     "ocean_double_sigma_coordinate",
     248             :     "atmosphere_ln_pressure_coordinate",
     249             :     "atmosphere_sigma_coordinate",
     250             :     "atmosphere_hybrid_sigma_pressure_coordinate",
     251             :     "atmosphere_hybrid_height_coordinate",
     252             :     "atmosphere_sleve_coordinate",
     253             :     "ocean_sigma_coordinate",
     254             :     "ocean_s_coordinate",
     255             :     "ocean_sigma_z_coordinate",
     256             :     "ocean_double_sigma_coordinate",
     257             :     nullptr};
     258             : 
     259             : static const char *const papszCFTimeAttribNames[] = {CF_AXIS, CF_STD_NAME,
     260             :                                                      nullptr};
     261             : static const char *const papszCFTimeAttribValues[] = {"T", "time", nullptr};
     262             : static const char *const papszCFTimeUnitsValues[] = {
     263             :     "days since",   "day since", "d since",       "hours since",
     264             :     "hour since",   "h since",   "hr since",      "minutes since",
     265             :     "minute since", "min since", "seconds since", "second since",
     266             :     "sec since",    "s since",   nullptr};
     267             : 
     268             : /************************************************************************/
     269             : /* ==================================================================== */
     270             : /*                        netCDFWriterConfig classes                    */
     271             : /* ==================================================================== */
     272             : /************************************************************************/
     273             : 
     274             : class netCDFWriterConfigAttribute
     275             : {
     276             :   public:
     277             :     CPLString m_osName;
     278             :     CPLString m_osType;
     279             :     CPLString m_osValue;
     280             : 
     281             :     bool Parse(CPLXMLNode *psNode);
     282             : };
     283             : 
     284             : class netCDFWriterConfigField
     285             : {
     286             :   public:
     287             :     CPLString m_osName;
     288             :     CPLString m_osNetCDFName;
     289             :     CPLString m_osMainDim;
     290             :     std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
     291             : 
     292             :     bool Parse(CPLXMLNode *psNode);
     293             : };
     294             : 
     295             : class netCDFWriterConfigLayer
     296             : {
     297             :   public:
     298             :     CPLString m_osName;
     299             :     CPLString m_osNetCDFName;
     300             :     std::map<CPLString, CPLString> m_oLayerCreationOptions;
     301             :     std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
     302             :     std::map<CPLString, netCDFWriterConfigField> m_oFields;
     303             : 
     304             :     bool Parse(CPLXMLNode *psNode);
     305             : };
     306             : 
     307             : class netCDFWriterConfiguration
     308             : {
     309             :   public:
     310             :     bool m_bIsValid;
     311             :     std::map<CPLString, CPLString> m_oDatasetCreationOptions;
     312             :     std::map<CPLString, CPLString> m_oLayerCreationOptions;
     313             :     std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
     314             :     std::map<CPLString, netCDFWriterConfigField> m_oFields;
     315             :     std::map<CPLString, netCDFWriterConfigLayer> m_oLayers;
     316             : 
     317        1327 :     netCDFWriterConfiguration() : m_bIsValid(false)
     318             :     {
     319        1327 :     }
     320             : 
     321             :     bool Parse(const char *pszFilename);
     322             :     static bool SetNameValue(CPLXMLNode *psNode,
     323             :                              std::map<CPLString, CPLString> &oMap);
     324             : };
     325             : 
     326             : /************************************************************************/
     327             : /* ==================================================================== */
     328             : /*                           netCDFDataset                              */
     329             : /* ==================================================================== */
     330             : /************************************************************************/
     331             : 
     332             : class netCDFRasterBand;
     333             : class netCDFLayer;
     334             : 
     335             : class netCDFDataset final : public GDALPamDataset
     336             : {
     337             :     friend class netCDFRasterBand;  // TMP
     338             :     friend class netCDFLayer;
     339             :     friend class netCDFVariable;
     340             :     friend class nccfdriver::netCDFVID;
     341             : 
     342             :     typedef enum
     343             :     {
     344             :         SINGLE_LAYER,
     345             :         SEPARATE_FILES,
     346             :         SEPARATE_GROUPS
     347             :     } MultipleLayerBehavior;
     348             : 
     349             :     /* basic dataset vars */
     350             :     CPLString osFilename;
     351             : #ifdef ENABLE_NCDUMP
     352             :     bool bFileToDestroyAtClosing;
     353             : #endif
     354             :     int cdfid;
     355             : #ifdef ENABLE_UFFD
     356             :     cpl_uffd_context *pCtx = nullptr;
     357             : #endif
     358             :     VSILFILE *fpVSIMEM = nullptr;
     359             :     int nSubDatasets;
     360             :     CPLStringList aosSubDatasets;
     361             :     CPLStringList aosMetadata;
     362             : 
     363             :     // Used to report metadata found in Sentinel 5
     364             :     std::map<std::string, CPLStringList> m_oMapDomainToJSon{};
     365             : 
     366             :     CPLStringList papszDimName;
     367             :     bool bBottomUp;
     368             :     NetCDFFormatEnum eFormat;
     369             :     bool bIsGdalFile;   /* was this file created by GDAL? */
     370             :     bool bIsGdalCfFile; /* was this file created by the (new) CF-compliant
     371             :                            driver? */
     372             :     char *pszCFProjection;
     373             :     const char *pszCFCoordinates;
     374             :     int nCFVersionMajor = 1;
     375             :     int nCFVersionMinor = 6;
     376             :     bool bSGSupport;
     377             :     MultipleLayerBehavior eMultipleLayerBehavior;
     378             :     std::vector<netCDFDataset *> apoVectorDatasets;
     379             :     std::string logHeader;
     380             :     int logCount;
     381             :     nccfdriver::netCDFVID vcdf;
     382             :     nccfdriver::OGR_NCScribe GeometryScribe;
     383             :     nccfdriver::OGR_NCScribe FieldScribe;
     384             :     nccfdriver::WBufferManager bufManager;
     385             : 
     386             :     bool bWriteGDALVersion = true;
     387             :     bool bWriteGDALHistory = true;
     388             : 
     389             :     /* projection/GT */
     390             :     GDALGeoTransform m_gt{};
     391             :     OGRSpatialReference m_oSRS{};
     392             :     int nXDimID;
     393             :     int nYDimID;
     394             :     bool bIsProjected;
     395             :     bool bIsGeographic;
     396             :     bool bSwitchedXY = false;
     397             : 
     398             :     /* state vars */
     399             :     bool bDefineMode;
     400             :     bool m_bHasProjection = false;
     401             :     bool m_bHasGeoTransform = false;
     402             :     bool m_bAddedProjectionVarsDefs = false;
     403             :     bool m_bAddedProjectionVarsData = false;
     404             :     bool bAddedGridMappingRef;
     405             : 
     406             :     /* create vars */
     407             :     CPLStringList aosCreationOptions;
     408             :     NetCDFCompressEnum eCompress;
     409             :     int nZLevel;
     410             :     bool bChunking;
     411             :     int nCreateMode;
     412             :     bool bSignedData;
     413             : 
     414             :     // IDs of the dimensions of the variables
     415             :     std::vector<int> m_anDimIds{};
     416             : 
     417             :     // Extra dimension info (size of those arrays is m_anDimIds.size() - 2)
     418             :     std::vector<int> m_anExtraDimVarIds{};
     419             :     std::vector<int> m_anExtraDimGroupIds{};
     420             : 
     421             :     std::vector<std::shared_ptr<OGRLayer>> papoLayers;
     422             : 
     423             :     netCDFWriterConfiguration oWriterConfig;
     424             : 
     425             :     struct ChunkKey
     426             :     {
     427             :         size_t xChunk;  // netCDF chunk number along X axis
     428             :         size_t yChunk;  // netCDF chunk number along Y axis
     429             :         int nBand;
     430             : 
     431          26 :         ChunkKey(size_t xChunkIn, size_t yChunkIn, int nBandIn)
     432          26 :             : xChunk(xChunkIn), yChunk(yChunkIn), nBand(nBandIn)
     433             :         {
     434          26 :         }
     435             : 
     436          28 :         bool operator==(const ChunkKey &other) const
     437             :         {
     438          48 :             return xChunk == other.xChunk && yChunk == other.yChunk &&
     439          48 :                    nBand == other.nBand;
     440             :         }
     441             : 
     442          22 :         bool operator!=(const ChunkKey &other) const
     443             :         {
     444          22 :             return !(operator==(other));
     445             :         }
     446             :     };
     447             : 
     448             :     struct KeyHasher
     449             :     {
     450          45 :         std::size_t operator()(const ChunkKey &k) const
     451             :         {
     452          45 :             return std::hash<size_t>{}(k.xChunk) ^
     453          45 :                    (std::hash<size_t>{}(k.yChunk) << 1) ^
     454          45 :                    (std::hash<size_t>{}(k.nBand) << 2);
     455             :         }
     456             :     };
     457             : 
     458             :     typedef lru11::Cache<
     459             :         ChunkKey, std::shared_ptr<std::vector<GByte>>, lru11::NullLock,
     460             :         std::unordered_map<
     461             :             ChunkKey,
     462             :             typename std::list<lru11::KeyValuePair<
     463             :                 ChunkKey, std::shared_ptr<std::vector<GByte>>>>::iterator,
     464             :             KeyHasher>>
     465             :         ChunkCacheType;
     466             : 
     467             :     std::unique_ptr<ChunkCacheType> poChunkCache;
     468             : 
     469             :     static double rint(double);
     470             : 
     471             :     double FetchCopyParam(const char *pszGridMappingValue, const char *pszParam,
     472             :                           double dfDefault, bool *pbFound = nullptr) const;
     473             : 
     474             :     std::vector<std::string>
     475             :     FetchStandardParallels(const char *pszGridMappingValue) const;
     476             : 
     477             :     const char *FetchAttr(const char *pszVarFullName,
     478             :                           const char *pszAttr) const;
     479             :     const char *FetchAttr(int nGroupId, int nVarId, const char *pszAttr) const;
     480             : 
     481             :     bool ProcessCreationOptions();
     482             :     int DefVarDeflate(int nVarId, bool bChunkingArg = true) const;
     483             :     CPLErr AddProjectionVars(bool bDefsOnly, GDALProgressFunc pfnProgress,
     484             :                              void *pProgressData);
     485             :     bool AddGridMappingRef();
     486             : 
     487          11 :     bool GetDefineMode() const
     488             :     {
     489          11 :         return bDefineMode;
     490             :     }
     491             : 
     492             :     bool SetDefineMode(bool bNewDefineMode);
     493             : 
     494             :     CPLErr ReadAttributes(int, int);
     495             : 
     496             :     void CreateSubDatasetList(int nGroupId);
     497             : 
     498             :     void SetProjectionFromVar(int nGroupId, int nVarId, bool bReadSRSOnly,
     499             :                               const char *pszGivenGM, std::string *,
     500             :                               nccfdriver::SGeometry_Reader *,
     501             :                               std::vector<std::string> *paosRemovedMDItems);
     502             :     void SetProjectionFromVar(int nGroupId, int nVarId, bool bReadSRSOnly);
     503             : 
     504             :     bool ProcessNASAL2OceanGeoLocation(int nGroupId, int nVarId);
     505             : 
     506             :     bool ProcessNASAEMITGeoLocation(int nGroupId, int nVarId);
     507             : 
     508             :     int ProcessCFGeolocation(int nGroupId, int nVarId,
     509             :                              const std::string &osGeolocWKT,
     510             :                              std::string &osGeolocXNameOut,
     511             :                              std::string &osGeolocYNameOut);
     512             :     CPLErr Set1DGeolocation(int nGroupId, int nVarId, const char *szDimName);
     513             :     double *Get1DGeolocation(const char *szDimName, int &nVarLen);
     514             : 
     515             :     static bool CloneAttributes(int old_cdfid, int new_cdfid, int nSrcVarId,
     516             :                                 int nDstVarId);
     517             :     static bool CloneVariableContent(int old_cdfid, int new_cdfid,
     518             :                                      int nSrcVarId, int nDstVarId);
     519             :     static bool CloneGrp(int nOldGrpId, int nNewGrpId, bool bIsNC4,
     520             :                          int nLayerId, int nDimIdToGrow, size_t nNewSize);
     521             :     bool GrowDim(int nLayerId, int nDimIdToGrow, size_t nNewSize);
     522             : 
     523             :     void ProcessSentinel3_SRAL_MWR();
     524             : 
     525             :     CPLErr
     526             :     FilterVars(int nCdfId, bool bKeepRasters, bool bKeepVectors,
     527             :                const CPLStringList &aosIgnoreVars, int *pnRasterVars,
     528             :                int *pnGroupId, int *pnVarId, int *pnIgnoredVars,
     529             :                // key is (dim1Id, dim2Id, nc_type varType)
     530             :                // value is (groupId, varId)
     531             :                std::map<std::array<int, 3>, std::vector<std::pair<int, int>>>
     532             :                    &oMap2DDimsToGroupAndVar);
     533             :     CPLErr CreateGrpVectorLayers(int nCdfId, const CPLString &osFeatureType,
     534             :                                  const std::vector<int> &anPotentialVectorVarID,
     535             :                                  const std::map<int, int> &oMapDimIdToCount,
     536             :                                  int nVarXId, int nVarYId, int nVarZId,
     537             :                                  int nProfileDimId, int nParentIndexVarID,
     538             :                                  bool bKeepRasters);
     539             : 
     540             :     bool DetectAndFillSGLayers(int ncid);
     541             :     CPLErr LoadSGVarIntoLayer(int ncid, int nc_basevarId);
     542             : 
     543             :     static GDALDataset *OpenMultiDim(GDALOpenInfo *);
     544             :     std::shared_ptr<GDALGroup> m_poRootGroup{};
     545             : 
     546             :     void SetGeoTransformNoUpdate(const GDALGeoTransform &gt);
     547             :     void SetSpatialRefNoUpdate(const OGRSpatialReference *);
     548             : 
     549             :   protected:
     550             :     OGRLayer *ICreateLayer(const char *pszName,
     551             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     552             :                            CSLConstList papszOptions) override;
     553             : 
     554             :     CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override;
     555             : 
     556             :   public:
     557             :     netCDFDataset();
     558             :     ~netCDFDataset() override;
     559             :     bool SGCommitPendingTransaction();
     560             :     void SGLogPendingTransaction();
     561             :     static std::string generateLogName();
     562             : 
     563             :     /* Projection/GT */
     564             :     CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
     565             :     CPLErr SetGeoTransform(const GDALGeoTransform &gt) override;
     566             :     const OGRSpatialReference *GetSpatialRef() const override;
     567             :     CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
     568             : 
     569             :     char **GetMetadataDomainList() override;
     570             :     CSLConstList GetMetadata(const char *) override;
     571             : 
     572             :     CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
     573             :                            const char *pszDomain = "") override;
     574             :     CPLErr SetMetadata(CSLConstList papszMD,
     575             :                        const char *pszDomain = "") override;
     576             : 
     577             :     int TestCapability(const char *pszCap) const override;
     578             : 
     579        2853 :     int GetLayerCount() const override
     580             :     {
     581        2853 :         return static_cast<int>(this->papoLayers.size());
     582             :     }
     583             : 
     584             :     const OGRLayer *GetLayer(int nIdx) const override;
     585             : 
     586             :     std::shared_ptr<GDALGroup> GetRootGroup() const override;
     587             : 
     588         194 :     int GetCDFID() const
     589             :     {
     590         194 :         return cdfid;
     591             :     }
     592             : 
     593        1993 :     inline bool HasInfiniteRecordDim()
     594             :     {
     595        1993 :         return !bSGSupport;
     596             :     }
     597             : 
     598             :     /* static functions */
     599             :     static GDALDataset *Open(GDALOpenInfo *);
     600             : 
     601             :     static netCDFDataset *CreateLL(const char *pszFilename, int nXSize,
     602             :                                    int nYSize, int nBands,
     603             :                                    CSLConstList papszOptions);
     604             :     static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
     605             :                                int nBands, GDALDataType eType,
     606             :                                CSLConstList papszOptions);
     607             :     static GDALDataset *CreateCopy(const char *pszFilename,
     608             :                                    GDALDataset *poSrcDS, int bStrict,
     609             :                                    CSLConstList papszOptions,
     610             :                                    GDALProgressFunc pfnProgress,
     611             :                                    void *pProgressData);
     612             : 
     613             :     static GDALDataset *
     614             :     CreateMultiDimensional(const char *pszFilename,
     615             :                            CSLConstList papszRootGroupOptions,
     616             :                            CSLConstList papzOptions);
     617             : };
     618             : 
     619             : class netCDFLayer final : public OGRLayer
     620             : {
     621             :     typedef union
     622             :     {
     623             :         signed char chVal;
     624             :         unsigned char uchVal;
     625             :         short sVal;
     626             :         unsigned short usVal;
     627             :         int nVal;
     628             :         unsigned int unVal;
     629             :         GIntBig nVal64;
     630             :         GUIntBig unVal64;
     631             :         float fVal;
     632             :         double dfVal;
     633             :     } NCDFNoDataUnion;
     634             : 
     635             :     typedef struct
     636             :     {
     637             :         NCDFNoDataUnion uNoData;
     638             :         nc_type nType;
     639             :         int nVarId;
     640             :         int nDimCount;
     641             :         bool bHasWarnedAboutTruncation;
     642             :         int nMainDimId;
     643             :         int nSecDimId;
     644             :         bool bIsDays;
     645             :     } FieldDesc;
     646             : 
     647             :     netCDFDataset *m_poDS;
     648             :     int m_nLayerCDFId;
     649             :     OGRFeatureDefn *m_poFeatureDefn;
     650             :     CPLString m_osRecordDimName;
     651             :     int m_nRecordDimID;
     652             :     int m_nDefaultWidth;
     653             :     bool m_bAutoGrowStrings;
     654             :     int m_nDefaultMaxWidthDimId;
     655             :     int m_nXVarID;
     656             :     int m_nYVarID;
     657             :     int m_nZVarID;
     658             :     nc_type m_nXVarNCDFType;
     659             :     nc_type m_nYVarNCDFType;
     660             :     nc_type m_nZVarNCDFType;
     661             :     NCDFNoDataUnion m_uXVarNoData;
     662             :     NCDFNoDataUnion m_uYVarNoData;
     663             :     NCDFNoDataUnion m_uZVarNoData;
     664             :     CPLString m_osWKTVarName;
     665             :     int m_nWKTMaxWidth;
     666             :     int m_nWKTMaxWidthDimId;
     667             :     int m_nWKTVarID;
     668             :     nc_type m_nWKTNCDFType;
     669             :     CPLString m_osCoordinatesValue;
     670             :     std::vector<FieldDesc> m_aoFieldDesc;
     671             :     bool m_bLegacyCreateMode;
     672             :     int m_nCurFeatureId;
     673             :     CPLString m_osGridMapping;
     674             :     bool m_bWriteGDALTags;
     675             :     bool m_bUseStringInNC4;
     676             :     bool m_bNCDumpCompat;
     677             : 
     678             :     CPLString m_osProfileDimName;
     679             :     int m_nProfileDimID;
     680             :     CPLString m_osProfileVariables;
     681             :     int m_nProfileVarID;
     682             :     bool m_bProfileVarUnlimited;
     683             :     int m_nParentIndexVarID;
     684             :     std::shared_ptr<nccfdriver::SGeometry_Reader> m_simpleGeometryReader;
     685             :     std::unique_ptr<nccfdriver::netCDFVID>
     686             :         layerVID_alloc;  // Allocation wrapper for group specific netCDFVID
     687             :     nccfdriver::netCDFVID &layerVID;  // refers to the "correct" VID
     688             :     std::string m_sgCRSname;
     689             :     size_t m_SGeometryFeatInd;
     690             : 
     691             :     const netCDFWriterConfigLayer *m_poLayerConfig;
     692             : 
     693             :     nccfdriver::ncLayer_SG_Metadata m_layerSGDefn;
     694             : 
     695             :     OGRFeature *GetNextRawFeature();
     696             :     double Get1DVarAsDouble(int nVarId, nc_type nVarType, size_t nIndex,
     697             :                             const NCDFNoDataUnion &noDataVal, bool *pbIsNoData);
     698             :     CPLErr GetFillValue(int nVarID, char **ppszValue);
     699             :     CPLErr GetFillValue(int nVarID, double *pdfValue);
     700             :     void GetNoDataValueForFloat(int nVarId, NCDFNoDataUnion *puNoData);
     701             :     void GetNoDataValueForDouble(int nVarId, NCDFNoDataUnion *puNoData);
     702             :     void GetNoDataValue(int nVarId, nc_type nVarType,
     703             :                         NCDFNoDataUnion *puNoData);
     704             :     bool FillVarFromFeature(OGRFeature *poFeature, int nMainDimId,
     705             :                             size_t nIndex);
     706             :     OGRFeature *buildSGeometryFeature(size_t featureInd);
     707             :     void netCDFWriteAttributesFromConf(
     708             :         int cdfid, int varid,
     709             :         const std::vector<netCDFWriterConfigAttribute> &aoAttributes);
     710             : 
     711             :   protected:
     712             :     bool FillFeatureFromVar(OGRFeature *poFeature, int nMainDimId,
     713             :                             size_t nIndex);
     714             : 
     715             :   public:
     716             :     netCDFLayer(netCDFDataset *poDS, int nLayerCDFId, const char *pszName,
     717             :                 OGRwkbGeometryType eGeomType, OGRSpatialReference *poSRS);
     718             :     ~netCDFLayer() override;
     719             : 
     720             :     bool Create(CSLConstList papszOptions,
     721             :                 const netCDFWriterConfigLayer *poLayerConfig);
     722             :     void SetRecordDimID(int nRecordDimID);
     723             :     void SetXYZVars(int nXVarId, int nYVarId, int nZVarId);
     724             :     void SetWKTGeometryField(const char *pszWKTVarName);
     725             :     void SetGridMapping(const char *pszGridMapping);
     726             :     void SetProfile(int nProfileDimID, int nParentIndexVarID);
     727             : 
     728          64 :     void EnableSGBypass()
     729             :     {
     730          64 :         this->m_bLegacyCreateMode = false;
     731          64 :     }
     732             : 
     733             :     bool AddField(int nVarId);
     734             : 
     735           3 :     int GetCDFID() const
     736             :     {
     737           3 :         return m_nLayerCDFId;
     738             :     }
     739             : 
     740          14 :     void SetCDFID(int nId)
     741             :     {
     742          14 :         m_nLayerCDFId = nId;
     743          14 :     }
     744             : 
     745          64 :     void SetSGeometryRepresentation(
     746             :         const std::shared_ptr<nccfdriver::SGeometry_Reader> &sg)
     747             :     {
     748          64 :         m_simpleGeometryReader = sg;
     749          64 :     }
     750             : 
     751          44 :     nccfdriver::ncLayer_SG_Metadata &getLayerSGMetadata()
     752             :     {
     753          44 :         return m_layerSGDefn;
     754             :     }
     755             : 
     756             :     void ResetReading() override;
     757             :     OGRFeature *GetNextFeature() override;
     758             : 
     759             :     GIntBig GetFeatureCount(int bForce) override;
     760             : 
     761             :     int TestCapability(const char *pszCap) const override;
     762             : 
     763             :     using OGRLayer::GetLayerDefn;
     764             :     const OGRFeatureDefn *GetLayerDefn() const override;
     765             : 
     766             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     767             :     virtual OGRErr CreateField(const OGRFieldDefn *poFieldDefn,
     768             :                                int bApproxOK) override;
     769             : 
     770             :     GDALDataset *GetDataset() override;
     771             : };
     772             : 
     773             : std::string NCDFGetProjectedCFUnit(const OGRSpatialReference *poSRS);
     774             : void NCDFWriteLonLatVarsAttributes(nccfdriver::netCDFVID &vcdf, int nVarLonID,
     775             :                                    int nVarLatID);
     776             : void NCDFWriteRLonRLatVarsAttributes(nccfdriver::netCDFVID &vcdf,
     777             :                                      int nVarRLonID, int nVarRLatID);
     778             : void NCDFWriteXYVarsAttributes(nccfdriver::netCDFVID &vcdf, int nVarXID,
     779             :                                int nVarYID, const OGRSpatialReference *poSRS);
     780             : int NCDFWriteSRSVariable(int cdfid, const OGRSpatialReference *poSRS,
     781             :                          char **ppszCFProjection, bool bWriteGDALTags,
     782             :                          const std::string & = std::string());
     783             : 
     784             : double NCDFGetDefaultNoDataValue(int nCdfId, int nVarId, int nVarType,
     785             :                                  bool &bGotNoData);
     786             : 
     787             : int64_t NCDFGetDefaultNoDataValueAsInt64(int nCdfId, int nVarId,
     788             :                                          bool &bGotNoData);
     789             : uint64_t NCDFGetDefaultNoDataValueAsUInt64(int nCdfId, int nVarId,
     790             :                                            bool &bGotNoData);
     791             : 
     792             : CPLErr NCDFGetAttr(int nCdfId, int nVarId, const char *pszAttrName,
     793             :                    double *pdfValue);
     794             : CPLErr NCDFGetAttr(int nCdfId, int nVarId, const char *pszAttrName,
     795             :                    char **pszValue);
     796             : CPLErr NCDFGetAttr(int nCdfId, int nVarId, const char *pszAttrName,
     797             :                    std::string &osValue);
     798             : bool NCDFIsUnlimitedDim(bool bIsNC4, int cdfid, int nDimId);
     799             : bool NCDFIsUserDefinedType(int ncid, int type);
     800             : 
     801             : CPLString NCDFGetGroupFullName(int nGroupId);
     802             : 
     803             : CPLErr NCDFResolveVar(int nStartGroupId, const char *pszVar, int *pnGroupId,
     804             :                       int *pnVarId, bool bMandatory = false);
     805             : 
     806             : // Dimension check functions.
     807             : bool NCDFIsVarLongitude(int nCdfId, int nVarId, const char *pszVarName);
     808             : bool NCDFIsVarLatitude(int nCdfId, int nVarId, const char *pszVarName);
     809             : bool NCDFIsVarProjectionX(int nCdfId, int nVarId, const char *pszVarName);
     810             : bool NCDFIsVarProjectionY(int nCdfId, int nVarId, const char *pszVarName);
     811             : bool NCDFIsVarVerticalCoord(int nCdfId, int nVarId, const char *pszVarName);
     812             : bool NCDFIsVarTimeCoord(int nCdfId, int nVarId, const char *pszVarName);
     813             : 
     814             : std::string NCDFReadMetadataAsJson(int cdfid);
     815             : 
     816             : char **NCDFTokenizeCoordinatesAttribute(const char *pszCoordinates);
     817             : 
     818             : extern CPLMutex *hNCMutex;
     819             : 
     820             : #ifdef ENABLE_NCDUMP
     821             : bool netCDFDatasetCreateTempFile(NetCDFFormatEnum eFormat,
     822             :                                  const char *pszTmpFilename, VSILFILE *fpSrc);
     823             : #endif
     824             : 
     825             : int GDAL_nc_open(const char *pszFilename, int nMode, int *pID);
     826             : int GDAL_nc_close(int cdfid);
     827             : 
     828             : #endif

Generated by: LCOV version 1.14