LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfvirtual.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 109 157 69.4 %
Date: 2026-10-23 13:59:38 Functions: 19 24 79.2 %

          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             : #include "netcdfdataset.h"
      13             : #include "netcdfvirtual.h"
      14             : 
      15             : // netCDF Virtual
      16             : // Provides a layer of "virtual ncID"
      17             : // that can be mapped to a real netCDF ID
      18             : namespace nccfdriver
      19             : {
      20           3 : void netCDFVDimension::invalidate()
      21             : {
      22           3 :     this->valid = false;
      23           3 :     real_dim_name.clear();
      24           3 : }
      25             : 
      26         253 : netCDFVVariable::netCDFVVariable(const char *name, nc_type xtype, int ndims,
      27         253 :                                  const int *dimidsp)
      28         253 :     : real_var_name(name), ntype(xtype), ndimc(ndims), dimid(new int[ndims])
      29             : {
      30         552 :     for (int c = 0; c < ndims; c++)
      31             :     {
      32         299 :         dimid.get()[c] = dimidsp[c];
      33             :     }
      34         253 : }
      35             : 
      36          20 : void netCDFVVariable::invalidate()
      37             : {
      38          20 :     this->valid = false;
      39          20 :     real_var_name.clear();
      40          20 :     attribs.clear();
      41          20 : }
      42             : 
      43         163 : int netCDFVID::nc_def_vdim(const char *name, size_t len)
      44             : {
      45         163 :     if (directMode)
      46             :     {
      47             :         int ddim;
      48             :         int err;
      49          17 :         if ((err = nc_def_dim(ncid, name, len, &ddim)) != NC_NOERR)
      50             :         {
      51           0 :             NCDF_ERR(err);
      52             :             throw SG_Exception_VWrite_Failure("netCDF file",
      53           0 :                                               "a dimension definition");
      54             :         }
      55             : 
      56          17 :         return ddim;
      57             :     }
      58             : 
      59         146 :     int dimID = dimTicket;
      60             : 
      61             :     // Check if name is already defined
      62         146 :     if (nameDimTable.count(std::string(name)) > 0)
      63             :     {
      64           0 :         throw SG_Exception_DupName(name, "virtual dimension collection");
      65             :     }
      66             : 
      67             :     // Add to lookup tables
      68         146 :     dimList.push_back(netCDFVDimension(name, len, dimTicket));
      69         146 :     dimTicket++;
      70         146 :     nameDimTable.insert(std::pair<std::string, int>(std::string(name), dimID));
      71             : 
      72             :     // Return virtual dimID
      73         146 :     return dimID;
      74             : }
      75             : 
      76         353 : int netCDFVID::nc_def_vvar(const char *name, nc_type xtype, int ndims,
      77             :                            const int *dimidsp)
      78             : {
      79         353 :     if (directMode)
      80             :     {
      81             :         int dvar;
      82             :         int err;
      83         100 :         if ((err = nc_def_var(ncid, name, xtype, ndims, dimidsp, &dvar)) !=
      84             :             NC_NOERR)
      85             :         {
      86           0 :             NCDF_ERR(err);
      87             :             throw SG_Exception_VWrite_Failure("netCDF file",
      88           0 :                                               "a dimension definition");
      89             :         }
      90             : 
      91         100 :         return dvar;
      92             :     }
      93             : 
      94         253 :     int varID = varTicket;
      95             : 
      96             :     // Check if name is already defined
      97         253 :     if (nameVarTable.count(std::string(name)) > 0)
      98             :     {
      99           0 :         throw SG_Exception_DupName(name, "virtual variable collection");
     100             :     }
     101             : 
     102             :     // Add to lookup tables
     103         253 :     varList.push_back(netCDFVVariable(name, xtype, ndims, dimidsp));
     104         253 :     varTicket++;
     105         253 :     nameVarTable.insert(std::pair<std::string, int>(std::string(name), varID));
     106             : 
     107             :     // Return virtual dimID
     108         253 :     return varID;
     109             : }
     110             : 
     111           3 : void netCDFVID::nc_del_vdim(int dimid)
     112             : {
     113             :     // First remove from name map
     114           3 :     nameDimTable.erase(this->dimList[dimid].getName());
     115             : 
     116             :     // Then clear actual dim
     117           3 :     this->dimList[dimid].invalidate();
     118           3 : }
     119             : 
     120          20 : void netCDFVID::nc_del_vvar(int varid)
     121             : {
     122             :     // First remove from name map
     123          20 :     nameVarTable.erase(this->varList[varid].getName());
     124             : 
     125             :     // Then clear actual variable
     126          20 :     this->varList[varid].invalidate();
     127          20 : }
     128             : 
     129         135 : void netCDFVID::nc_resize_vdim(int dimid, size_t dimlen)
     130             : {
     131         135 :     netCDFVDimension &dim = virtualDIDToDim(dimid);
     132             : 
     133         135 :     if (dim.getRealID() == INVALID_DIM_ID)
     134             :     {
     135         135 :         dim.setLen(dimlen);
     136             :     }
     137         135 : }
     138             : 
     139          39 : void netCDFVID::nc_set_define_mode()
     140             : {
     141          39 :     m_poDS->SetDefineMode(true);
     142          39 : }
     143             : 
     144          39 : void netCDFVID::nc_set_data_mode()
     145             : {
     146          39 :     m_poDS->SetDefineMode(false);
     147          39 : }
     148             : 
     149          39 : void netCDFVID::nc_vmap()
     150             : {
     151          39 :     nc_set_define_mode();
     152             : 
     153         185 :     for (netCDFVDimension &dim : dimList)
     154             :     {
     155         146 :         int realDimID = -1;
     156             : 
     157         146 :         if (!dim.isValid())
     158             :         {
     159           3 :             continue;  // don't do anywork if variable is invalid
     160             :         }
     161             : 
     162         143 :         NCDF_ERR(
     163             :             nc_def_dim(ncid, dim.getName().c_str(), dim.getLen(), &realDimID));
     164         143 :         dim.setRealID(realDimID);
     165             :     }
     166             : 
     167         292 :     for (netCDFVVariable &var : varList)
     168             :     {
     169         253 :         int realVarID = -1;
     170             : 
     171         253 :         if (!var.isValid())
     172             :         {
     173          20 :             continue;  // don't do any work if variable is invalid
     174             :         }
     175             : 
     176             :         // Convert each virtual dimID to a physical dimID:
     177             :         std::unique_ptr<int, std::default_delete<int[]>> newdims(
     178         466 :             new int[var.getDimCount()]);
     179         512 :         for (int dimct = 0; dimct < var.getDimCount(); dimct++)
     180             :         {
     181         279 :             newdims.get()[dimct] =
     182         279 :                 virtualDIDToDim(var.getDimIds()[dimct]).getRealID();
     183             :         }
     184             : 
     185         233 :         NCDF_ERR(nc_def_var(ncid, var.getName().c_str(), var.getType(),
     186             :                             var.getDimCount(), newdims.get(), &realVarID));
     187         233 :         var.setRealID(realVarID);
     188             : 
     189             :         // Now write each of its attributes
     190         961 :         for (auto &attr : var.getAttributes())
     191             :         {
     192         728 :             attr->vsync(ncid, realVarID);
     193             :         }
     194             : 
     195         233 :         var.getAttributes().clear();
     196             :     }
     197             : 
     198          39 :     nc_set_data_mode();
     199          39 : }
     200             : 
     201             : /* Enquiry Functions
     202             :  * (For use with enquiry information about virtual entities)
     203             :  */
     204       25064 : netCDFVVariable &netCDFVID::virtualVIDToVar(int virtualID)
     205             : {
     206       25064 :     if (virtualID >= static_cast<int>(varList.size()) || virtualID < 0)
     207             :     {
     208           0 :         throw SG_Exception_NVOOB("virtual variable collection");
     209             :     }
     210             : 
     211       25064 :     return varList[virtualID];
     212             : }
     213             : 
     214        1290 : netCDFVDimension &netCDFVID::virtualDIDToDim(int virtualID)
     215             : {
     216        1290 :     if (virtualID >= static_cast<int>(dimList.size()) || virtualID < 0)
     217             :     {
     218           0 :         throw SG_Exception_NVOOB("virtual dimension collection");
     219             :     }
     220             : 
     221        1290 :     return dimList[virtualID];
     222             : }
     223             : 
     224           0 : int netCDFVID::nameToVirtualVID(const std::string &name) const
     225             : {
     226           0 :     if (nameVarTable.count(name) < 1)
     227             :     {
     228           0 :         throw SG_Exception_BadMapping(name.c_str(), "variable ID lookup");
     229             :     }
     230             : 
     231           0 :     return nameVarTable.at(name);
     232             : }
     233             : 
     234           0 : int netCDFVID::nameToVirtualDID(const std::string &name) const
     235             : {
     236           0 :     if (nameDimTable.count(name) < 1)
     237             :     {
     238           0 :         throw SG_Exception_BadMapping(name.c_str(), "dimension ID lookup");
     239             :     }
     240           0 :     return nameDimTable.at(name);
     241             : }
     242             : 
     243             : /* Attribute writing
     244             :  *
     245             :  */
     246             : 
     247        1556 : void netCDFVID::nc_put_vatt_text(int varid, const char *name, const char *value)
     248             : {
     249        1556 :     if (directMode)
     250             :     {
     251             :         int err;
     252         877 :         if ((err = nc_put_att_text(ncid, varid, name, strlen(value), value)) !=
     253             :             NC_NOERR)
     254             :         {
     255           0 :             NCDF_ERR(err);
     256           0 :             throw SG_Exception_VWrite_Failure("variable", "text attribute");
     257             :         }
     258         877 :         return;
     259             :     }
     260             : 
     261         679 :     nc_put_vatt_generic<netCDFVTextAttribute, char>(varid, name, value);
     262             : }
     263             : 
     264          74 : void netCDFVID::nc_put_vatt_int(int varid, const char *name, const int *value)
     265             : {
     266          74 :     if (directMode)
     267             :     {
     268             :         int err;
     269          25 :         if ((err = nc_put_att_int(ncid, varid, name, NC_INT, 1, value)) !=
     270             :             NC_NOERR)
     271             :         {
     272           0 :             NCDF_ERR(err);
     273           0 :             throw SG_Exception_VWrite_Failure("variable", "int attribute");
     274             :         }
     275          25 :         return;
     276             :     }
     277             : 
     278          49 :     nc_put_vatt_generic<netCDFVIntAttribute, int>(varid, name, value);
     279             : }
     280             : 
     281           1 : void netCDFVID::nc_put_vatt_double(int varid, const char *name,
     282             :                                    const double *value)
     283             : {
     284           1 :     if (directMode)
     285             :     {
     286             :         int err;
     287           1 :         if ((err = nc_put_att_double(ncid, varid, name, NC_DOUBLE, 1, value)) !=
     288             :             NC_NOERR)
     289             :         {
     290           0 :             NCDF_ERR(err);
     291           0 :             throw SG_Exception_VWrite_Failure("variable", "double attribute");
     292             :         }
     293           1 :         return;
     294             :     }
     295             : 
     296           0 :     nc_put_vatt_generic<netCDFVDoubleAttribute, double>(varid, name, value);
     297             : }
     298             : 
     299           0 : void netCDFVID::nc_put_vatt_float(int varid, const char *name,
     300             :                                   const float *value)
     301             : {
     302           0 :     if (directMode)
     303             :     {
     304             :         int err;
     305           0 :         if ((err = nc_put_att_float(ncid, varid, name, NC_FLOAT, 1, value)) !=
     306             :             NC_NOERR)
     307             :         {
     308           0 :             NCDF_ERR(err);
     309           0 :             throw SG_Exception_VWrite_Failure("variable", "float attribute");
     310             :         }
     311           0 :         return;
     312             :     }
     313             : 
     314           0 :     nc_put_vatt_generic<netCDFVFloatAttribute, float>(varid, name, value);
     315             : }
     316             : 
     317           0 : void netCDFVID::nc_put_vatt_byte(int varid, const char *name,
     318             :                                  const signed char *value)
     319             : {
     320           0 :     if (directMode)
     321             :     {
     322             :         int err;
     323           0 :         if ((err = nc_put_att_schar(ncid, varid, name, NC_BYTE, 1, value)) !=
     324             :             NC_NOERR)
     325             :         {
     326           0 :             NCDF_ERR(err);
     327           0 :             throw SG_Exception_VWrite_Failure("variable", "byte attribute");
     328             :         }
     329           0 :         return;
     330             :     }
     331             : 
     332           0 :     nc_put_vatt_generic<netCDFVByteAttribute, signed char>(varid, name, value);
     333             : }
     334             : 
     335         679 : void netCDFVTextAttribute::vsync(int realncid, int realvarid)
     336             : {
     337         679 :     if (nc_put_att_text(realncid, realvarid, name.c_str(), value.size(),
     338         679 :                         value.c_str()) != NC_NOERR)
     339             :     {
     340           0 :         throw SG_Exception_VWrite_Failure("variable", "attribute");
     341             :     }
     342         679 : }
     343             : 
     344             : /* Single Datum Writing
     345             :  * (mostly just convenience functions)
     346             :  */
     347           0 : void netCDFVID::nc_put_vvar1_text(int varid, const size_t *index,
     348             :                                   const char *value)
     349             : {
     350           0 :     int rvarid = !directMode ? virtualVIDToVar(varid).getRealID() : varid;
     351           0 :     if (rvarid == INVALID_VAR_ID)
     352           0 :         return;  // invalidated variable, don't care condition that Scribe
     353             :                  // relies on
     354             : 
     355           0 :     if (nc_put_var1_text(ncid, rvarid, index, value) != NC_NOERR)
     356             :     {
     357           0 :         throw SG_Exception_VWrite_Failure("variable", "datum");
     358             :     }
     359             : }
     360             : 
     361         876 : void netCDFVID::nc_put_vvara_text(int varid, const size_t *start,
     362             :                                   const size_t *count, const char *value)
     363             : {
     364         876 :     int rvarid = !directMode ? virtualVIDToVar(varid).getRealID() : varid;
     365         876 :     if (rvarid == INVALID_VAR_ID)
     366           0 :         return;  // invalidated variable, don't care condition that Scribe
     367             :                  // relies on
     368         876 :     if (nc_put_vara_text(ncid, rvarid, start, count, value) != NC_NOERR)
     369             :     {
     370           0 :         throw SG_Exception_VWrite_Failure("variable", "datum");
     371             :     }
     372             : }
     373             : 
     374          14 : void netCDFVID::nc_put_vvar1_string(int varid, const size_t *index,
     375             :                                     const char **value)
     376             : {
     377          14 :     int rvarid = !directMode ? virtualVIDToVar(varid).getRealID() : varid;
     378             : 
     379          14 :     if (rvarid == INVALID_VAR_ID)
     380           0 :         return;  // invalidated variable
     381             : 
     382          14 :     if (nc_put_var1_string(ncid, rvarid, index, value) != NC_NOERR)
     383             :     {
     384           0 :         throw SG_Exception_VWrite_Failure("variable", "datum");
     385             :     }
     386             : }
     387             : 
     388             : netCDFVAttribute::~netCDFVAttribute() = default;
     389             : 
     390             : }  // namespace nccfdriver

Generated by: LCOV version 1.14