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: 2024-11-21 22:18:42 Functions: 14 14 100.0 %

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

Generated by: LCOV version 1.14