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 : }