1 : /**********************************************************************
2 : * $Id: nashandler.cpp 25170 2012-10-21 20:02:05Z rouault $
3 : *
4 : * Project: NAS Reader
5 : * Purpose: Implementation of NASHandler class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : **********************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam
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 <ctype.h>
31 : #include "nasreaderp.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 :
35 : #define MAX_TOKEN_SIZE 1000
36 :
37 : /************************************************************************/
38 : /* NASHandler() */
39 : /************************************************************************/
40 :
41 9 : NASHandler::NASHandler( NASReader *poReader )
42 :
43 : {
44 9 : m_poReader = poReader;
45 9 : m_pszCurField = NULL;
46 9 : m_pszGeometry = NULL;
47 9 : m_nGeomAlloc = m_nGeomLen = 0;
48 9 : m_nDepthFeature = m_nDepthElement = m_nDepth = 0;
49 9 : m_bIgnoreFeature = FALSE;
50 9 : }
51 :
52 : /************************************************************************/
53 : /* ~NASHandler() */
54 : /************************************************************************/
55 :
56 9 : NASHandler::~NASHandler()
57 :
58 : {
59 9 : CPLFree( m_pszCurField );
60 9 : CPLFree( m_pszGeometry );
61 9 : }
62 :
63 : /************************************************************************/
64 : /* GetAttributes() */
65 : /************************************************************************/
66 :
67 449744 : CPLString NASHandler::GetAttributes(const Attributes* attrs)
68 : {
69 449744 : CPLString osRes;
70 : char *pszString;
71 :
72 459649 : for(unsigned int i=0; i < attrs->getLength(); i++)
73 : {
74 9905 : osRes += " ";
75 9905 : pszString = tr_strdup(attrs->getQName(i));
76 9905 : osRes += pszString;
77 9905 : CPLFree( pszString );
78 9905 : osRes += "=\"";
79 9905 : pszString = tr_strdup(attrs->getValue(i));
80 9905 : osRes += pszString;
81 9905 : CPLFree( pszString );
82 9905 : osRes += "\"";
83 : }
84 0 : return osRes;
85 : }
86 :
87 :
88 : /************************************************************************/
89 : /* startElement() */
90 : /************************************************************************/
91 :
92 2235313 : void NASHandler::startElement(const XMLCh* const uri,
93 : const XMLCh* const localname,
94 : const XMLCh* const qname,
95 : const Attributes& attrs )
96 :
97 : {
98 : char szElementName[MAX_TOKEN_SIZE];
99 2235313 : GMLReadState *poState = m_poReader->GetState();
100 2235313 : const char *pszLast = NULL;
101 :
102 2235313 : tr_strcpy( szElementName, localname );
103 :
104 2235313 : if ( ( m_bIgnoreFeature && m_nDepth >= m_nDepthFeature ) ||
105 : ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement ) )
106 : {
107 1563631 : m_nDepth ++;
108 1563631 : return;
109 : }
110 :
111 : // ignore attributes of external references and "objektkoordinaten"
112 : // (see PostNAS #3 and #15)
113 671682 : if ( EQUAL( szElementName, "zeigtAufExternes" ) ||
114 : EQUAL( szElementName, "objektkoordinaten" ) )
115 : {
116 339 : m_osIgnoredElement = szElementName;
117 339 : m_nDepthElement = m_nDepth;
118 339 : m_nDepth ++;
119 :
120 339 : return;
121 : }
122 :
123 : #ifdef DEBUG_VERBOSE
124 : CPLDebug("NAS",
125 : "%*sstartElement %s m_bIgnoreFeature:%d depth:%d depthFeature:%d featureClass:%s",
126 : m_nDepth, "", szElementName,
127 : m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
128 : poState->m_poFeature ? poState->m_poFeature->GetClass()->GetElementName() : "(no feature)"
129 : );
130 : #endif
131 :
132 : /* -------------------------------------------------------------------- */
133 : /* If we are in the midst of collecting a feature attribute */
134 : /* value, then this must be a complex attribute which we don't */
135 : /* try to collect for now, so just terminate the field */
136 : /* collection. */
137 : /* -------------------------------------------------------------------- */
138 671343 : if( m_pszCurField != NULL )
139 : {
140 26 : CPLFree( m_pszCurField );
141 26 : m_pszCurField = NULL;
142 : }
143 :
144 : /* -------------------------------------------------------------------- */
145 : /* If we are collecting geometry, or if we determine this is a */
146 : /* geometry element then append to the geometry info. */
147 : /* -------------------------------------------------------------------- */
148 671343 : if( m_pszGeometry != NULL
149 : || IsGeometryElement( szElementName ) )
150 : {
151 449744 : int nLNLen = tr_strlen( localname );
152 449744 : CPLString osAttributes = GetAttributes( &attrs );
153 :
154 : /* should save attributes too! */
155 :
156 449744 : if( m_pszGeometry == NULL )
157 6684 : m_nGeometryDepth = poState->m_nPathLength;
158 :
159 449744 : if( m_nGeomLen + nLNLen + 4 + (int)osAttributes.size() > m_nGeomAlloc )
160 : {
161 6684 : m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + osAttributes.size() + 1000);
162 : m_pszGeometry = (char *)
163 6684 : CPLRealloc( m_pszGeometry, m_nGeomAlloc);
164 : }
165 :
166 449744 : strcpy( m_pszGeometry+m_nGeomLen, "<" );
167 449744 : tr_strcpy( m_pszGeometry+m_nGeomLen+1, localname );
168 :
169 449744 : if( osAttributes.size() > 0 )
170 : {
171 9572 : strcat( m_pszGeometry+m_nGeomLen, " " );
172 9572 : strcat( m_pszGeometry+m_nGeomLen, osAttributes );
173 : }
174 :
175 449744 : strcat( m_pszGeometry+m_nGeomLen, ">" );
176 449744 : m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
177 : }
178 :
179 : /* -------------------------------------------------------------------- */
180 : /* Is this the ogc:Filter element in a wfs:Delete or */
181 : /* wfsext:Replace operation? If so we translate it as a */
182 : /* specialized sort of feature. */
183 : /* -------------------------------------------------------------------- */
184 221599 : else if( EQUAL(szElementName,"Filter")
185 : && (pszLast = m_poReader->GetState()->GetLastComponent()) != NULL
186 : && (EQUAL(pszLast,"Delete") || EQUAL(pszLast,"Replace")) )
187 : {
188 6 : const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
189 6 : if ( pszFilteredClassName != NULL &&
190 : strcmp("Delete", pszFilteredClassName) != 0 )
191 : {
192 0 : m_bIgnoreFeature = TRUE;
193 0 : m_nDepthFeature = m_nDepth;
194 0 : m_nDepth ++;
195 :
196 0 : return;
197 : }
198 :
199 6 : m_bIgnoreFeature = FALSE;
200 :
201 6 : m_poReader->PushFeature( "Delete", attrs );
202 :
203 6 : m_nDepthFeature = m_nDepth;
204 6 : m_nDepth ++;
205 :
206 6 : CPLAssert( m_osLastTypeName != "" );
207 6 : m_poReader->SetFeaturePropertyDirectly( "typeName", CPLStrdup(m_osLastTypeName) );
208 6 : m_poReader->SetFeaturePropertyDirectly( "context", CPLStrdup(pszLast) );
209 :
210 6 : if( EQUAL( pszLast, "Replace" ) )
211 : {
212 2 : CPLAssert( m_osLastReplacingFID != "" );
213 2 : CPLAssert( m_osLastSafeToIgnore != "" );
214 2 : m_poReader->SetFeaturePropertyDirectly( "replacedBy", CPLStrdup(m_osLastReplacingFID) );
215 2 : m_poReader->SetFeaturePropertyDirectly( "safeToIgnore", CPLStrdup(m_osLastSafeToIgnore) );
216 : }
217 :
218 6 : return;
219 : }
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* Is it a feature? If so push a whole new state, and return. */
223 : /* -------------------------------------------------------------------- */
224 221593 : else if( m_poReader->IsFeatureElement( szElementName ) )
225 : {
226 69646 : m_osLastTypeName = szElementName;
227 :
228 69646 : const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
229 :
230 69646 : pszLast = m_poReader->GetState()->GetLastComponent();
231 139292 : if( pszLast != NULL && EQUAL(pszLast,"Replace") )
232 : {
233 : int nIndex;
234 : XMLCh Name[100];
235 :
236 3 : tr_strcpy( Name, "gml:id" );
237 3 : nIndex = attrs.getIndex( Name );
238 :
239 3 : CPLAssert( nIndex!=-1 );
240 3 : CPLAssert( m_osLastReplacingFID=="" );
241 :
242 : // Capture "gml:id" attribute as part of the property value -
243 : // primarily this is for the wfsext:Replace operation's attribute.
244 3 : char *pszReplacingFID = tr_strdup( attrs.getValue( nIndex ) );
245 3 : m_osLastReplacingFID = pszReplacingFID;
246 3 : CPLFree( pszReplacingFID );
247 :
248 : #ifdef DEBUG_VERBOSE
249 : CPLDebug("NAS", "%*s### Replace typeName=%s replacedBy=%s", m_nDepth, "", m_osLastTypeName.c_str(), m_osLastReplacingFID.c_str() );
250 : #endif
251 : }
252 :
253 69646 : if ( pszFilteredClassName != NULL &&
254 : strcmp(szElementName, pszFilteredClassName) != 0 )
255 : {
256 60918 : m_bIgnoreFeature = TRUE;
257 60918 : m_nDepthFeature = m_nDepth;
258 60918 : m_nDepth ++;
259 :
260 60918 : return;
261 : }
262 :
263 8728 : m_bIgnoreFeature = FALSE;
264 :
265 8728 : m_poReader->PushFeature( szElementName, attrs );
266 :
267 8728 : m_nDepthFeature = m_nDepth;
268 8728 : m_nDepth ++;
269 :
270 8728 : return;
271 : }
272 :
273 : /* -------------------------------------------------------------------- */
274 : /* If it is the wfs:Delete element, then remember the typeName */
275 : /* attribute so we can assign it to the feature that will be */
276 : /* produced when we process the Filter element. */
277 : /* -------------------------------------------------------------------- */
278 151947 : else if( EQUAL(szElementName,"Delete") )
279 : {
280 : int nIndex;
281 : XMLCh Name[100];
282 :
283 4 : tr_strcpy( Name, "typeName" );
284 4 : nIndex = attrs.getIndex( Name );
285 :
286 4 : if( nIndex != -1 )
287 : {
288 4 : char *pszTypeName = tr_strdup( attrs.getValue( nIndex ) );
289 4 : m_osLastTypeName = pszTypeName;
290 4 : CPLFree( pszTypeName );
291 : }
292 :
293 4 : m_osLastSafeToIgnore = "";
294 8 : m_osLastReplacingFID = "";
295 : }
296 :
297 : /* -------------------------------------------------------------------- */
298 : /* If it is the wfsext:Replace element, then remember the */
299 : /* safeToIgnore attribute so we can assign it to the feature */
300 : /* that will be produced when we process the Filter element. */
301 : /* -------------------------------------------------------------------- */
302 151943 : else if( EQUAL(szElementName,"Replace") )
303 : {
304 : int nIndex;
305 : XMLCh Name[100];
306 :
307 3 : tr_strcpy( Name, "safeToIgnore" );
308 3 : nIndex = attrs.getIndex( Name );
309 :
310 3 : if( nIndex != -1 )
311 : {
312 3 : char *pszSafeToIgnore = tr_strdup( attrs.getValue( nIndex ) );
313 3 : m_osLastSafeToIgnore = pszSafeToIgnore;
314 3 : CPLFree( pszSafeToIgnore );
315 : }
316 : else
317 : {
318 0 : CPLError( CE_Warning, CPLE_AppDefined, "NAS: safeToIgnore attribute missing" );
319 0 : m_osLastSafeToIgnore = "false";
320 : }
321 :
322 3 : m_osLastReplacingFID = "";
323 : }
324 :
325 : /* -------------------------------------------------------------------- */
326 : /* If it is (or at least potentially is) a simple attribute, */
327 : /* then start collecting it. */
328 : /* -------------------------------------------------------------------- */
329 151940 : else if( m_poReader->IsAttributeElement( szElementName ) )
330 : {
331 37877 : CPLFree( m_pszCurField );
332 37877 : m_pszCurField = CPLStrdup("");
333 :
334 : // Capture href as OB property.
335 37877 : m_poReader->CheckForRelations( szElementName, attrs );
336 :
337 : // Capture "fid" attribute as part of the property value -
338 : // primarily this is for wfs:Delete operation's FeatureId attribute.
339 37877 : if( EQUAL(szElementName,"FeatureId") )
340 6 : m_poReader->CheckForFID( attrs, &m_pszCurField );
341 : }
342 :
343 : /* -------------------------------------------------------------------- */
344 : /* Push the element onto the current state's path. */
345 : /* -------------------------------------------------------------------- */
346 601691 : poState->PushPath( szElementName );
347 :
348 601691 : m_nDepth ++;
349 : }
350 :
351 : /************************************************************************/
352 : /* endElement() */
353 : /************************************************************************/
354 2235294 : void NASHandler::endElement(const XMLCh* const uri,
355 : const XMLCh* const localname,
356 : const XMLCh* const qname )
357 :
358 : {
359 : char szElementName[MAX_TOKEN_SIZE];
360 2235294 : GMLReadState *poState = m_poReader->GetState();
361 :
362 2235294 : tr_strcpy( szElementName, localname );
363 :
364 :
365 2235294 : m_nDepth --;
366 :
367 2235294 : if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
368 : {
369 1622854 : if (m_nDepth == m_nDepthFeature)
370 : {
371 60918 : m_bIgnoreFeature = FALSE;
372 60918 : m_nDepthFeature = 0;
373 : }
374 1622854 : return;
375 : }
376 :
377 612440 : if ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement )
378 : {
379 2034 : if ( m_nDepth == m_nDepthElement )
380 : {
381 339 : m_osIgnoredElement = "";
382 339 : m_nDepthElement = 0;
383 : }
384 2034 : return;
385 : }
386 :
387 : #ifdef DEBUG_VERBOSE
388 : CPLDebug("NAS",
389 : "%*sendElement %s m_bIgnoreFeature:%d depth:%d depthFeature:%d featureClass:%s",
390 : m_nDepth, "", szElementName,
391 : m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
392 : poState->m_poFeature ? poState->m_poFeature->GetClass()->GetElementName() : "(no feature)"
393 : );
394 : #endif
395 :
396 : /* -------------------------------------------------------------------- */
397 : /* Is this closing off an attribute value? We assume so if */
398 : /* we are collecting an attribute value and got to this point. */
399 : /* We don't bother validating that the closing tag matches the */
400 : /* opening tag. */
401 : /* -------------------------------------------------------------------- */
402 610406 : if( m_pszCurField != NULL )
403 : {
404 37851 : CPLAssert( poState->m_poFeature != NULL );
405 :
406 37851 : m_poReader->SetFeaturePropertyDirectly( poState->osPath.c_str(), m_pszCurField );
407 37851 : m_pszCurField = NULL;
408 : }
409 :
410 : /* -------------------------------------------------------------------- */
411 : /* If we are collecting Geometry than store it, and consider if */
412 : /* this is the end of the geometry. */
413 : /* -------------------------------------------------------------------- */
414 610406 : if( m_pszGeometry != NULL )
415 : {
416 449744 : int nLNLen = tr_strlen( localname );
417 :
418 : /* should save attributes too! */
419 :
420 449744 : if( m_nGeomLen + nLNLen + 4 > m_nGeomAlloc )
421 : {
422 0 : m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + 1000);
423 : m_pszGeometry = (char *)
424 0 : CPLRealloc( m_pszGeometry, m_nGeomAlloc);
425 : }
426 :
427 449744 : strcat( m_pszGeometry+m_nGeomLen, "</" );
428 449744 : tr_strcpy( m_pszGeometry+m_nGeomLen+2, localname );
429 449744 : strcat( m_pszGeometry+m_nGeomLen+nLNLen+2, ">" );
430 449744 : m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
431 :
432 449744 : if( poState->m_nPathLength == m_nGeometryDepth+1 )
433 : {
434 6684 : if( poState->m_poFeature != NULL )
435 : {
436 6684 : CPLXMLNode* psNode = CPLParseXMLString(m_pszGeometry);
437 6684 : if (psNode)
438 : {
439 : /* workaround common malformed gml:pos with just a
440 : * elevation value instead of a full 3D coordinate:
441 : *
442 : * <gml:Point gml:id="BII2H">
443 : * <gml:pos srsName="urn:adv:crs:ETRS89_h">41.394</gml:pos>
444 : * </gml:Point>
445 : *
446 : */
447 : const char *pszPos;
448 6684 : if( (pszPos = CPLGetXMLValue( psNode, "=Point.pos", NULL ) ) != NULL
449 : && strstr(pszPos, " ") == NULL )
450 : {
451 0 : CPLSetXMLValue( psNode, "pos", CPLSPrintf("0 0 %s", pszPos) );
452 : }
453 :
454 13368 : if ( poState->m_poFeature->GetGeometryList() &&
455 6684 : poState->m_poFeature->GetGeometryList()[0] )
456 : {
457 0 : int iId = poState->m_poFeature->GetClass()->GetPropertyIndex( "gml_id" );
458 0 : const GMLProperty *poIdProp = poState->m_poFeature->GetProperty(iId);
459 : #if DEBUG_VERBOSE
460 : char *pszOldGeom = CPLSerializeXMLTree( poState->m_poFeature->GetGeometryList()[0] );
461 :
462 : CPLDebug("NAS", "Overwriting other geometry (%s; replace:%s; with:%s)",
463 : poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)",
464 : m_pszGeometry,
465 : pszOldGeom
466 : );
467 :
468 : CPLFree( pszOldGeom );
469 : #else
470 : CPLError( CE_Warning, CPLE_AppDefined, "NAS: Overwriting other geometry (%s)",
471 0 : poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)" );
472 : #endif
473 : }
474 :
475 6684 : poState->m_poFeature->SetGeometryDirectly( psNode );
476 : }
477 : else
478 0 : CPLError( CE_Warning, CPLE_AppDefined, "NAS: Invalid geometry skipped" );
479 : }
480 : else
481 0 : CPLError( CE_Warning, CPLE_AppDefined, "NAS: Skipping geometry without feature" );
482 :
483 6684 : CPLFree( m_pszGeometry );
484 6684 : m_pszGeometry = NULL;
485 6684 : m_nGeomAlloc = m_nGeomLen = 0;
486 : }
487 : }
488 :
489 : /* -------------------------------------------------------------------- */
490 : /* If we are collecting a feature, and this element tag matches */
491 : /* element name for the class, then we have finished the */
492 : /* feature, and we pop the feature read state. */
493 : /* -------------------------------------------------------------------- */
494 610406 : if( m_nDepth == m_nDepthFeature && poState->m_poFeature != NULL
495 : && EQUAL(szElementName,
496 : poState->m_poFeature->GetClass()->GetElementName()) )
497 : {
498 8728 : m_nDepthFeature = 0;
499 8728 : m_poReader->PopState();
500 : }
501 :
502 : /* -------------------------------------------------------------------- */
503 : /* Ends of a wfs:Delete should be triggered on the close of the */
504 : /* <Filter> element. */
505 : /* -------------------------------------------------------------------- */
506 601678 : else if( m_nDepth == m_nDepthFeature
507 : && poState->m_poFeature != NULL
508 : && EQUAL(szElementName,"Filter")
509 : && EQUAL(poState->m_poFeature->GetClass()->GetElementName(),
510 : "Delete") )
511 : {
512 6 : m_nDepthFeature = 0;
513 6 : m_poReader->PopState();
514 : }
515 :
516 : /* -------------------------------------------------------------------- */
517 : /* Otherwise, we just pop the element off the local read states */
518 : /* element stack. */
519 : /* -------------------------------------------------------------------- */
520 : else
521 : {
522 601672 : if( EQUAL(szElementName,poState->GetLastComponent()) )
523 601672 : poState->PopPath();
524 : else
525 : {
526 0 : CPLAssert( FALSE );
527 : }
528 : }
529 : }
530 :
531 : /************************************************************************/
532 : /* characters() */
533 : /************************************************************************/
534 :
535 : #if XERCES_VERSION_MAJOR >= 3
536 : void NASHandler::characters( const XMLCh *const chars_in,
537 : const XMLSize_t length )
538 : #else
539 4417187 : void NASHandler::characters(const XMLCh* const chars_in,
540 : const unsigned int length )
541 : #endif
542 :
543 : {
544 4417187 : const XMLCh *chars = chars_in;
545 :
546 4417187 : if( m_pszCurField != NULL )
547 : {
548 35363 : int nCurFieldLength = strlen(m_pszCurField);
549 :
550 35363 : if (nCurFieldLength == 0)
551 : {
552 : // Ignore white space
553 70920 : while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
554 194 : chars++;
555 : }
556 :
557 35363 : char *pszTranslated = tr_strdup(chars);
558 :
559 35363 : if( m_pszCurField == NULL )
560 : {
561 0 : m_pszCurField = pszTranslated;
562 0 : nCurFieldLength = strlen(m_pszCurField);
563 : }
564 : else
565 : {
566 : m_pszCurField = (char *)
567 : CPLRealloc( m_pszCurField,
568 35363 : nCurFieldLength+strlen(pszTranslated)+1 );
569 35363 : strcpy( m_pszCurField + nCurFieldLength, pszTranslated );
570 35363 : CPLFree( pszTranslated );
571 : }
572 : }
573 4381824 : else if( m_pszGeometry != NULL )
574 : {
575 892804 : if (m_nGeomLen == 0)
576 : {
577 : // Ignore white space
578 0 : while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
579 0 : chars++;
580 : }
581 :
582 892804 : int nCharsLen = tr_strlen(chars);
583 :
584 892804 : if( m_nGeomLen + nCharsLen*4 + 4 > m_nGeomAlloc )
585 : {
586 11966 : m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nCharsLen*4 + 1000);
587 : m_pszGeometry = (char *)
588 11966 : CPLRealloc( m_pszGeometry, m_nGeomAlloc);
589 : }
590 :
591 892804 : tr_strcpy( m_pszGeometry+m_nGeomLen, chars );
592 892804 : m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
593 : }
594 4417187 : }
595 :
596 : /************************************************************************/
597 : /* fatalError() */
598 : /************************************************************************/
599 :
600 0 : void NASHandler::fatalError( const SAXParseException &exception)
601 :
602 : {
603 : char *pszErrorMessage;
604 :
605 0 : pszErrorMessage = tr_strdup( exception.getMessage() );
606 : CPLError( CE_Failure, CPLE_AppDefined,
607 : "XML Parsing Error: %s at line %d, column %d\n",
608 0 : pszErrorMessage, (int)exception.getLineNumber(), (int)exception.getColumnNumber() );
609 :
610 0 : CPLFree( pszErrorMessage );
611 0 : }
612 :
613 : /************************************************************************/
614 : /* IsGeometryElement() */
615 : /************************************************************************/
616 :
617 228283 : int NASHandler::IsGeometryElement( const char *pszElement )
618 :
619 : {
620 : return strcmp(pszElement,"Polygon") == 0
621 : || strcmp(pszElement,"MultiPolygon") == 0
622 : || strcmp(pszElement,"MultiPoint") == 0
623 : || strcmp(pszElement,"MultiLineString") == 0
624 : || strcmp(pszElement,"MultiSurface") == 0
625 : || strcmp(pszElement,"GeometryCollection") == 0
626 : || strcmp(pszElement,"Point") == 0
627 : || strcmp(pszElement,"Curve") == 0
628 : || strcmp(pszElement,"MultiCurve") == 0
629 : || strcmp(pszElement,"CompositeCurve") == 0
630 : || strcmp(pszElement,"Surface") == 0
631 : || strcmp(pszElement,"PolygonPatch") == 0
632 228283 : || strcmp(pszElement,"LineString") == 0;
633 : }
|