LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfwriterconfig.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 114 117 97.4 %
Date: 2026-07-09 08:35:43 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  netCDF read/write Driver
       4             :  * Purpose:  GDAL bindings over netCDF library.
       5             :  * Author:   Even Rouault <even.rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "netcdfdataset.h"
      14             : 
      15          13 : bool netCDFWriterConfiguration::SetNameValue(
      16             :     CPLXMLNode *psNode, std::map<CPLString, CPLString> &oMap)
      17             : {
      18          13 :     const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
      19          13 :     const char *pszValue = CPLGetXMLValue(psNode, "value", nullptr);
      20          13 :     if (pszName != nullptr && pszValue != nullptr)
      21             :     {
      22           4 :         oMap[pszName] = pszValue;
      23           4 :         return true;
      24             :     }
      25           9 :     CPLError(CE_Failure, CPLE_IllegalArg, "Missing name/value");
      26           9 :     return false;
      27             : }
      28             : 
      29          26 : bool netCDFWriterConfiguration::Parse(const char *pszFilename)
      30             : {
      31          26 :     CPLXMLNode *psRoot = STARTS_WITH(pszFilename, "<Configuration")
      32          26 :                              ? CPLParseXMLString(pszFilename)
      33           1 :                              : CPLParseXMLFile(pszFilename);
      34          26 :     if (psRoot == nullptr)
      35           2 :         return false;
      36          48 :     CPLXMLTreeCloser oCloser(psRoot);
      37             : 
      38          33 :     for (CPLXMLNode *psIter = psRoot->psChild; psIter != nullptr;
      39           9 :          psIter = psIter->psNext)
      40             :     {
      41          30 :         if (psIter->eType != CXT_Element)
      42           0 :             continue;
      43          30 :         if (EQUAL(psIter->pszValue, "DatasetCreationOption"))
      44             :         {
      45           4 :             if (!SetNameValue(psIter, m_oDatasetCreationOptions))
      46             :             {
      47           3 :                 return false;
      48             :             }
      49             :         }
      50          26 :         else if (EQUAL(psIter->pszValue, "LayerCreationOption"))
      51             :         {
      52           4 :             if (!SetNameValue(psIter, m_oLayerCreationOptions))
      53             :             {
      54           3 :                 return false;
      55             :             }
      56             :         }
      57          22 :         else if (EQUAL(psIter->pszValue, "Attribute"))
      58             :         {
      59           6 :             netCDFWriterConfigAttribute oAtt;
      60           6 :             if (oAtt.Parse(psIter))
      61             :             {
      62           2 :                 m_aoAttributes.push_back(std::move(oAtt));
      63             :             }
      64             :             else
      65             :             {
      66           4 :                 return false;
      67             :             }
      68             :         }
      69          16 :         else if (EQUAL(psIter->pszValue, "Field"))
      70             :         {
      71           5 :             netCDFWriterConfigField oField;
      72           5 :             if (oField.Parse(psIter))
      73             :             {
      74           6 :                 m_oFields[!oField.m_osName.empty()
      75           4 :                               ? oField.m_osName
      76          10 :                               : CPLString("__") + oField.m_osNetCDFName] =
      77           3 :                     oField;
      78             :             }
      79             :             else
      80             :             {
      81           2 :                 return false;
      82             :             }
      83             :         }
      84          11 :         else if (EQUAL(psIter->pszValue, "Layer"))
      85             :         {
      86          10 :             netCDFWriterConfigLayer oLayer;
      87          10 :             if (oLayer.Parse(psIter))
      88             :             {
      89           1 :                 m_oLayers[oLayer.m_osName] = std::move(oLayer);
      90             :             }
      91             :             else
      92             :             {
      93           9 :                 return false;
      94             :             }
      95             :         }
      96             :         else
      97             :         {
      98           1 :             CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
      99             :         }
     100             :     }
     101             : 
     102           3 :     m_bIsValid = true;
     103             : 
     104           3 :     return true;
     105             : }
     106             : 
     107          16 : bool netCDFWriterConfigAttribute::Parse(CPLXMLNode *psNode)
     108             : {
     109          16 :     const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
     110          16 :     const char *pszValue = CPLGetXMLValue(psNode, "value", nullptr);
     111          16 :     const char *pszType = CPLGetXMLValue(psNode, "type", "string");
     112          16 :     if (!EQUAL(pszType, "string") && !EQUAL(pszType, "integer") &&
     113           3 :         !EQUAL(pszType, "double"))
     114             :     {
     115           2 :         CPLError(CE_Failure, CPLE_NotSupported, "type='%s' unsupported",
     116             :                  pszType);
     117           2 :         return false;
     118             :     }
     119          14 :     if (pszName == nullptr || pszValue == nullptr)
     120             :     {
     121           7 :         CPLError(CE_Failure, CPLE_IllegalArg, "Missing name/value");
     122           7 :         return false;
     123             :     }
     124           7 :     m_osName = pszName;
     125           7 :     m_osValue = pszValue;
     126           7 :     m_osType = pszType;
     127           7 :     return true;
     128             : }
     129             : 
     130           8 : bool netCDFWriterConfigField::Parse(CPLXMLNode *psNode)
     131             : {
     132           8 :     const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
     133           8 :     const char *pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
     134           8 :     const char *pszMainDim = CPLGetXMLValue(psNode, "main_dim", nullptr);
     135           8 :     if (pszName == nullptr && pszNetCDFName == nullptr)
     136             :     {
     137           2 :         CPLError(CE_Failure, CPLE_IllegalArg,
     138             :                  "Both name and netcdf_name are missing");
     139           2 :         return false;
     140             :     }
     141           6 :     if (pszName != nullptr)
     142           4 :         m_osName = pszName;
     143           6 :     if (pszNetCDFName != nullptr)
     144           6 :         m_osNetCDFName = pszNetCDFName;
     145           6 :     if (pszMainDim != nullptr)
     146           2 :         m_osMainDim = pszMainDim;
     147             : 
     148          22 :     for (CPLXMLNode *psIter = psNode->psChild; psIter != nullptr;
     149          16 :          psIter = psIter->psNext)
     150             :     {
     151          17 :         if (psIter->eType != CXT_Element)
     152          12 :             continue;
     153           5 :         if (EQUAL(psIter->pszValue, "Attribute"))
     154             :         {
     155           5 :             netCDFWriterConfigAttribute oAtt;
     156           5 :             if (oAtt.Parse(psIter))
     157             :             {
     158           4 :                 m_aoAttributes.push_back(std::move(oAtt));
     159             :             }
     160             :             else
     161             :             {
     162           1 :                 return false;
     163             :             }
     164             :         }
     165             :         else
     166             :         {
     167           0 :             CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
     168             :         }
     169             :     }
     170             : 
     171           5 :     return true;
     172             : }
     173             : 
     174          10 : bool netCDFWriterConfigLayer::Parse(CPLXMLNode *psNode)
     175             : {
     176          10 :     const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
     177          10 :     const char *pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
     178          10 :     if (pszName == nullptr)
     179             :     {
     180           1 :         CPLError(CE_Failure, CPLE_IllegalArg, "Missing name");
     181           1 :         return false;
     182             :     }
     183           9 :     m_osName = pszName;
     184           9 :     if (pszNetCDFName != nullptr)
     185           9 :         m_osNetCDFName = pszNetCDFName;
     186             : 
     187          25 :     for (CPLXMLNode *psIter = psNode->psChild; psIter != nullptr;
     188          16 :          psIter = psIter->psNext)
     189             :     {
     190          24 :         if (psIter->eType != CXT_Element)
     191          11 :             continue;
     192          13 :         if (EQUAL(psIter->pszValue, "LayerCreationOption"))
     193             :         {
     194           5 :             if (!netCDFWriterConfiguration::SetNameValue(
     195           5 :                     psIter, m_oLayerCreationOptions))
     196             :             {
     197           3 :                 return false;
     198             :             }
     199             :         }
     200           8 :         else if (EQUAL(psIter->pszValue, "Attribute"))
     201             :         {
     202           5 :             netCDFWriterConfigAttribute oAtt;
     203           5 :             if (oAtt.Parse(psIter))
     204             :             {
     205           1 :                 m_aoAttributes.push_back(std::move(oAtt));
     206             :             }
     207             :             else
     208             :             {
     209           4 :                 return false;
     210             :             }
     211             :         }
     212           3 :         else if (EQUAL(psIter->pszValue, "Field"))
     213             :         {
     214           3 :             netCDFWriterConfigField oField;
     215           3 :             if (oField.Parse(psIter))
     216             :             {
     217           4 :                 m_oFields[!oField.m_osName.empty()
     218           3 :                               ? oField.m_osName
     219           7 :                               : CPLString("__") + oField.m_osNetCDFName] =
     220           4 :                     std::move(oField);
     221             :             }
     222             :             else
     223             :             {
     224           1 :                 return false;
     225             :             }
     226             :         }
     227             :         else
     228             :         {
     229           0 :             CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
     230             :         }
     231             :     }
     232             : 
     233           1 :     return true;
     234             : }

Generated by: LCOV version 1.14