PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwin_wkb.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://postgis.net
5 *
6 * PostGIS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * PostGIS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * Copyright (C) 2009 Paul Ramsey <pramsey@cleverelephant.ca>
22 *
23 **********************************************************************/
24
25
26#include "../postgis_config.h"
27/*#define POSTGIS_DEBUG_LEVEL 4*/
28#include "liblwgeom_internal.h" /* NOTE: includes lwgeom_log.h */
29#include "lwgeom_log.h"
30#include <math.h>
31#include <limits.h>
32
34#define LW_PARSER_MAX_DEPTH 200
35
39typedef struct
40{
41 const uint8_t *wkb; /* Points to start of WKB */
42 int32_t srid; /* Current SRID we are handling */
43 size_t wkb_size; /* Expected size of WKB */
44 int8_t swap_bytes; /* Do an endian flip? */
45 int8_t check; /* Simple validity checks on geometries */
46 int8_t lwtype; /* Current type we are handling */
47 int8_t has_z; /* Z? */
48 int8_t has_m; /* M? */
49 int8_t has_srid; /* SRID? */
50 int8_t error; /* An error was found (not enough bytes to read) */
51 uint8_t depth; /* Current recursion level (to prevent stack overflows). Maxes at LW_PARSER_MAX_DEPTH */
52 const uint8_t *pos; /* Current parse position */
54
55
60
61
62
63/**********************************************************************/
64
65/* Our static character->number map. Anything > 15 is invalid */
66static uint8_t hex2char[256] = {
67 /* not Hex characters */
68 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
69 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
70 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
71 /* 0-9 */
72 0,1,2,3,4,5,6,7,8,9,20,20,20,20,20,20,
73 /* A-F */
74 20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
75 /* not Hex characters */
76 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
77 /* a-f */
78 20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
79 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
80 /* not Hex characters (upper 128 characters) */
81 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
82 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
83 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
84 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
85 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
86 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
87 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
88 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20
89 };
90
91
92uint8_t* bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
93{
94 uint8_t *buf = NULL;
95 register uint8_t h1, h2;
96 uint32_t i;
97
98 if( hexsize % 2 )
99 lwerror("Invalid hex string, length (%d) has to be a multiple of two!", hexsize);
100
101 buf = lwalloc(hexsize/2);
102
103 if( ! buf )
104 lwerror("Unable to allocate memory buffer.");
105
106 for( i = 0; i < hexsize/2; i++ )
107 {
108 h1 = hex2char[(int)hexbuf[2*i]];
109 h2 = hex2char[(int)hexbuf[2*i+1]];
110 if( h1 > 15 )
111 lwerror("Invalid hex character (%c) encountered", hexbuf[2*i]);
112 if( h2 > 15 )
113 lwerror("Invalid hex character (%c) encountered", hexbuf[2*i+1]);
114 /* First character is high bits, second is low bits */
115 buf[i] = ((h1 & 0x0F) << 4) | (h2 & 0x0F);
116 }
117 return buf;
118}
119
120
121/**********************************************************************/
122
123
124
125
126
131static inline void wkb_parse_state_check(wkb_parse_state *s, size_t next)
132{
133 if( (s->pos + next) > (s->wkb + s->wkb_size) )
134 {
135 lwerror("WKB structure does not match expected size!");
136 s->error = LW_TRUE;
137 }
138}
139
145static void lwtype_from_wkb_state(wkb_parse_state *s, uint32_t wkb_type)
146{
147 uint32_t wkb_simple_type;
148
149 LWDEBUG(4, "Entered function");
150
151 s->has_z = LW_FALSE;
152 s->has_m = LW_FALSE;
153 s->has_srid = LW_FALSE;
154
155 /* If any of the higher bits are set, this is probably an extended type. */
156 if( wkb_type & 0xF0000000 )
157 {
158 if( wkb_type & WKBZOFFSET ) s->has_z = LW_TRUE;
159 if( wkb_type & WKBMOFFSET ) s->has_m = LW_TRUE;
160 if( wkb_type & WKBSRIDFLAG ) s->has_srid = LW_TRUE;
161 LWDEBUGF(4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
162 }
163
164 /* Mask off the flags */
165 wkb_type = wkb_type & 0x0FFFFFFF;
166 /* Strip out just the type number (1-12) from the ISO number (eg 3001-3012) */
167 wkb_simple_type = wkb_type % 1000;
168
169 /* Extract the Z/M information from ISO style numbers */
170 if( wkb_type >= 3000 && wkb_type < 4000 )
171 {
172 s->has_z = LW_TRUE;
173 s->has_m = LW_TRUE;
174 }
175 else if ( wkb_type >= 2000 && wkb_type < 3000 )
176 {
177 s->has_m = LW_TRUE;
178 }
179 else if ( wkb_type >= 1000 && wkb_type < 2000 )
180 {
181 s->has_z = LW_TRUE;
182 }
183
184 switch (wkb_simple_type)
185 {
186 case WKB_POINT_TYPE:
187 s->lwtype = POINTTYPE;
188 break;
190 s->lwtype = LINETYPE;
191 break;
192 case WKB_POLYGON_TYPE:
193 s->lwtype = POLYGONTYPE;
194 break;
196 s->lwtype = MULTIPOINTTYPE;
197 break;
199 s->lwtype = MULTILINETYPE;
200 break;
202 s->lwtype = MULTIPOLYGONTYPE;
203 break;
205 s->lwtype = COLLECTIONTYPE;
206 break;
208 s->lwtype = CIRCSTRINGTYPE;
209 break;
211 s->lwtype = COMPOUNDTYPE;
212 break;
214 s->lwtype = CURVEPOLYTYPE;
215 break;
217 s->lwtype = MULTICURVETYPE;
218 break;
220 s->lwtype = MULTISURFACETYPE;
221 break;
223 s->lwtype = POLYHEDRALSURFACETYPE;
224 break;
225 case WKB_TIN_TYPE:
226 s->lwtype = TINTYPE;
227 break;
229 s->lwtype = TRIANGLETYPE;
230 break;
231
232 /* PostGIS 1.5 emits 13, 14 for CurvePolygon, MultiCurve */
233 /* These numbers aren't SQL/MM (numbers currently only */
234 /* go up to 12. We can handle the old data here (for now??) */
235 /* converting them into the lwtypes that are intended. */
236 case WKB_CURVE_TYPE:
237 s->lwtype = CURVEPOLYTYPE;
238 break;
239 case WKB_SURFACE_TYPE:
240 s->lwtype = MULTICURVETYPE;
241 break;
242
243 default: /* Error! */
244 lwerror("Unknown WKB type (%d)! Full WKB type number was (%d).", wkb_simple_type, wkb_type);
245 break;
246 }
247
248 LWDEBUGF(4,"Got lwtype %s (%u)", lwtype_name(s->lwtype), s->lwtype);
249
250 return;
251}
252
258{
259 char char_value = 0;
260 LWDEBUG(4, "Entered function");
261
263 if (s->error)
264 return 0;
265 LWDEBUG(4, "Passed state check");
266
267 char_value = s->pos[0];
268 LWDEBUGF(4, "Read byte value: %x", char_value);
269 s->pos += WKB_BYTE_SIZE;
270
271 return char_value;
272}
273
279{
280 uint32_t i = 0;
281
283 if (s->error)
284 return 0;
285
286 memcpy(&i, s->pos, WKB_INT_SIZE);
287
288 /* Swap? Copy into a stack-allocated integer. */
289 if( s->swap_bytes )
290 {
291 int j = 0;
292 uint8_t tmp;
293
294 for( j = 0; j < WKB_INT_SIZE/2; j++ )
295 {
296 tmp = ((uint8_t*)(&i))[j];
297 ((uint8_t*)(&i))[j] = ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1];
298 ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1] = tmp;
299 }
300 }
301
302 s->pos += WKB_INT_SIZE;
303 return i;
304}
305
311{
312 double d = 0;
313
314 memcpy(&d, s->pos, WKB_DOUBLE_SIZE);
315
316 /* Swap? Copy into a stack-allocated integer. */
317 if( s->swap_bytes )
318 {
319 int i = 0;
320 uint8_t tmp;
321
322 for( i = 0; i < WKB_DOUBLE_SIZE/2; i++ )
323 {
324 tmp = ((uint8_t*)(&d))[i];
325 ((uint8_t*)(&d))[i] = ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1];
326 ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1] = tmp;
327 }
328
329 }
330
331 s->pos += WKB_DOUBLE_SIZE;
332 return d;
333}
334
341{
342 POINTARRAY *pa = NULL;
343 size_t pa_size;
344 uint32_t ndims = 2;
345 uint32_t npoints = 0;
346 static uint32_t maxpoints = UINT_MAX / WKB_DOUBLE_SIZE / 4;
347
348 /* Calculate the size of this point array. */
349 npoints = integer_from_wkb_state(s);
350 if (s->error)
351 return NULL;
352 if (npoints > maxpoints)
353 {
354 lwerror("Pointarray length (%d) is too large");
355 return NULL;
356 }
357
358 LWDEBUGF(4,"Pointarray has %d points", npoints);
359
360 if( s->has_z ) ndims++;
361 if( s->has_m ) ndims++;
362 pa_size = npoints * ndims * WKB_DOUBLE_SIZE;
363
364 /* Empty! */
365 if( npoints == 0 )
366 return ptarray_construct(s->has_z, s->has_m, npoints);
367
368 /* Does the data we want to read exist? */
369 wkb_parse_state_check(s, pa_size);
370 if (s->error)
371 return NULL;
372
373 /* If we're in a native endianness, we can just copy the data directly! */
374 if( ! s->swap_bytes )
375 {
376 pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
377 s->pos += pa_size;
378 }
379 /* Otherwise we have to read each double, separately. */
380 else
381 {
382 uint32_t i = 0;
383 double *dlist;
384 pa = ptarray_construct(s->has_z, s->has_m, npoints);
385 dlist = (double*)(pa->serialized_pointlist);
386 for( i = 0; i < npoints * ndims; i++ )
387 {
388 dlist[i] = double_from_wkb_state(s);
389 }
390 }
391
392 return pa;
393}
394
405{
406 static uint32_t npoints = 1;
407 POINTARRAY *pa = NULL;
408 size_t pa_size;
409 uint32_t ndims = 2;
410 const POINT2D *pt;
411
412 /* Count the dimensions. */
413 if( s->has_z ) ndims++;
414 if( s->has_m ) ndims++;
415 pa_size = ndims * WKB_DOUBLE_SIZE;
416
417 /* Does the data we want to read exist? */
418 wkb_parse_state_check(s, pa_size);
419 if (s->error)
420 return NULL;
421
422 /* If we're in a native endianness, we can just copy the data directly! */
423 if( ! s->swap_bytes )
424 {
425 pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
426 s->pos += pa_size;
427 }
428 /* Otherwise we have to read each double, separately */
429 else
430 {
431 uint32_t i = 0;
432 double *dlist;
433 pa = ptarray_construct(s->has_z, s->has_m, npoints);
434 dlist = (double*)(pa->serialized_pointlist);
435 for( i = 0; i < ndims; i++ )
436 {
437 dlist[i] = double_from_wkb_state(s);
438 }
439 }
440
441 /* Check for POINT(NaN NaN) ==> POINT EMPTY */
442 pt = getPoint2d_cp(pa, 0);
443 if ( isnan(pt->x) && isnan(pt->y) )
444 {
445 ptarray_free(pa);
446 return lwpoint_construct_empty(s->srid, s->has_z, s->has_m);
447 }
448 else
449 {
450 return lwpoint_construct(s->srid, NULL, pa);
451 }
452}
453
463{
465 if (s->error)
466 return NULL;
467
468 if( pa == NULL || pa->npoints == 0 )
469 {
470 if (pa)
471 ptarray_free(pa);
472 return lwline_construct_empty(s->srid, s->has_z, s->has_m);
473 }
474
475 if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
476 {
477 lwerror("%s must have at least two points", lwtype_name(s->lwtype));
478 return NULL;
479 }
480
481 return lwline_construct(s->srid, NULL, pa);
482}
483
494{
496 if (s->error)
497 return NULL;
498
499 if( pa == NULL || pa->npoints == 0 )
500 {
501 if (pa)
502 ptarray_free(pa);
503 return lwcircstring_construct_empty(s->srid, s->has_z, s->has_m);
504 }
505
506 if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 3 )
507 {
508 lwerror("%s must have at least three points", lwtype_name(s->lwtype));
509 return NULL;
510 }
511
512 if( s->check & LW_PARSER_CHECK_ODD && ! (pa->npoints % 2) )
513 {
514 lwerror("%s must have an odd number of points", lwtype_name(s->lwtype));
515 return NULL;
516 }
517
518 return lwcircstring_construct(s->srid, NULL, pa);
519}
520
530{
531 uint32_t nrings = integer_from_wkb_state(s);
532 if (s->error)
533 return NULL;
534 uint32_t i = 0;
535 LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);
536
537 LWDEBUGF(4,"Polygon has %d rings", nrings);
538
539 /* Empty polygon? */
540 if( nrings == 0 )
541 return poly;
542
543 for( i = 0; i < nrings; i++ )
544 {
546 if (pa == NULL)
547 {
548 lwpoly_free(poly);
549 return NULL;
550 }
551
552 /* Check for at least four points. */
553 if (s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4)
554 {
555 lwpoly_free(poly);
556 LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
557 lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
558 return NULL;
559 }
560
561 /* Check that first and last points are the same. */
562 if( s->check & LW_PARSER_CHECK_CLOSURE && ! ptarray_is_closed_2d(pa) )
563 {
564 lwpoly_free(poly);
565 LWDEBUGF(2, "%s must have closed rings", lwtype_name(s->lwtype));
566 lwerror("%s must have closed rings", lwtype_name(s->lwtype));
567 return NULL;
568 }
569
570 /* Skip zero-member rings, they add nothing */
571 if ( pa->npoints == 0)
572 {
573 LWDEBUGF(2, "Skipping empty ring [%d]", i);
574 ptarray_free(pa);
575 continue;
576 }
577
578 /* Add ring to polygon */
579 if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
580 {
581 lwpoly_free(poly);
582 LWDEBUG(2, "Unable to add ring to polygon");
583 lwerror("Unable to add ring to polygon");
584 return NULL;
585 }
586
587 }
588 return poly;
589}
590
600{
601 uint32_t nrings = integer_from_wkb_state(s);
602 if (s->error)
603 return NULL;
604 LWTRIANGLE *tri = lwtriangle_construct_empty(s->srid, s->has_z, s->has_m);
605 POINTARRAY *pa = NULL;
606
607 /* Empty triangle? */
608 if( nrings == 0 )
609 return tri;
610
611 /* Should be only one ring. */
612 if ( nrings != 1 )
613 lwerror("Triangle has wrong number of rings: %d", nrings);
614
615 /* There's only one ring, we hope? */
617
618 /* If there's no points, return an empty triangle. */
619 if( pa == NULL )
620 return tri;
621
622 /* Check for at least four points. */
623 if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
624 {
625 LWDEBUGF(2, "%s must have at least four points", lwtype_name(s->lwtype));
626 lwerror("%s must have at least four points", lwtype_name(s->lwtype));
627 return NULL;
628 }
629
630 if( s->check & LW_PARSER_CHECK_ZCLOSURE && ! ptarray_is_closed_z(pa) )
631 {
632 lwerror("%s must have closed rings", lwtype_name(s->lwtype));
633 return NULL;
634 }
635
636 /* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
637 if (tri->points)
638 ptarray_free(tri->points);
639
640 tri->points = pa;
641 return tri;
642}
643
648{
649 uint32_t ngeoms = integer_from_wkb_state(s);
650 if (s->error)
651 return NULL;
652 LWCURVEPOLY *cp = lwcurvepoly_construct_empty(s->srid, s->has_z, s->has_m);
653 LWGEOM *geom = NULL;
654 uint32_t i;
655
656 /* Empty collection? */
657 if ( ngeoms == 0 )
658 return cp;
659
660 for ( i = 0; i < ngeoms; i++ )
661 {
662 geom = lwgeom_from_wkb_state(s);
663 if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
664 {
665 lwgeom_free(geom);
666 lwgeom_free((LWGEOM *)cp);
667 lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
668 return NULL;
669 }
670 }
671
672 return cp;
673}
674
685{
686 uint32_t ngeoms = integer_from_wkb_state(s);
687 if (s->error)
688 return NULL;
689 LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, s->srid, s->has_z, s->has_m);
690 LWGEOM *geom = NULL;
691 uint32_t i;
692
693 LWDEBUGF(4,"Collection has %d components", ngeoms);
694
695 /* Empty collection? */
696 if ( ngeoms == 0 )
697 return col;
698
699 /* Be strict in polyhedral surface closures */
700 if ( s->lwtype == POLYHEDRALSURFACETYPE )
701 s->check |= LW_PARSER_CHECK_ZCLOSURE;
702
703 s->depth++;
704 if (s->depth >= LW_PARSER_MAX_DEPTH)
705 {
707 lwerror("Geometry has too many chained collections");
708 return NULL;
709 }
710 for ( i = 0; i < ngeoms; i++ )
711 {
712 geom = lwgeom_from_wkb_state(s);
713 if ( lwcollection_add_lwgeom(col, geom) == NULL )
714 {
715 lwgeom_free(geom);
716 lwgeom_free((LWGEOM *)col);
717 lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
718 return NULL;
719 }
720 }
721 s->depth--;
722
723 return col;
724}
725
726
735{
736 char wkb_little_endian;
737 uint32_t wkb_type;
738
739 LWDEBUG(4,"Entered function");
740
741 /* Fail when handed incorrect starting byte */
742 wkb_little_endian = byte_from_wkb_state(s);
743 if (s->error)
744 return NULL;
745 if( wkb_little_endian != 1 && wkb_little_endian != 0 )
746 {
747 LWDEBUG(4,"Leaving due to bad first byte!");
748 lwerror("Invalid endian flag value encountered.");
749 return NULL;
750 }
751
752 /* Check the endianness of our input */
753 s->swap_bytes = LW_FALSE;
754
755 /* Machine arch is big endian, request is for little */
756 if (IS_BIG_ENDIAN && wkb_little_endian)
757 s->swap_bytes = LW_TRUE;
758 /* Machine arch is little endian, request is for big */
759 else if ((!IS_BIG_ENDIAN) && (!wkb_little_endian))
760 s->swap_bytes = LW_TRUE;
761
762 /* Read the type number */
763 wkb_type = integer_from_wkb_state(s);
764 if (s->error)
765 return NULL;
766 LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
767 lwtype_from_wkb_state(s, wkb_type);
768
769 /* Read the SRID, if necessary */
770 if( s->has_srid )
771 {
773 if (s->error)
774 return NULL;
775 /* TODO: warn on explicit UNKNOWN srid ? */
776 LWDEBUGF(4,"Got SRID: %u", s->srid);
777 }
778
779 /* Do the right thing */
780 switch( s->lwtype )
781 {
782 case POINTTYPE:
784 break;
785 case LINETYPE:
787 break;
788 case CIRCSTRINGTYPE:
790 break;
791 case POLYGONTYPE:
793 break;
794 case TRIANGLETYPE:
796 break;
797 case CURVEPOLYTYPE:
799 break;
800 case MULTIPOINTTYPE:
801 case MULTILINETYPE:
802 case MULTIPOLYGONTYPE:
803 case COMPOUNDTYPE:
804 case MULTICURVETYPE:
805 case MULTISURFACETYPE:
807 case TINTYPE:
808 case COLLECTIONTYPE:
810 break;
811
812 /* Unknown type! */
813 default:
814 lwerror("%s: Unsupported geometry type: %s", __func__, lwtype_name(s->lwtype));
815 }
816
817 /* Return value to keep compiler happy. */
818 return NULL;
819
820}
821
822/* TODO add check for SRID consistency */
823
833LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
834{
836
837 /* Initialize the state appropriately */
838 s.wkb = wkb;
839 s.wkb_size = wkb_size;
840 s.swap_bytes = LW_FALSE;
841 s.check = check;
842 s.lwtype = 0;
843 s.srid = SRID_UNKNOWN;
844 s.has_z = LW_FALSE;
845 s.has_m = LW_FALSE;
846 s.has_srid = LW_FALSE;
847 s.error = LW_FALSE;
848 s.pos = wkb;
849 s.depth = 1;
850
851 if (!wkb || !wkb_size)
852 return NULL;
853
854 return lwgeom_from_wkb_state(&s);
855}
856
857LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
858{
859 int hexwkb_len;
860 uint8_t *wkb;
861 LWGEOM *lwgeom;
862
863 if ( ! hexwkb )
864 {
865 lwerror("lwgeom_from_hexwkb: null input");
866 return NULL;
867 }
868
869 hexwkb_len = strlen(hexwkb);
870 wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
871 lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
872 lwfree(wkb);
873 return lwgeom;
874}
char * s
Definition cu_in_wkt.c:23
#define LW_PARSER_CHECK_ODD
Definition liblwgeom.h:2056
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define WKBMOFFSET
Definition liblwgeom.h:139
#define LW_FALSE
Definition liblwgeom.h:108
#define COLLECTIONTYPE
Definition liblwgeom.h:122
#define COMPOUNDTYPE
Definition liblwgeom.h:124
#define LW_PARSER_CHECK_CLOSURE
Definition liblwgeom.h:2057
#define LW_FAILURE
Definition liblwgeom.h:110
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1138
#define CURVEPOLYTYPE
Definition liblwgeom.h:125
LWCURVEPOLY * lwcurvepoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwcurvepoly.c:35
#define MULTILINETYPE
Definition liblwgeom.h:120
#define LW_PARSER_CHECK_ZCLOSURE
Definition liblwgeom.h:2058
#define MULTISURFACETYPE
Definition liblwgeom.h:127
#define LINETYPE
Definition liblwgeom.h:117
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition lwpoint.c:129
#define MULTIPOINTTYPE
Definition liblwgeom.h:119
#define WKBSRIDFLAG
Definition liblwgeom.h:140
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition lwpoly.c:247
LWTRIANGLE * lwtriangle_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwtriangle.c:58
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:116
void * lwalloc(size_t size)
Definition lwutil.c:227
#define TINTYPE
Definition liblwgeom.h:130
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:121
void lwfree(void *mem)
Definition lwutil.c:242
#define POLYGONTYPE
Definition liblwgeom.h:118
#define POLYHEDRALSURFACETYPE
Definition liblwgeom.h:128
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
Add a ring, allocating extra space if necessary.
Definition lwcurvepoly.c:71
#define CIRCSTRINGTYPE
Definition liblwgeom.h:123
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition ptarray.c:727
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwpoint.c:151
void lwcollection_free(LWCOLLECTION *col)
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition liblwgeom.h:2055
void ptarray_free(POINTARRAY *pa)
Definition ptarray.c:327
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
#define MULTICURVETYPE
Definition liblwgeom.h:126
#define TRIANGLETYPE
Definition liblwgeom.h:129
LWCIRCSTRING * lwcircstring_construct_empty(int32_t srid, char hasz, char hasm)
POINTARRAY * ptarray_construct_copy_data(char hasz, char hasm, uint32_t npoints, const uint8_t *ptlist)
Construct a new POINTARRAY, copying in the data from ptlist.
Definition ptarray.c:305
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition ptarray.c:701
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:107
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwpoly.c:161
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:229
LWLINE * lwline_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwline.c:55
LWCIRCSTRING * lwcircstring_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
#define WKBZOFFSET
Flags applied in EWKB to indicate Z/M dimensions and presence/absence of SRID and bounding boxes.
Definition liblwgeom.h:138
int32_t clamp_srid(int32_t srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition lwutil.c:333
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition ptarray.c:51
#define WKB_COMPOUNDCURVE_TYPE
#define IS_BIG_ENDIAN
#define WKB_POLYHEDRALSURFACE_TYPE
#define WKB_GEOMETRYCOLLECTION_TYPE
#define WKB_BYTE_SIZE
#define WKB_INT_SIZE
#define WKB_TRIANGLE_TYPE
#define WKB_MULTIPOLYGON_TYPE
#define WKB_CURVE_TYPE
#define WKB_MULTIPOINT_TYPE
#define WKB_MULTISURFACE_TYPE
#define WKB_CURVEPOLYGON_TYPE
#define WKB_POINT_TYPE
Well-Known Binary (WKB) Geometry Types.
#define WKB_MULTICURVE_TYPE
#define WKB_SURFACE_TYPE
#define WKB_MULTILINESTRING_TYPE
#define WKB_LINESTRING_TYPE
#define WKB_CIRCULARSTRING_TYPE
#define WKB_POLYGON_TYPE
#define WKB_TIN_TYPE
#define WKB_DOUBLE_SIZE
Well-Known Binary (WKB) Output Variant Types.
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
static LWPOINT * lwpoint_from_wkb_state(wkb_parse_state *s)
POINT Read a WKB point, starting just after the endian byte, type number and optional srid number.
Definition lwin_wkb.c:404
static uint32_t integer_from_wkb_state(wkb_parse_state *s)
Int32 Read 4-byte integer and advance the parse state forward.
Definition lwin_wkb.c:278
static POINTARRAY * ptarray_from_wkb_state(wkb_parse_state *s)
POINTARRAY Read a dynamically sized point array and advance the parse state forward.
Definition lwin_wkb.c:340
static void wkb_parse_state_check(wkb_parse_state *s, size_t next)
Check that we are not about to read off the end of the WKB array.
Definition lwin_wkb.c:131
static double double_from_wkb_state(wkb_parse_state *s)
Double Read an 8-byte double and advance the parse state forward.
Definition lwin_wkb.c:310
static LWCIRCSTRING * lwcircstring_from_wkb_state(wkb_parse_state *s)
CIRCULARSTRING Read a WKB circularstring, starting just after the endian byte, type number and option...
Definition lwin_wkb.c:493
uint8_t * bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
Definition lwin_wkb.c:92
static LWCURVEPOLY * lwcurvepoly_from_wkb_state(wkb_parse_state *s)
CURVEPOLYTYPE.
Definition lwin_wkb.c:647
static char byte_from_wkb_state(wkb_parse_state *s)
Byte Read a byte and advance the parse state forward.
Definition lwin_wkb.c:257
static LWPOLY * lwpoly_from_wkb_state(wkb_parse_state *s)
POLYGON Read a WKB polygon, starting just after the endian byte, type number and optional srid number...
Definition lwin_wkb.c:529
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition lwin_wkb.c:857
static void lwtype_from_wkb_state(wkb_parse_state *s, uint32_t wkb_type)
Take in an unknown kind of wkb type number and ensure it comes out as an extended WKB type number (wi...
Definition lwin_wkb.c:145
#define LW_PARSER_MAX_DEPTH
Max depth in a geometry.
Definition lwin_wkb.c:34
static LWTRIANGLE * lwtriangle_from_wkb_state(wkb_parse_state *s)
TRIANGLE Read a WKB triangle, starting just after the endian byte, type number and optional srid numb...
Definition lwin_wkb.c:599
static LWCOLLECTION * lwcollection_from_wkb_state(wkb_parse_state *s)
POLYHEDRALSURFACETYPE.
Definition lwin_wkb.c:684
LWGEOM * lwgeom_from_wkb_state(wkb_parse_state *s)
Internal function declarations.
Definition lwin_wkb.c:734
static uint8_t hex2char[256]
Definition lwin_wkb.c:66
static LWLINE * lwline_from_wkb_state(wkb_parse_state *s)
LINESTRING Read a WKB linestring, starting just after the endian byte, type number and optional srid ...
Definition lwin_wkb.c:462
LWGEOM * lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
WKB inputs must have a declared size, to prevent malformed WKB from reading off the end of the memory...
Definition lwin_wkb.c:833
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition lwinline.h:91
POINTARRAY * points
Definition liblwgeom.h:481
double y
Definition liblwgeom.h:376
double x
Definition liblwgeom.h:376
uint32_t npoints
Definition liblwgeom.h:413
uint8_t * serialized_pointlist
Definition liblwgeom.h:420
const uint8_t * pos
Definition lwin_wkb.c:52
int8_t swap_bytes
Definition lwin_wkb.c:44
const uint8_t * wkb
Definition lwin_wkb.c:41
uint8_t depth
Definition lwin_wkb.c:51
int8_t has_srid
Definition lwin_wkb.c:49
int8_t lwtype
Definition lwin_wkb.c:46
int32_t srid
Definition lwin_wkb.c:42
size_t wkb_size
Definition lwin_wkb.c:43
Used for passing the parse state between the parsing functions.
Definition lwin_wkb.c:40