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

Generated by: LCOV version 1.14