LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfsg.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 50 73 68.5 %
Date: 2024-11-21 22:18:42 Functions: 20 29 69.0 %

          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             :     virtual const char *get_err_msg() = 0;
     248             :     virtual ~SG_Exception();
     249             : };
     250             : 
     251             : // Mismatched dimension exception
     252             : class SG_Exception_Dim_MM : public SG_Exception
     253             : {
     254             :     std::string err_msg;
     255             : 
     256             :   public:
     257           1 :     const char *get_err_msg() override
     258             :     {
     259           1 :         return err_msg.c_str();
     260             :     }
     261             : 
     262             :     SG_Exception_Dim_MM(const char *geometry_container, const char *field_1,
     263             :                         const char *field_2);
     264             : };
     265             : 
     266             : // Missing (existential) property error
     267             : class SG_Exception_Existential : public SG_Exception
     268             : {
     269             :     std::string err_msg;
     270             : 
     271             :   public:
     272           2 :     const char *get_err_msg() override
     273             :     {
     274           2 :         return err_msg.c_str();
     275             :     }
     276             : 
     277             :     SG_Exception_Existential(const char *geometry_container,
     278             :                              const char *missing_name);
     279             : };
     280             : 
     281             : // Missing dependent property (arg_1 is dependent on arg_2)
     282             : class SG_Exception_Dep : public SG_Exception
     283             : {
     284             :     std::string err_msg;
     285             : 
     286             :   public:
     287           0 :     const char *get_err_msg() override
     288             :     {
     289           0 :         return err_msg.c_str();
     290             :     }
     291             : 
     292             :     SG_Exception_Dep(const char *geometry_container, const char *arg_1,
     293             :                      const char *arg_2);
     294             : };
     295             : 
     296             : // The sum of all values in a variable does not match the sum of another
     297             : // variable
     298             : class SG_Exception_BadSum : public SG_Exception
     299             : {
     300             :     std::string err_msg;
     301             : 
     302             :   public:
     303           0 :     const char *get_err_msg() override
     304             :     {
     305           0 :         return err_msg.c_str();
     306             :     }
     307             : 
     308             :     SG_Exception_BadSum(const char *geometry_container, const char *arg_1,
     309             :                         const char *arg_2);
     310             : };
     311             : 
     312             : // Unsupported Feature Type
     313             : class SG_Exception_BadFeature : public SG_Exception
     314             : {
     315             :     std::string err_msg;
     316             : 
     317             :   public:
     318           1 :     const char *get_err_msg() override
     319             :     {
     320           1 :         return err_msg.c_str();
     321             :     }
     322             : 
     323           1 :     SG_Exception_BadFeature()
     324           1 :         : err_msg("Unsupported or unrecognized feature type.")
     325             :     {
     326           1 :     }
     327             : };
     328             : 
     329             : // Failed Read
     330             : class SG_Exception_BadPoint : public SG_Exception
     331             : {
     332             :     std::string err_msg;
     333             : 
     334             :   public:
     335           0 :     const char *get_err_msg() override
     336             :     {
     337           0 :         return err_msg.c_str();
     338             :     }
     339             : 
     340           0 :     SG_Exception_BadPoint()
     341           0 :         : err_msg("An attempt was made to read an invalid point (likely index "
     342           0 :                   "out of bounds).")
     343             :     {
     344           0 :     }
     345             : };
     346             : 
     347             : // Too many dimensions on node coordinates variable
     348             : class SG_Exception_Not1D : public SG_Exception
     349             : {
     350             :     std::string err_msg;
     351             : 
     352             :   public:
     353           0 :     const char *get_err_msg() override
     354             :     {
     355           0 :         return err_msg.c_str();
     356             :     }
     357             : 
     358           0 :     SG_Exception_Not1D()
     359           0 :         : err_msg("A node coordinates axis variable or node_counts is not one "
     360           0 :                   "dimensional.")
     361             :     {
     362           0 :     }
     363             : };
     364             : 
     365             : // Too many empty dimension
     366             : class SG_Exception_EmptyDim : public SG_Exception
     367             : {
     368             :     std::string err_msg;
     369             : 
     370             :   public:
     371           0 :     const char *get_err_msg() override
     372             :     {
     373           0 :         return err_msg.c_str();
     374             :     }
     375             : 
     376           0 :     SG_Exception_EmptyDim()
     377           0 :         : err_msg("A dimension has length <= 0, but it must have length > 0")
     378             :     {
     379           0 :     }
     380             : };
     381             : 
     382             : // general corruption or malformed error
     383             : class SG_Exception_General_Malformed : public SG_Exception
     384             : {
     385             :     std::string err_msg;
     386             : 
     387             :   public:
     388           0 :     const char *get_err_msg() override
     389             :     {
     390           0 :         return err_msg.c_str();
     391             :     }
     392             : 
     393             :     explicit SG_Exception_General_Malformed(const char *);
     394             : };
     395             : 
     396             : // Invalid value detected
     397             : class SG_Exception_Value_Violation : public SG_Exception
     398             : {
     399             :     std::string err_msg;
     400             : 
     401             :   public:
     402           2 :     const char *get_err_msg() override
     403             :     {
     404           2 :         return err_msg.c_str();
     405             :     }
     406             : 
     407           2 :     SG_Exception_Value_Violation(const char *containername, const char *type,
     408             :                                  const char *badvalue)
     409           4 :         : err_msg(std::string("[") + std::string(containername) +
     410           8 :                   std::string("] ") + std::string(type) +
     411           6 :                   std::string(" values may not be ") + std::string(badvalue))
     412             :     {
     413           2 :     }
     414             : };
     415             : 
     416             : // Required value(s)
     417             : class SG_Exception_Value_Required : public SG_Exception
     418             : {
     419             :     std::string err_msg;
     420             : 
     421             :   public:
     422           1 :     const char *get_err_msg() override
     423             :     {
     424           1 :         return err_msg.c_str();
     425             :     }
     426             : 
     427           1 :     SG_Exception_Value_Required(const char *containername, const char *type,
     428             :                                 const char *expvalue)
     429           2 :         : err_msg(std::string("[") + std::string(containername) +
     430           4 :                   std::string("] ") + std::string(type) +
     431           3 :                   std::string(" values must be ") + std::string(expvalue))
     432             :     {
     433           1 :     }
     434             : };
     435             : 
     436             : // Some helpers which simply call some netcdf library functions, unless
     437             : // otherwise mentioned, ncid, refers to its use in netcdf.h
     438             : 
     439             : /* Retrieves the version from the value Conventions global attr
     440             :  * Returns: a double precision decimal corresponding to the conventions value
     441             :  *    if not CF-x.y then return negative value, -1
     442             :  */
     443             : double getCFVersion(int ncid);
     444             : 
     445             : /* Given a geometry_container varID, searches that variable for a geometry_type
     446             :  * attribute Returns: the equivalent geometry type
     447             :  */
     448             : geom_t getGeometryType(int ncid, int varid);
     449             : 
     450             : void inPlaceSerialize_Point(SGeometry_Reader *ge, size_t seek_pos,
     451             :                             std::vector<unsigned char> &buffer);
     452             : void inPlaceSerialize_LineString(SGeometry_Reader *ge, int node_count,
     453             :                                  size_t seek_begin,
     454             :                                  std::vector<unsigned char> &buffer);
     455             : void inPlaceSerialize_PolygonExtOnly(SGeometry_Reader *ge, int node_count,
     456             :                                      size_t seek_begin,
     457             :                                      std::vector<unsigned char> &buffer);
     458             : void inPlaceSerialize_Polygon(SGeometry_Reader *ge, std::vector<int> &pnc,
     459             :                               int ring_count, size_t seek_begin,
     460             :                               std::vector<unsigned char> &buffer);
     461             : 
     462             : /* scanForGeometryContainers
     463             :  * A simple function that scans a netCDF File for Geometry Containers
     464             :  * -
     465             :  * Scans the given ncid for geometry containers
     466             :  * The vector passed in will be overwritten with a vector of scan results
     467             :  */
     468             : int scanForGeometryContainers(int ncid, std::set<int> &r_ids);
     469             : 
     470             : /* Attribute Fetch
     471             :  * -
     472             :  * A function which makes it a bit easier to fetch single text attribute values
     473             :  * ncid: as used in netcdf.h
     474             :  * varID: variable id in which to look for the attribute
     475             :  * attrName: name of attribute to fine
     476             :  * alloc: a reference to a string that will be filled with the attribute (i.e.
     477             :  * truncated and filled with the return value) Returns: a reference to the
     478             :  * string to fill (a.k.a. string pointed to by alloc reference)
     479             :  */
     480             : std::string &attrf(int ncid, int varId, const char *attrName,
     481             :                    std::string &alloc);
     482             : }  // namespace nccfdriver
     483             : 
     484             : #endif

Generated by: LCOV version 1.14