1 /*
2
3 gg_gml.c -- GML parser/lexer
4
5 version 5.0, 2020 August 1
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 ------------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2011-2021
28 the Initial Developer. All Rights Reserved.
29
30 Alternatively, the contents of this file may be used under the terms of
31 either the GNU General Public License Version 2 or later (the "GPL"), or
32 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 in which case the provisions of the GPL or the LGPL are applicable instead
34 of those above. If you wish to allow use of your version of this file only
35 under the terms of either the GPL or the LGPL, and not to allow others to
36 use your version of this file under the terms of the MPL, indicate your
37 decision by deleting the provisions above and replace them with the notice
38 and other provisions required by the GPL or the LGPL. If you do not delete
39 the provisions above, a recipient may use your version of this file under
40 the terms of any one of the MPL, the GPL or the LGPL.
41
42 */
43
44 #include <sys/types.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48
49 #include <assert.h>
50
51 #if defined(_WIN32) && !defined(__MINGW32__)
52 #include "config-msvc.h"
53 #else
54 #include "config.h"
55 #endif
56
57 #include <spatialite/sqlite.h>
58 #include <spatialite/debug.h>
59
60 #include <spatialite/gaiageo.h>
61 #include <spatialite_private.h>
62
63 #if defined(_WIN32) || defined(WIN32)
64 #include <io.h>
65 #ifndef isatty
66 #define isatty _isatty
67 #endif
68 #ifndef fileno
69 #define fileno _fileno
70 #endif
71 #endif
72
73 #define GML_PARSER_OPEN_NODE 1
74 #define GML_PARSER_SELF_CLOSED_NODE 2
75 #define GML_PARSER_CLOSED_NODE 3
76
77 #define GAIA_GML_UNKNOWN 0
78 #define GAIA_GML_POINT 1
79 #define GAIA_GML_LINESTRING 2
80 #define GAIA_GML_CURVE 3
81 #define GAIA_GML_POLYGON 4
82 #define GAIA_GML_MULTIPOINT 5
83 #define GAIA_GML_MULTILINESTRING 6
84 #define GAIA_GML_MULTICURVE 7
85 #define GAIA_GML_MULTIPOLYGON 8
86 #define GAIA_GML_MULTISURFACE 9
87 #define GAIA_GML_MULTIGEOMETRY 10
88 #define GAIA_GML_BOX 11
89
90 #define GML_DYN_NONE 0
91 #define GML_DYN_DYNLINE 1
92 #define GML_DYN_GEOM 2
93 #define GML_DYN_DYNPG 3
94 #define GML_DYN_NODE 4
95 #define GML_DYN_COORD 5
96 #define GML_DYN_ATTRIB 6
97
98 #define GML_DYN_BLOCK 1024
99
100
101
102 /*
103 ** CAVEAT: we must redefine any Lemon/Flex own macro
104 */
105 #define YYMINORTYPE GML_MINORTYPE
106 #define YY_CHAR GML_YY_CHAR
107 #define input gml_input
108 #define ParseAlloc gmlParseAlloc
109 #define ParseFree gmlParseFree
110 #define ParseStackPeak gmlParseStackPeak
111 #define Parse gmlParse
112 #define yyStackEntry gml_yyStackEntry
113 #define yyzerominor gml_yyzerominor
114 #define yy_accept gml_yy_accept
115 #define yy_action gml_yy_action
116 #define yy_base gml_yy_base
117 #define yy_buffer_stack gml_yy_buffer_stack
118 #define yy_buffer_stack_max gml_yy_buffer_stack_max
119 #define yy_buffer_stack_top gml_yy_buffer_stack_top
120 #define yy_c_buf_p gml_yy_c_buf_p
121 #define yy_chk gml_yy_chk
122 #define yy_def gml_yy_def
123 #define yy_default gml_yy_default
124 #define yy_destructor gml_yy_destructor
125 #define yy_ec gml_yy_ec
126 #define yy_fatal_error gml_yy_fatal_error
127 #define yy_find_reduce_action gml_yy_find_reduce_action
128 #define yy_find_shift_action gml_yy_find_shift_action
129 #define yy_get_next_buffer gml_yy_get_next_buffer
130 #define yy_get_previous_state gml_yy_get_previous_state
131 #define yy_init gml_yy_init
132 #define yy_init_globals gml_yy_init_globals
133 #define yy_lookahead gml_yy_lookahead
134 #define yy_meta gml_yy_meta
135 #define yy_nxt gml_yy_nxt
136 #define yy_parse_failed gml_yy_parse_failed
137 #define yy_pop_parser_stack gml_yy_pop_parser_stack
138 #define yy_reduce gml_yy_reduce
139 #define yy_reduce_ofst gml_yy_reduce_ofst
140 #define yy_shift gml_yy_shift
141 #define yy_shift_ofst gml_yy_shift_ofst
142 #define yy_start gml_yy_start
143 #define yy_state_type gml_yy_state_type
144 #define yy_syntax_error gml_yy_syntax_error
145 #define yy_trans_info gml_yy_trans_info
146 #define yy_try_NUL_trans gml_yy_try_NUL_trans
147 #define yyParser gml_yyParser
148 #define yyStackEntry gml_yyStackEntry
149 #define yyStackOverflow gml_yyStackOverflow
150 #define yyRuleInfo gml_yyRuleInfo
151 #define yyunput gml_yyunput
152 #define yyzerominor gml_yyzerominor
153 #define yyTraceFILE gml_yyTraceFILE
154 #define yyTracePrompt gml_yyTracePrompt
155 #define yyTokenName gml_yyTokenName
156 #define yyRuleName gml_yyRuleName
157 #define ParseTrace gml_ParseTrace
158
159 #define yylex gml_yylex
160 #define YY_DECL int yylex (yyscan_t yyscanner)
161
162
163 /* include LEMON generated header */
164 #include "Gml.h"
165
166
167 typedef union
168 {
169 char *pval;
170 struct symtab *symp;
171 } gml_yystype;
172 #define YYSTYPE gml_yystype
173
174
175 /*
176 ** This is a linked-list struct to store all the values for each token.
177 */
178 typedef struct gmlFlexTokenStruct
179 {
180 char *value;
181 struct gmlFlexTokenStruct *Next;
182 } gmlFlexToken;
183
184 typedef struct gml_coord
185 {
186 char *Value;
187 struct gml_coord *Next;
188 } gmlCoord;
189 typedef gmlCoord *gmlCoordPtr;
190
191 typedef struct gml_attr
192 {
193 char *Key;
194 char *Value;
195 struct gml_attr *Next;
196 } gmlAttr;
197 typedef gmlAttr *gmlAttrPtr;
198
199 typedef struct gml_node
200 {
201 char *Tag;
202 int Type;
203 int Error;
204 struct gml_attr *Attributes;
205 struct gml_coord *Coordinates;
206 struct gml_node *Next;
207 } gmlNode;
208 typedef gmlNode *gmlNodePtr;
209
210 typedef struct gml_dynamic_ring
211 {
212 gaiaDynamicLinePtr ring;
213 int interior;
214 int has_z;
215 struct gml_dynamic_ring *next;
216 } gmlDynamicRing;
217 typedef gmlDynamicRing *gmlDynamicRingPtr;
218
219 typedef struct gml_dynamic_polygon
220 {
221 struct gml_dynamic_ring *first;
222 struct gml_dynamic_ring *last;
223 } gmlDynamicPolygon;
224 typedef gmlDynamicPolygon *gmlDynamicPolygonPtr;
225
226 struct gml_dyn_block
227 {
228 /* a struct taking trace of dynamic allocations */
229 int type[GML_DYN_BLOCK];
230 void *ptr[GML_DYN_BLOCK];
231 int index;
232 struct gml_dyn_block *next;
233 };
234
235 struct gml_data
236 {
237 /* a struct used to make the lexer-parser reentrant and thread-safe */
238 int gml_parse_error;
239 int gml_line;
240 int gml_col;
241 struct gml_dyn_block *gml_first_dyn_block;
242 struct gml_dyn_block *gml_last_dyn_block;
243 gmlNodePtr result;
244 YYSTYPE GmlLval;
245 };
246
247 static struct gml_dyn_block *
gmlCreateDynBlock(void)248 gmlCreateDynBlock (void)
249 {
250 /* allocating a new block to trace dynamic allocations */
251 int i;
252 struct gml_dyn_block *p = malloc (sizeof (struct gml_dyn_block));
253 for (i = 0; i < GML_DYN_BLOCK; i++)
254 {
255 /* initializing map entries */
256 p->type[i] = GML_DYN_NONE;
257 p->ptr[i] = NULL;
258 }
259 p->index = 0;
260 p->next = NULL;
261 return p;
262 }
263
264 static void
gmlMapDynAlloc(struct gml_data * p_data,int type,void * ptr)265 gmlMapDynAlloc (struct gml_data *p_data, int type, void *ptr)
266 {
267 /* appending a dynamic allocation into the map */
268 struct gml_dyn_block *p;
269 if (p_data->gml_first_dyn_block == NULL)
270 {
271 /* inserting the first block of the map */
272 p = gmlCreateDynBlock ();
273 p_data->gml_first_dyn_block = p;
274 p_data->gml_last_dyn_block = p;
275 }
276 if (p_data->gml_last_dyn_block->index >= GML_DYN_BLOCK)
277 {
278 /* adding a further block to the map */
279 p = gmlCreateDynBlock ();
280 p_data->gml_last_dyn_block->next = p;
281 p_data->gml_last_dyn_block = p;
282 }
283 p_data->gml_last_dyn_block->type[p_data->gml_last_dyn_block->index] = type;
284 p_data->gml_last_dyn_block->ptr[p_data->gml_last_dyn_block->index] = ptr;
285 p_data->gml_last_dyn_block->index++;
286 }
287
288 static void
gmlMapDynClean(struct gml_data * p_data,void * ptr)289 gmlMapDynClean (struct gml_data *p_data, void *ptr)
290 {
291 /* deleting a dynamic allocation from the map */
292 int i;
293 struct gml_dyn_block *p = p_data->gml_first_dyn_block;
294 while (p)
295 {
296 for (i = 0; i < GML_DYN_BLOCK; i++)
297 {
298 switch (p->type[i])
299 {
300 case GML_DYN_DYNLINE:
301 case GML_DYN_GEOM:
302 case GML_DYN_DYNPG:
303 case GML_DYN_NODE:
304 case GML_DYN_COORD:
305 case GML_DYN_ATTRIB:
306 if (p->ptr[i] == ptr)
307 {
308 p->type[i] = GML_DYN_NONE;
309 return;
310 }
311 break;
312 };
313 }
314 p = p->next;
315 }
316 }
317
318 static void
gml_free_dyn_polygon(gmlDynamicPolygonPtr dyn)319 gml_free_dyn_polygon (gmlDynamicPolygonPtr dyn)
320 {
321 /* deleting a dynamic polygon (ring collection) */
322 gmlDynamicRingPtr r;
323 gmlDynamicRingPtr rn;
324 if (!dyn)
325 return;
326 r = dyn->first;
327 while (r)
328 {
329 rn = r->next;
330 if (r->ring)
331 gaiaFreeDynamicLine (r->ring);
332 free (r);
333 r = rn;
334 }
335 free (dyn);
336 }
337
338 static void
gml_free_coord(gmlCoordPtr c)339 gml_free_coord (gmlCoordPtr c)
340 {
341 /* deleting a GML coordinate */
342 if (c == NULL)
343 return;
344 if (c->Value)
345 free (c->Value);
346 free (c);
347 }
348
349 static void
gml_free_attrib(gmlAttrPtr a)350 gml_free_attrib (gmlAttrPtr a)
351 {
352 /* deleting a GML attribute */
353 if (a == NULL)
354 return;
355 if (a->Key)
356 free (a->Key);
357 if (a->Value)
358 free (a->Value);
359 free (a);
360 }
361
362 static void
gml_free_node(gmlNodePtr n)363 gml_free_node (gmlNodePtr n)
364 {
365 /* deleting a GML node */
366 gmlAttrPtr a;
367 gmlAttrPtr an;
368 gmlCoordPtr c;
369 gmlCoordPtr cn;
370 if (n == NULL)
371 return;
372 a = n->Attributes;
373 while (a)
374 {
375 an = a->Next;
376 gml_free_attrib (a);
377 a = an;
378 }
379 c = n->Coordinates;
380 while (c)
381 {
382 cn = c->Next;
383 gml_free_coord (c);
384 c = cn;
385 }
386 if (n->Tag)
387 free (n->Tag);
388 free (n);
389 }
390
391 static void
gmlCleanMapDynAlloc(struct gml_data * p_data,int clean_all)392 gmlCleanMapDynAlloc (struct gml_data *p_data, int clean_all)
393 {
394 /* cleaning the dynamic allocations map */
395 int i;
396 struct gml_dyn_block *pn;
397 struct gml_dyn_block *p = p_data->gml_first_dyn_block;
398 while (p)
399 {
400 if (clean_all)
401 {
402 for (i = 0; i < GML_DYN_BLOCK; i++)
403 {
404 /* deleting Geometry objects */
405 switch (p->type[i])
406 {
407 case GML_DYN_DYNLINE:
408 gaiaFreeDynamicLine ((gaiaDynamicLinePtr)
409 (p->ptr[i]));
410 break;
411 case GML_DYN_GEOM:
412 gaiaFreeGeomColl ((gaiaGeomCollPtr) (p->ptr[i]));
413 break;
414 case GML_DYN_DYNPG:
415 gml_free_dyn_polygon ((gmlDynamicPolygonPtr)
416 (p->ptr[i]));
417 break;
418 case GML_DYN_NODE:
419 gml_free_node ((gmlNodePtr) (p->ptr[i]));
420 break;
421 case GML_DYN_COORD:
422 gml_free_coord ((gmlCoordPtr) (p->ptr[i]));
423 break;
424 case GML_DYN_ATTRIB:
425 gml_free_attrib ((gmlAttrPtr) (p->ptr[i]));
426 break;
427 };
428 }
429 }
430 /* deleting the map block */
431 pn = p->next;
432 free (p);
433 p = pn;
434 }
435 }
436
437 static gmlDynamicPolygonPtr
gml_alloc_dyn_polygon(struct gml_data * p_data)438 gml_alloc_dyn_polygon (struct gml_data *p_data)
439 {
440 /* creating a dynamic polygon (ring collection) */
441 gmlDynamicPolygonPtr p = malloc (sizeof (gmlDynamicPolygon));
442 gmlMapDynAlloc (p_data, GML_DYN_DYNPG, p);
443 p->first = NULL;
444 p->last = NULL;
445 return p;
446 }
447
448 static void
gml_add_polygon_ring(struct gml_data * p_data,gmlDynamicPolygonPtr dyn_pg,gaiaDynamicLinePtr dyn,int interior,int has_z)449 gml_add_polygon_ring (struct gml_data *p_data, gmlDynamicPolygonPtr dyn_pg,
450 gaiaDynamicLinePtr dyn, int interior, int has_z)
451 {
452 /* inserting a further ring into the collection (dynamic polygon) */
453 gmlDynamicRingPtr p = malloc (sizeof (gmlDynamicRing));
454 p->ring = dyn;
455 p->interior = interior;
456 p->has_z = has_z;
457 p->next = NULL;
458 if (dyn_pg->first == NULL)
459 dyn_pg->first = p;
460 if (dyn_pg->last != NULL)
461 dyn_pg->last->next = p;
462 dyn_pg->last = p;
463 gmlMapDynClean (p_data, p);
464 }
465
466 static void
gml_freeString(char ** ptr)467 gml_freeString (char **ptr)
468 {
469 /* releasing a string from the lexer */
470 if (*ptr != NULL)
471 free (*ptr);
472 *ptr = NULL;
473 }
474
475 static void
gml_saveString(char ** ptr,const char * str)476 gml_saveString (char **ptr, const char *str)
477 {
478 /* saving a string from the lexer */
479 int len = strlen (str);
480 gml_freeString (ptr);
481 *ptr = malloc (len + 1);
482 strcpy (*ptr, str);
483 }
484
485 static gmlCoordPtr
gml_coord(struct gml_data * p_data,void * value)486 gml_coord (struct gml_data *p_data, void *value)
487 {
488 /* creating a coord Item */
489 int len;
490 gmlFlexToken *tok = (gmlFlexToken *) value;
491 gmlCoordPtr c = malloc (sizeof (gmlCoord));
492 gmlMapDynAlloc (p_data, GML_DYN_COORD, c);
493 len = strlen (tok->value);
494 c->Value = malloc (len + 1);
495 strcpy (c->Value, tok->value);
496 c->Next = NULL;
497 return c;
498 }
499
500 static gmlAttrPtr
gml_attribute(struct gml_data * p_data,void * key,void * value)501 gml_attribute (struct gml_data *p_data, void *key, void *value)
502 {
503 /* creating an attribute */
504 int len;
505 gmlFlexToken *k_tok = (gmlFlexToken *) key;
506 gmlFlexToken *v_tok = (gmlFlexToken *) value;
507 gmlAttrPtr a = malloc (sizeof (gmlAttr));
508 gmlMapDynAlloc (p_data, GML_DYN_ATTRIB, a);
509 len = strlen (k_tok->value);
510 a->Key = malloc (len + 1);
511 strcpy (a->Key, k_tok->value);
512 len = strlen (v_tok->value);
513 /* we need to de-quote the string, removing first and last ".." */
514 if (*(v_tok->value + 0) == '"' && *(v_tok->value + len - 1) == '"')
515 {
516 int bytesToCopy = len - 2;
517 char *startingPointForCopy = v_tok->value + 1;
518 a->Value = malloc (bytesToCopy + 1);
519 memcpy (a->Value, startingPointForCopy, bytesToCopy);
520 *(a->Value + bytesToCopy) = '\0';
521 }
522 else
523 {
524 a->Value = malloc (len + 1);
525 strcpy (a->Value, v_tok->value);
526 }
527 a->Next = NULL;
528 return a;
529 }
530
531 static void
gml_freeTree(struct gml_data * p_data,gmlNodePtr t)532 gml_freeTree (struct gml_data *p_data, gmlNodePtr t)
533 {
534 /* deleting a GML tree */
535 gmlNodePtr n;
536 gmlNodePtr nn;
537 n = t;
538 while (n)
539 {
540 nn = n->Next;
541 gmlMapDynClean (p_data, n);
542 gml_free_node (n);
543 n = nn;
544 }
545 }
546
547 static gmlNodePtr
gml_createNode(struct gml_data * p_data,void * tag,void * attributes,void * coords)548 gml_createNode (struct gml_data *p_data, void *tag, void *attributes,
549 void *coords)
550 {
551 /* creating a node */
552 gmlAttrPtr a;
553 gmlCoordPtr c;
554 int len;
555 gmlFlexToken *tok = (gmlFlexToken *) tag;
556 gmlNodePtr n = malloc (sizeof (gmlNode));
557 gmlMapDynAlloc (p_data, GML_DYN_NODE, n);
558 len = strlen (tok->value);
559 n->Tag = malloc (len + 1);
560 strcpy (n->Tag, tok->value);
561 n->Type = GML_PARSER_OPEN_NODE;
562 n->Error = 0;
563 a = (gmlAttrPtr) attributes;
564 while (a)
565 {
566 /* transferring ownership of attributes */
567 gmlMapDynClean (p_data, a);
568 a = a->Next;
569 }
570 n->Attributes = attributes;
571 c = (gmlCoordPtr) coords;
572 while (c)
573 {
574 /* transferring ownership of attributes */
575 gmlMapDynClean (p_data, c);
576 c = c->Next;
577 }
578 n->Coordinates = coords;
579 n->Next = NULL;
580 return n;
581 }
582
583 static gmlNodePtr
gml_createSelfClosedNode(struct gml_data * p_data,void * tag,void * attributes)584 gml_createSelfClosedNode (struct gml_data *p_data, void *tag, void *attributes)
585 {
586 /* creating a self-closed node */
587 gmlAttrPtr a;
588 int len;
589 gmlFlexToken *tok = (gmlFlexToken *) tag;
590 gmlNodePtr n = malloc (sizeof (gmlNode));
591 gmlMapDynAlloc (p_data, GML_DYN_NODE, n);
592 len = strlen (tok->value);
593 n->Tag = malloc (len + 1);
594 strcpy (n->Tag, tok->value);
595 n->Type = GML_PARSER_SELF_CLOSED_NODE;
596 n->Error = 0;
597 a = (gmlAttrPtr) attributes;
598 while (a)
599 {
600 /* transferring ownership of attributes */
601 gmlMapDynClean (p_data, a);
602 a = a->Next;
603 }
604 n->Attributes = attributes;
605 n->Coordinates = NULL;
606 n->Next = NULL;
607 return n;
608 }
609
610 static gmlNodePtr
gml_closingNode(struct gml_data * p_data,void * tag)611 gml_closingNode (struct gml_data *p_data, void *tag)
612 {
613 /* creating a closing node */
614 int len;
615 gmlFlexToken *tok = (gmlFlexToken *) tag;
616 gmlNodePtr n = malloc (sizeof (gmlNode));
617 gmlMapDynAlloc (p_data, GML_DYN_NODE, n);
618 len = strlen (tok->value);
619 n->Tag = malloc (len + 1);
620 strcpy (n->Tag, tok->value);
621 n->Type = GML_PARSER_CLOSED_NODE;
622 n->Error = 0;
623 n->Attributes = NULL;
624 n->Coordinates = NULL;
625 n->Next = NULL;
626 return n;
627 }
628
629 static int
gml_cleanup(gmlFlexToken * token)630 gml_cleanup (gmlFlexToken * token)
631 {
632 gmlFlexToken *ptok;
633 gmlFlexToken *ptok_n;
634 if (token == NULL)
635 return 0;
636 ptok = token;
637 while (ptok)
638 {
639 ptok_n = ptok->Next;
640 if (ptok->value != NULL)
641 free (ptok->value);
642 free (ptok);
643 ptok = ptok_n;
644 }
645 return 0;
646 }
647
648 static void
gml_xferString(char ** p,const char * str)649 gml_xferString (char **p, const char *str)
650 {
651 /* saving some token */
652 int len;
653 if (str == NULL)
654 {
655 *p = NULL;
656 return;
657 }
658 len = strlen (str);
659 *p = malloc (len + 1);
660 strcpy (*p, str);
661 }
662
663 static int
gml_get_srid(gmlNodePtr node)664 gml_get_srid (gmlNodePtr node)
665 {
666 /* attempting to guess the SRID */
667 int len;
668 gmlAttrPtr attr = node->Attributes;
669 while (attr)
670 {
671 if (strcmp (attr->Key, "srsName") == 0)
672 {
673 len = strlen (attr->Value);
674 if (len > 5)
675 {
676 if (strncmp (attr->Value, "EPSG:", 5) == 0)
677 return atoi (attr->Value + 5);
678 }
679 if (len > 21)
680 {
681 if (strncmp (attr->Value, "urn:ogc:def:crs:EPSG:", 21) ==
682 0)
683 {
684 int i = strlen (attr->Value) - 1;
685 for (; i >= 0; i--)
686 {
687 if (*(attr->Value + i) == ':')
688 return atoi (attr->Value + i + 1);
689 }
690 }
691 }
692 if (len > 40)
693 {
694 if (strncmp
695 (attr->Value,
696 "http://www.opengis.net/gml/srs/epsg.xml#", 40) == 0)
697 {
698 int i = strlen (attr->Value) - 1;
699 for (; i >= 0; i--)
700 {
701 if (*(attr->Value + i) == '#')
702 return atoi (attr->Value + i + 1);
703 }
704 }
705 }
706 }
707 attr = attr->Next;
708 }
709 return -1;
710 }
711
712 static int
guessGmlSrid(gmlNodePtr node)713 guessGmlSrid (gmlNodePtr node)
714 {
715 /* attempting to guess the SRID */
716 int srid = -1;
717 gmlNodePtr n = node;
718 while (n)
719 {
720 /* looping on GML Members */
721 srid = gml_get_srid (n);
722 if (srid >= 0)
723 return srid;
724 n = n->Next;
725 }
726 return srid;
727 }
728
729 static int
gml_get_dimension(gmlNodePtr node)730 gml_get_dimension (gmlNodePtr node)
731 {
732 /* attempting to establish if there is a Z coordinate */
733 gmlAttrPtr attr = node->Attributes;
734 while (attr)
735 {
736 if (strcmp (attr->Key, "srsDimension") == 0)
737 {
738 if (atoi (attr->Value) == 3)
739 return 3;
740 else
741 return 2;
742 }
743 if (strcmp (attr->Key, "dimension") == 0)
744 {
745 if (atoi (attr->Value) == 3)
746 return 3;
747 else
748 return 2;
749 }
750 attr = attr->Next;
751 }
752 return -1;
753 }
754
755 static int
gml_check_coord(const char * value)756 gml_check_coord (const char *value)
757 {
758 /* checking a GML coordinate */
759 int decimal = 0;
760 int exp = 0;
761 int expsign = 0;
762 const char *p = value;
763 if (*p == '+' || *p == '-')
764 p++;
765 while (*p != '\0')
766 {
767 if (*p == '.')
768 {
769 if (!decimal)
770 decimal = 1;
771 else
772 return 0;
773 }
774 else if (*p >= '0' && *p <= '9')
775 ;
776 else if (*p == 'e' || *p == 'E')
777 exp++;
778 else if (*p == '+' || *p == '-')
779 {
780 if (!exp)
781 return 0;
782 expsign++;
783 }
784 else
785 return 0;
786 p++;
787 }
788 if (exp > 1 || expsign > 1)
789 return 0;
790 return 1;
791 }
792
793 static int
gml_check_coords(const char * value)794 gml_check_coords (const char *value)
795 {
796 /* extracting GML v2.x coords from a comma-separated string */
797 const char *in = value;
798 int count = 0;
799 char buf[1024];
800 char *out = buf;
801 *out = '\0';
802
803 while (*in != '\0')
804 {
805 if (*in == ',')
806 {
807 *out = '\0';
808 if (*buf != '\0')
809 {
810 if (!gml_check_coord (buf))
811 return 0;
812 switch (count)
813 {
814 case 0:
815 count += 1;
816 break;
817 case 1:
818 count += 1;
819 break;
820 case 2:
821 count += 1;
822 break;
823 default:
824 count += 1;
825 break;
826 };
827 }
828 in++;
829 out = buf;
830 *out = '\0';
831 continue;
832 }
833 *out++ = *in++;
834 }
835 *out = '\0';
836 /* parsing the last item */
837 if (*buf != '\0')
838 {
839 if (!gml_check_coord (buf))
840 return 0;
841 switch (count)
842 {
843 case 0:
844 count += 1;
845 break;
846 case 1:
847 count += 1;
848 break;
849 case 2:
850 count += 1;
851 break;
852 default:
853 count += 1;
854 break;
855 };
856 }
857 if (count == 2 || count == 3)
858 return count;
859 return -1;
860 }
861
862 static int
gml_check_point_v2(gmlCoordPtr coord)863 gml_check_point_v2 (gmlCoordPtr coord)
864 {
865 /* Dimensions for GML v2.x <gml:coordinates> [Point] */
866 int count = 0;
867 gmlCoordPtr c = coord;
868 while (c)
869 {
870 count = gml_check_coords (c->Value);
871 if (count == 2 || count == 3)
872 return count;
873 c = c->Next;
874 }
875 return -1;
876 }
877
878 static int
gml_check_point_v3(gmlCoordPtr coord)879 gml_check_point_v3 (gmlCoordPtr coord)
880 {
881 /* Dimensions for GML v2.x <gml:pos> [Point] */
882 int count = 0;
883 gmlCoordPtr c = coord;
884 while (c)
885 {
886 if (!gml_check_coord (c->Value))
887 return 0;
888 switch (count)
889 {
890 case 0:
891 count++;
892 break;
893 case 1:
894 count++;
895 break;
896 case 2:
897 count++;
898 break;
899 default:
900 count++;
901 break;
902 };
903 c = c->Next;
904 }
905 if (count == 2 || count == 3)
906 return count;
907 return -1;
908 }
909
910 static int
guessGmlDimensions(gmlNodePtr node)911 guessGmlDimensions (gmlNodePtr node)
912 {
913 int dims = -1;
914 gmlNodePtr n = node;
915 while (n)
916 {
917 /* looping on GML Members */
918 dims = gml_get_dimension (n);
919 if (dims == 2 || dims == 3)
920 return dims;
921
922 if (strcmp (n->Tag, "gml:coordinates") == 0
923 || strcmp (n->Tag, "coordinates") == 0)
924 {
925 dims = gml_check_point_v2 (n->Coordinates);
926 if (dims == 2 || dims == 3)
927 return dims;
928 }
929 if (strcmp (n->Tag, "gml:pos") == 0 || strcmp (n->Tag, "pos") == 0)
930 {
931 dims = gml_check_point_v3 (n->Coordinates);
932 if (dims == 2 || dims == 3)
933 return dims;
934 }
935 n = n->Next;
936 }
937 return 2;
938 }
939
940 static int
guessGmlGeometryType(gmlNodePtr node)941 guessGmlGeometryType (gmlNodePtr node)
942 {
943 /* attempting to guess the Geometry Type for a GML node */
944 int type = GAIA_GML_UNKNOWN;
945 if (strcmp (node->Tag, "gml:Point") == 0
946 || strcmp (node->Tag, "Point") == 0)
947 type = GAIA_GML_POINT;
948 if (strcmp (node->Tag, "gml:LineString") == 0
949 || strcmp (node->Tag, "LineString") == 0)
950 type = GAIA_GML_LINESTRING;
951 if (strcmp (node->Tag, "gml:Curve") == 0
952 || strcmp (node->Tag, "Curve") == 0)
953 type = GAIA_GML_CURVE;
954 if (strcmp (node->Tag, "gml:Polygon") == 0
955 || strcmp (node->Tag, "Polygon") == 0)
956 type = GAIA_GML_POLYGON;
957 if (strcmp (node->Tag, "gml:MultiPoint") == 0
958 || strcmp (node->Tag, "MultiPoint") == 0)
959 type = GAIA_GML_MULTIPOINT;
960 if (strcmp (node->Tag, "gml:MultiLineString") == 0
961 || strcmp (node->Tag, "MultiLineString") == 0)
962 type = GAIA_GML_MULTILINESTRING;
963 if (strcmp (node->Tag, "gml:MultiCurve") == 0
964 || strcmp (node->Tag, "MultiCurve") == 0)
965 type = GAIA_GML_MULTICURVE;
966 if (strcmp (node->Tag, "gml:MultiPolygon") == 0
967 || strcmp (node->Tag, "MultiPolygon") == 0)
968 type = GAIA_GML_MULTIPOLYGON;
969 if (strcmp (node->Tag, "gml:MultiSurface") == 0
970 || strcmp (node->Tag, "MultiSurface") == 0)
971 type = GAIA_GML_MULTISURFACE;
972 if (strcmp (node->Tag, "gml:MultiGeometry") == 0
973 || strcmp (node->Tag, "MultiGeometry") == 0)
974 type = GAIA_GML_MULTIGEOMETRY;
975 if (strcmp (node->Tag, "gml:Box") == 0 || strcmp (node->Tag, "Box") == 0)
976 type = GAIA_GML_BOX;
977 return type;
978 }
979
980 static int
gml_extract_coords(const char * value,double * x,double * y,double * z,int * count)981 gml_extract_coords (const char *value, double *x, double *y, double *z,
982 int *count)
983 {
984 /* extracting GML v2.x coords from a comma-separated string */
985 const char *in = value;
986 char buf[1024];
987 char *out = buf;
988 *out = '\0';
989
990 while (*in != '\0')
991 {
992 if (*in == ',')
993 {
994 *out = '\0';
995 if (*buf != '\0')
996 {
997 if (!gml_check_coord (buf))
998 return 0;
999 switch (*count)
1000 {
1001 case 0:
1002 *x = atof (buf);
1003 *count += 1;
1004 break;
1005 case 1:
1006 *y = atof (buf);
1007 *count += 1;
1008 break;
1009 case 2:
1010 *z = atof (buf);
1011 *count += 1;
1012 break;
1013 default:
1014 *count += 1;
1015 break;
1016 };
1017 }
1018 in++;
1019 out = buf;
1020 *out = '\0';
1021 continue;
1022 }
1023 *out++ = *in++;
1024 }
1025 *out = '\0';
1026 /* parsing the last item */
1027 if (*buf != '\0')
1028 {
1029 if (!gml_check_coord (buf))
1030 return 0;
1031 switch (*count)
1032 {
1033 case 0:
1034 *x = atof (buf);
1035 *count += 1;
1036 break;
1037 case 1:
1038 *y = atof (buf);
1039 *count += 1;
1040 break;
1041 case 2:
1042 *z = atof (buf);
1043 *count += 1;
1044 break;
1045 default:
1046 *count += 1;
1047 break;
1048 };
1049 }
1050 return 1;
1051 }
1052
1053 static int
gml_parse_point_v2(gmlCoordPtr coord,double * x,double * y,double * z)1054 gml_parse_point_v2 (gmlCoordPtr coord, double *x, double *y, double *z)
1055 {
1056 /* parsing GML v2.x <gml:coordinates> [Point] */
1057 int count = 0;
1058 gmlCoordPtr c = coord;
1059 while (c)
1060 {
1061 if (!gml_extract_coords (c->Value, x, y, z, &count))
1062 return 0;
1063 c = c->Next;
1064 }
1065 if (count == 2)
1066 {
1067 *z = 0.0;
1068 return 1;
1069 }
1070 if (count == 3)
1071 return 1;
1072 return 0;
1073 }
1074
1075 static int
gml_parse_point_v3(gmlCoordPtr coord,double * x,double * y,double * z)1076 gml_parse_point_v3 (gmlCoordPtr coord, double *x, double *y, double *z)
1077 {
1078 /* parsing GML v2.x <gml:pos> [Point] */
1079 int count = 0;
1080 gmlCoordPtr c = coord;
1081 while (c)
1082 {
1083 if (!gml_check_coord (c->Value))
1084 return 0;
1085 switch (count)
1086 {
1087 case 0:
1088 *x = atof (c->Value);
1089 count++;
1090 break;
1091 case 1:
1092 *y = atof (c->Value);
1093 count++;
1094 break;
1095 case 2:
1096 *z = atof (c->Value);
1097 count++;
1098 break;
1099 default:
1100 count++;
1101 break;
1102 };
1103 c = c->Next;
1104 }
1105 if (count == 2)
1106 {
1107 *z = 0.0;
1108 return 1;
1109 }
1110 if (count == 3)
1111 return 1;
1112 return 0;
1113 }
1114
1115 static int
gml_parse_point(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node,gmlNodePtr * next)1116 gml_parse_point (struct gml_data *p_data, gaiaGeomCollPtr geom, gmlNodePtr node,
1117 gmlNodePtr * next)
1118 {
1119 /* parsing a <gml:Point> */
1120 int srid = geom->Srid;
1121 int has_z = 0;
1122 double x;
1123 double y;
1124 double z;
1125 gaiaGeomCollPtr pt;
1126 gaiaGeomCollPtr last;
1127 if (geom->DimensionModel == GAIA_XY_Z
1128 || geom->DimensionModel == GAIA_XY_Z_M)
1129 has_z = 1;
1130
1131 if (strcmp (node->Tag, "gml:coordinates") == 0
1132 || strcmp (node->Tag, "coordinates") == 0)
1133 {
1134 /* parsing a GML v.2.x <gml:Point> */
1135 if (!gml_parse_point_v2 (node->Coordinates, &x, &y, &z))
1136 return 0;
1137 node = node->Next;
1138 if (node == NULL)
1139 return 0;
1140 if (strcmp (node->Tag, "gml:coordinates") == 0
1141 || strcmp (node->Tag, "coordinates") == 0)
1142 ;
1143 else
1144 return 0;
1145 node = node->Next;
1146 if (node == NULL)
1147 return 0;
1148 if (strcmp (node->Tag, "gml:Point") == 0
1149 || strcmp (node->Tag, "Point") == 0)
1150 ;
1151 else
1152 return 0;
1153 *next = node->Next;
1154 goto ok;
1155 }
1156 if (strcmp (node->Tag, "gml:pos") == 0 || strcmp (node->Tag, "pos") == 0)
1157 {
1158 /* parsing a GML v.3.x <gml:Point> */
1159 if (!gml_parse_point_v3 (node->Coordinates, &x, &y, &z))
1160 return 0;
1161 node = node->Next;
1162 if (node == NULL)
1163 return 0;
1164 if (strcmp (node->Tag, "gml:pos") == 0
1165 || strcmp (node->Tag, "pos") == 0)
1166 ;
1167 else
1168 return 0;
1169 node = node->Next;
1170 if (node == NULL)
1171 return 0;
1172 if (strcmp (node->Tag, "gml:Point") == 0
1173 || strcmp (node->Tag, "Point") == 0)
1174 ;
1175 else
1176 return 0;
1177 *next = node->Next;
1178 goto ok;
1179 }
1180 return 0;
1181
1182 ok:
1183 /* ok, GML nodes match as expected */
1184 if (has_z)
1185 {
1186 pt = gaiaAllocGeomCollXYZ ();
1187 gmlMapDynAlloc (p_data, GML_DYN_GEOM, pt);
1188 pt->Srid = srid;
1189 gaiaAddPointToGeomCollXYZ (pt, x, y, z);
1190 }
1191 else
1192 {
1193 pt = gaiaAllocGeomColl ();
1194 gmlMapDynAlloc (p_data, GML_DYN_GEOM, pt);
1195 pt->Srid = srid;
1196 gaiaAddPointToGeomColl (pt, x, y);
1197 }
1198 last = geom;
1199 while (1)
1200 {
1201 /* searching the last Geometry within chain */
1202 if (last->Next == NULL)
1203 break;
1204 last = last->Next;
1205 }
1206 last->Next = pt;
1207 return 1;
1208 }
1209
1210 static int
gml_extract_multi_coord(const char * value,double * x,double * y,double * z,int * count,int * follow)1211 gml_extract_multi_coord (const char *value, double *x, double *y, double *z,
1212 int *count, int *follow)
1213 {
1214 /* extracting GML v2.x coords from a comma-separated string */
1215 const char *in = value;
1216 char buf[1024];
1217 char *out = buf;
1218 int last = ' ';
1219 *out = '\0';
1220 while (*in != '\0')
1221 {
1222 last = *in;
1223 if (*in == ',')
1224 {
1225 *out = '\0';
1226 if (*buf != '\0')
1227 {
1228 if (!gml_check_coord (buf))
1229 return 0;
1230 switch (*count)
1231 {
1232 case 0:
1233 *x = atof (buf);
1234 *count += 1;
1235 break;
1236 case 1:
1237 *y = atof (buf);
1238 *count += 1;
1239 break;
1240 case 2:
1241 *z = atof (buf);
1242 *count += 1;
1243 break;
1244 default:
1245 *count += 1;
1246 break;
1247 };
1248 }
1249 in++;
1250 out = buf;
1251 *out = '\0';
1252 continue;
1253 }
1254 *out++ = *in++;
1255 }
1256 *out = '\0';
1257 /* parsing the last item */
1258 if (*buf != '\0')
1259 {
1260 if (!gml_check_coord (buf))
1261 return 0;
1262 switch (*count)
1263 {
1264 case 0:
1265 *x = atof (buf);
1266 *count += 1;
1267 break;
1268 case 1:
1269 *y = atof (buf);
1270 *count += 1;
1271 break;
1272 case 2:
1273 *z = atof (buf);
1274 *count += 1;
1275 break;
1276 default:
1277 *count += 1;
1278 break;
1279 };
1280 }
1281 if (last == ',')
1282 *follow = 1;
1283 else
1284 *follow = 0;
1285 return 1;
1286 }
1287
1288 static int
gml_extract_multi_coords(gmlCoordPtr coord,double * x,double * y,double * z,int * count,gmlCoordPtr * next)1289 gml_extract_multi_coords (gmlCoordPtr coord, double *x, double *y, double *z,
1290 int *count, gmlCoordPtr * next)
1291 {
1292 /* extracting GML v2.x coords from a comma-separated string */
1293 int follow;
1294 gmlCoordPtr c = coord;
1295 while (c)
1296 {
1297 if (!gml_extract_multi_coord (c->Value, x, y, z, count, &follow))
1298 return 0;
1299 if (!follow && c->Next != NULL)
1300 {
1301 if (*(c->Next->Value) == ',')
1302 follow = 1;
1303 }
1304 if (follow)
1305 c = c->Next;
1306 else
1307 {
1308 *next = c->Next;
1309 break;
1310 }
1311 }
1312 return 1;
1313 }
1314
1315 static void
gml_add_point_to_line(gaiaDynamicLinePtr dyn,double x,double y)1316 gml_add_point_to_line (gaiaDynamicLinePtr dyn, double x, double y)
1317 {
1318 /* appending a point */
1319 gaiaAppendPointToDynamicLine (dyn, x, y);
1320 }
1321
1322 static void
gml_add_point_to_lineZ(gaiaDynamicLinePtr dyn,double x,double y,double z)1323 gml_add_point_to_lineZ (gaiaDynamicLinePtr dyn, double x, double y, double z)
1324 {
1325 /* appending a point */
1326 gaiaAppendPointZToDynamicLine (dyn, x, y, z);
1327 }
1328
1329 static int
gml_parse_coordinates(gmlCoordPtr coord,gaiaDynamicLinePtr dyn,int * has_z)1330 gml_parse_coordinates (gmlCoordPtr coord, gaiaDynamicLinePtr dyn, int *has_z)
1331 {
1332 /* parsing GML v2.x <gml:coordinates> [Linestring or Ring] */
1333 int count = 0;
1334 double x;
1335 double y;
1336 double z;
1337 gmlCoordPtr next = NULL;
1338 gmlCoordPtr c = coord;
1339 while (c)
1340 {
1341 if (!gml_extract_multi_coords (c, &x, &y, &z, &count, &next))
1342 return 0;
1343 if (count == 2)
1344 {
1345 *has_z = 0;
1346 gml_add_point_to_line (dyn, x, y);
1347 count = 0;
1348 }
1349 else if (count == 3)
1350 {
1351 *has_z = 1;
1352 gml_add_point_to_lineZ (dyn, x, y, z);
1353 count = 0;
1354 }
1355 else
1356 return 0;
1357 c = next;
1358 }
1359 return 1;
1360 }
1361
1362 static int
gml_parse_posList(gmlCoordPtr coord,gaiaDynamicLinePtr dyn,int has_z)1363 gml_parse_posList (gmlCoordPtr coord, gaiaDynamicLinePtr dyn, int has_z)
1364 {
1365 /* parsing GML v3.x <gml:posList> [Linestring or Ring] */
1366 int count = 0;
1367 double x = 0.0;
1368 double y = 0.0;
1369 double z = 0.0;
1370 gmlCoordPtr c = coord;
1371 if (has_z < 0)
1372 has_z = 0;
1373 while (c)
1374 {
1375 if (!gml_check_coord (c->Value))
1376 return 0;
1377 if (!has_z)
1378 {
1379 switch (count)
1380 {
1381 case 0:
1382 x = atof (c->Value);
1383 count++;
1384 break;
1385 case 1:
1386 y = atof (c->Value);
1387 gml_add_point_to_line (dyn, x, y);
1388 count = 0;
1389 break;
1390 };
1391 }
1392 else
1393 {
1394 switch (count)
1395 {
1396 case 0:
1397 x = atof (c->Value);
1398 count++;
1399 break;
1400 case 1:
1401 y = atof (c->Value);
1402 count++;
1403 break;
1404 case 2:
1405 z = atof (c->Value);
1406 gml_add_point_to_lineZ (dyn, x, y, z);
1407 count = 0;
1408 break;
1409 };
1410 }
1411 c = c->Next;
1412 }
1413 if (count != 0)
1414 return 0;
1415 return 1;
1416 }
1417
1418 static int
gml_parse_pos_chain(gmlNodePtr * xnode,gaiaDynamicLinePtr dyn,int has_z)1419 gml_parse_pos_chain (gmlNodePtr * xnode, gaiaDynamicLinePtr dyn, int has_z)
1420 {
1421 /* parsing a chain of gml:pos elements */
1422 int error = 0;
1423 double x;
1424 double y;
1425 double z;
1426 int count = 0;
1427 gmlNodePtr last_node = *xnode;
1428 gmlNodePtr node = *xnode;
1429 while (node != NULL)
1430 {
1431 if (strcmp (node->Tag, "gml:pos") == 0
1432 || strcmp (node->Tag, "pos") == 0)
1433 ;
1434 else
1435 break;
1436 if (!gml_parse_point_v3 (node->Coordinates, &x, &y, &z))
1437 return 0;
1438 if (has_z)
1439 gml_add_point_to_lineZ (dyn, x, y, z);
1440 else
1441 gml_add_point_to_line (dyn, x, y);
1442 node = node->Next;
1443 if (strcmp (node->Tag, "gml:pos") == 0
1444 || strcmp (node->Tag, "pos") == 0)
1445 last_node = node;
1446 else
1447 {
1448 error = 1;
1449 break;
1450 }
1451 count++;
1452 node = node->Next;
1453 }
1454 if (count >= 2 && error == 0)
1455 {
1456 /* valid <gml:pos> sequence found */
1457 *xnode = last_node;
1458 return 1;
1459 }
1460 return 0;
1461 }
1462
1463 static int
gml_count_dyn_points(gaiaDynamicLinePtr dyn)1464 gml_count_dyn_points (gaiaDynamicLinePtr dyn)
1465 {
1466 /* count how many vertices are into sone linestring/ring */
1467 int iv = 0;
1468 gaiaPointPtr pt = dyn->First;
1469 while (pt)
1470 {
1471 iv++;
1472 pt = pt->Next;
1473 }
1474 return iv;
1475 }
1476
1477 static int
gml_parse_box(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node,int srid,gmlNodePtr * next)1478 gml_parse_box (struct gml_data *p_data, gaiaGeomCollPtr geom,
1479 gmlNodePtr node, int srid, gmlNodePtr * next)
1480 {
1481 /* parsing a <gml:Box> */
1482 gaiaGeomCollPtr last;
1483 gaiaGeomCollPtr pg;
1484 gaiaPolygonPtr new_pg;
1485 gaiaRingPtr ring;
1486 gaiaPointPtr pt;
1487 double minx;
1488 double miny;
1489 double maxx;
1490 double maxy;
1491 int has_z;
1492 int points = 0;
1493 gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
1494 gmlMapDynAlloc (p_data, GML_DYN_DYNLINE, dyn);
1495
1496 if (strcmp (node->Tag, "gml:coordinates") == 0
1497 || strcmp (node->Tag, "coordinates") == 0)
1498 {
1499 /* parsing a GML v.2.x <gml:LineString> */
1500 if (!gml_parse_coordinates (node->Coordinates, dyn, &has_z))
1501 goto error;
1502 node = node->Next;
1503 if (node == NULL)
1504 goto error;
1505 if (strcmp (node->Tag, "gml:coordinates") == 0
1506 || strcmp (node->Tag, "coordinates") == 0)
1507 ;
1508 else
1509 goto error;
1510 node = node->Next;
1511 if (node == NULL)
1512 goto error;
1513 if (strcmp (node->Tag, "gml:Box") == 0
1514 || strcmp (node->Tag, "Box") == 0)
1515 ;
1516 else
1517 goto error;
1518 *next = node->Next;
1519 goto ok;
1520 }
1521
1522 ok:
1523 /* ok, GML nodes match as expected */
1524 points = gml_count_dyn_points (dyn);
1525 if (points != 2)
1526 goto error;
1527 pt = dyn->First;
1528 minx = pt->X;
1529 miny = pt->Y;
1530 maxx = pt->X;
1531 maxy = pt->Y;
1532 while (pt)
1533 {
1534 if (pt->X < minx)
1535 minx = pt->X;
1536 if (pt->Y < miny)
1537 miny = pt->Y;
1538 if (pt->X > maxx)
1539 maxx = pt->X;
1540 if (pt->Y > maxy)
1541 maxy = pt->Y;
1542 pt = pt->Next;
1543 }
1544 pg = gaiaAllocGeomColl ();
1545 gmlMapDynAlloc (p_data, GML_DYN_GEOM, pg);
1546 pg->Srid = srid;
1547 new_pg = gaiaAddPolygonToGeomColl (pg, 5, 0);
1548 /* initializing the EXTERIOR RING */
1549 ring = new_pg->Exterior;
1550 gaiaSetPoint (ring->Coords, 0, minx, miny);
1551 gaiaSetPoint (ring->Coords, 1, maxx, miny);
1552 gaiaSetPoint (ring->Coords, 2, maxx, maxy);
1553 gaiaSetPoint (ring->Coords, 3, minx, maxy);
1554 gaiaSetPoint (ring->Coords, 4, minx, miny);
1555 last = geom;
1556 while (1)
1557 {
1558 /* searching the last Geometry within chain */
1559 if (last->Next == NULL)
1560 break;
1561 last = last->Next;
1562 }
1563 last->Next = pg;
1564 gmlMapDynClean (p_data, dyn);
1565 gaiaFreeDynamicLine (dyn);
1566 return 1;
1567
1568 error:
1569 gmlMapDynClean (p_data, dyn);
1570 gaiaFreeDynamicLine (dyn);
1571 return 0;
1572 }
1573
1574 static int
gml_parse_linestring(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node,gmlNodePtr * next)1575 gml_parse_linestring (struct gml_data *p_data, gaiaGeomCollPtr geom,
1576 gmlNodePtr node, gmlNodePtr * next)
1577 {
1578 /* parsing a <gml:LineString> */
1579 int srid = geom->Srid;
1580 int has_z = 0;
1581 gaiaGeomCollPtr ln;
1582 gaiaGeomCollPtr last;
1583 gaiaLinestringPtr new_ln;
1584 gaiaPointPtr pt;
1585 int iv;
1586 int points = 0;
1587 gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
1588 gmlMapDynAlloc (p_data, GML_DYN_DYNLINE, dyn);
1589 if (geom->DimensionModel == GAIA_XY_Z
1590 || geom->DimensionModel == GAIA_XY_Z_M)
1591 has_z = 1;
1592
1593 if (strcmp (node->Tag, "gml:coordinates") == 0
1594 || strcmp (node->Tag, "coordinates") == 0)
1595 {
1596 /* parsing a GML v.2.x <gml:LineString> */
1597 if (!gml_parse_coordinates (node->Coordinates, dyn, &has_z))
1598 goto error;
1599 node = node->Next;
1600 if (node == NULL)
1601 goto error;
1602 if (strcmp (node->Tag, "gml:coordinates") == 0
1603 || strcmp (node->Tag, "coordinates") == 0)
1604 ;
1605 else
1606 goto error;
1607 node = node->Next;
1608 if (node == NULL)
1609 goto error;
1610 if (strcmp (node->Tag, "gml:LineString") == 0
1611 || strcmp (node->Tag, "LineString") == 0)
1612 ;
1613 else
1614 goto error;
1615 *next = node->Next;
1616 goto ok;
1617 }
1618 if (strcmp (node->Tag, "gml:posList") == 0
1619 || strcmp (node->Tag, "posList") == 0)
1620 {
1621 /* parsing a GML v.3.x <gml:LineString> */
1622 if (!gml_parse_posList (node->Coordinates, dyn, has_z))
1623 goto error;
1624 node = node->Next;
1625 if (node == NULL)
1626 goto error;
1627 if (strcmp (node->Tag, "gml:posList") == 0
1628 || strcmp (node->Tag, "posList") == 0)
1629 ;
1630 else
1631 goto error;
1632 node = node->Next;
1633 if (node == NULL)
1634 goto error;
1635 if (strcmp (node->Tag, "gml:LineString") == 0
1636 || strcmp (node->Tag, "LineString") == 0)
1637 ;
1638 else
1639 goto error;
1640 *next = node->Next;
1641 goto ok;
1642 }
1643 if (strcmp (node->Tag, "gml:pos") == 0 || strcmp (node->Tag, "pos") == 0)
1644 {
1645 /* parsing a GML v.3.x <gml:LineString><gml:pos ...> */
1646 gmlNodePtr node2 = node;
1647 if (!gml_parse_pos_chain (&node2, dyn, has_z))
1648 goto error;
1649 node = node2->Next;
1650 if (node == NULL)
1651 goto error;
1652 if (strcmp (node->Tag, "gml:LineString") == 0
1653 || strcmp (node->Tag, "LineString") == 0)
1654 ;
1655 else
1656 goto error;
1657 *next = node->Next;
1658 goto ok;
1659 }
1660
1661 ok:
1662 /* ok, GML nodes match as expected */
1663 points = gml_count_dyn_points (dyn);
1664 if (points < 2)
1665 goto error;
1666 if (has_z)
1667 {
1668 ln = gaiaAllocGeomCollXYZ ();
1669 gmlMapDynAlloc (p_data, GML_DYN_GEOM, ln);
1670 ln->Srid = srid;
1671 new_ln = gaiaAddLinestringToGeomColl (ln, points);
1672 pt = dyn->First;
1673 iv = 0;
1674 while (pt)
1675 {
1676 gaiaSetPointXYZ (new_ln->Coords, iv, pt->X, pt->Y, pt->Z);
1677 iv++;
1678 pt = pt->Next;
1679 }
1680 }
1681 else
1682 {
1683 ln = gaiaAllocGeomColl ();
1684 gmlMapDynAlloc (p_data, GML_DYN_GEOM, ln);
1685 ln->Srid = srid;
1686 new_ln = gaiaAddLinestringToGeomColl (ln, points);
1687 pt = dyn->First;
1688 iv = 0;
1689 while (pt)
1690 {
1691 gaiaSetPoint (new_ln->Coords, iv, pt->X, pt->Y);
1692 iv++;
1693 pt = pt->Next;
1694 }
1695 }
1696 last = geom;
1697 while (1)
1698 {
1699 /* searching the last Geometry within chain */
1700 if (last->Next == NULL)
1701 break;
1702 last = last->Next;
1703 }
1704 last->Next = ln;
1705 gmlMapDynClean (p_data, dyn);
1706 gaiaFreeDynamicLine (dyn);
1707 return 1;
1708
1709 error:
1710 gmlMapDynClean (p_data, dyn);
1711 gaiaFreeDynamicLine (dyn);
1712 return 0;
1713 }
1714
1715 static int
gml_parse_curve(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node,gmlNodePtr * next)1716 gml_parse_curve (struct gml_data *p_data, gaiaGeomCollPtr geom, gmlNodePtr node,
1717 gmlNodePtr * next)
1718 {
1719 /* parsing a <gml:Curve> */
1720 int srid = geom->Srid;
1721 int has_z = 0;
1722 gaiaGeomCollPtr ln;
1723 gaiaGeomCollPtr last;
1724 gaiaLinestringPtr new_ln;
1725 gaiaPointPtr pt;
1726 int iv;
1727 int points = 0;
1728 gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
1729 gmlMapDynAlloc (p_data, GML_DYN_DYNLINE, dyn);
1730 if (geom->DimensionModel == GAIA_XY_Z
1731 || geom->DimensionModel == GAIA_XY_Z_M)
1732 has_z = 1;
1733
1734 if (strcmp (node->Tag, "gml:segments") == 0
1735 || strcmp (node->Tag, "segments") == 0)
1736 {
1737 /* parsing a GML v.3.x <gml:Curve> */
1738 node = node->Next;
1739 if (node == NULL)
1740 goto error;
1741 if (strcmp (node->Tag, "gml:LineStringSegment") == 0
1742 || strcmp (node->Tag, "LineStringSegment") == 0)
1743 ;
1744 else
1745 goto error;
1746 node = node->Next;
1747 if (node == NULL)
1748 goto error;
1749 if (strcmp (node->Tag, "gml:posList") == 0
1750 || strcmp (node->Tag, "posList") == 0)
1751 {
1752 /* parsing a GML v.3.x <gml:LineStringSegment><gml:posList ...> */
1753 if (!gml_parse_posList (node->Coordinates, dyn, has_z))
1754 goto error;
1755 node = node->Next;
1756 if (node == NULL)
1757 goto error;
1758 if (strcmp (node->Tag, "gml:posList") == 0
1759 || strcmp (node->Tag, "posList") == 0)
1760 ;
1761 else
1762 goto error;
1763
1764 }
1765 else if (strcmp (node->Tag, "gml:pos") == 0
1766 || strcmp (node->Tag, "pos") == 0)
1767 {
1768 /* parsing a GML v.3.x <gml:LineStringSegment><gml:pos ...> */
1769 gmlNodePtr node2 = node;
1770 if (!gml_parse_pos_chain (&node2, dyn, has_z))
1771 goto error;
1772 node = node2;
1773 if (node == NULL)
1774 goto error;
1775 }
1776 else
1777 goto error;
1778 node = node->Next;
1779 if (node == NULL)
1780 goto error;
1781 if (strcmp (node->Tag, "gml:LineStringSegment") == 0
1782 || strcmp (node->Tag, "LineStringSegment") == 0)
1783 ;
1784 else
1785 goto error;
1786 node = node->Next;
1787 if (node == NULL)
1788 goto error;
1789 if (strcmp (node->Tag, "gml:segments") == 0
1790 || strcmp (node->Tag, "segments") == 0)
1791 ;
1792 else
1793 goto error;
1794 node = node->Next;
1795 if (node == NULL)
1796 goto error;
1797 if (strcmp (node->Tag, "gml:Curve") == 0
1798 || strcmp (node->Tag, "Curve") == 0)
1799 ;
1800 else
1801 goto error;
1802 *next = node->Next;
1803 goto ok;
1804 }
1805 goto error;
1806
1807 ok:
1808 /* ok, GML nodes match as expected */
1809 points = gml_count_dyn_points (dyn);
1810 if (points < 2)
1811 goto error;
1812 if (has_z)
1813 {
1814 ln = gaiaAllocGeomCollXYZ ();
1815 gmlMapDynAlloc (p_data, GML_DYN_GEOM, ln);
1816 ln->Srid = srid;
1817 new_ln = gaiaAddLinestringToGeomColl (ln, points);
1818 pt = dyn->First;
1819 iv = 0;
1820 while (pt)
1821 {
1822 gaiaSetPointXYZ (new_ln->Coords, iv, pt->X, pt->Y, pt->Z);
1823 iv++;
1824 pt = pt->Next;
1825 }
1826 }
1827 else
1828 {
1829 ln = gaiaAllocGeomColl ();
1830 gmlMapDynAlloc (p_data, GML_DYN_GEOM, ln);
1831 ln->Srid = srid;
1832 new_ln = gaiaAddLinestringToGeomColl (ln, points);
1833 pt = dyn->First;
1834 iv = 0;
1835 while (pt)
1836 {
1837 gaiaSetPoint (new_ln->Coords, iv, pt->X, pt->Y);
1838 iv++;
1839 pt = pt->Next;
1840 }
1841 }
1842 last = geom;
1843 while (1)
1844 {
1845 /* searching the last Geometry within chain */
1846 if (last->Next == NULL)
1847 break;
1848 last = last->Next;
1849 }
1850 last->Next = ln;
1851 gmlMapDynClean (p_data, dyn);
1852 gaiaFreeDynamicLine (dyn);
1853 return 1;
1854
1855 error:
1856 gmlMapDynClean (p_data, dyn);
1857 gaiaFreeDynamicLine (dyn);
1858 return 0;
1859 }
1860
1861 static int
gml_parse_alt_ring(gmlNodePtr node,int has_z,gmlNodePtr * next,gaiaDynamicLinePtr dyn)1862 gml_parse_alt_ring (gmlNodePtr node,
1863 int has_z, gmlNodePtr * next, gaiaDynamicLinePtr dyn)
1864 {
1865 /* alternative Ring syntax */
1866 if (strcmp (node->Tag, "gml:Ring") == 0 || strcmp (node->Tag, "Ring") == 0)
1867 {
1868 node = node->Next;
1869 if (node == NULL)
1870 return 0;
1871 if (strcmp (node->Tag, "gml:curveMember") == 0
1872 || strcmp (node->Tag, "curveMember") == 0)
1873 ;
1874 else
1875 return 0;
1876 node = node->Next;
1877 if (node == NULL)
1878 return 0;
1879 if (strcmp (node->Tag, "gml:Curve") == 0
1880 || strcmp (node->Tag, "Curve") == 0)
1881 ;
1882 else
1883 return 0;
1884 node = node->Next;
1885 if (node == NULL)
1886 return 0;
1887 if (strcmp (node->Tag, "gml:segments") == 0
1888 || strcmp (node->Tag, "segments") == 0)
1889 {
1890 node = node->Next;
1891 if (node == NULL)
1892 return 0;
1893 if (strcmp (node->Tag, "gml:LineStringSegment") == 0
1894 || strcmp (node->Tag, "LineStringSegment") == 0)
1895 ;
1896 else
1897 return 0;
1898 node = node->Next;
1899 if (node == NULL)
1900 return 0;
1901 if (strcmp (node->Tag, "gml:posList") == 0
1902 || strcmp (node->Tag, "posList") == 0)
1903 {
1904 if (!gml_parse_posList (node->Coordinates, dyn, has_z))
1905 return 0;
1906 node = node->Next;
1907 if (node == NULL)
1908 return 0;
1909 if (strcmp (node->Tag, "gml:posList") == 0
1910 || strcmp (node->Tag, "posList") == 0)
1911 ;
1912 else
1913 return 0;
1914 node = node->Next;
1915 if (node == NULL)
1916 return 0;
1917 if (strcmp (node->Tag, "gml:LineStringSegment") == 0
1918 || strcmp (node->Tag, "LineStringSegment") == 0)
1919 ;
1920 else
1921 return 0;
1922 node = node->Next;
1923 if (node == NULL)
1924 return 0;
1925 if (strcmp (node->Tag, "gml:segments") == 0
1926 || strcmp (node->Tag, "segments") == 0)
1927 ;
1928 else
1929 return 0;
1930 node = node->Next;
1931 if (node == NULL)
1932 return 0;
1933 if (strcmp (node->Tag, "gml:Curve") == 0
1934 || strcmp (node->Tag, "Curve") == 0)
1935 ;
1936 else
1937 return 0;
1938 node = node->Next;
1939 if (node == NULL)
1940 return 0;
1941 if (strcmp (node->Tag, "gml:curveMember") == 0
1942 || strcmp (node->Tag, "curveMember") == 0)
1943 ;
1944 else
1945 return 0;
1946 node = node->Next;
1947 if (node == NULL)
1948 return 0;
1949 if (strcmp (node->Tag, "gml:Ring") == 0
1950 || strcmp (node->Tag, "Ring") == 0)
1951 *next = node;
1952 return 1;
1953 }
1954
1955 }
1956 }
1957 return 0;
1958 }
1959
1960 static gaiaDynamicLinePtr
gml_parse_ring(struct gml_data * p_data,gmlNodePtr node,int * interior,int has_z,gmlNodePtr * next)1961 gml_parse_ring (struct gml_data *p_data, gmlNodePtr node, int *interior,
1962 int has_z, gmlNodePtr * next)
1963 {
1964 /* parsing a generic GML ring */
1965 gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
1966 gmlMapDynAlloc (p_data, GML_DYN_DYNLINE, dyn);
1967
1968 if (strcmp (node->Tag, "gml:outerBoundaryIs") == 0
1969 || strcmp (node->Tag, "outerBoundaryIs") == 0)
1970 {
1971 /* parsing a GML v.2.x <gml:outerBoundaryIs> */
1972 node = node->Next;
1973 if (node == NULL)
1974 goto error;
1975 if (strcmp (node->Tag, "gml:LinearRing") == 0
1976 || strcmp (node->Tag, "LinearRing") == 0)
1977 ;
1978 else
1979 goto error;
1980 node = node->Next;
1981 if (node == NULL)
1982 goto error;
1983 if (strcmp (node->Tag, "gml:coordinates") == 0
1984 || strcmp (node->Tag, "coordinates") == 0)
1985 {
1986 /* parsing a GML v.2.x <gml:coordinates> */
1987 if (!gml_parse_coordinates (node->Coordinates, dyn, &has_z))
1988 goto error;
1989 node = node->Next;
1990 if (node == NULL)
1991 goto error;
1992 if (strcmp (node->Tag, "gml:coordinates") == 0
1993 || strcmp (node->Tag, "coordinates") == 0)
1994 ;
1995 else
1996 goto error;
1997 }
1998 else if (strcmp (node->Tag, "gml:posList") == 0
1999 || strcmp (node->Tag, "posList") == 0)
2000 {
2001 /* parsing a GML v.3.x <gml:posList> */
2002 if (!gml_parse_posList (node->Coordinates, dyn, has_z))
2003 goto error;
2004 node = node->Next;
2005 if (node == NULL)
2006 goto error;
2007 if (strcmp (node->Tag, "gml:posList") == 0
2008 || strcmp (node->Tag, "posList") == 0)
2009 ;
2010 else
2011 goto error;
2012 }
2013 else if (strcmp (node->Tag, "gml:pos") == 0
2014 || strcmp (node->Tag, "pos") == 0)
2015 {
2016 /* parsing a GML v.3.x <gml:LinearRing><gml:pos ...> */
2017 gmlNodePtr node2 = node;
2018 if (!gml_parse_pos_chain (&node2, dyn, has_z))
2019 goto error;
2020 node = node2;
2021 if (node == NULL)
2022 goto error;
2023 }
2024 else
2025 goto error;
2026 node = node->Next;
2027 if (node == NULL)
2028 goto error;
2029 if (strcmp (node->Tag, "gml:LinearRing") == 0
2030 || strcmp (node->Tag, "LinearRing") == 0)
2031 ;
2032 else
2033 goto error;
2034 node = node->Next;
2035 if (node == NULL)
2036 goto error;
2037 if (strcmp (node->Tag, "gml:outerBoundaryIs") == 0
2038 || strcmp (node->Tag, "outerBoundaryIs") == 0)
2039 ;
2040 else
2041 goto error;
2042 *interior = 0;
2043 *next = node->Next;
2044 return dyn;
2045 }
2046 if (strcmp (node->Tag, "gml:innerBoundaryIs") == 0
2047 || strcmp (node->Tag, "innerBoundaryIs") == 0)
2048 {
2049 /* parsing a GML v.2.x <gml:innerBoundaryIs> */
2050 node = node->Next;
2051 if (node == NULL)
2052 goto error;
2053 if (strcmp (node->Tag, "gml:LinearRing") == 0
2054 || strcmp (node->Tag, "LinearRing") == 0)
2055 ;
2056 else
2057 goto error;
2058 node = node->Next;
2059 if (node == NULL)
2060 goto error;
2061 if (strcmp (node->Tag, "gml:coordinates") == 0
2062 || strcmp (node->Tag, "coordinates") == 0)
2063 {
2064 /* parsing a GML v.2.x <gml:coordinates> */
2065 if (!gml_parse_coordinates (node->Coordinates, dyn, &has_z))
2066 goto error;
2067 node = node->Next;
2068 if (node == NULL)
2069 goto error;
2070 if (strcmp (node->Tag, "gml:coordinates") == 0
2071 || strcmp (node->Tag, "coordinates") == 0)
2072 ;
2073 else
2074 goto error;
2075 }
2076 else if (strcmp (node->Tag, "gml:posList") == 0
2077 || strcmp (node->Tag, "posList") == 0)
2078 {
2079 /* parsing a GML v.3.x <gml:posList> */
2080 if (!gml_parse_posList (node->Coordinates, dyn, has_z))
2081 goto error;
2082 node = node->Next;
2083 if (node == NULL)
2084 goto error;
2085 if (strcmp (node->Tag, "gml:posList") == 0
2086 || strcmp (node->Tag, "posList") == 0)
2087 ;
2088 else
2089 goto error;
2090 }
2091 else if (strcmp (node->Tag, "gml:pos") == 0
2092 || strcmp (node->Tag, "pos") == 0)
2093 {
2094 /* parsing a GML v.3.x <gml:LinearRing><gml:pos ...> */
2095 gmlNodePtr node2 = node;
2096 if (!gml_parse_pos_chain (&node2, dyn, has_z))
2097 goto error;
2098 node = node2;
2099 if (node == NULL)
2100 goto error;
2101 }
2102 else
2103 goto error;
2104 node = node->Next;
2105 if (node == NULL)
2106 goto error;
2107 if (strcmp (node->Tag, "gml:LinearRing") == 0
2108 || strcmp (node->Tag, "LinearRing") == 0)
2109 ;
2110 else
2111 goto error;
2112 node = node->Next;
2113 if (node == NULL)
2114 goto error;
2115 if (strcmp (node->Tag, "gml:innerBoundaryIs") == 0
2116 || strcmp (node->Tag, "innerBoundaryIs") == 0)
2117 ;
2118 else
2119 goto error;
2120 *interior = 1;
2121 *next = node->Next;
2122 return dyn;
2123 }
2124 if (strcmp (node->Tag, "gml:exterior") == 0
2125 || strcmp (node->Tag, "exterior") == 0)
2126 {
2127 /* parsing a GML v.3.x <gml:exterior> */
2128 node = node->Next;
2129 if (node == NULL)
2130 goto error;
2131 if (strcmp (node->Tag, "gml:LinearRing") == 0
2132 || strcmp (node->Tag, "LinearRing") == 0)
2133 ;
2134 else if (strcmp (node->Tag, "gml:Ring") == 0
2135 || strcmp (node->Tag, "Ring") == 0)
2136 {
2137 if (gml_parse_alt_ring (node, has_z, next, dyn))
2138 {
2139 *interior = 0;
2140 node = *next;
2141 goto ex_exterior;
2142 }
2143 else
2144 goto error;
2145 }
2146 else
2147 goto error;
2148 node = node->Next;
2149 if (node == NULL)
2150 goto error;
2151 if (strcmp (node->Tag, "gml:posList") == 0
2152 || strcmp (node->Tag, "posList") == 0)
2153 {
2154 /* parsing a GML v.3.x <gml:LinearRing><gml:posList ...> */
2155 if (!gml_parse_posList (node->Coordinates, dyn, has_z))
2156 goto error;
2157 node = node->Next;
2158 if (node == NULL)
2159 goto error;
2160 if (strcmp (node->Tag, "gml:posList") == 0
2161 || strcmp (node->Tag, "posList") == 0)
2162 ;
2163 else
2164 goto error;
2165 }
2166 else if (strcmp (node->Tag, "gml:pos") == 0
2167 || strcmp (node->Tag, "pos") == 0)
2168 {
2169 /* parsing a GML v.3.x <gml:LinearRing><gml:pos ...> */
2170 gmlNodePtr node2 = node;
2171 if (!gml_parse_pos_chain (&node2, dyn, has_z))
2172 goto error;
2173 node = node2;
2174 if (node == NULL)
2175 goto error;
2176 }
2177 else
2178 goto error;
2179 node = node->Next;
2180 if (node == NULL)
2181 goto error;
2182 if (strcmp (node->Tag, "gml:LinearRing") == 0
2183 || strcmp (node->Tag, "LinearRing") == 0)
2184 ;
2185 else
2186 goto error;
2187 ex_exterior:
2188 node = node->Next;
2189 if (node == NULL)
2190 goto error;
2191 if (strcmp (node->Tag, "gml:exterior") == 0
2192 || strcmp (node->Tag, "exterior") == 0)
2193 ;
2194 else
2195 goto error;
2196 *interior = 0;
2197 *next = node->Next;
2198 return dyn;
2199 }
2200 if (strcmp (node->Tag, "gml:interior") == 0
2201 || strcmp (node->Tag, "interior") == 0)
2202 {
2203 /* parsing a GML v.3.x <gml:interior> */
2204 node = node->Next;
2205 if (node == NULL)
2206 goto error;
2207 if (strcmp (node->Tag, "gml:LinearRing") == 0
2208 || strcmp (node->Tag, "LinearRing") == 0)
2209 ;
2210 else if (strcmp (node->Tag, "gml:Ring") == 0
2211 || strcmp (node->Tag, "Ring") == 0)
2212 {
2213 if (gml_parse_alt_ring (node, has_z, next, dyn))
2214 {
2215 *interior = 1;
2216 node = *next;
2217 goto ex_interior;
2218 }
2219 else
2220 goto error;
2221 }
2222 else
2223 goto error;
2224 node = node->Next;
2225 if (node == NULL)
2226 goto error;
2227 if (strcmp (node->Tag, "gml:posList") == 0
2228 || strcmp (node->Tag, "posList") == 0)
2229 {
2230 /* parsing a GML v.3.x <gml:LinearRing><gml:posList ...> */
2231 if (!gml_parse_posList (node->Coordinates, dyn, has_z))
2232 goto error;
2233 node = node->Next;
2234 if (node == NULL)
2235 goto error;
2236 if (strcmp (node->Tag, "gml:posList") == 0
2237 || strcmp (node->Tag, "posList") == 0)
2238 ;
2239 else
2240 goto error;
2241 }
2242 else if (strcmp (node->Tag, "gml:pos") == 0
2243 || strcmp (node->Tag, "pos") == 0)
2244 {
2245 /* parsing a GML v.3.x <gml:LinearRing><gml:pos ...> */
2246 gmlNodePtr node2 = node;
2247 if (!gml_parse_pos_chain (&node2, dyn, has_z))
2248 goto error;
2249 node = node2;
2250 if (node == NULL)
2251 goto error;
2252 }
2253 else
2254 goto error;
2255 node = node->Next;
2256 if (node == NULL)
2257 goto error;
2258 if (strcmp (node->Tag, "gml:LinearRing") == 0
2259 || strcmp (node->Tag, "LinearRing") == 0)
2260 ;
2261 else
2262 goto error;
2263 ex_interior:
2264 node = node->Next;
2265 if (node == NULL)
2266 goto error;
2267 if (strcmp (node->Tag, "gml:interior") == 0
2268 || strcmp (node->Tag, "interior") == 0)
2269 ;
2270 else
2271 goto error;
2272 *interior = 1;
2273 *next = node->Next;
2274 return dyn;
2275 }
2276
2277 error:
2278 gmlMapDynClean (p_data, dyn);
2279 gaiaFreeDynamicLine (dyn);
2280 return 0;
2281 }
2282
2283 static int
gml_parse_polygon(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node,gmlNodePtr * next_n)2284 gml_parse_polygon (struct gml_data *p_data, gaiaGeomCollPtr geom,
2285 gmlNodePtr node, gmlNodePtr * next_n)
2286 {
2287 /* parsing a <gml:Polygon> */
2288 int srid = geom->Srid;
2289 int has_z = 0;
2290 int interior;
2291 int inners;
2292 int outers;
2293 int points = 0;
2294 int iv;
2295 int ib = 0;
2296 gaiaGeomCollPtr pg;
2297 gaiaGeomCollPtr last_g;
2298 gaiaPolygonPtr new_pg;
2299 gaiaRingPtr ring;
2300 gaiaDynamicLinePtr dyn;
2301 gaiaPointPtr pt;
2302 gaiaDynamicLinePtr exterior_ring = NULL;
2303 gmlNodePtr next;
2304 gmlDynamicRingPtr dyn_rng;
2305 gmlDynamicPolygonPtr dyn_pg = gml_alloc_dyn_polygon (p_data);
2306 gmlNodePtr n = node;
2307 if (geom->DimensionModel == GAIA_XY_Z
2308 || geom->DimensionModel == GAIA_XY_Z_M)
2309 has_z = 1;
2310
2311 while (n)
2312 {
2313 /* looping on rings */
2314 if (strcmp (n->Tag, "gml:Polygon") == 0
2315 || strcmp (n->Tag, "Polygon") == 0)
2316 {
2317 *next_n = n->Next;
2318 break;
2319 }
2320 dyn = gml_parse_ring (p_data, n, &interior, has_z, &next);
2321 if (dyn == NULL)
2322 goto error;
2323 if (gml_count_dyn_points (dyn) < 4)
2324 {
2325 /* cannot be a valid ring */
2326 goto error;
2327 }
2328 /* checking if the ring is closed */
2329 if (has_z)
2330 {
2331 if (dyn->First->X == dyn->Last->X
2332 && dyn->First->Y == dyn->Last->Y
2333 && dyn->First->Z == dyn->Last->Z)
2334 ;
2335 else
2336 goto error;
2337 }
2338 else
2339 {
2340 if (dyn->First->X == dyn->Last->X
2341 && dyn->First->Y == dyn->Last->Y)
2342 ;
2343 else
2344 goto error;
2345 }
2346 gml_add_polygon_ring (p_data, dyn_pg, dyn, interior, has_z);
2347 n = next;
2348 }
2349 /* ok, GML nodes match as expected */
2350 inners = 0;
2351 outers = 0;
2352 dyn_rng = dyn_pg->first;
2353 while (dyn_rng)
2354 {
2355 /* verifying the rings collection */
2356 if (dyn_rng->interior)
2357 inners++;
2358 else
2359 {
2360 outers++;
2361 points = gml_count_dyn_points (dyn_rng->ring);
2362 exterior_ring = dyn_rng->ring;
2363 }
2364 dyn_rng = dyn_rng->next;
2365 }
2366 if (outers != 1) /* no exterior ring declared */
2367 goto error;
2368
2369 if (has_z)
2370 {
2371 pg = gaiaAllocGeomCollXYZ ();
2372 gmlMapDynAlloc (p_data, GML_DYN_GEOM, pg);
2373 pg->Srid = srid;
2374 new_pg = gaiaAddPolygonToGeomColl (pg, points, inners);
2375 /* initializing the EXTERIOR RING */
2376 ring = new_pg->Exterior;
2377 pt = exterior_ring->First;
2378 iv = 0;
2379 while (pt)
2380 {
2381 gaiaSetPointXYZ (ring->Coords, iv, pt->X, pt->Y, pt->Z);
2382 iv++;
2383 pt = pt->Next;
2384 }
2385 dyn_rng = dyn_pg->first;
2386 while (dyn_rng)
2387 {
2388 /* initializing any INTERIOR RING */
2389 if (dyn_rng->interior == 0)
2390 {
2391 dyn_rng = dyn_rng->next;
2392 continue;
2393 }
2394 points = gml_count_dyn_points (dyn_rng->ring);
2395 ring = gaiaAddInteriorRing (new_pg, ib, points);
2396 ib++;
2397 pt = dyn_rng->ring->First;
2398 iv = 0;
2399 while (pt)
2400 {
2401 gaiaSetPointXYZ (ring->Coords, iv, pt->X, pt->Y, pt->Z);
2402 iv++;
2403 pt = pt->Next;
2404 }
2405 dyn_rng = dyn_rng->next;
2406 }
2407 }
2408 else
2409 {
2410 pg = gaiaAllocGeomColl ();
2411 gmlMapDynAlloc (p_data, GML_DYN_GEOM, pg);
2412 pg->Srid = srid;
2413 new_pg = gaiaAddPolygonToGeomColl (pg, points, inners);
2414 /* initializing the EXTERIOR RING */
2415 ring = new_pg->Exterior;
2416 pt = exterior_ring->First;
2417 iv = 0;
2418 while (pt)
2419 {
2420 gaiaSetPoint (ring->Coords, iv, pt->X, pt->Y);
2421 iv++;
2422 pt = pt->Next;
2423 }
2424 dyn_rng = dyn_pg->first;
2425 while (dyn_rng)
2426 {
2427 /* initializing any INTERIOR RING */
2428 if (dyn_rng->interior == 0)
2429 {
2430 dyn_rng = dyn_rng->next;
2431 continue;
2432 }
2433 points = gml_count_dyn_points (dyn_rng->ring);
2434 ring = gaiaAddInteriorRing (new_pg, ib, points);
2435 ib++;
2436 pt = dyn_rng->ring->First;
2437 iv = 0;
2438 while (pt)
2439 {
2440 gaiaSetPoint (ring->Coords, iv, pt->X, pt->Y);
2441 iv++;
2442 pt = pt->Next;
2443 }
2444 dyn_rng = dyn_rng->next;
2445 }
2446 }
2447
2448 last_g = geom;
2449 while (1)
2450 {
2451 /* searching the last Geometry within chain */
2452 if (last_g->Next == NULL)
2453 break;
2454 last_g = last_g->Next;
2455 }
2456 last_g->Next = pg;
2457 gml_free_dyn_polygon (dyn_pg);
2458 return 1;
2459
2460 error:
2461 gml_free_dyn_polygon (dyn_pg);
2462 return 0;
2463 }
2464
2465 static int
gml_parse_multi_point(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node)2466 gml_parse_multi_point (struct gml_data *p_data, gaiaGeomCollPtr geom,
2467 gmlNodePtr node)
2468 {
2469 /* parsing a <gml:MultiPoint> */
2470 int pts;
2471 gmlNodePtr n2;
2472 gmlNodePtr next;
2473 gmlNodePtr n = node;
2474
2475 while (n)
2476 {
2477 /* looping on Point Members */
2478 if (n->Next == NULL)
2479 {
2480 /* verifying the last GML node */
2481 if (strcmp (n->Tag, "gml:MultiPoint") == 0
2482 || strcmp (n->Tag, "MultiPoint") == 0)
2483 break;
2484 else
2485 return 0;
2486 }
2487 if (strcmp (n->Tag, "gml:pointMember") == 0
2488 || strcmp (n->Tag, "pointMember") == 0
2489 || strcmp (n->Tag, "gml:pointMembers") == 0
2490 || strcmp (n->Tag, "pointMembers") == 0)
2491 ;
2492 else
2493 return 0;
2494 n2 = n->Next;
2495 pts = 0;
2496 while (n2)
2497 {
2498 /* looping on Point(s) */
2499 if (strcmp (n2->Tag, "gml:Point") == 0
2500 || strcmp (n2->Tag, "Point") == 0)
2501 ;
2502 else
2503 {
2504 n = n2;
2505 break;
2506 }
2507 n2 = n2->Next;
2508 if (n2 == NULL)
2509 return 0;
2510 if (!gml_parse_point (p_data, geom, n2, &next))
2511 return 0;
2512 n2 = next;
2513 if (n2 == NULL)
2514 return 0;
2515 pts++;
2516 }
2517 if (!pts)
2518 return 0;
2519 if (strcmp (n->Tag, "gml:pointMember") == 0
2520 || strcmp (n->Tag, "pointMember") == 0
2521 || strcmp (n->Tag, "gml:pointMembers") == 0
2522 || strcmp (n->Tag, "pointMembers") == 0)
2523 ;
2524 else
2525 return 0;
2526 n = n->Next;
2527 }
2528 return 1;
2529 }
2530
2531 static int
gml_parse_multi_linestring(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node)2532 gml_parse_multi_linestring (struct gml_data *p_data, gaiaGeomCollPtr geom,
2533 gmlNodePtr node)
2534 {
2535 /* parsing a <gml:MultiLineString> */
2536 int lns;
2537 gmlNodePtr n2;
2538 gmlNodePtr next;
2539 gmlNodePtr n = node;
2540
2541 while (n)
2542 {
2543 /* looping on LineString Members */
2544 if (n->Next == NULL)
2545 {
2546 /* verifying the last GML node */
2547 if (strcmp (n->Tag, "gml:MultiLineString") == 0
2548 || strcmp (n->Tag, "MultiLineString") == 0)
2549 break;
2550 else
2551 return 0;
2552 }
2553 if (strcmp (n->Tag, "gml:lineStringMember") == 0
2554 || strcmp (n->Tag, "lineStringMember") == 0
2555 || strcmp (n->Tag, "gml:lineStringMembers") == 0
2556 || strcmp (n->Tag, "lineStringMembers") == 0)
2557 ;
2558 else
2559 return 0;
2560 n2 = n->Next;
2561 lns = 0;
2562 while (n2)
2563 {
2564 /* looping on Linestring(s) */
2565 if (strcmp (n2->Tag, "gml:LineString") == 0
2566 || strcmp (n2->Tag, "LineString") == 0)
2567 ;
2568 else
2569 {
2570 n = n2;
2571 break;
2572 }
2573 n2 = n2->Next;
2574 if (n2 == NULL)
2575 return 0;
2576 if (!gml_parse_linestring (p_data, geom, n2, &next))
2577 return 0;
2578 n2 = next;
2579 if (n2 == NULL)
2580 return 0;
2581 lns++;
2582 }
2583 if (!lns)
2584 return 0;
2585 if (strcmp (n->Tag, "gml:lineStringMember") == 0
2586 || strcmp (n->Tag, "lineStringMember") == 0
2587 || strcmp (n->Tag, "gml:lineStringMembers") == 0
2588 || strcmp (n->Tag, "lineStringMembers") == 0)
2589 ;
2590 else
2591 return 0;
2592 n = n->Next;
2593 }
2594 return 1;
2595 }
2596
2597 static int
gml_parse_multi_curve(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node)2598 gml_parse_multi_curve (struct gml_data *p_data, gaiaGeomCollPtr geom,
2599 gmlNodePtr node)
2600 {
2601 /* parsing a <gml:MultiCurve> */
2602 int lns;
2603 gmlNodePtr n2;
2604 gmlNodePtr next;
2605 gmlNodePtr n = node;
2606
2607 while (n)
2608 {
2609 /* looping on Curve Members */
2610 if (n->Next == NULL)
2611 {
2612 /* verifying the last GML node */
2613 if (strcmp (n->Tag, "gml:MultiCurve") == 0
2614 || strcmp (n->Tag, "MultiCurve") == 0)
2615 break;
2616 else
2617 return 0;
2618 }
2619 if (strcmp (n->Tag, "gml:curveMember") == 0
2620 || strcmp (n->Tag, "curveMember") == 0
2621 || strcmp (n->Tag, "gml:curveMembers") == 0
2622 || strcmp (n->Tag, "curveMembers") == 0)
2623 ;
2624 else
2625 return 0;
2626 n2 = n->Next;
2627 lns = 0;
2628 while (n2)
2629 {
2630 /* looping on Curve(s) */
2631 if (strcmp (n2->Tag, "gml:LineString") == 0
2632 || strcmp (n2->Tag, "LineString") == 0)
2633 {
2634 n2 = n2->Next;
2635 if (n2 == NULL)
2636 return 0;
2637 if (!gml_parse_linestring (p_data, geom, n2, &next))
2638 return 0;
2639 n2 = next;
2640 if (n2 == NULL)
2641 return 0;
2642 lns++;
2643 }
2644 if (strcmp (n2->Tag, "gml:Curve") == 0
2645 || strcmp (n2->Tag, "Curve") == 0)
2646 ;
2647 else
2648 {
2649 n = n2;
2650 break;
2651 }
2652 n2 = n2->Next;
2653 if (n2 == NULL)
2654 return 0;
2655 if (!gml_parse_curve (p_data, geom, n2, &next))
2656 return 0;
2657 n2 = next;
2658 if (n2 == NULL)
2659 return 0;
2660 lns++;
2661 }
2662 if (!lns)
2663 return 0;
2664 if (strcmp (n->Tag, "gml:curveMember") == 0
2665 || strcmp (n->Tag, "curveMember") == 0
2666 || strcmp (n->Tag, "gml:curveMembers") == 0
2667 || strcmp (n->Tag, "curveMembers") == 0)
2668 ;
2669 else
2670 return 0;
2671 n = n->Next;
2672 }
2673 return 1;
2674 }
2675
2676 static int
gml_parse_multi_polygon(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node)2677 gml_parse_multi_polygon (struct gml_data *p_data, gaiaGeomCollPtr geom,
2678 gmlNodePtr node)
2679 {
2680 /* parsing a <gml:MultiPolygon> */
2681 int pgs;
2682 gmlNodePtr n2;
2683 gmlNodePtr next;
2684 gmlNodePtr n = node;
2685
2686 while (n)
2687 {
2688 /* looping on Polygon Members */
2689 if (n->Next == NULL)
2690 {
2691 /* verifying the last GML node */
2692 if (strcmp (n->Tag, "gml:MultiPolygon") == 0
2693 || strcmp (n->Tag, "MultiPolygon") == 0)
2694 break;
2695 else
2696 return 0;
2697 }
2698 if (strcmp (n->Tag, "gml:polygonMember") == 0
2699 || strcmp (n->Tag, "polygonMember") == 0
2700 || strcmp (n->Tag, "gml:polygonMembers") == 0
2701 || strcmp (n->Tag, "polygonMembers") == 0)
2702 ;
2703 else
2704 return 0;
2705 n2 = n->Next;
2706 pgs = 0;
2707 while (n2)
2708 {
2709 /* looping on Polygon(s) */
2710 if (strcmp (n2->Tag, "gml:Polygon") == 0
2711 || strcmp (n2->Tag, "Polygon") == 0)
2712 ;
2713 else
2714 {
2715 n = n2;
2716 break;
2717 }
2718 n2 = n2->Next;
2719 if (n2 == NULL)
2720 return 0;
2721 if (!gml_parse_polygon (p_data, geom, n2, &next))
2722 return 0;
2723 n2 = next;
2724 if (n2 == NULL)
2725 return 0;
2726 pgs++;
2727 }
2728 if (!pgs)
2729 return 0;
2730 if (strcmp (n->Tag, "gml:polygonMember") == 0
2731 || strcmp (n->Tag, "polygonMember") == 0
2732 || strcmp (n->Tag, "gml:polygonMembers") == 0
2733 || strcmp (n->Tag, "polygonMembers") == 0)
2734 ;
2735 else
2736 return 0;
2737 n = n->Next;
2738 }
2739 return 1;
2740 }
2741
2742 static int
gml_parse_multi_surface(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node)2743 gml_parse_multi_surface (struct gml_data *p_data, gaiaGeomCollPtr geom,
2744 gmlNodePtr node)
2745 {
2746 /* parsing a <gml:MultiSurface> */
2747 int pgs;
2748 gmlNodePtr n2;
2749 gmlNodePtr next;
2750 gmlNodePtr n = node;
2751
2752 while (n)
2753 {
2754 /* looping on Surface Members */
2755 if (n->Next == NULL)
2756 {
2757 /* verifying the last GML node */
2758 if (strcmp (n->Tag, "gml:MultiSurface") == 0
2759 || strcmp (n->Tag, "MultiSurface") == 0)
2760 break;
2761 else
2762 return 0;
2763 }
2764 if (strcmp (n->Tag, "gml:surfaceMember") == 0
2765 || strcmp (n->Tag, "surfaceMember") == 0
2766 || strcmp (n->Tag, "gml:surfaceMembers") == 0
2767 || strcmp (n->Tag, "surfaceMembers") == 0)
2768 ;
2769 else
2770 return 0;
2771 n2 = n->Next;
2772 pgs = 0;
2773 while (n2)
2774 {
2775 /* looping on Polygon(s) */
2776 if (strcmp (n2->Tag, "gml:Polygon") == 0
2777 || strcmp (n2->Tag, "Polygon") == 0)
2778 ;
2779 else
2780 {
2781 n = n2;
2782 break;
2783 }
2784 n2 = n2->Next;
2785 if (n2 == NULL)
2786 return 0;
2787 if (!gml_parse_polygon (p_data, geom, n2, &next))
2788 return 0;
2789 n2 = next;
2790 if (n2 == NULL)
2791 return 0;
2792 pgs++;
2793 }
2794 if (!pgs)
2795 return 0;
2796 if (strcmp (n->Tag, "gml:surfaceMember") == 0
2797 || strcmp (n->Tag, "surfaceMember") == 0
2798 || strcmp (n->Tag, "gml:surfaceMembers") == 0
2799 || strcmp (n->Tag, "surfaceMembers") == 0)
2800 ;
2801 else
2802 return 0;
2803 n = n->Next;
2804 }
2805 return 1;
2806 }
2807
2808 static int
gml_parse_multi_geometry(struct gml_data * p_data,gaiaGeomCollPtr geom,gmlNodePtr node)2809 gml_parse_multi_geometry (struct gml_data *p_data, gaiaGeomCollPtr geom,
2810 gmlNodePtr node)
2811 {
2812 /* parsing a <gml:MultiGeometry> */
2813 int elems;
2814 gmlNodePtr n2;
2815 gmlNodePtr next;
2816 gmlNodePtr n = node;
2817
2818 while (n)
2819 {
2820 /* looping on Geometry Members */
2821 if (n->Next == NULL)
2822 {
2823 /* verifying the last GML node */
2824 if (strcmp (n->Tag, "gml:MultiGeometry") == 0
2825 || strcmp (n->Tag, "MultiGeometry") == 0)
2826 break;
2827 else
2828 return 0;
2829 }
2830 if (strcmp (n->Tag, "gml:geometryMember") == 0
2831 || strcmp (n->Tag, "geometryMember") == 0
2832 || strcmp (n->Tag, "gml:geometryMembers") == 0
2833 || strcmp (n->Tag, "geometryMembers") == 0)
2834 ;
2835 else
2836 return 0;
2837 n2 = n->Next;
2838 elems = 0;
2839 while (n2)
2840 {
2841 /* looping on elements */
2842 if (strcmp (n2->Tag, "gml:Point") == 0
2843 || strcmp (n2->Tag, "Point") == 0)
2844 {
2845 n2 = n2->Next;
2846 if (n2 == NULL)
2847 return 0;
2848 if (!gml_parse_point (p_data, geom, n2, &next))
2849 return 0;
2850 n2 = next;
2851 }
2852 else if (strcmp (n2->Tag, "gml:LineString") == 0
2853 || strcmp (n2->Tag, "LineString") == 0)
2854 {
2855 n2 = n2->Next;
2856 if (n2 == NULL)
2857 return 0;
2858 if (!gml_parse_linestring (p_data, geom, n2, &next))
2859 return 0;
2860 n2 = next;
2861 }
2862 else if (strcmp (n2->Tag, "gml:Curve") == 0
2863 || strcmp (n2->Tag, "Curve") == 0)
2864 {
2865 n2 = n2->Next;
2866 if (n2 == NULL)
2867 return 0;
2868 if (!gml_parse_curve (p_data, geom, n2, &next))
2869 return 0;
2870 n2 = next;
2871 }
2872 else if (strcmp (n2->Tag, "gml:Polygon") == 0
2873 || strcmp (n2->Tag, "Polygon") == 0)
2874 {
2875 n2 = n2->Next;
2876 if (n2 == NULL)
2877 return 0;
2878 if (!gml_parse_polygon (p_data, geom, n2, &next))
2879 return 0;
2880 n2 = next;
2881 }
2882 else
2883 {
2884 n = n2;
2885 break;
2886 }
2887 elems++;
2888 }
2889 if (!elems)
2890 return 0;
2891 if (strcmp (n->Tag, "gml:geometryMember") == 0
2892 || strcmp (n->Tag, "geometryMember") == 0
2893 || strcmp (n->Tag, "gml:geometryMembers") == 0
2894 || strcmp (n->Tag, "geometryMembers") == 0)
2895 ;
2896 else
2897 return 0;
2898 n = n->Next;
2899 }
2900 return 1;
2901 }
2902
2903 static gaiaGeomCollPtr
gml_validate_geometry(const void * cache,struct gml_data * p_data,gaiaGeomCollPtr chain,sqlite3 * sqlite_handle)2904 gml_validate_geometry (const void *cache, struct gml_data *p_data,
2905 gaiaGeomCollPtr chain, sqlite3 * sqlite_handle)
2906 {
2907 int xy = 0;
2908 int xyz = 0;
2909 int pts = 0;
2910 int lns = 0;
2911 int pgs = 0;
2912 gaiaPointPtr pt;
2913 gaiaLinestringPtr ln;
2914 gaiaPolygonPtr pg;
2915 gaiaPointPtr save_pt = NULL;
2916 gaiaLinestringPtr save_ln = NULL;
2917 gaiaPolygonPtr save_pg = NULL;
2918 gaiaRingPtr i_ring;
2919 gaiaRingPtr o_ring;
2920 int ib;
2921 int delete_g2;
2922 gaiaGeomCollPtr g;
2923 gaiaGeomCollPtr g2;
2924 gaiaGeomCollPtr geom;
2925 char *proj_from;
2926 char *proj_to;
2927
2928 g = chain;
2929 while (g)
2930 {
2931 if (g != chain)
2932 {
2933 if (g->DimensionModel == GAIA_XY)
2934 xy++;
2935 if (g->DimensionModel == GAIA_XY_Z)
2936 xyz++;
2937 }
2938 pt = g->FirstPoint;
2939 while (pt)
2940 {
2941 pts++;
2942 save_pt = pt;
2943 pt = pt->Next;
2944 }
2945 ln = g->FirstLinestring;
2946 while (ln)
2947 {
2948 lns++;
2949 save_ln = ln;
2950 ln = ln->Next;
2951 }
2952 pg = g->FirstPolygon;
2953 while (pg)
2954 {
2955 pgs++;
2956 save_pg = pg;
2957 pg = pg->Next;
2958 }
2959 g = g->Next;
2960 }
2961 if (pts == 1 && lns == 0 && pgs == 0)
2962 {
2963 /* POINT */
2964 if (xy > 0)
2965 {
2966 /* 2D [XY] */
2967 geom = gaiaAllocGeomColl ();
2968 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
2969 geom->Srid = chain->Srid;
2970 if (chain->DeclaredType == GAIA_MULTIPOINT)
2971 geom->DeclaredType = GAIA_MULTIPOINT;
2972 else if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
2973 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
2974 else
2975 geom->DeclaredType = GAIA_POINT;
2976 gaiaAddPointToGeomColl (geom, save_pt->X, save_pt->Y);
2977 return geom;
2978 }
2979 else
2980 {
2981 /* 3D [XYZ] */
2982 geom = gaiaAllocGeomCollXYZ ();
2983 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
2984 geom->Srid = chain->Srid;
2985 if (chain->DeclaredType == GAIA_MULTIPOINT)
2986 geom->DeclaredType = GAIA_MULTIPOINT;
2987 else if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
2988 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
2989 else
2990 geom->DeclaredType = GAIA_POINT;
2991 gaiaAddPointToGeomCollXYZ (geom, save_pt->X, save_pt->Y,
2992 save_pt->Z);
2993 return geom;
2994 }
2995 }
2996 if (pts == 0 && lns == 1 && pgs == 0)
2997 {
2998 /* LINESTRING */
2999 if (xy > 0)
3000 {
3001 /* 2D [XY] */
3002 geom = gaiaAllocGeomColl ();
3003 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3004 }
3005 else
3006 {
3007 /* 3D [XYZ] */
3008 geom = gaiaAllocGeomCollXYZ ();
3009 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3010 }
3011 geom->Srid = chain->Srid;
3012 if (chain->DeclaredType == GAIA_MULTILINESTRING)
3013 geom->DeclaredType = GAIA_MULTILINESTRING;
3014 else if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3015 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3016 else
3017 geom->DeclaredType = GAIA_LINESTRING;
3018 ln = gaiaAddLinestringToGeomColl (geom, save_ln->Points);
3019 gaiaCopyLinestringCoords (ln, save_ln);
3020 return geom;
3021 }
3022 if (pts == 0 && lns == 0 && pgs == 1)
3023 {
3024 /* POLYGON */
3025 if (xy > 0)
3026 {
3027 /* 2D [XY] */
3028 geom = gaiaAllocGeomColl ();
3029 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3030 }
3031 else
3032 {
3033 /* 3D [XYZ] */
3034 geom = gaiaAllocGeomCollXYZ ();
3035 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3036 }
3037 geom->Srid = chain->Srid;
3038 if (chain->DeclaredType == GAIA_MULTIPOLYGON)
3039 geom->DeclaredType = GAIA_MULTIPOLYGON;
3040 else if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3041 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3042 else
3043 geom->DeclaredType = GAIA_POLYGON;
3044 i_ring = save_pg->Exterior;
3045 pg = gaiaAddPolygonToGeomColl (geom, i_ring->Points,
3046 save_pg->NumInteriors);
3047 o_ring = pg->Exterior;
3048 gaiaCopyRingCoords (o_ring, i_ring);
3049 for (ib = 0; ib < save_pg->NumInteriors; ib++)
3050 {
3051 i_ring = save_pg->Interiors + ib;
3052 o_ring = gaiaAddInteriorRing (pg, ib, i_ring->Points);
3053 gaiaCopyRingCoords (o_ring, i_ring);
3054 }
3055 return geom;
3056 }
3057 if (pts >= 1 && lns == 0 && pgs == 0)
3058 {
3059 /* MULTIPOINT */
3060 if (xy > 0)
3061 {
3062 /* 2D [XY] */
3063 geom = gaiaAllocGeomColl ();
3064 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3065 geom->Srid = chain->Srid;
3066 if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3067 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3068 else
3069 geom->DeclaredType = GAIA_MULTIPOINT;
3070 g = chain;
3071 while (g)
3072 {
3073 if (geom->Srid <= 0)
3074 {
3075 /* we haven't yet set any SRID */
3076 geom->Srid = g->Srid;
3077 }
3078 g2 = g;
3079 delete_g2 = 0;
3080 if (g->Srid != geom->Srid && g->Srid > 0
3081 && sqlite_handle != NULL)
3082 {
3083 /* we'll try to apply a reprojection */
3084 #ifndef OMIT_PROJ /* but only if PROJ.4 is actually available */
3085 getProjParams (sqlite_handle, g->Srid, &proj_from);
3086 getProjParams (sqlite_handle, geom->Srid, &proj_to);
3087 if (proj_to == NULL || proj_from == NULL)
3088 ;
3089 else
3090 {
3091 if (cache != NULL)
3092 g2 = gaiaTransform_r (cache, g, proj_from,
3093 proj_to);
3094 else
3095 g2 = gaiaTransform (g, proj_from,
3096 proj_to);
3097 if (!g2)
3098 g2 = g;
3099 else
3100 delete_g2 = 1;
3101 }
3102 if (proj_from)
3103 free (proj_from);
3104 if (proj_to)
3105 free (proj_to);
3106 #endif
3107 }
3108 pt = g2->FirstPoint;
3109 while (pt)
3110 {
3111 gaiaAddPointToGeomColl (geom, pt->X, pt->Y);
3112 pt = pt->Next;
3113 }
3114 if (delete_g2)
3115 {
3116 gmlMapDynClean (p_data, g2);
3117 gaiaFreeGeomColl (g2);
3118 }
3119 g = g->Next;
3120 }
3121 return geom;
3122 }
3123 else
3124 {
3125 /* 3D [XYZ] */
3126 geom = gaiaAllocGeomCollXYZ ();
3127 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3128 geom->Srid = chain->Srid;
3129 if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3130 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3131 else
3132 geom->DeclaredType = GAIA_MULTIPOINT;
3133 g = chain;
3134 while (g)
3135 {
3136 if (geom->Srid <= 0)
3137 {
3138 /* we haven't yet a SRID set */
3139 geom->Srid = g->Srid;
3140 }
3141 g2 = g;
3142 delete_g2 = 0;
3143 if (g->Srid != geom->Srid && g->Srid > 0
3144 && sqlite_handle != NULL)
3145 {
3146 /* we'll try to apply a reprojection */
3147 #ifndef OMIT_PROJ /* but only if PROJ.4 is actually available */
3148 getProjParams (sqlite_handle, g->Srid, &proj_from);
3149 getProjParams (sqlite_handle, geom->Srid, &proj_to);
3150 if (proj_to == NULL || proj_from == NULL)
3151 ;
3152 else
3153 {
3154 if (cache != NULL)
3155 g2 = gaiaTransform_r (cache, g, proj_from,
3156 proj_to);
3157 else
3158 g2 = gaiaTransform (g, proj_from,
3159 proj_to);
3160 if (!g2)
3161 g2 = g;
3162 else
3163 delete_g2 = 1;
3164 }
3165 if (proj_from)
3166 free (proj_from);
3167 if (proj_to)
3168 free (proj_to);
3169 #endif
3170 }
3171 pt = g2->FirstPoint;
3172 while (pt)
3173 {
3174 gaiaAddPointToGeomCollXYZ (geom, pt->X, pt->Y,
3175 pt->Z);
3176 pt = pt->Next;
3177 }
3178 if (delete_g2)
3179 {
3180 gmlMapDynClean (p_data, g2);
3181 gaiaFreeGeomColl (g2);
3182 }
3183 g = g->Next;
3184 }
3185 return geom;
3186 }
3187 }
3188 if (pts == 0 && lns >= 1 && pgs == 0)
3189 {
3190 /* MULTILINESTRING */
3191 if (xy > 0)
3192 {
3193 /* 2D [XY] */
3194 geom = gaiaAllocGeomColl ();
3195 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3196 geom->Srid = chain->Srid;
3197 if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3198 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3199 else
3200 geom->DeclaredType = GAIA_MULTILINESTRING;
3201 g = chain;
3202 while (g)
3203 {
3204 if (geom->Srid <= 0)
3205 {
3206 /* we haven't yet set any SRID */
3207 geom->Srid = g->Srid;
3208 }
3209 g2 = g;
3210 delete_g2 = 0;
3211 if (g->Srid != geom->Srid && g->Srid > 0
3212 && sqlite_handle != NULL)
3213 {
3214 /* we'll try to apply a reprojection */
3215 #ifndef OMIT_PROJ /* but only if PROJ.4 is actually available */
3216 getProjParams (sqlite_handle, g->Srid, &proj_from);
3217 getProjParams (sqlite_handle, geom->Srid, &proj_to);
3218 if (proj_to == NULL || proj_from == NULL)
3219 ;
3220 else
3221 {
3222 if (cache != NULL)
3223 g2 = gaiaTransform_r (cache, g, proj_from,
3224 proj_to);
3225 else
3226 g2 = gaiaTransform (g, proj_from,
3227 proj_to);
3228 if (!g2)
3229 g2 = g;
3230 else
3231 delete_g2 = 1;
3232 }
3233 if (proj_from)
3234 free (proj_from);
3235 if (proj_to)
3236 free (proj_to);
3237 #endif
3238 }
3239 ln = g2->FirstLinestring;
3240 while (ln)
3241 {
3242 save_ln =
3243 gaiaAddLinestringToGeomColl (geom, ln->Points);
3244 gaiaCopyLinestringCoords (save_ln, ln);
3245 ln = ln->Next;
3246 }
3247 if (delete_g2)
3248 {
3249 gmlMapDynClean (p_data, g2);
3250 gaiaFreeGeomColl (g2);
3251 }
3252 g = g->Next;
3253 }
3254 return geom;
3255 }
3256 else
3257 {
3258 /* 3D [XYZ] */
3259 geom = gaiaAllocGeomCollXYZ ();
3260 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3261 geom->Srid = chain->Srid;
3262 if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3263 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3264 else
3265 geom->DeclaredType = GAIA_MULTILINESTRING;
3266 g = chain;
3267 while (g)
3268 {
3269 if (geom->Srid <= 0)
3270 {
3271 /* we haven't yet a SRID set */
3272 geom->Srid = g->Srid;
3273 }
3274 g2 = g;
3275 delete_g2 = 0;
3276 if (g->Srid != geom->Srid && g->Srid > 0
3277 && sqlite_handle != NULL)
3278 {
3279 /* we'll try to apply a reprojection */
3280 #ifndef OMIT_PROJ /* but only if PROJ.4 is actually available */
3281 getProjParams (sqlite_handle, g->Srid, &proj_from);
3282 getProjParams (sqlite_handle, geom->Srid, &proj_to);
3283 if (proj_to == NULL || proj_from == NULL)
3284 ;
3285 else
3286 {
3287 if (cache != NULL)
3288 g2 = gaiaTransform_r (cache, g, proj_from,
3289 proj_to);
3290 else
3291 g2 = gaiaTransform (g, proj_from,
3292 proj_to);
3293 if (!g2)
3294 g2 = g;
3295 else
3296 delete_g2 = 1;
3297 }
3298 if (proj_from)
3299 free (proj_from);
3300 if (proj_to)
3301 free (proj_to);
3302 #endif
3303 }
3304 ln = g2->FirstLinestring;
3305 while (ln)
3306 {
3307 save_ln =
3308 gaiaAddLinestringToGeomColl (geom, ln->Points);
3309 gaiaCopyLinestringCoords (save_ln, ln);
3310 ln = ln->Next;
3311 }
3312 if (delete_g2)
3313 {
3314 gmlMapDynClean (p_data, g2);
3315 gaiaFreeGeomColl (g2);
3316 }
3317 g = g->Next;
3318 }
3319 return geom;
3320 }
3321 }
3322 if (pts == 0 && lns == 0 && pgs >= 1)
3323 {
3324 /* MULTIPOLYGON */
3325 if (xy > 0)
3326 {
3327 /* 2D [XY] */
3328 geom = gaiaAllocGeomColl ();
3329 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3330 geom->Srid = chain->Srid;
3331 if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3332 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3333 else
3334 geom->DeclaredType = GAIA_MULTIPOLYGON;
3335 g = chain;
3336 while (g)
3337 {
3338 if (geom->Srid <= 0)
3339 {
3340 /* we haven't yet set any SRID */
3341 geom->Srid = g->Srid;
3342 }
3343 g2 = g;
3344 delete_g2 = 0;
3345 if (g->Srid != geom->Srid && g->Srid > 0
3346 && sqlite_handle != NULL)
3347 {
3348 /* we'll try to apply a reprojection */
3349 #ifndef OMIT_PROJ /* but only if PROJ.4 is actually available */
3350 getProjParams (sqlite_handle, g->Srid, &proj_from);
3351 getProjParams (sqlite_handle, geom->Srid, &proj_to);
3352 if (proj_to == NULL || proj_from == NULL)
3353 ;
3354 else
3355 {
3356 if (cache != NULL)
3357 g2 = gaiaTransform_r (cache, g, proj_from,
3358 proj_to);
3359 else
3360 g2 = gaiaTransform (g, proj_from,
3361 proj_to);
3362 if (!g2)
3363 g2 = g;
3364 else
3365 delete_g2 = 1;
3366 }
3367 if (proj_from)
3368 free (proj_from);
3369 if (proj_to)
3370 free (proj_to);
3371 #endif
3372 }
3373 pg = g2->FirstPolygon;
3374 while (pg)
3375 {
3376 i_ring = pg->Exterior;
3377 save_pg =
3378 gaiaAddPolygonToGeomColl (geom, i_ring->Points,
3379 pg->NumInteriors);
3380 o_ring = save_pg->Exterior;
3381 gaiaCopyRingCoords (o_ring, i_ring);
3382 for (ib = 0; ib < pg->NumInteriors; ib++)
3383 {
3384 i_ring = pg->Interiors + ib;
3385 o_ring =
3386 gaiaAddInteriorRing (save_pg, ib,
3387 i_ring->Points);
3388 gaiaCopyRingCoords (o_ring, i_ring);
3389 }
3390 pg = pg->Next;
3391 }
3392 if (delete_g2)
3393 {
3394 gmlMapDynClean (p_data, g2);
3395 gaiaFreeGeomColl (g2);
3396 }
3397 g = g->Next;
3398 }
3399 return geom;
3400 }
3401 else
3402 {
3403 /* 3D [XYZ] */
3404 geom = gaiaAllocGeomCollXYZ ();
3405 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3406 geom->Srid = chain->Srid;
3407 if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3408 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3409 else
3410 geom->DeclaredType = GAIA_MULTIPOLYGON;
3411 g = chain;
3412 while (g)
3413 {
3414 if (geom->Srid <= 0)
3415 {
3416 /* we haven't yet a SRID set */
3417 geom->Srid = g->Srid;
3418 }
3419 g2 = g;
3420 delete_g2 = 0;
3421 if (g->Srid != geom->Srid && g->Srid > 0
3422 && sqlite_handle != NULL)
3423 {
3424 /* we'll try to apply a reprojection */
3425 #ifndef OMIT_PROJ /* but only if PROJ.4 is actually available */
3426 getProjParams (sqlite_handle, g->Srid, &proj_from);
3427 getProjParams (sqlite_handle, geom->Srid, &proj_to);
3428 if (proj_to == NULL || proj_from == NULL)
3429 ;
3430 else
3431 {
3432 if (cache != NULL)
3433 g2 = gaiaTransform_r (cache, g, proj_from,
3434 proj_to);
3435 else
3436 g2 = gaiaTransform (g, proj_from,
3437 proj_to);
3438 if (!g2)
3439 g2 = g;
3440 else
3441 delete_g2 = 1;
3442 }
3443 if (proj_from)
3444 free (proj_from);
3445 if (proj_to)
3446 free (proj_to);
3447 #endif
3448 }
3449 pg = g2->FirstPolygon;
3450 while (pg)
3451 {
3452 i_ring = pg->Exterior;
3453 save_pg =
3454 gaiaAddPolygonToGeomColl (geom, i_ring->Points,
3455 pg->NumInteriors);
3456 o_ring = save_pg->Exterior;
3457 gaiaCopyRingCoords (o_ring, i_ring);
3458 for (ib = 0; ib < pg->NumInteriors; ib++)
3459 {
3460 i_ring = pg->Interiors + ib;
3461 o_ring =
3462 gaiaAddInteriorRing (save_pg, ib,
3463 i_ring->Points);
3464 gaiaCopyRingCoords (o_ring, i_ring);
3465 }
3466 pg = pg->Next;
3467 }
3468 if (delete_g2)
3469 {
3470 gmlMapDynClean (p_data, g2);
3471 gaiaFreeGeomColl (g2);
3472 }
3473 g = g->Next;
3474 }
3475 return geom;
3476 }
3477 }
3478 if ((pts + lns + pgs) > 0)
3479 {
3480 /* GEOMETRYCOLLECTION */
3481 if (xy > 0)
3482 {
3483 /* 2D [XY] */
3484 geom = gaiaAllocGeomColl ();
3485 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3486 geom->Srid = chain->Srid;
3487 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3488 g = chain;
3489 while (g)
3490 {
3491 if (geom->Srid <= 0)
3492 {
3493 /* we haven't yet set any SRID */
3494 geom->Srid = g->Srid;
3495 }
3496 g2 = g;
3497 delete_g2 = 0;
3498 if (g->Srid != geom->Srid && g->Srid > 0
3499 && sqlite_handle != NULL)
3500 {
3501 /* we'll try to apply a reprojection */
3502 #ifndef OMIT_PROJ /* but only if PROJ.4 is actually available */
3503 getProjParams (sqlite_handle, g->Srid, &proj_from);
3504 getProjParams (sqlite_handle, geom->Srid, &proj_to);
3505 if (proj_to == NULL || proj_from == NULL)
3506 ;
3507 else
3508 {
3509 if (cache != NULL)
3510 g2 = gaiaTransform_r (cache, g, proj_from,
3511 proj_to);
3512 else
3513 g2 = gaiaTransform (g, proj_from,
3514 proj_to);
3515 if (!g2)
3516 g2 = g;
3517 else
3518 delete_g2 = 1;
3519 }
3520 if (proj_from)
3521 free (proj_from);
3522 if (proj_to)
3523 free (proj_to);
3524 #endif
3525 }
3526 pt = g2->FirstPoint;
3527 while (pt)
3528 {
3529 gaiaAddPointToGeomColl (geom, pt->X, pt->Y);
3530 pt = pt->Next;
3531 }
3532 ln = g2->FirstLinestring;
3533 while (ln)
3534 {
3535 save_ln =
3536 gaiaAddLinestringToGeomColl (geom, ln->Points);
3537 gaiaCopyLinestringCoords (save_ln, ln);
3538 ln = ln->Next;
3539 }
3540 pg = g2->FirstPolygon;
3541 while (pg)
3542 {
3543 i_ring = pg->Exterior;
3544 save_pg =
3545 gaiaAddPolygonToGeomColl (geom, i_ring->Points,
3546 pg->NumInteriors);
3547 o_ring = save_pg->Exterior;
3548 gaiaCopyRingCoords (o_ring, i_ring);
3549 for (ib = 0; ib < pg->NumInteriors; ib++)
3550 {
3551 i_ring = pg->Interiors + ib;
3552 o_ring =
3553 gaiaAddInteriorRing (save_pg, ib,
3554 i_ring->Points);
3555 gaiaCopyRingCoords (o_ring, i_ring);
3556 }
3557 pg = pg->Next;
3558 }
3559 if (delete_g2)
3560 {
3561 gmlMapDynClean (p_data, g2);
3562 gaiaFreeGeomColl (g2);
3563 }
3564 g = g->Next;
3565 }
3566 return geom;
3567 }
3568 else
3569 {
3570 /* 3D [XYZ] */
3571 geom = gaiaAllocGeomCollXYZ ();
3572 gmlMapDynAlloc (p_data, GML_DYN_GEOM, geom);
3573 geom->Srid = chain->Srid;
3574 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3575 g = chain;
3576 while (g)
3577 {
3578 if (geom->Srid <= 0)
3579 {
3580 /* we haven't yet a SRID set */
3581 geom->Srid = g->Srid;
3582 }
3583 g2 = g;
3584 delete_g2 = 0;
3585 if (g->Srid != geom->Srid && g->Srid > 0
3586 && sqlite_handle != NULL)
3587 {
3588 /* we'll try to apply a reprojection */
3589 #ifndef OMIT_PROJ /* but only if PROJ.4 is actually available */
3590 getProjParams (sqlite_handle, g->Srid, &proj_from);
3591 getProjParams (sqlite_handle, geom->Srid, &proj_to);
3592 if (*proj_to == '\0' || *proj_from == '\0')
3593 ;
3594 else
3595 {
3596 if (cache != NULL)
3597 g2 = gaiaTransform_r (cache, g, proj_from,
3598 proj_to);
3599 else
3600 g2 = gaiaTransform (g, proj_from,
3601 proj_to);
3602 if (!g2)
3603 g2 = g;
3604 else
3605 delete_g2 = 1;
3606 }
3607 if (proj_from)
3608 free (proj_from);
3609 if (proj_to)
3610 free (proj_to);
3611 #endif
3612 }
3613 pt = g2->FirstPoint;
3614 while (pt)
3615 {
3616 gaiaAddPointToGeomCollXYZ (geom, pt->X, pt->Y,
3617 pt->Z);
3618 pt = pt->Next;
3619 }
3620 ln = g2->FirstLinestring;
3621 while (ln)
3622 {
3623 save_ln =
3624 gaiaAddLinestringToGeomColl (geom, ln->Points);
3625 gaiaCopyLinestringCoords (save_ln, ln);
3626 ln = ln->Next;
3627 }
3628 pg = g2->FirstPolygon;
3629 while (pg)
3630 {
3631 i_ring = pg->Exterior;
3632 save_pg =
3633 gaiaAddPolygonToGeomColl (geom, i_ring->Points,
3634 pg->NumInteriors);
3635 o_ring = save_pg->Exterior;
3636 gaiaCopyRingCoords (o_ring, i_ring);
3637 for (ib = 0; ib < pg->NumInteriors; ib++)
3638 {
3639 i_ring = pg->Interiors + ib;
3640 o_ring =
3641 gaiaAddInteriorRing (save_pg, ib,
3642 i_ring->Points);
3643 gaiaCopyRingCoords (o_ring, i_ring);
3644 }
3645 pg = pg->Next;
3646 }
3647 if (delete_g2)
3648 {
3649 gmlMapDynClean (p_data, g2);
3650 gaiaFreeGeomColl (g2);
3651 }
3652 g = g->Next;
3653 }
3654 return geom;
3655 }
3656 }
3657 return NULL;
3658 }
3659
3660 static void
gml_free_geom_chain(struct gml_data * p_data,gaiaGeomCollPtr geom)3661 gml_free_geom_chain (struct gml_data *p_data, gaiaGeomCollPtr geom)
3662 {
3663 /* deleting a chain of preliminary geometries */
3664 gaiaGeomCollPtr gn;
3665 while (geom)
3666 {
3667 gn = geom->Next;
3668 gmlMapDynClean (p_data, geom);
3669 gaiaFreeGeomColl (geom);
3670 geom = gn;
3671 }
3672 }
3673
3674 static gaiaGeomCollPtr
gml_build_geometry(const void * cache,struct gml_data * p_data,gmlNodePtr tree,sqlite3 * sqlite_handle)3675 gml_build_geometry (const void *cache, struct gml_data *p_data, gmlNodePtr tree,
3676 sqlite3 * sqlite_handle)
3677 {
3678 /* attempting to build a geometry from GML nodes */
3679 gaiaGeomCollPtr geom;
3680 gaiaGeomCollPtr result;
3681 int geom_type;
3682 int dims = 2;
3683 gmlNodePtr next;
3684
3685 if (tree == NULL)
3686 return NULL;
3687 geom_type = guessGmlGeometryType (tree);
3688 if (geom_type == GAIA_GML_UNKNOWN)
3689 {
3690 /* unsupported main geometry type */
3691 return NULL;
3692 }
3693
3694 /* creating the main geometry */
3695 dims = guessGmlDimensions (tree);
3696 if (dims == 2)
3697 geom = gaiaAllocGeomColl ();
3698 else
3699 geom = gaiaAllocGeomCollXYZ ();
3700 geom->Srid = guessGmlSrid (tree);
3701
3702 switch (geom_type)
3703 {
3704 /* parsing GML nodes accordingly with declared GML type */
3705 case GAIA_GML_POINT:
3706 geom->DeclaredType = GAIA_POINT;
3707 if (!gml_parse_point (p_data, geom, tree->Next, &next))
3708 goto error;
3709 break;
3710 case GAIA_GML_LINESTRING:
3711 geom->DeclaredType = GAIA_LINESTRING;
3712 if (!gml_parse_linestring (p_data, geom, tree->Next, &next))
3713 goto error;
3714 break;
3715 case GAIA_GML_CURVE:
3716 geom->DeclaredType = GAIA_LINESTRING;
3717 if (!gml_parse_curve (p_data, geom, tree->Next, &next))
3718 goto error;
3719 break;
3720 case GAIA_GML_POLYGON:
3721 geom->DeclaredType = GAIA_POLYGON;
3722 if (!gml_parse_polygon (p_data, geom, tree->Next, &next))
3723 goto error;
3724 if (next != NULL)
3725 goto error;
3726 break;
3727 case GAIA_GML_MULTIPOINT:
3728 geom->DeclaredType = GAIA_MULTIPOINT;
3729 if (!gml_parse_multi_point (p_data, geom, tree->Next))
3730 goto error;
3731 break;
3732 case GAIA_GML_MULTILINESTRING:
3733 geom->DeclaredType = GAIA_MULTILINESTRING;
3734 if (!gml_parse_multi_linestring (p_data, geom, tree->Next))
3735 goto error;
3736 break;
3737 case GAIA_GML_MULTICURVE:
3738 geom->DeclaredType = GAIA_MULTILINESTRING;
3739 if (!gml_parse_multi_curve (p_data, geom, tree->Next))
3740 goto error;
3741 break;
3742 case GAIA_GML_MULTIPOLYGON:
3743 geom->DeclaredType = GAIA_MULTIPOLYGON;
3744 if (!gml_parse_multi_polygon (p_data, geom, tree->Next))
3745 goto error;
3746 break;
3747 case GAIA_GML_MULTISURFACE:
3748 geom->DeclaredType = GAIA_MULTIPOLYGON;
3749 if (!gml_parse_multi_surface (p_data, geom, tree->Next))
3750 goto error;
3751 break;
3752 case GAIA_GML_MULTIGEOMETRY:
3753 geom->DeclaredType = GAIA_GEOMETRYCOLLECTION;
3754 if (!gml_parse_multi_geometry (p_data, geom, tree->Next))
3755 goto error;
3756 break;
3757 case GAIA_GML_BOX:
3758 geom->DeclaredType = GAIA_POLYGON;
3759 if (!gml_parse_box (p_data, geom, tree->Next, geom->Srid, &next))
3760 goto error;
3761 break;
3762 };
3763
3764 /* attempting to build the final geometry */
3765 result = gml_validate_geometry (cache, p_data, geom, sqlite_handle);
3766 if (result == NULL)
3767 goto error;
3768 gml_free_geom_chain (p_data, geom);
3769 return result;
3770
3771 error:
3772 gml_free_geom_chain (p_data, geom);
3773 return NULL;
3774 }
3775
3776
3777 /* including LEMON generated code */
3778 #include "Gml.c"
3779
3780
3781
3782 /*
3783 ** CAVEAT: there is an incompatibility between LEMON and FLEX
3784 ** this macro resolves the issue
3785 */
3786 #undef yy_accept
3787 #define yy_accept yy_gml_flex_accept
3788
3789
3790
3791 /* including FLEX generated code */
3792 #include "lex.Gml.c"
3793
3794
3795
3796 static gaiaGeomCollPtr
gaiaParseGmlCommon(const void * cache,const unsigned char * dirty_buffer,sqlite3 * sqlite_handle)3797 gaiaParseGmlCommon (const void *cache, const unsigned char *dirty_buffer,
3798 sqlite3 * sqlite_handle)
3799 {
3800 void *pParser = ParseAlloc (malloc);
3801 /* Linked-list of token values */
3802 gmlFlexToken *tokens = malloc (sizeof (gmlFlexToken));
3803 /* Pointer to the head of the list */
3804 gmlFlexToken *head = tokens;
3805 int yv;
3806 gaiaGeomCollPtr geom = NULL;
3807 yyscan_t scanner;
3808 struct gml_data str_data;
3809
3810 /* initializing the helper structs */
3811 str_data.gml_line = 1;
3812 str_data.gml_col = 1;
3813 str_data.gml_parse_error = 0;
3814 str_data.gml_first_dyn_block = NULL;
3815 str_data.gml_last_dyn_block = NULL;
3816 str_data.result = NULL;
3817
3818 /* initializing the scanner state */
3819 Gmllex_init_extra (&str_data, &scanner);
3820
3821 str_data.GmlLval.pval = NULL;
3822 tokens->value = NULL;
3823 tokens->Next = NULL;
3824 Gml_scan_string ((char *) dirty_buffer, scanner);
3825
3826 /*
3827 / Keep tokenizing until we reach the end
3828 / yylex() will return the next matching Token for us.
3829 */
3830 while ((yv = yylex (scanner)) != 0)
3831 {
3832 if (yv == -1)
3833 {
3834 str_data.gml_parse_error = 1;
3835 break;
3836 }
3837 tokens->Next = malloc (sizeof (gmlFlexToken));
3838 tokens->Next->Next = NULL;
3839 gml_xferString (&(tokens->Next->value), str_data.GmlLval.pval);
3840 /* Pass the token to the GML parser created from lemon */
3841 Parse (pParser, yv, &(tokens->Next->value), &str_data);
3842 tokens = tokens->Next;
3843 }
3844 /* This denotes the end of a line as well as the end of the parser */
3845 Parse (pParser, GML_NEWLINE, 0, &str_data);
3846 ParseFree (pParser, free);
3847 Gmllex_destroy (scanner);
3848
3849 /* Assigning the token as the end to avoid seg faults while cleaning */
3850 tokens->Next = NULL;
3851 gml_cleanup (head);
3852 gml_freeString (&(str_data.GmlLval.pval));
3853
3854 if (str_data.gml_parse_error)
3855 {
3856 if (str_data.result)
3857 {
3858 /* if a Geometry-result has been produced, the stack is already cleaned */
3859 gml_freeTree (&str_data, str_data.result);
3860 gmlCleanMapDynAlloc (&str_data, 0);
3861 }
3862 else
3863 {
3864 /* otherwise we are required to clean the stack */
3865 gmlCleanMapDynAlloc (&str_data, 1);
3866 }
3867 return NULL;
3868 }
3869
3870 if (str_data.result == NULL)
3871 {
3872 gmlCleanMapDynAlloc (&str_data, 0);
3873 return NULL;
3874 }
3875
3876 /* attempting to build a geometry from GML */
3877 geom =
3878 gml_build_geometry (cache, &str_data, str_data.result, sqlite_handle);
3879 gml_freeTree (&str_data, str_data.result);
3880 gmlCleanMapDynAlloc (&str_data, 0);
3881 return geom;
3882 }
3883
3884 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaParseGml(const unsigned char * dirty_buffer,sqlite3 * sqlite_handle)3885 gaiaParseGml (const unsigned char *dirty_buffer, sqlite3 * sqlite_handle)
3886 {
3887 return gaiaParseGmlCommon (NULL, dirty_buffer, sqlite_handle);
3888 }
3889
3890 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaParseGml_r(const void * p_cache,const unsigned char * dirty_buffer,sqlite3 * sqlite_handle)3891 gaiaParseGml_r (const void *p_cache, const unsigned char *dirty_buffer,
3892 sqlite3 * sqlite_handle)
3893 {
3894 return gaiaParseGmlCommon (p_cache, dirty_buffer, sqlite_handle);
3895 }
3896
3897
3898 /*
3899 ** CAVEAT: we must now undefine any Lemon/Flex own macro
3900 */
3901 #undef YYNOCODE
3902 #undef YYNSTATE
3903 #undef YYNRULE
3904 #undef YY_SHIFT_MAX
3905 #undef YY_SHIFT_USE_DFLT
3906 #undef YY_REDUCE_USE_DFLT
3907 #undef YY_REDUCE_MAX
3908 #undef YY_FLUSH_BUFFER
3909 #undef YY_DO_BEFORE_ACTION
3910 #undef YY_NUM_RULES
3911 #undef YY_END_OF_BUFFER
3912 #undef YY_END_FILE
3913 #undef YYACTIONTYPE
3914 #undef YY_SZ_ACTTAB
3915 #undef YY_NEW_FILE
3916 #undef BEGIN
3917 #undef YY_START
3918 #undef YY_CURRENT_BUFFER
3919 #undef YY_CURRENT_BUFFER_LVALUE
3920 #undef YY_STATE_BUF_SIZE
3921 #undef YY_DECL
3922 #undef YY_FATAL_ERROR
3923 #undef YYMINORTYPE
3924 #undef YY_CHAR
3925 #undef YYSTYPE
3926 #undef input
3927 #undef ParseAlloc
3928 #undef ParseFree
3929 #undef ParseStackPeak
3930 #undef Parse
3931 #undef yyalloc
3932 #undef yyfree
3933 #undef yyin
3934 #undef yyleng
3935 #undef yyless
3936 #undef yylex
3937 #undef yylineno
3938 #undef yyout
3939 #undef yyrealloc
3940 #undef yyrestart
3941 #undef yyStackEntry
3942 #undef yytext
3943 #undef yywrap
3944 #undef yyzerominor
3945 #undef yy_accept
3946 #undef yy_action
3947 #undef yy_base
3948 #undef yy_buffer_stack
3949 #undef yy_buffer_stack_max
3950 #undef yy_buffer_stack_top
3951 #undef yy_c_buf_p
3952 #undef yy_chk
3953 #undef yy_create_buffer
3954 #undef yy_def
3955 #undef yy_default
3956 #undef yy_delete_buffer
3957 #undef yy_destructor
3958 #undef yy_ec
3959 #undef yy_fatal_error
3960 #undef yy_find_reduce_action
3961 #undef yy_find_shift_action
3962 #undef yy_flex_debug
3963 #undef yy_flush_buffer
3964 #undef yy_get_next_buffer
3965 #undef yy_get_previous_state
3966 #undef yy_init
3967 #undef yy_init_buffer
3968 #undef yy_init_globals
3969 #undef yy_load_buffer
3970 #undef yy_load_buffer_state
3971 #undef yy_lookahead
3972 #undef yy_meta
3973 #undef yy_new_buffer
3974 #undef yy_nxt
3975 #undef yy_parse_failed
3976 #undef yy_pop_parser_stack
3977 #undef yy_reduce
3978 #undef yy_reduce_ofst
3979 #undef yy_set_bol
3980 #undef yy_set_interactive
3981 #undef yy_shift
3982 #undef yy_shift_ofst
3983 #undef yy_start
3984 #undef yy_state_type
3985 #undef yy_switch_to_buffer
3986 #undef yy_syntax_error
3987 #undef yy_trans_info
3988 #undef yy_try_NUL_trans
3989 #undef yyParser
3990 #undef yyStackEntry
3991 #undef yyStackOverflow
3992 #undef yyRuleInfo
3993 #undef yytext_ptr
3994 #undef yyunput
3995 #undef yyzerominor
3996 #undef ParseARG_SDECL
3997 #undef ParseARG_PDECL
3998 #undef ParseARG_FETCH
3999 #undef ParseARG_STORE
4000 #undef REJECT
4001 #undef yymore
4002 #undef YY_MORE_ADJ
4003 #undef YY_RESTORE_YY_MORE_OFFSET
4004 #undef YY_LESS_LINENO
4005 #undef yyTracePrompt
4006 #undef yyTraceFILE
4007 #undef yyTokenName
4008 #undef yyRuleName
4009 #undef ParseTrace
4010
4011 #undef yylex
4012 #undef YY_DECL
4013