LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfsg.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 46 58 79.3 %
Date: 2025-06-19 12:30:01 Functions: 18 21 85.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  netCDF read/write Driver
       4             :  * Purpose:  GDAL bindings over netCDF library.
       5             :  * Author:   Winor Chen <wchen329 at wisc.edu>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2019, Winor Chen <wchen329 at wisc.edu>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : #ifndef __NETCDFSG_H__
      13             : #define __NETCDFSG_H__
      14             : #include <cstring>
      15             : #include <memory>
      16             : #include <set>
      17             : #include <string>
      18             : #include <vector>
      19             : #include "netcdf.h"
      20             : 
      21             : // Interface used for netCDF functions
      22             : // implementing awareness for the CF-1.8 convention
      23             : //
      24             : // Author: wchen329
      25             : namespace nccfdriver
      26             : {
      27             : // Constants
      28             : const int INVALID_VAR_ID = -2;
      29             : const int INVALID_DIM_ID = INVALID_VAR_ID;
      30             : 
      31             : // Enum used for easily identifying Geometry types
      32             : enum geom_t
      33             : {
      34             :     NONE,          // no geometry found
      35             :     POLYGON,       // OGRPolygon
      36             :     MULTIPOLYGON,  // OGRMultipolygon
      37             :     LINE,          // OGRLineString
      38             :     MULTILINE,     // OGRMultiLineString
      39             :     POINT,         // OGRPoint
      40             :     MULTIPOINT,    // OGRMultiPoint
      41             :     UNSUPPORTED    // Unsupported feature type
      42             : };
      43             : 
      44             : // Concrete "Point" class, holds n dimensional double precision floating point
      45             : // value, defaults to all zero values
      46             : class Point
      47             : {
      48             :     int size;
      49             :     std::unique_ptr<double, std::default_delete<double[]>> values;
      50             :     Point(Point &);
      51             :     Point operator=(const Point &);
      52             : 
      53             :   public:
      54          67 :     explicit Point(int dim)
      55          67 :         : size(dim),
      56             :           values(std::unique_ptr<double, std::default_delete<double[]>>(
      57          67 :               new double[dim]))
      58             :     {
      59          67 :     }
      60             : 
      61      269842 :     double &operator[](size_t i)
      62             :     {
      63      269842 :         return this->values.get()[i];
      64             :     }
      65             : 
      66             :     int getOrder()
      67             :     {
      68             :         return this->size;
      69             :     }
      70             : };
      71             : 
      72             : // Simple geometry - doesn't actually hold the points, rather serves
      73             : // as a pseudo reference to a NC variable
      74             : class SGeometry_Reader
      75             : {
      76             :     std::string container_name_s;  // name of the underlying geometry container
      77             :     geom_t type;                   // internal geometry type structure
      78             :     int ncid;                      // ncid - as used in netcdf.h
      79             :     int gc_varId;  // the id of the underlying geometry_container variable
      80             :     std::string gm_name_s;  // grid mapping variable name
      81             :     int gm_varId;           // id used for grid mapping
      82             :     int inst_dimId;         // dimension id for geometry instance dimension
      83             :     size_t inst_dimLen;     // value of instance dimension
      84             :     int touple_order;       // amount of "coordinates" in a point
      85             :     std::vector<int> nodec_varIds;  // varIds for each node_coordinate entry
      86             :     std::vector<int>
      87             :         node_counts;  // node counts of each geometry in a container
      88             :     std::vector<int>
      89             :         pnode_counts;  // part node counts of each geometry in a container
      90             :     std::vector<bool> int_rings;     // list of parts that are interior rings
      91             :     std::vector<size_t> bound_list;  // a quick list used to store the real
      92             :                                      // beginning indices of shapes
      93             :     std::vector<size_t> pnc_bl;      // a quick list of indices for part counts
      94             :                                      // corresponding to a geometry
      95             :     std::vector<int>
      96             :         parts_count;  // a count of total parts in a single geometry instance
      97             :     std::vector<int> poly_count;       // count of polygons, for use only when
      98             :                                        // interior rings are present
      99             :     std::unique_ptr<Point> pt_buffer;  // holds the current point
     100             :     SGeometry_Reader(SGeometry_Reader &);
     101             :     SGeometry_Reader operator=(const SGeometry_Reader &);
     102             : 
     103             :   public:
     104             :     /* int SGeometry_Reader::get_ncID()
     105             :      * return the group/file ID that the SGeometry object is operating over
     106             :      */
     107          86 :     int get_ncID()
     108             :     {
     109          86 :         return ncid;
     110             :     }
     111             : 
     112             :     /* int SGeometry_Reader::get_axisCount()
     113             :      * Returns the count of axis (i.e. X, Y, Z)
     114             :      */
     115       68284 :     int get_axisCount()
     116             :     {
     117       68284 :         return this->touple_order;
     118             :     }
     119             : 
     120             :     /* int SGeometry_Reader::getInstDim()
     121             :      * Returns the geometry instance dimension ID of this geometry
     122             :      */
     123         492 :     int getInstDim()
     124             :     {
     125         492 :         return this->inst_dimId;
     126             :     }
     127             : 
     128             :     /* size_t SGeometry_Reader::getInstDimLen()
     129             :      * Returns the length of the instance dimension
     130             :      */
     131             :     size_t getInstDimLen()
     132             :     {
     133             :         return this->inst_dimLen;
     134             :     }
     135             : 
     136             :     /* std::string& getGridMappingName()
     137             :      * returns the variable name which holds grid mapping data
     138             :      */
     139          43 :     std::string &getGridMappingName()
     140             :     {
     141          43 :         return this->gm_name_s;
     142             :     }
     143             : 
     144             :     /* int SGeometry_Reader::getGridMappingVarID();
     145             :      * returns the varID of the associated grid mapping variable ID
     146             :      */
     147          67 :     int getGridMappingVarID()
     148             :     {
     149          67 :         return this->gm_varId;
     150             :     }
     151             : 
     152             :     /* geom_t getGeometryType()
     153             :      * Retrieves the associated geometry type with this geometry
     154             :      */
     155        1543 :     geom_t getGeometryType()
     156             :     {
     157        1543 :         return this->type;
     158             :     }
     159             : 
     160             :     /* void SGeometry_Reader::get_geometry_count()
     161             :      * returns a size, indicating the amount of geometries
     162             :      * contained in the variable
     163             :      */
     164             :     size_t get_geometry_count();
     165             : 
     166             :     /* const char* SGeometry_Reader::getContainerName()
     167             :      * Returns the container name as a string
     168             :      */
     169             :     std::string &getContainerName()
     170             :     {
     171             :         return container_name_s;
     172             :     }
     173             : 
     174             :     /* int SGeometry_Reader::getContainerId()
     175             :      * Get the ncID of the geometry_container variable
     176             :      */
     177          67 :     int getContainerId()
     178             :     {
     179          67 :         return gc_varId;
     180             :     }
     181             : 
     182             :     /* std::vector<unsigned char> serializeToWKB
     183             :      * Returns a pre-allocated array which serves as the WKB reference to this
     184             :      * geometry
     185             :      */
     186             :     std::vector<unsigned char> serializeToWKB(size_t featureInd);
     187             : 
     188             :     /* Return a point at a specific index specifically
     189             :      * this point should NOT be explicitly freed.
     190             :      *
     191             :      */
     192             :     Point &operator[](size_t ind);
     193             : 
     194             :     /* std::vector<int>& getNodeCoordVars
     195             :      * Returns a vector with the node coord vars in X, Y, Z (if present) order
     196             :      */
     197          86 :     std::vector<int> &getNodeCoordVars()
     198             :     {
     199          86 :         return this->nodec_varIds;
     200             :     }
     201             : 
     202             :     /* ncID - as used in netcdf.h
     203             :      * baseVarId - the id of a variable with a geometry container attribute
     204             :      */
     205             :     SGeometry_Reader(int ncId, int baseVarId);
     206             : };
     207             : 
     208             : /* SGeometry_PropertyScanner
     209             :  * Holds names of properties for geometry containers
     210             :  * Pass in the geometry_container ID, automatically scans the netcdf Dataset for
     211             :  * properties associated
     212             :  *
     213             :  * to construct: pass in the ncid which the reader should work over
     214             :  */
     215             : class SGeometry_PropertyScanner
     216             : {
     217             :     std::vector<int> v_ids;
     218             :     std::vector<std::string> v_headers;
     219             :     int nc;
     220             : 
     221             :     void open(int container_id);  // opens and initializes a geometry_container
     222             :                                   // into the scanner
     223             : 
     224             :   public:
     225             :     std::vector<std::string> &headers()
     226             :     {
     227             :         return this->v_headers;
     228             :     }
     229             : 
     230          66 :     std::vector<int> &ids()
     231             :     {
     232          66 :         return this->v_ids;
     233             :     }
     234             : 
     235          67 :     SGeometry_PropertyScanner(int ncid, int cid) : nc(ncid)
     236             :     {
     237          67 :         this->open(cid);
     238          67 :     }
     239             : };
     240             : 
     241             : // General exception interface for Simple Geometries
     242             : // Whatever pointer returned should NOT be freed- it will be deconstructed
     243             : // automatically, if needed
     244             : class SG_Exception
     245             : {
     246             :   public:
     247             :     ~SG_Exception();
     248             : 
     249           7 :     const char *get_err_msg() const
     250             :     {
     251           7 :         return err_msg.c_str();
     252             :     }
     253             : 
     254             :   protected:
     255           3 :     SG_Exception() = default;
     256             : 
     257           4 :     explicit SG_Exception(const std::string &s) : err_msg(s)
     258             :     {
     259           4 :     }
     260             : 
     261             :     std::string err_msg;
     262             : };
     263             : 
     264             : // Mismatched dimension exception
     265             : class SG_Exception_Dim_MM : public SG_Exception
     266             : {
     267             :   public:
     268             :     SG_Exception_Dim_MM(const char *geometry_container, const char *field_1,
     269             :                         const char *field_2);
     270             : };
     271             : 
     272             : // Missing (existential) property error
     273             : class SG_Exception_Existential : public SG_Exception
     274             : {
     275             :   public:
     276             :     SG_Exception_Existential(const char *geometry_container,
     277             :                              const char *missing_name);
     278             : };
     279             : 
     280             : // Missing dependent property (arg_1 is dependent on arg_2)
     281             : class SG_Exception_Dep : public SG_Exception
     282             : {
     283             :   public:
     284             :     SG_Exception_Dep(const char *geometry_container, const char *arg_1,
     285             :                      const char *arg_2);
     286             : };
     287             : 
     288             : // The sum of all values in a variable does not match the sum of another
     289             : // variable
     290             : class SG_Exception_BadSum : public SG_Exception
     291             : {
     292             :   public:
     293             :     SG_Exception_BadSum(const char *geometry_container, const char *arg_1,
     294             :                         const char *arg_2);
     295             : };
     296             : 
     297             : // Unsupported Feature Type
     298             : class SG_Exception_BadFeature : public SG_Exception
     299             : {
     300             :   public:
     301           1 :     SG_Exception_BadFeature()
     302           1 :         : SG_Exception("Unsupported or unrecognized feature type.")
     303             :     {
     304           1 :     }
     305             : };
     306             : 
     307             : // Failed Read
     308             : class SG_Exception_BadPoint : public SG_Exception
     309             : {
     310             :   public:
     311           0 :     SG_Exception_BadPoint()
     312           0 :         : SG_Exception(
     313             :               "An attempt was made to read an invalid point (likely index "
     314           0 :               "out of bounds).")
     315             :     {
     316           0 :     }
     317             : };
     318             : 
     319             : // Too many dimensions on node coordinates variable
     320             : class SG_Exception_Not1D : public SG_Exception
     321             : {
     322             :   public:
     323           0 :     SG_Exception_Not1D()
     324           0 :         : SG_Exception(
     325             :               "A node coordinates axis variable or node_counts is not one "
     326           0 :               "dimensional.")
     327             :     {
     328           0 :     }
     329             : };
     330             : 
     331             : // Too many empty dimension
     332             : class SG_Exception_EmptyDim : public SG_Exception
     333             : {
     334             :   public:
     335           0 :     SG_Exception_EmptyDim()
     336           0 :         : SG_Exception(
     337           0 :               "A dimension has length <= 0, but it must have length > 0")
     338             :     {
     339           0 :     }
     340             : };
     341             : 
     342             : // general corruption or malformed error
     343             : class SG_Exception_General_Malformed : public SG_Exception
     344             : {
     345             :   public:
     346             :     explicit SG_Exception_General_Malformed(const char *);
     347             : };
     348             : 
     349             : // Invalid value detected
     350             : class SG_Exception_Value_Violation : public SG_Exception
     351             : {
     352             :   public:
     353           2 :     SG_Exception_Value_Violation(const char *containername, const char *type,
     354             :                                  const char *badvalue)
     355           4 :         : SG_Exception(std::string("[") + std::string(containername) +
     356           8 :                        std::string("] ") + std::string(type) +
     357           8 :                        std::string(" values may not be ") +
     358           6 :                        std::string(badvalue))
     359             :     {
     360           2 :     }
     361             : };
     362             : 
     363             : // Required value(s)
     364             : class SG_Exception_Value_Required : public SG_Exception
     365             : {
     366             :   public:
     367           1 :     SG_Exception_Value_Required(const char *containername, const char *type,
     368             :                                 const char *expvalue)
     369           2 :         : SG_Exception(std::string("[") + std::string(containername) +
     370           4 :                        std::string("] ") + std::string(type) +
     371           3 :                        std::string(" values must be ") + std::string(expvalue))
     372             :     {
     373           1 :     }
     374             : };
     375             : 
     376             : // Some helpers which simply call some netcdf library functions, unless
     377             : // otherwise mentioned, ncid, refers to its use in netcdf.h
     378             : 
     379             : /* Retrieves the version from the value Conventions global attr
     380             :  * Returns: a double precision decimal corresponding to the conventions value
     381             :  *    if not CF-x.y then return negative value, -1
     382             :  */
     383             : double getCFVersion(int ncid);
     384             : 
     385             : /* Given a geometry_container varID, searches that variable for a geometry_type
     386             :  * attribute Returns: the equivalent geometry type
     387             :  */
     388             : geom_t getGeometryType(int ncid, int varid);
     389             : 
     390             : void inPlaceSerialize_Point(SGeometry_Reader *ge, size_t seek_pos,
     391             :                             std::vector<unsigned char> &buffer);
     392             : void inPlaceSerialize_LineString(SGeometry_Reader *ge, int node_count,
     393             :                                  size_t seek_begin,
     394             :                                  std::vector<unsigned char> &buffer);
     395             : void inPlaceSerialize_PolygonExtOnly(SGeometry_Reader *ge, int node_count,
     396             :                                      size_t seek_begin,
     397             :                                      std::vector<unsigned char> &buffer);
     398             : void inPlaceSerialize_Polygon(SGeometry_Reader *ge, std::vector<int> &pnc,
     399             :                               int ring_count, size_t seek_begin,
     400             :                               std::vector<unsigned char> &buffer);
     401             : 
     402             : /* scanForGeometryContainers
     403             :  * A simple function that scans a netCDF File for Geometry Containers
     404             :  * -
     405             :  * Scans the given ncid for geometry containers
     406             :  * The vector passed in will be overwritten with a vector of scan results
     407             :  */
     408             : int scanForGeometryContainers(int ncid, std::set<int> &r_ids);
     409             : 
     410             : /* Attribute Fetch
     411             :  * -
     412             :  * A function which makes it a bit easier to fetch single text attribute values
     413             :  * ncid: as used in netcdf.h
     414             :  * varID: variable id in which to look for the attribute
     415             :  * attrName: name of attribute to fine
     416             :  * alloc: a reference to a string that will be filled with the attribute (i.e.
     417             :  * truncated and filled with the return value) Returns: a reference to the
     418             :  * string to fill (a.k.a. string pointed to by alloc reference)
     419             :  */
     420             : std::string &attrf(int ncid, int varId, const char *attrName,
     421             :                    std::string &alloc);
     422             : }  // namespace nccfdriver
     423             : 
     424             : #endif

Generated by: LCOV version 1.14