LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/gml - gmlfeature.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 97 134 72.4 %
Date: 2024-05-06 22:33:47 Functions: 8 10 80.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  * Project:  GML Reader
       4             :  * Purpose:  Implementation of GMLFeature.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  **********************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam
       9             :  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      22             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_port.h"
      31             : #include "gmlreader.h"
      32             : 
      33             : #include <cstdio>
      34             : 
      35             : #include "cpl_conv.h"
      36             : #include "cpl_error.h"
      37             : #include "cpl_minixml.h"
      38             : #include "cpl_string.h"
      39             : 
      40             : /************************************************************************/
      41             : /*                             GMLFeature()                             */
      42             : /************************************************************************/
      43             : 
      44        2469 : GMLFeature::GMLFeature(GMLFeatureClass *poClass)
      45             :     : m_poClass(poClass), m_pszFID(nullptr), m_nPropertyCount(0),
      46             :       m_pasProperties(nullptr), m_nGeometryCount(0),
      47        2469 :       m_papsGeometry(m_apsGeometry)  // TODO(schwehr): Allowed in init list?
      48             : {
      49        2469 :     m_apsGeometry[0] = nullptr;
      50        2469 :     m_apsGeometry[1] = nullptr;
      51        2469 : }
      52             : 
      53             : /************************************************************************/
      54             : /*                            ~GMLFeature()                             */
      55             : /************************************************************************/
      56             : 
      57        4938 : GMLFeature::~GMLFeature()
      58             : 
      59             : {
      60        2469 :     CPLFree(m_pszFID);
      61             : 
      62        9113 :     for (int i = 0; i < m_nPropertyCount; i++)
      63             :     {
      64        6644 :         const int nSubProperties = m_pasProperties[i].nSubProperties;
      65        6644 :         if (nSubProperties == 1)
      66             :         {
      67        6063 :             CPLFree(m_pasProperties[i].aszSubProperties[0]);
      68             :         }
      69         581 :         else if (nSubProperties > 1)
      70             :         {
      71         700 :             for (int j = 0; j < nSubProperties; j++)
      72         472 :                 CPLFree(m_pasProperties[i].papszSubProperties[j]);
      73         228 :             CPLFree(m_pasProperties[i].papszSubProperties);
      74             :         }
      75             :     }
      76             : 
      77        2469 :     if (m_nGeometryCount == 1)
      78             :     {
      79        2225 :         CPLDestroyXMLNode(m_apsGeometry[0]);
      80             :     }
      81         244 :     else if (m_nGeometryCount > 1)
      82             :     {
      83         281 :         for (int i = 0; i < m_nGeometryCount; i++)
      84         192 :             CPLDestroyXMLNode(m_papsGeometry[i]);
      85          89 :         CPLFree(m_papsGeometry);
      86             :     }
      87             : 
      88        2469 :     if (m_psBoundedByGeometry)
      89          20 :         CPLDestroyXMLNode(m_psBoundedByGeometry);
      90             : 
      91        2469 :     CPLFree(m_pasProperties);
      92        2469 : }
      93             : 
      94             : /************************************************************************/
      95             : /*                               SetFID()                               */
      96             : /************************************************************************/
      97             : 
      98        1439 : void GMLFeature::SetFID(const char *pszFID)
      99             : 
     100             : {
     101        1439 :     CPLFree(m_pszFID);
     102        1439 :     if (pszFID != nullptr)
     103        1439 :         m_pszFID = CPLStrdup(pszFID);
     104             :     else
     105           0 :         m_pszFID = nullptr;
     106        1439 : }
     107             : 
     108             : /************************************************************************/
     109             : /*                        SetPropertyDirectly()                         */
     110             : /************************************************************************/
     111             : 
     112        6535 : void GMLFeature::SetPropertyDirectly(int iIndex, char *pszValue)
     113             : 
     114             : {
     115        6535 :     CPLAssert(pszValue);
     116        6535 :     if (iIndex >= m_nPropertyCount)
     117             :     {
     118        2537 :         const int nClassPropertyCount = m_poClass->GetPropertyCount();
     119        5074 :         m_pasProperties = static_cast<GMLProperty *>(CPLRealloc(
     120        2537 :             m_pasProperties, sizeof(GMLProperty) * nClassPropertyCount));
     121        3809 :         for (int i = 0; i < m_nPropertyCount; i++)
     122             :         {
     123             :             // Make sure papszSubProperties point to the right address in case
     124             :             // m_pasProperties has been relocated.
     125        1272 :             if (m_pasProperties[i].nSubProperties <= 1)
     126        1082 :                 m_pasProperties[i].papszSubProperties =
     127        1082 :                     m_pasProperties[i].aszSubProperties;
     128             :         }
     129        9181 :         for (int i = m_nPropertyCount; i < nClassPropertyCount; i++)
     130             :         {
     131        6644 :             m_pasProperties[i].nSubProperties = 0;
     132        6644 :             m_pasProperties[i].papszSubProperties =
     133        6644 :                 m_pasProperties[i].aszSubProperties;
     134        6644 :             m_pasProperties[i].aszSubProperties[0] = nullptr;
     135        6644 :             m_pasProperties[i].aszSubProperties[1] = nullptr;
     136             :         }
     137        2537 :         m_nPropertyCount = nClassPropertyCount;
     138             :     }
     139             : 
     140        6535 :     GMLProperty *psProperty = &m_pasProperties[iIndex];
     141        6535 :     const int nSubProperties = psProperty->nSubProperties;
     142        6535 :     if (nSubProperties == 0)
     143             :     {
     144        6291 :         psProperty->aszSubProperties[0] = pszValue;
     145             :     }
     146         244 :     else if (nSubProperties == 1)
     147             :     {
     148         228 :         psProperty->papszSubProperties = static_cast<char **>(
     149         228 :             CPLMalloc(sizeof(char *) * (nSubProperties + 2)));
     150         228 :         psProperty->papszSubProperties[0] = psProperty->aszSubProperties[0];
     151         228 :         psProperty->aszSubProperties[0] = nullptr;
     152         228 :         psProperty->papszSubProperties[nSubProperties] = pszValue;
     153         228 :         psProperty->papszSubProperties[nSubProperties + 1] = nullptr;
     154             :     }
     155             :     else
     156             :     {
     157          16 :         psProperty->papszSubProperties = static_cast<char **>(
     158          32 :             CPLRealloc(psProperty->papszSubProperties,
     159          16 :                        sizeof(char *) * (nSubProperties + 2)));
     160          16 :         psProperty->papszSubProperties[nSubProperties] = pszValue;
     161          16 :         psProperty->papszSubProperties[nSubProperties + 1] = nullptr;
     162             :     }
     163        6535 :     psProperty->nSubProperties++;
     164        6535 : }
     165             : 
     166             : /************************************************************************/
     167             : /*                                Dump()                                */
     168             : /************************************************************************/
     169             : 
     170           0 : void GMLFeature::Dump(CPL_UNUSED FILE *fp)
     171             : {
     172           0 :     printf("GMLFeature(%s):\n", m_poClass->GetName()); /*ok*/
     173             : 
     174           0 :     if (m_pszFID != nullptr)
     175           0 :         printf("  FID = %s\n", m_pszFID); /*ok*/
     176             : 
     177           0 :     for (int i = 0; i < m_nPropertyCount; i++)
     178             :     {
     179           0 :         const GMLProperty *psGMLProperty = GetProperty(i);
     180           0 :         printf("  %s = ", m_poClass->GetProperty(i)->GetName()); /*ok*/
     181           0 :         if (psGMLProperty != nullptr)
     182             :         {
     183           0 :             for (int j = 0; j < psGMLProperty->nSubProperties; j++)
     184             :             {
     185           0 :                 if (j > 0)
     186           0 :                     printf(", ");                                   /*ok*/
     187           0 :                 printf("%s", psGMLProperty->papszSubProperties[j]); /*ok*/
     188             :             }
     189           0 :             printf("\n"); /*ok*/
     190             :         }
     191             :     }
     192             : 
     193           0 :     for (int i = 0; i < m_nGeometryCount; i++)
     194             :     {
     195           0 :         char *pszXML = CPLSerializeXMLTree(m_papsGeometry[i]);
     196           0 :         printf("  %s\n", pszXML); /*ok*/
     197           0 :         CPLFree(pszXML);
     198             :     }
     199           0 : }
     200             : 
     201             : /************************************************************************/
     202             : /*                        SetGeometryDirectly()                         */
     203             : /************************************************************************/
     204             : 
     205        2310 : void GMLFeature::SetGeometryDirectly(CPLXMLNode *psGeom)
     206             : 
     207             : {
     208        2310 :     if (m_apsGeometry[0] != nullptr)
     209          16 :         CPLDestroyXMLNode(m_apsGeometry[0]);
     210        2310 :     m_nGeometryCount = 1;
     211        2310 :     m_apsGeometry[0] = psGeom;
     212        2310 : }
     213             : 
     214             : /************************************************************************/
     215             : /*                        SetGeometryDirectly()                         */
     216             : /************************************************************************/
     217             : 
     218         172 : void GMLFeature::SetGeometryDirectly(int nIdx, CPLXMLNode *psGeom)
     219             : 
     220             : {
     221         172 :     if (nIdx == 0 && m_nGeometryCount <= 1)
     222             :     {
     223          78 :         SetGeometryDirectly(psGeom);
     224          78 :         return;
     225             :     }
     226          94 :     else if (nIdx > 0 && m_nGeometryCount <= 1)
     227             :     {
     228          89 :         m_papsGeometry =
     229          89 :             static_cast<CPLXMLNode **>(CPLMalloc(2 * sizeof(CPLXMLNode *)));
     230          89 :         m_papsGeometry[0] = m_apsGeometry[0];
     231          89 :         m_papsGeometry[1] = nullptr;
     232          89 :         m_apsGeometry[0] = nullptr;
     233             :     }
     234             : 
     235          94 :     if (nIdx >= m_nGeometryCount)
     236             :     {
     237          92 :         m_papsGeometry = static_cast<CPLXMLNode **>(
     238          92 :             CPLRealloc(m_papsGeometry, (nIdx + 2) * sizeof(CPLXMLNode *)));
     239         307 :         for (int i = m_nGeometryCount; i <= nIdx + 1; i++)
     240         215 :             m_papsGeometry[i] = nullptr;
     241          92 :         m_nGeometryCount = nIdx + 1;
     242             :     }
     243          94 :     if (m_papsGeometry[nIdx] != nullptr)
     244           0 :         CPLDestroyXMLNode(m_papsGeometry[nIdx]);
     245          94 :     m_papsGeometry[nIdx] = psGeom;
     246             : }
     247             : 
     248             : /************************************************************************/
     249             : /*                          GetGeometryRef()                            */
     250             : /************************************************************************/
     251             : 
     252        2609 : const CPLXMLNode *GMLFeature::GetGeometryRef(int nIdx) const
     253             : {
     254        2609 :     if (nIdx < 0 || nIdx >= m_nGeometryCount)
     255        2404 :         return nullptr;
     256         205 :     return m_papsGeometry[nIdx];
     257             : }
     258             : 
     259             : /************************************************************************/
     260             : /*                             AddGeometry()                            */
     261             : /************************************************************************/
     262             : 
     263           0 : void GMLFeature::AddGeometry(CPLXMLNode *psGeom)
     264             : 
     265             : {
     266           0 :     if (m_nGeometryCount == 0)
     267             :     {
     268           0 :         m_apsGeometry[0] = psGeom;
     269             :     }
     270           0 :     else if (m_nGeometryCount == 1)
     271             :     {
     272           0 :         m_papsGeometry = static_cast<CPLXMLNode **>(
     273           0 :             CPLMalloc((m_nGeometryCount + 2) * sizeof(CPLXMLNode *)));
     274           0 :         m_papsGeometry[0] = m_apsGeometry[0];
     275           0 :         m_apsGeometry[0] = nullptr;
     276           0 :         m_papsGeometry[m_nGeometryCount] = psGeom;
     277           0 :         m_papsGeometry[m_nGeometryCount + 1] = nullptr;
     278             :     }
     279             :     else
     280             :     {
     281           0 :         m_papsGeometry = static_cast<CPLXMLNode **>(CPLRealloc(
     282           0 :             m_papsGeometry, (m_nGeometryCount + 2) * sizeof(CPLXMLNode *)));
     283           0 :         m_papsGeometry[m_nGeometryCount] = psGeom;
     284           0 :         m_papsGeometry[m_nGeometryCount + 1] = nullptr;
     285             :     }
     286           0 :     m_nGeometryCount++;
     287           0 : }
     288             : 
     289             : /************************************************************************/
     290             : /*                         SetBoundedByGeometry()                       */
     291             : /************************************************************************/
     292             : 
     293          20 : void GMLFeature::SetBoundedByGeometry(CPLXMLNode *psGeom)
     294             : 
     295             : {
     296          20 :     if (m_psBoundedByGeometry)
     297           0 :         CPLDestroyXMLNode(m_psBoundedByGeometry);
     298          20 :     m_psBoundedByGeometry = psGeom;
     299          20 : }

Generated by: LCOV version 1.14