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

Generated by: LCOV version 1.14