LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfsgwriterutil.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 136 170 80.0 %
Date: 2024-11-21 22:18:42 Functions: 72 153 47.1 %

          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 __NETCDFSGWRITERUTIL_H__
      13             : #define __NETCDFSGWRITERUTIL_H__
      14             : #include <cstdio>
      15             : #include <queue>
      16             : #include <typeinfo>
      17             : #include <vector>
      18             : #include "cpl_vsi.h"
      19             : #include "ogr_core.h"
      20             : #include "ogrsf_frmts.h"
      21             : #include "netcdflayersg.h"
      22             : #include "netcdfsg.h"
      23             : #include "netcdfvirtual.h"
      24             : 
      25             : namespace nccfdriver
      26             : {
      27             : 
      28             : /* OGR_SGeometry_Feature
      29             :  * Constructs over a OGRFeature
      30             :  * gives some basic information about that SGeometry Feature such as
      31             :  * Hold references... limited to scope of its references
      32             :  * - what's its geometry type
      33             :  * - how much total points it has
      34             :  * - how many parts it has
      35             :  * - a vector of counts of points for each part
      36             :  */
      37             : class SGeometry_Feature
      38             : {
      39             :     bool hasInteriorRing;
      40             :     const OGRGeometry *geometry_ref;
      41             :     geom_t type;
      42             :     size_t total_point_count;
      43             :     size_t total_part_count;
      44             :     std::vector<size_t> ppart_node_count;
      45             :     std::vector<bool> part_at_ind_interior;  // for use with Multipolygons ONLY
      46             :     mutable OGRPoint pt_buffer;
      47             : 
      48             :   public:
      49         446 :     geom_t getType()
      50             :     {
      51         446 :         return this->type;
      52             :     }
      53             : 
      54         409 :     size_t getTotalNodeCount()
      55             :     {
      56         409 :         return this->total_point_count;
      57             :     }
      58             : 
      59        1558 :     size_t getTotalPartCount()
      60             :     {
      61        1558 :         return this->total_part_count;
      62             :     }
      63             : 
      64       68422 :     std::vector<size_t> &getPerPartNodeCount()
      65             :     {
      66       68422 :         return this->ppart_node_count;
      67             :     }
      68             : 
      69             :     const OGRPoint &getPoint(size_t part_no, int point_index) const;
      70             :     explicit SGeometry_Feature(OGRFeature &);
      71             : 
      72             :     bool getHasInteriorRing()
      73             :     {
      74             :         return this->hasInteriorRing;
      75             :     }
      76             : 
      77         591 :     bool IsPartAtIndInteriorRing(size_t ind)
      78             :     {
      79         591 :         return this->part_at_ind_interior[ind];
      80             :     }  // ONLY used for Multipolygon
      81             : };
      82             : 
      83             : /* A memory buffer with a soft limit
      84             :  * Has basic capability of over quota checking, and memory counting
      85             :  */
      86             : class WBuffer
      87             : {
      88             :     unsigned long long used_mem = 0;
      89             : 
      90             :   public:
      91             :     /* addCount(...)
      92             :      * Takes in a size, and directly adds that size to memory count
      93             :      */
      94             :     void addCount(unsigned long long memuse);
      95             : 
      96             :     /* subCount(...)
      97             :      * Directly subtracts the specified size from used_mem
      98             :      */
      99             :     void subCount(unsigned long long memfree);
     100             : 
     101         892 :     unsigned long long &getUsage()
     102             :     {
     103         892 :         return used_mem;
     104             :     }
     105             : 
     106         360 :     void reset()
     107             :     {
     108         360 :         this->used_mem = 0;
     109         360 :     }
     110             : 
     111        1932 :     WBuffer()
     112        1932 :     {
     113        1932 :     }
     114             : };
     115             : 
     116             : /* OGR_SGFS_Transaction
     117             :  * Abstract class for a committable transaction
     118             :  *
     119             :  */
     120             : class OGR_SGFS_Transaction
     121             : {
     122             :     int varId = INVALID_VAR_ID;
     123             : 
     124             :   public:
     125             :     /* int commit(...);
     126             :      * Arguments: int ncid, the dataset to write to
     127             :      *            int write_loc, the index in which to write to
     128             :      * Implementation: should write the transaction to netCDF file
     129             :      *
     130             :      */
     131             :     virtual void commit(netCDFVID &n, size_t write_loc) = 0;
     132             : 
     133             :     /* unsigned long long count(...)
     134             :      * Implementation: supposed to return an approximate count of memory usage
     135             :      * Most classes will implement with sizeof(*this), except if otherwise
     136             :      * uncounted for dynamic allocation is involved.
     137             :      */
     138             :     virtual unsigned long long count() = 0;
     139             : 
     140             :     /* appendToLog
     141             :      * Implementation - given a file pointer, a transaction will be written to
     142             :      * that log file in the format:
     143             :      * -
     144             :      * transactionVarId - sizeof(int) bytes
     145             :      * NC_TYPE - sizeof(int) bytes
     146             :      * (nc_char only) OP - 1 byte (0 if does not require COUNT or non-zero i.e.
     147             :      * 1 if does) (nc_char only): SIZE of data - sizeof(size_t) bytes DATA -
     148             :      * size depends on NC_TYPE
     149             :      */
     150             :     virtual void appendToLog(VSILFILE *) = 0;
     151             : 
     152             :     /* ~OGR_SGFS_Transaction()
     153             :      * Empty. Simply here to stop the compiler from complaining...
     154             :      */
     155      224718 :     virtual ~OGR_SGFS_Transaction()
     156      224718 :     {
     157      224718 :     }
     158             : 
     159             :     /* OGR_SGFS_Transaction()
     160             :      * Empty. Simply here to stop one of the CI machines from complaining...
     161             :      */
     162      224718 :     OGR_SGFS_Transaction()
     163      224718 :     {
     164      224718 :     }
     165             : 
     166             :     /* void getVarId(...);
     167             :      * Gets the var in which to commit the transaction to.
     168             :      */
     169      769574 :     int getVarId()
     170             :     {
     171      769574 :         return this->varId;
     172             :     }
     173             : 
     174             :     /* nc_type getType
     175             :      * Returns the type of transaction being saved
     176             :      */
     177             :     virtual nc_type getType() = 0;
     178             : 
     179             :     /* void setVarId(...);
     180             :      * Sets the var in which to commit the transaction to.
     181             :      */
     182      224718 :     void setVarId(int vId)
     183             :     {
     184      224718 :         this->varId = vId;
     185      224718 :     }
     186             : };
     187             : 
     188             : typedef std::map<int, void *> NCWMap;
     189             : typedef std::pair<int, void *> NCWEntry;  // NC Writer Entry
     190             : typedef std::unique_ptr<OGR_SGFS_Transaction>
     191             :     MTPtr;  // a.k.a Managed Transaction Ptr
     192             : 
     193             : template <class T_c_type, nc_type T_nc_type>
     194       87851 : void genericLogAppend(T_c_type r, int vId, VSILFILE *f)
     195             : {
     196       87851 :     T_c_type rep = r;
     197       87851 :     int varId = vId;
     198       87851 :     int type = T_nc_type;
     199       87851 :     VSIFWriteL(&varId, sizeof(int), 1, f);     // write varID data
     200       87851 :     VSIFWriteL(&type, sizeof(int), 1, f);      // write NC type
     201       87851 :     VSIFWriteL(&rep, sizeof(T_c_type), 1, f);  // write data
     202       87851 : }
     203             : 
     204             : template <class T_c_type, class T_r_type>
     205       87851 : MTPtr genericLogDataRead(int varId, VSILFILE *f)
     206             : {
     207             :     T_r_type data;
     208       87851 :     if (!VSIFReadL(&data, sizeof(T_r_type), 1, f))
     209             :     {
     210           0 :         return MTPtr(nullptr);  // invalid read case
     211             :     }
     212       87851 :     return MTPtr(new T_c_type(varId, data));
     213             : }
     214             : 
     215             : /* OGR_SGFS_NC_Char_Transaction
     216             :  * Writes to an NC_CHAR variable
     217             :  */
     218             : class OGR_SGFS_NC_Char_Transaction : public OGR_SGFS_Transaction
     219             : {
     220             :     std::string char_rep;
     221             : 
     222             :   public:
     223           0 :     void commit(netCDFVID &n, size_t write_loc) override
     224             :     {
     225           0 :         n.nc_put_vvar1_text(OGR_SGFS_Transaction::getVarId(), &write_loc,
     226             :                             char_rep.c_str());
     227           0 :     }
     228             : 
     229           0 :     unsigned long long count() override
     230             :     {
     231           0 :         return char_rep.size() + sizeof(*this);
     232             :     }  // account for actual character representation, this class
     233             : 
     234             :     void appendToLog(VSILFILE *f) override;
     235             : 
     236           0 :     nc_type getType() override
     237             :     {
     238           0 :         return NC_CHAR;
     239             :     }
     240             : 
     241           0 :     OGR_SGFS_NC_Char_Transaction(int i_varId, const char *pszVal)
     242           0 :         : char_rep(pszVal)
     243             :     {
     244           0 :         OGR_SGFS_Transaction::setVarId(i_varId);
     245           0 :     }
     246             : };
     247             : 
     248             : /* OGR_SGFS_NC_CharA_Transaction
     249             :  * Writes to an NC_CHAR variable, using vara instead of var1
     250             :  * Used to store 2D character array values, specifically
     251             :  */
     252             : class OGR_SGFS_NC_CharA_Transaction : public OGR_SGFS_Transaction
     253             : {
     254             :     std::string char_rep;
     255             :     size_t counts[2];
     256             : 
     257             :   public:
     258         884 :     void commit(netCDFVID &n, size_t write_loc) override
     259             :     {
     260         884 :         size_t ind[2] = {write_loc, 0};
     261         884 :         n.nc_put_vvara_text(OGR_SGFS_Transaction::getVarId(), ind, counts,
     262             :                             char_rep.c_str());
     263         884 :     }
     264             : 
     265        2356 :     unsigned long long count() override
     266             :     {
     267        2356 :         return char_rep.size() + sizeof(*this);
     268             :     }  // account for actual character representation, this class
     269             : 
     270             :     void appendToLog(VSILFILE *f) override;
     271             : 
     272         884 :     nc_type getType() override
     273             :     {
     274         884 :         return NC_CHAR;
     275             :     }
     276             : 
     277        1472 :     OGR_SGFS_NC_CharA_Transaction(int i_varId, const char *pszVal)
     278        1472 :         : char_rep(pszVal), counts{1, char_rep.length()}
     279             :     {
     280        1472 :         OGR_SGFS_Transaction::setVarId(i_varId);
     281        1472 :     }
     282             : };
     283             : 
     284             : template <class VClass, nc_type ntype>
     285             : class OGR_SGFS_NC_Transaction_Generic : public OGR_SGFS_Transaction
     286             : {
     287             :     VClass rep;
     288             : 
     289             :   public:
     290       23250 :     void commit(netCDFVID &n, size_t write_loc) override
     291             :     {
     292       23250 :         n.nc_put_vvar_generic<VClass>(OGR_SGFS_Transaction::getVarId(),
     293       23250 :                                       &write_loc, &rep);
     294       23250 :     }
     295             : 
     296      358613 :     unsigned long long count() override
     297             :     {
     298      358613 :         return sizeof(*this);
     299             :     }
     300             : 
     301       87851 :     void appendToLog(VSILFILE *f) override
     302             :     {
     303       87851 :         genericLogAppend<VClass, ntype>(rep, OGR_SGFS_Transaction::getVarId(),
     304             :                                         f);
     305       87851 :     }
     306             : 
     307      223232 :     OGR_SGFS_NC_Transaction_Generic(int i_varId, VClass in) : rep(in)
     308             :     {
     309      223232 :         OGR_SGFS_Transaction::setVarId(i_varId);
     310      223232 :     }
     311             : 
     312      112131 :     VClass getData()
     313             :     {
     314      112131 :         return rep;
     315             :     }
     316             : 
     317      382893 :     nc_type getType() override
     318             :     {
     319      382893 :         return ntype;
     320             :     }
     321             : };
     322             : 
     323             : typedef OGR_SGFS_NC_Transaction_Generic<signed char, NC_BYTE>
     324             :     OGR_SGFS_NC_Byte_Transaction;
     325             : typedef OGR_SGFS_NC_Transaction_Generic<short, NC_SHORT>
     326             :     OGR_SGFS_NC_Short_Transaction;
     327             : typedef OGR_SGFS_NC_Transaction_Generic<int, NC_INT>
     328             :     OGR_SGFS_NC_Int_Transaction;
     329             : typedef OGR_SGFS_NC_Transaction_Generic<float, NC_FLOAT>
     330             :     OGR_SGFS_NC_Float_Transaction;
     331             : typedef OGR_SGFS_NC_Transaction_Generic<double, NC_DOUBLE>
     332             :     OGR_SGFS_NC_Double_Transaction;
     333             : typedef OGR_SGFS_NC_Transaction_Generic<unsigned, NC_UINT>
     334             :     OGR_SGFS_NC_UInt_Transaction;
     335             : typedef OGR_SGFS_NC_Transaction_Generic<unsigned long long, NC_UINT64>
     336             :     OGR_SGFS_NC_UInt64_Transaction;
     337             : typedef OGR_SGFS_NC_Transaction_Generic<long long, NC_INT64>
     338             :     OGR_SGFS_NC_Int64_Transaction;
     339             : typedef OGR_SGFS_NC_Transaction_Generic<unsigned char, NC_UBYTE>
     340             :     OGR_SGFS_NC_UByte_Transaction;
     341             : typedef OGR_SGFS_NC_Transaction_Generic<unsigned short, NC_USHORT>
     342             :     OGR_SGFS_NC_UShort_Transaction;
     343             : 
     344             : /* OGR_SGFS_NC_String_Transaction
     345             :  * Writes to an NC_STRING variable, in a similar manner as NC_Char
     346             :  */
     347             : class OGR_SGFS_NC_String_Transaction : public OGR_SGFS_Transaction
     348             : {
     349             :     std::string char_rep;
     350             : 
     351             :   public:
     352          14 :     void commit(netCDFVID &n, size_t write_loc) override
     353             :     {
     354          14 :         const char *writable = char_rep.c_str();
     355          14 :         n.nc_put_vvar1_string(OGR_SGFS_Transaction::getVarId(), &write_loc,
     356             :                               &(writable));
     357          14 :     }
     358             : 
     359          28 :     unsigned long long count() override
     360             :     {
     361          28 :         return char_rep.size() + sizeof(*this);
     362             :     }  // account for actual character representation, this class
     363             : 
     364          28 :     nc_type getType() override
     365             :     {
     366          28 :         return NC_STRING;
     367             :     }
     368             : 
     369             :     void appendToLog(VSILFILE *f) override;
     370             : 
     371          14 :     OGR_SGFS_NC_String_Transaction(int i_varId, const char *pszVal)
     372          14 :         : char_rep(pszVal)
     373             :     {
     374          14 :         OGR_SGFS_Transaction::setVarId(i_varId);
     375          14 :     }
     376             : };
     377             : 
     378             : /* WTransactionLog
     379             :  * -
     380             :  * A temporary file which contains transactions to be written to a netCDF file.
     381             :  * Once the transaction log is created it is set on write mode, it can only be
     382             :  * read to after startRead() is called
     383             :  */
     384             : class WTransactionLog
     385             : {
     386             :     bool readMode = false;
     387             :     std::string wlogName;  // name of the temporary file, should be unique
     388             :     VSILFILE *log = nullptr;
     389             : 
     390             :     WTransactionLog(WTransactionLog &);  // avoid possible undefined behavior
     391             :     WTransactionLog operator=(const WTransactionLog &);
     392             : 
     393             :   public:
     394         360 :     bool logIsNull()
     395             :     {
     396         360 :         return log == nullptr;
     397             :     }
     398             : 
     399             :     void startLog();   // always call this first to open the file
     400             :     void startRead();  // then call this before reading it
     401             :     void push(MTPtr);
     402             : 
     403             :     // read mode
     404             :     MTPtr
     405             :     pop();  // to test for EOF, test to see if pointer returned is null ptr
     406             : 
     407             :     // construction, destruction
     408             :     explicit WTransactionLog(const std::string &logName);
     409             :     ~WTransactionLog();
     410             : };
     411             : 
     412             : /* OGR_NCScribe
     413             :  * Buffers several netCDF transactions in memory or in a log.
     414             :  * General scribe class
     415             :  */
     416             : class OGR_NCScribe
     417             : {
     418             :     netCDFVID &ncvd;
     419             :     WBuffer buf;
     420             :     WTransactionLog wl;
     421             :     bool singleDatumMode = false;
     422             : 
     423             :     std::queue<MTPtr> transactionQueue;
     424             :     std::map<int, size_t> varWriteInds;
     425             :     std::map<int, size_t> varMaxInds;
     426             : 
     427             :   public:
     428             :     /* size_t getWriteCount()
     429             :      * Return the total write count (happened + pending) of certain variable
     430             :      */
     431             :     size_t getWriteCount(int varId)
     432             :     {
     433             :         return this->varMaxInds.at(varId);
     434             :     }
     435             : 
     436             :     /* void commit_transaction()
     437             :      * Replays all transactions to disk (according to fs stipulations)
     438             :      */
     439             :     void commit_transaction();
     440             : 
     441             :     /* MTPtr pop()
     442             :      * Get the next transaction, if it exists.
     443             :      * If not, it will just return a shared_ptr with nullptr inside
     444             :      */
     445             :     MTPtr pop();
     446             : 
     447             :     /* void log_transacion()
     448             :      * Saves the current queued transactions to a log.
     449             :      */
     450             :     void log_transaction();
     451             : 
     452             :     /* void enqueue_transaction()
     453             :      * Add a transaction to perform
     454             :      * Once a transaction is enqueued, it will only be dequeued on commit
     455             :      */
     456             :     void enqueue_transaction(MTPtr transactionAdd);
     457             : 
     458        1932 :     WBuffer &getMemBuffer()
     459             :     {
     460        1932 :         return buf;
     461             :     }
     462             : 
     463             :     /* OGR_SGeometry_Field_Scribe()
     464             :      * Constructs a Field Scribe over a dataset
     465             :      */
     466        1932 :     OGR_NCScribe(netCDFVID &ncd, const std::string &name) : ncvd(ncd), wl(name)
     467             :     {
     468        1932 :     }
     469             : 
     470             :     /* setSingleDatumMode(...)
     471             :      * Enables or disables single datum mode
     472             :      * DO NOT use this when a commit is taking place, otherwise
     473             :      * corruption may occur...
     474             :      */
     475           2 :     void setSingleDatumMode(bool sdm)
     476             :     {
     477           2 :         this->singleDatumMode = sdm;
     478           2 :     }
     479             : };
     480             : 
     481             : class ncLayer_SG_Metadata
     482             : {
     483             :     int &ncID;  // ncid REF. which tracks ncID changes that may be made upstream
     484             : 
     485             :     netCDFVID &vDataset;
     486             :     OGR_NCScribe &ncb;
     487             :     geom_t writableType = NONE;
     488             :     std::string containerVarName;
     489             :     int containerVar_realID = INVALID_VAR_ID;
     490             :     bool interiorRingDetected =
     491             :         false;  // flips on when an interior ring polygon has been detected
     492             :     std::vector<int>
     493             :         node_coordinates_varIDs;  // ids in X, Y (and then possibly Z) order
     494             :     int node_coordinates_dimID = INVALID_DIM_ID;  // dim of all node_coordinates
     495             :     int node_count_dimID = INVALID_DIM_ID;        // node count dim
     496             :     int node_count_varID = INVALID_DIM_ID;
     497             :     int pnc_dimID =
     498             :         INVALID_DIM_ID;  // part node count dim AND interior ring dim
     499             :     int pnc_varID = INVALID_VAR_ID;
     500             :     int intring_varID = INVALID_VAR_ID;
     501             :     size_t next_write_pos_node_coord = 0;
     502             :     size_t next_write_pos_node_count = 0;
     503             :     size_t next_write_pos_pnc = 0;
     504             : 
     505             :   public:
     506         216 :     geom_t getWritableType()
     507             :     {
     508         216 :         return this->writableType;
     509             :     }
     510             : 
     511             :     void writeSGeometryFeature(SGeometry_Feature &ft);
     512             : 
     513         525 :     int get_containerRealID()
     514             :     {
     515         525 :         return this->containerVar_realID;
     516             :     }
     517             : 
     518          77 :     std::string get_containerName()
     519             :     {
     520          77 :         return this->containerVarName;
     521             :     }
     522             : 
     523          67 :     int get_node_count_dimID()
     524             :     {
     525          67 :         return this->node_count_dimID;
     526             :     }
     527             : 
     528          55 :     int get_node_coord_dimID()
     529             :     {
     530          55 :         return this->node_coordinates_dimID;
     531             :     }
     532             : 
     533          34 :     int get_pnc_dimID()
     534             :     {
     535          34 :         return this->pnc_dimID;
     536             :     }
     537             : 
     538           4 :     int get_pnc_varID()
     539             :     {
     540           4 :         return this->pnc_varID;
     541             :     }
     542             : 
     543          17 :     int get_intring_varID()
     544             :     {
     545          17 :         return this->intring_varID;
     546             :     }
     547             : 
     548          38 :     std::vector<int> &get_nodeCoordVarIDs()
     549             :     {
     550          38 :         return this->node_coordinates_varIDs;
     551             :     }
     552             : 
     553          42 :     size_t get_next_write_pos_node_coord()
     554             :     {
     555          42 :         return this->next_write_pos_node_coord;
     556             :     }
     557             : 
     558          32 :     size_t get_next_write_pos_node_count()
     559             :     {
     560          32 :         return this->next_write_pos_node_count;
     561             :     }
     562             : 
     563          27 :     size_t get_next_write_pos_pnc()
     564             :     {
     565          27 :         return this->next_write_pos_pnc;
     566             :     }
     567             : 
     568          45 :     bool getInteriorRingDetected()
     569             :     {
     570          45 :         return this->interiorRingDetected;
     571             :     }
     572             : 
     573             :     void initializeNewContainer(int containerVID);
     574             :     ncLayer_SG_Metadata(int &i_ncID, geom_t geo, netCDFVID &ncdf,
     575             :                         OGR_NCScribe &scribe);
     576             : };
     577             : 
     578             : /* WBufferManager
     579             :  * -
     580             :  * Simply takes a collection of buffers in and a quota limit and sums all the
     581             :  * usages up to establish if buffers are over the soft limit (collectively)
     582             :  *
     583             :  * The buffers added, however, are not memory managed by WBufferManager
     584             :  */
     585             : class WBufferManager
     586             : {
     587             :     unsigned long long buffer_soft_limit = 0;
     588             :     std::vector<WBuffer *> bufs;
     589             : 
     590             :   public:
     591             :     bool isOverQuota();
     592             : 
     593           4 :     void adjustLimit(unsigned long long lim)
     594             :     {
     595           4 :         this->buffer_soft_limit = lim;
     596           4 :     }
     597             : 
     598        1932 :     void addBuffer(WBuffer *b)
     599             :     {
     600        1932 :         this->bufs.push_back(b);
     601        1932 :     }
     602             : 
     603         966 :     explicit WBufferManager(unsigned long long lim) : buffer_soft_limit(lim)
     604             :     {
     605         966 :     }
     606             : };
     607             : 
     608             : // Exception Classes
     609             : class SGWriter_Exception : public SG_Exception
     610             : {
     611             :   public:
     612           0 :     const char *get_err_msg() override
     613             :     {
     614           0 :         return "A general error occurred when writing a netCDF dataset";
     615             :     }
     616             : };
     617             : 
     618             : class SGWriter_Exception_NCWriteFailure : public SGWriter_Exception
     619             : {
     620             :     std::string msg;
     621             : 
     622             :   public:
     623           0 :     const char *get_err_msg() override
     624             :     {
     625           0 :         return this->msg.c_str();
     626             :     }
     627             : 
     628             :     SGWriter_Exception_NCWriteFailure(const char *layer_name,
     629             :                                       const char *failure_name,
     630             :                                       const char *failure_type);
     631             : };
     632             : 
     633             : class SGWriter_Exception_NCInqFailure : public SGWriter_Exception
     634             : {
     635             :     std::string msg;
     636             : 
     637             :   public:
     638           0 :     const char *get_err_msg() override
     639             :     {
     640           0 :         return this->msg.c_str();
     641             :     }
     642             : 
     643             :     SGWriter_Exception_NCInqFailure(const char *layer_name,
     644             :                                     const char *failure_name,
     645             :                                     const char *failure_type);
     646             : };
     647             : 
     648             : class SGWriter_Exception_NCDefFailure : public SGWriter_Exception
     649             : {
     650             :     std::string msg;
     651             : 
     652             :   public:
     653           0 :     const char *get_err_msg() override
     654             :     {
     655           0 :         return this->msg.c_str();
     656             :     }
     657             : 
     658             :     SGWriter_Exception_NCDefFailure(const char *layer_name,
     659             :                                     const char *failure_name,
     660             :                                     const char *failure_type);
     661             : };
     662             : 
     663             : class SGWriter_Exception_NullGeometry : public SGWriter_Exception
     664             : {
     665             :     std::string msg;
     666             : 
     667             :   public:
     668           0 :     const char *get_err_msg() override
     669             :     {
     670           0 :         return this->msg.c_str();
     671             :     }
     672             : 
     673           0 :     SGWriter_Exception_NullGeometry()
     674           0 :         : msg("A null  geometry was detected when writing a netCDF file. "
     675           0 :               "Empty geometries are not allowed.")
     676             :     {
     677           0 :     }
     678             : };
     679             : 
     680             : class SGWriter_Exception_NCDelFailure : public SGWriter_Exception
     681             : {
     682             :     std::string msg;
     683             : 
     684             :   public:
     685           0 :     const char *get_err_msg() override
     686             :     {
     687           0 :         return this->msg.c_str();
     688             :     }
     689             : 
     690           0 :     SGWriter_Exception_NCDelFailure(const char *layer, const char *what)
     691           0 :         : msg("[" + std::string(layer) +
     692           0 :               "] Failed to delete: " + std::string(what))
     693             :     {
     694           0 :     }
     695             : };
     696             : 
     697             : // Helper Functions that for writing
     698             : 
     699             : /* std::vector<..> writeGeometryContainer(...)
     700             :  * Writes a geometry container of a given geometry type given the following
     701             :  * arguments: int ncID - ncid as used in netcdf.h, group or file id std::string
     702             :  * name - what to name this container geom_t geometry_type - the geometry type
     703             :  * of the container std::vector<..> node_coordinate_names - variable names
     704             :  * corresponding to each axis Only writes attributes that are for sure required.
     705             :  * i.e. does NOT required interior ring for anything or part node count for
     706             :  * Polygons
     707             :  *
     708             :  * Returns: geometry container variable ID
     709             :  */
     710             : int write_Geometry_Container(
     711             :     int ncID, const std::string &name, geom_t geometry_type,
     712             :     const std::vector<std::string> &node_coordinate_names);
     713             : 
     714             : template <class W_type>
     715      112131 : inline void NCWMapAllocIfNeeded(int varid, NCWMap &mapAdd, size_t numEntries,
     716             :                                 std::vector<int> &v)
     717             : {
     718      112131 :     if (mapAdd.count(varid) < 1)
     719             :     {
     720         201 :         mapAdd.insert(NCWEntry(varid, CPLMalloc(sizeof(W_type) * numEntries)));
     721         201 :         v.push_back(varid);
     722             :     }
     723      112131 : }
     724             : 
     725             : template <class W_type>
     726      112131 : inline void NCWMapWriteAndCommit(int varid, NCWMap &mapAdd, size_t currentEntry,
     727             :                                  size_t numEntries, W_type data,
     728             :                                  netCDFVID &vcdf)
     729             : {
     730      112131 :     W_type *ptr = static_cast<W_type *>(mapAdd.at(varid));
     731      112131 :     ptr[currentEntry] = data;
     732             :     static const size_t BEGIN = 0;
     733             : 
     734             :     // If all items are ready, write the array, and free it, delete the pointer
     735      112131 :     if (currentEntry == (numEntries - 1))
     736             :     {
     737             :         try
     738             :         {
     739             :             // Write the whole array at once
     740         201 :             vcdf.nc_put_vvara_generic<W_type>(varid, &BEGIN, &numEntries, ptr);
     741             :         }
     742           0 :         catch (SG_Exception_VWrite_Failure &e)
     743             :         {
     744           0 :             CPLError(CE_Warning, CPLE_FileIO, "%s", e.get_err_msg());
     745             :         }
     746             : 
     747         201 :         CPLFree(mapAdd.at(varid));
     748         201 :         mapAdd.erase(varid);
     749             :     }
     750      112131 : }
     751             : }  // namespace nccfdriver
     752             : 
     753             : #endif

Generated by: LCOV version 1.14