LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfvirtual.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 110 158 69.6 %
Date: 2024-05-04 12:52:34 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : #include "netcdfdataset.h"
      29             : #include "netcdfvirtual.h"
      30             : 
      31             : // netCDF Virtual
      32             : // Provides a layer of "virtual ncID"
      33             : // that can be mapped to a real netCDF ID
      34             : namespace nccfdriver
      35             : {
      36           4 : void netCDFVDimension::invalidate()
      37             : {
      38           4 :     this->valid = false;
      39           4 :     real_dim_name.clear();
      40           4 : }
      41             : 
      42         260 : netCDFVVariable::netCDFVVariable(const char *name, nc_type xtype, int ndims,
      43         260 :                                  const int *dimidsp)
      44         260 :     : real_var_name(name), ntype(xtype), ndimc(ndims), dimid(new int[ndims])
      45             : {
      46         568 :     for (int c = 0; c < ndims; c++)
      47             :     {
      48         308 :         dimid.get()[c] = dimidsp[c];
      49             :     }
      50         260 : }
      51             : 
      52          21 : void netCDFVVariable::invalidate()
      53             : {
      54          21 :     this->valid = false;
      55          21 :     real_var_name.clear();
      56          21 :     attribs.clear();
      57          21 : }
      58             : 
      59         168 : int netCDFVID::nc_def_vdim(const char *name, size_t len)
      60             : {
      61         168 :     if (directMode)
      62             :     {
      63             :         int ddim;
      64             :         int err;
      65          19 :         if ((err = nc_def_dim(ncid, name, len, &ddim)) != NC_NOERR)
      66             :         {
      67           0 :             NCDF_ERR(err);
      68             :             throw SG_Exception_VWrite_Failure("netCDF file",
      69           0 :                                               "a dimension definition");
      70             :         }
      71             : 
      72          19 :         return ddim;
      73             :     }
      74             : 
      75         149 :     int dimID = dimTicket;
      76             : 
      77             :     // Check if name is already defined
      78         149 :     if (nameDimTable.count(std::string(name)) > 0)
      79             :     {
      80           0 :         throw SG_Exception_DupName(name, "virtual dimension collection");
      81             :     }
      82             : 
      83             :     // Add to lookup tables
      84         149 :     dimList.push_back(netCDFVDimension(name, len, dimTicket));
      85         149 :     dimTicket++;
      86         149 :     nameDimTable.insert(std::pair<std::string, int>(std::string(name), dimID));
      87             : 
      88             :     // Return virtual dimID
      89         149 :     return dimID;
      90             : }
      91             : 
      92         362 : int netCDFVID::nc_def_vvar(const char *name, nc_type xtype, int ndims,
      93             :                            const int *dimidsp)
      94             : {
      95         362 :     if (directMode)
      96             :     {
      97             :         int dvar;
      98             :         int err;
      99         102 :         if ((err = nc_def_var(ncid, name, xtype, ndims, dimidsp, &dvar)) !=
     100             :             NC_NOERR)
     101             :         {
     102           0 :             NCDF_ERR(err);
     103             :             throw SG_Exception_VWrite_Failure("netCDF file",
     104           0 :                                               "a dimension definition");
     105             :         }
     106             : 
     107         102 :         return dvar;
     108             :     }
     109             : 
     110         260 :     int varID = varTicket;
     111             : 
     112             :     // Check if name is already defined
     113         260 :     if (nameVarTable.count(std::string(name)) > 0)
     114             :     {
     115           0 :         throw SG_Exception_DupName(name, "virtual variable collection");
     116             :     }
     117             : 
     118             :     // Add to lookup tables
     119         260 :     varList.push_back(netCDFVVariable(name, xtype, ndims, dimidsp));
     120         260 :     varTicket++;
     121         260 :     nameVarTable.insert(std::pair<std::string, int>(std::string(name), varID));
     122             : 
     123             :     // Return virtual dimID
     124         260 :     return varID;
     125             : }
     126             : 
     127           4 : void netCDFVID::nc_del_vdim(int dimid)
     128             : {
     129             :     // First remove from name map
     130           4 :     nameDimTable.erase(this->dimList[dimid].getName());
     131             : 
     132             :     // Then clear actual dim
     133           4 :     this->dimList[dimid].invalidate();
     134           4 : }
     135             : 
     136          21 : void netCDFVID::nc_del_vvar(int varid)
     137             : {
     138             :     // First remove from name map
     139          21 :     nameVarTable.erase(this->varList[varid].getName());
     140             : 
     141             :     // Then clear actual variable
     142          21 :     this->varList[varid].invalidate();
     143          21 : }
     144             : 
     145         136 : void netCDFVID::nc_resize_vdim(int dimid, size_t dimlen)
     146             : {
     147         136 :     netCDFVDimension &dim = virtualDIDToDim(dimid);
     148             : 
     149         136 :     if (dim.getRealID() == INVALID_DIM_ID)
     150             :     {
     151         136 :         dim.setLen(dimlen);
     152             :     }
     153         136 : }
     154             : 
     155         109 : void netCDFVID::nc_set_define_mode()
     156             : {
     157         109 :     nc_redef(ncid);
     158         109 : }
     159             : 
     160         109 : void netCDFVID::nc_set_data_mode()
     161             : {
     162         109 :     nc_enddef(ncid);
     163         109 : }
     164             : 
     165         109 : void netCDFVID::nc_vmap()
     166             : {
     167         109 :     nc_set_define_mode();
     168             : 
     169         258 :     for (size_t itr_d = 0; itr_d < dimList.size(); itr_d++)
     170             :     {
     171             :         int realDimID;
     172         149 :         netCDFVDimension &dim = dimList[itr_d];
     173             : 
     174         149 :         if (!dim.isValid())
     175             :         {
     176           4 :             continue;  // don't do anywork if variable is invalid
     177             :         }
     178             : 
     179         145 :         nc_def_dim(ncid, dim.getName().c_str(), dim.getLen(), &realDimID);
     180         145 :         dimList[itr_d].setRealID(realDimID);
     181             :     }
     182             : 
     183         369 :     for (size_t itr_v = 0; itr_v < varList.size(); itr_v++)
     184             :     {
     185             :         int realVarID;
     186         260 :         netCDFVVariable &var = varList[itr_v];
     187             : 
     188         260 :         if (!var.isValid())
     189             :         {
     190          21 :             continue;  // don't do any work if variable is invalid
     191             :         }
     192             : 
     193             :         // Convert each virtual dimID to a physical dimID:
     194             :         std::unique_ptr<int, std::default_delete<int[]>> newdims(
     195         478 :             new int[var.getDimCount()]);
     196         526 :         for (int dimct = 0; dimct < var.getDimCount(); dimct++)
     197             :         {
     198         287 :             newdims.get()[dimct] =
     199         287 :                 virtualDIDToDim(var.getDimIds()[dimct]).getRealID();
     200             :         }
     201             : 
     202         239 :         nc_def_var(ncid, var.getName().c_str(), var.getType(),
     203         239 :                    var.getDimCount(), newdims.get(), &realVarID);
     204         239 :         var.setRealID(realVarID);
     205             : 
     206             :         // Now write each of its attributes
     207         988 :         for (size_t attrct = 0; attrct < var.getAttributes().size(); attrct++)
     208             :         {
     209         749 :             var.getAttributes()[attrct]->vsync(ncid, realVarID);
     210             :         }
     211             : 
     212         239 :         var.getAttributes().clear();
     213             :     }
     214             : 
     215         109 :     nc_set_data_mode();
     216         109 : }
     217             : 
     218             : /* Enquiry Functions
     219             :  * (For use with enquiry information about virtual entities)
     220             :  */
     221       25098 : netCDFVVariable &netCDFVID::virtualVIDToVar(int virtualID)
     222             : {
     223       25098 :     if (virtualID >= static_cast<int>(varList.size()) || virtualID < 0)
     224             :     {
     225           0 :         throw SG_Exception_NVOOB("virtual variable collection");
     226             :     }
     227             : 
     228       25098 :     return varList[virtualID];
     229             : }
     230             : 
     231        1307 : netCDFVDimension &netCDFVID::virtualDIDToDim(int virtualID)
     232             : {
     233        1307 :     if (virtualID >= static_cast<int>(dimList.size()) || virtualID < 0)
     234             :     {
     235           0 :         throw SG_Exception_NVOOB("virtual dimension collection");
     236             :     }
     237             : 
     238        1307 :     return dimList[virtualID];
     239             : }
     240             : 
     241           0 : int netCDFVID::nameToVirtualVID(const std::string &name)
     242             : {
     243           0 :     if (nameVarTable.count(name) < 1)
     244             :     {
     245           0 :         throw SG_Exception_BadMapping(name.c_str(), "variable ID lookup");
     246             :     }
     247             : 
     248           0 :     return nameVarTable.at(name);
     249             : }
     250             : 
     251           0 : int netCDFVID::nameToVirtualDID(const std::string &name)
     252             : {
     253           0 :     if (nameDimTable.count(name) < 1)
     254             :     {
     255           0 :         throw SG_Exception_BadMapping(name.c_str(), "dimension ID lookup");
     256             :     }
     257           0 :     return nameDimTable.at(name);
     258             : }
     259             : 
     260             : /* Attribute writing
     261             :  *
     262             :  */
     263             : 
     264        1679 : void netCDFVID::nc_put_vatt_text(int varid, const char *name, const char *value)
     265             : {
     266        1679 :     if (directMode)
     267             :     {
     268             :         int err;
     269         981 :         if ((err = nc_put_att_text(ncid, varid, name, strlen(value), value)) !=
     270             :             NC_NOERR)
     271             :         {
     272           0 :             NCDF_ERR(err);
     273           0 :             throw SG_Exception_VWrite_Failure("variable", "text attribute");
     274             :         }
     275         981 :         return;
     276             :     }
     277             : 
     278         698 :     nc_put_vatt_generic<netCDFVTextAttribute, char>(varid, name, value);
     279             : }
     280             : 
     281          78 : void netCDFVID::nc_put_vatt_int(int varid, const char *name, const int *value)
     282             : {
     283          78 :     if (directMode)
     284             :     {
     285             :         int err;
     286          27 :         if ((err = nc_put_att_int(ncid, varid, name, NC_INT, 1, value)) !=
     287             :             NC_NOERR)
     288             :         {
     289           0 :             NCDF_ERR(err);
     290           0 :             throw SG_Exception_VWrite_Failure("variable", "int attribute");
     291             :         }
     292          27 :         return;
     293             :     }
     294             : 
     295          51 :     nc_put_vatt_generic<netCDFVIntAttribute, int>(varid, name, value);
     296             : }
     297             : 
     298           1 : void netCDFVID::nc_put_vatt_double(int varid, const char *name,
     299             :                                    const double *value)
     300             : {
     301           1 :     if (directMode)
     302             :     {
     303             :         int err;
     304           1 :         if ((err = nc_put_att_double(ncid, varid, name, NC_DOUBLE, 1, value)) !=
     305             :             NC_NOERR)
     306             :         {
     307           0 :             NCDF_ERR(err);
     308           0 :             throw SG_Exception_VWrite_Failure("variable", "double attribute");
     309             :         }
     310           1 :         return;
     311             :     }
     312             : 
     313           0 :     nc_put_vatt_generic<netCDFVDoubleAttribute, double>(varid, name, value);
     314             : }
     315             : 
     316           0 : void netCDFVID::nc_put_vatt_float(int varid, const char *name,
     317             :                                   const float *value)
     318             : {
     319           0 :     if (directMode)
     320             :     {
     321             :         int err;
     322           0 :         if ((err = nc_put_att_float(ncid, varid, name, NC_FLOAT, 1, value)) !=
     323             :             NC_NOERR)
     324             :         {
     325           0 :             NCDF_ERR(err);
     326           0 :             throw SG_Exception_VWrite_Failure("variable", "float attribute");
     327             :         }
     328           0 :         return;
     329             :     }
     330             : 
     331           0 :     nc_put_vatt_generic<netCDFVFloatAttribute, float>(varid, name, value);
     332             : }
     333             : 
     334           0 : void netCDFVID::nc_put_vatt_byte(int varid, const char *name,
     335             :                                  const signed char *value)
     336             : {
     337           0 :     if (directMode)
     338             :     {
     339             :         int err;
     340           0 :         if ((err = nc_put_att_schar(ncid, varid, name, NC_BYTE, 1, value)) !=
     341             :             NC_NOERR)
     342             :         {
     343           0 :             NCDF_ERR(err);
     344           0 :             throw SG_Exception_VWrite_Failure("variable", "byte attribute");
     345             :         }
     346           0 :         return;
     347             :     }
     348             : 
     349           0 :     nc_put_vatt_generic<netCDFVByteAttribute, signed char>(varid, name, value);
     350             : }
     351             : 
     352         698 : void netCDFVTextAttribute::vsync(int realncid, int realvarid)
     353             : {
     354         698 :     if (nc_put_att_text(realncid, realvarid, name.c_str(), value.size(),
     355         698 :                         value.c_str()) != NC_NOERR)
     356             :     {
     357           0 :         throw SG_Exception_VWrite_Failure("variable", "attribute");
     358             :     }
     359         698 : }
     360             : 
     361             : /* Single Datum Writing
     362             :  * (mostly just convenience functions)
     363             :  */
     364           0 : void netCDFVID::nc_put_vvar1_text(int varid, const size_t *index,
     365             :                                   const char *value)
     366             : {
     367           0 :     int rvarid = !directMode ? virtualVIDToVar(varid).getRealID() : varid;
     368           0 :     if (rvarid == INVALID_VAR_ID)
     369           0 :         return;  // invalidated variable, don't care condition that Scribe
     370             :                  // relies on
     371             : 
     372           0 :     if (nc_put_var1_text(ncid, rvarid, index, value) != NC_NOERR)
     373             :     {
     374           0 :         throw SG_Exception_VWrite_Failure("variable", "datum");
     375             :     }
     376             : }
     377             : 
     378         884 : void netCDFVID::nc_put_vvara_text(int varid, const size_t *start,
     379             :                                   const size_t *count, const char *value)
     380             : {
     381         884 :     int rvarid = !directMode ? virtualVIDToVar(varid).getRealID() : varid;
     382         884 :     if (rvarid == INVALID_VAR_ID)
     383           0 :         return;  // invalidated variable, don't care condition that Scribe
     384             :                  // relies on
     385         884 :     if (nc_put_vara_text(ncid, rvarid, start, count, value) != NC_NOERR)
     386             :     {
     387           0 :         throw SG_Exception_VWrite_Failure("variable", "datum");
     388             :     }
     389             : }
     390             : 
     391          14 : void netCDFVID::nc_put_vvar1_string(int varid, const size_t *index,
     392             :                                     const char **value)
     393             : {
     394          14 :     int rvarid = !directMode ? virtualVIDToVar(varid).getRealID() : varid;
     395             : 
     396          14 :     if (rvarid == INVALID_VAR_ID)
     397           0 :         return;  // invalidated variable
     398             : 
     399          14 :     if (nc_put_var1_string(ncid, rvarid, index, value) != NC_NOERR)
     400             :     {
     401           0 :         throw SG_Exception_VWrite_Failure("variable", "datum");
     402             :     }
     403             : }
     404             : 
     405             : }  // namespace nccfdriver

Generated by: LCOV version 1.14