PostGIS 3.7.0dev-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 (%zu) 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
167 /* Catch strange Oracle WKB type numbers */
168 if ( wkb_type >= 4000 ) {
169 lwerror("Unknown WKB type (%d)!", wkb_type);
170 return;
171 }
172
173 /* Strip out just the type number (1-12) from the ISO number (eg 3001-3012) */
174 wkb_simple_type = wkb_type % 1000;
175
176 /* Extract the Z/M information from ISO style numbers */
177 if( wkb_type >= 3000 && wkb_type < 4000 )
178 {
179 s->has_z = LW_TRUE;
180 s->has_m = LW_TRUE;
181 }
182 else if ( wkb_type >= 2000 && wkb_type < 3000 )
183 {
184 s->has_m = LW_TRUE;
185 }
186 else if ( wkb_type >= 1000 && wkb_type < 2000 )
187 {
188 s->has_z = LW_TRUE;
189 }
190
191 switch (wkb_simple_type)
192 {
193 case WKB_POINT_TYPE:
194 s->lwtype = POINTTYPE;
195 break;
197 s->lwtype = LINETYPE;
198 break;
199 case WKB_POLYGON_TYPE:
200 s->lwtype = POLYGONTYPE;
201 break;
203 s->lwtype = MULTIPOINTTYPE;
204 break;
206 s->lwtype = MULTILINETYPE;
207 break;
209 s->lwtype = MULTIPOLYGONTYPE;
210 break;
212 s->lwtype = COLLECTIONTYPE;
213 break;
215 s->lwtype = CIRCSTRINGTYPE;
216 break;
218 s->lwtype = COMPOUNDTYPE;
219 break;
221 s->lwtype = CURVEPOLYTYPE;
222 break;
224 s->lwtype = MULTICURVETYPE;
225 break;
227 s->lwtype = MULTISURFACETYPE;
228 break;
230 s->lwtype = POLYHEDRALSURFACETYPE;
231 break;
232 case WKB_TIN_TYPE:
233 s->lwtype = TINTYPE;
234 break;
236 s->lwtype = TRIANGLETYPE;
237 break;
238
239 /* PostGIS 1.5 emits 13, 14 for CurvePolygon, MultiCurve */
240 /* These numbers aren't SQL/MM (numbers currently only */
241 /* go up to 12. We can handle the old data here (for now??) */
242 /* converting them into the lwtypes that are intended. */
243 case WKB_CURVE_TYPE:
244 s->lwtype = CURVEPOLYTYPE;
245 break;
246 case WKB_SURFACE_TYPE:
247 s->lwtype = MULTICURVETYPE;
248 break;
249
250 default: /* Error! */
251 lwerror("Unknown WKB type (%d)! Full WKB type number was (%d).", wkb_simple_type, wkb_type);
252 break;
253 }
254
255 LWDEBUGF(4,"Got lwtype %s (%u)", lwtype_name(s->lwtype), s->lwtype);
256
257 return;
258}
259
265{
266 char char_value = 0;
267 LWDEBUG(4, "Entered function");
268
270 if (s->error)
271 return 0;
272 LWDEBUG(4, "Passed state check");
273
274 char_value = s->pos[0];
275 LWDEBUGF(4, "Read byte value: %x", char_value);
276 s->pos += WKB_BYTE_SIZE;
277
278 return char_value;
279}
280
286{
287 uint32_t i = 0;
288
290 if (s->error)
291 return 0;
292
293 memcpy(&i, s->pos, WKB_INT_SIZE);
294
295 /* Swap? Copy into a stack-allocated integer. */
296 if( s->swap_bytes )
297 {
298 int j = 0;
299 uint8_t tmp;
300
301 for( j = 0; j < WKB_INT_SIZE/2; j++ )
302 {
303 tmp = ((uint8_t*)(&i))[j];
304 ((uint8_t*)(&i))[j] = ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1];
305 ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1] = tmp;
306 }
307 }
308
309 s->pos += WKB_INT_SIZE;
310 return i;
311}
312
318{
319 double d = 0;
320
321 memcpy(&d, s->pos, WKB_DOUBLE_SIZE);
322
323 /* Swap? Copy into a stack-allocated integer. */
324 if( s->swap_bytes )
325 {
326 int i = 0;
327 uint8_t tmp;
328
329 for( i = 0; i < WKB_DOUBLE_SIZE/2; i++ )
330 {
331 tmp = ((uint8_t*)(&d))[i];
332 ((uint8_t*)(&d))[i] = ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1];
333 ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1] = tmp;
334 }
335
336 }
337
338 s->pos += WKB_DOUBLE_SIZE;
339 return d;
340}
341
348{
349 POINTARRAY *pa = NULL;
350 size_t pa_size;
351 uint32_t ndims = 2;
352 uint32_t npoints = 0;
353 static uint32_t maxpoints = UINT_MAX / WKB_DOUBLE_SIZE / 4;
354
355 /* Calculate the size of this point array. */
356 npoints = integer_from_wkb_state(s);
357 if (s->error)
358 return NULL;
359
360 if (npoints > maxpoints)
361 {
362 s->error = LW_TRUE;
363 lwerror("Pointarray length (%d) is too large", npoints);
364 return NULL;
365 }
366
367 LWDEBUGF(4,"Pointarray has %d points", npoints);
368
369 if( s->has_z ) ndims++;
370 if( s->has_m ) ndims++;
371 pa_size = (size_t)npoints * ndims * WKB_DOUBLE_SIZE;
372
373 /* Empty! */
374 if( npoints == 0 )
375 return ptarray_construct(s->has_z, s->has_m, npoints);
376
377 /* Does the data we want to read exist? */
378 wkb_parse_state_check(s, pa_size);
379 if (s->error)
380 return NULL;
381
382 /* If we're in a native endianness, we can just copy the data directly! */
383 if( ! s->swap_bytes )
384 {
385 pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
386 s->pos += pa_size;
387 }
388 /* Otherwise we have to read each double, separately. */
389 else
390 {
391 uint32_t i = 0;
392 double *dlist;
393 pa = ptarray_construct(s->has_z, s->has_m, npoints);
394 dlist = (double*)(pa->serialized_pointlist);
395 for( i = 0; i < npoints * ndims; i++ )
396 {
397 dlist[i] = double_from_wkb_state(s);
398 }
399 }
400
401 return pa;
402}
403
414{
415 static uint32_t npoints = 1;
416 POINTARRAY *pa = NULL;
417 size_t pa_size;
418 uint32_t ndims = 2;
419 const POINT2D *pt;
420
421 /* Count the dimensions. */
422 if( s->has_z ) ndims++;
423 if( s->has_m ) ndims++;
424 pa_size = ndims * WKB_DOUBLE_SIZE;
425
426 /* Does the data we want to read exist? */
427 wkb_parse_state_check(s, pa_size);
428 if (s->error)
429 return NULL;
430
431 /* If we're in a native endianness, we can just copy the data directly! */
432 if( ! s->swap_bytes )
433 {
434 pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
435 s->pos += pa_size;
436 }
437 /* Otherwise we have to read each double, separately */
438 else
439 {
440 uint32_t i = 0;
441 double *dlist;
442 pa = ptarray_construct(s->has_z, s->has_m, npoints);
443 dlist = (double*)(pa->serialized_pointlist);
444 for( i = 0; i < ndims; i++ )
445 {
446 dlist[i] = double_from_wkb_state(s);
447 }
448 }
449
450 /* Check for POINT(NaN NaN) ==> POINT EMPTY */
451 pt = getPoint2d_cp(pa, 0);
452 if ( isnan(pt->x) && isnan(pt->y) )
453 {
454 ptarray_free(pa);
455 return lwpoint_construct_empty(s->srid, s->has_z, s->has_m);
456 }
457 else
458 {
459 return lwpoint_construct(s->srid, NULL, pa);
460 }
461}
462
472{
474 if (s->error)
475 return NULL;
476
477 if( pa == NULL || pa->npoints == 0 )
478 {
479 if (pa)
480 ptarray_free(pa);
481 return lwline_construct_empty(s->srid, s->has_z, s->has_m);
482 }
483
484 if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
485 {
486 lwerror("%s must have at least two points", lwtype_name(s->lwtype));
487 return NULL;
488 }
489
490 return lwline_construct(s->srid, NULL, pa);
491}
492
503{
505 if (s->error)
506 return NULL;
507
508 if( pa == NULL || pa->npoints == 0 )
509 {
510 if (pa)
511 ptarray_free(pa);
512 return lwcircstring_construct_empty(s->srid, s->has_z, s->has_m);
513 }
514
515 if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 3 )
516 {
517 lwerror("%s must have at least three points", lwtype_name(s->lwtype));
518 return NULL;
519 }
520
521 if( s->check & LW_PARSER_CHECK_ODD && ! (pa->npoints % 2) )
522 {
523 lwerror("%s must have an odd number of points", lwtype_name(s->lwtype));
524 return NULL;
525 }
526
527 return lwcircstring_construct(s->srid, NULL, pa);
528}
529
539{
540 uint32_t nrings = integer_from_wkb_state(s);
541 if (s->error)
542 return NULL;
543 uint32_t i = 0;
544 LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);
545
546 LWDEBUGF(4,"Polygon has %d rings", nrings);
547
548 /* Empty polygon? */
549 if( nrings == 0 )
550 return poly;
551
552 for( i = 0; i < nrings; i++ )
553 {
555 if (pa == NULL)
556 {
557 lwpoly_free(poly);
558 return NULL;
559 }
560
561 /* Check for at least four points. */
562 if (s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4)
563 {
564 lwpoly_free(poly);
565 ptarray_free(pa);
566 LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
567 lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
568 return NULL;
569 }
570
571 /* Check that first and last points are the same. */
572 if( s->check & LW_PARSER_CHECK_CLOSURE && ! ptarray_is_closed_2d(pa) )
573 {
574 lwpoly_free(poly);
575 ptarray_free(pa);
576 LWDEBUGF(2, "%s must have closed rings", lwtype_name(s->lwtype));
577 lwerror("%s must have closed rings", lwtype_name(s->lwtype));
578 return NULL;
579 }
580
581 /* Add ring to polygon */
582 if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
583 {
584 lwpoly_free(poly);
585 ptarray_free(pa);
586 LWDEBUG(2, "Unable to add ring to polygon");
587 lwerror("Unable to add ring to polygon");
588 return NULL;
589 }
590
591 }
592 return poly;
593}
594
604{
605 uint32_t nrings = integer_from_wkb_state(s);
606 if (s->error)
607 return NULL;
608
609 /* Empty triangle? */
610 if( nrings == 0 )
611 return lwtriangle_construct_empty(s->srid, s->has_z, s->has_m);
612
613 /* Should be only one ring. */
614 if (nrings != 1)
615 {
616 lwerror("Triangle has wrong number of rings: %d", nrings);
617 }
618
619 /* There's only one ring, we hope? */
621
622 /* If there's no points, return an empty triangle. */
623 if (pa == NULL)
624 return lwtriangle_construct_empty(s->srid, s->has_z, s->has_m);
625
626 /* Check for at least four points. */
627 if (s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4)
628 {
629 ptarray_free(pa);
630 lwerror("%s must have at least four points", lwtype_name(s->lwtype));
631 return NULL;
632 }
633
635 {
636 ptarray_free(pa);
637 lwerror("%s must have closed rings", lwtype_name(s->lwtype));
638 return NULL;
639 }
640
641 /* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
642 return lwtriangle_construct(s->srid, NULL, pa);
643}
644
649{
650 uint32_t ngeoms = integer_from_wkb_state(s);
651 if (s->error)
652 return NULL;
653 LWCURVEPOLY *cp = lwcurvepoly_construct_empty(s->srid, s->has_z, s->has_m);
654 LWGEOM *geom = NULL;
655 uint32_t i;
656
657 /* Empty collection? */
658 if ( ngeoms == 0 )
659 return cp;
660
661 s->depth++;
662 if (s->depth >= LW_PARSER_MAX_DEPTH)
663 {
664 lwgeom_free((LWGEOM *)cp);
665 lwerror("Geometry has too many chained curves");
666 return NULL;
667 }
668 for ( i = 0; i < ngeoms; i++ )
669 {
670 geom = lwgeom_from_wkb_state(s);
671 if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
672 {
673 lwgeom_free(geom);
674 lwgeom_free((LWGEOM *)cp);
675 lwerror("Unable to add geometry (%p) to curvepoly (%p)", (void *) geom, (void *) cp);
676 return NULL;
677 }
678 }
679 s->depth--;
680
681 return cp;
682}
683
694{
695 uint32_t ngeoms = integer_from_wkb_state(s);
696 if (s->error)
697 return NULL;
698 LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, s->srid, s->has_z, s->has_m);
699 LWGEOM *geom = NULL;
700 uint32_t i;
701
702 LWDEBUGF(4,"Collection has %d components", ngeoms);
703
704 /* Empty collection? */
705 if ( ngeoms == 0 )
706 return col;
707
708 /* Be strict in polyhedral surface closures */
709 if ( s->lwtype == POLYHEDRALSURFACETYPE )
710 s->check |= LW_PARSER_CHECK_ZCLOSURE;
711
712 s->depth++;
713 if (s->depth >= LW_PARSER_MAX_DEPTH)
714 {
716 lwerror("Geometry has too many chained collections");
717 return NULL;
718 }
719 for ( i = 0; i < ngeoms; i++ )
720 {
721 geom = lwgeom_from_wkb_state(s);
722 if ( lwcollection_add_lwgeom(col, geom) == NULL )
723 {
724 lwgeom_free(geom);
725 lwgeom_free((LWGEOM *)col);
726 lwerror("Unable to add geometry (%p) to collection (%p)", (void *) geom, (void *) col);
727 return NULL;
728 }
729 }
730 s->depth--;
731
732 return col;
733}
734
735
744{
745 char wkb_little_endian;
746 uint32_t wkb_type;
747
748 LWDEBUG(4,"Entered function");
749
750 /* Fail when handed incorrect starting byte */
751 wkb_little_endian = byte_from_wkb_state(s);
752 if (s->error)
753 return NULL;
754 if( wkb_little_endian != 1 && wkb_little_endian != 0 )
755 {
756 LWDEBUG(4,"Leaving due to bad first byte!");
757 lwerror("Invalid endian flag value encountered.");
758 return NULL;
759 }
760
761 /* Check the endianness of our input */
762 s->swap_bytes = LW_FALSE;
763
764 /* Machine arch is big endian, request is for little */
765 if (IS_BIG_ENDIAN && wkb_little_endian)
766 s->swap_bytes = LW_TRUE;
767 /* Machine arch is little endian, request is for big */
768 else if ((!IS_BIG_ENDIAN) && (!wkb_little_endian))
769 s->swap_bytes = LW_TRUE;
770
771 /* Read the type number */
772 wkb_type = integer_from_wkb_state(s);
773 if (s->error)
774 return NULL;
775 LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
776 lwtype_from_wkb_state(s, wkb_type);
777
778 /* Read the SRID, if necessary */
779 if( s->has_srid )
780 {
782 if (s->error)
783 return NULL;
784 /* TODO: warn on explicit UNKNOWN srid ? */
785 LWDEBUGF(4,"Got SRID: %u", s->srid);
786 }
787
788 /* Do the right thing */
789 switch( s->lwtype )
790 {
791 case POINTTYPE:
793 break;
794 case LINETYPE:
796 break;
797 case CIRCSTRINGTYPE:
799 break;
800 case POLYGONTYPE:
802 break;
803 case TRIANGLETYPE:
805 break;
806 case CURVEPOLYTYPE:
808 break;
809 case MULTIPOINTTYPE:
810 case MULTILINETYPE:
811 case MULTIPOLYGONTYPE:
812 case COMPOUNDTYPE:
813 case MULTICURVETYPE:
814 case MULTISURFACETYPE:
816 case TINTYPE:
817 case COLLECTIONTYPE:
819 break;
820
821 /* Unknown type! */
822 default:
823 lwerror("%s: Unsupported geometry type: %s", __func__, lwtype_name(s->lwtype));
824 }
825
826 /* Return value to keep compiler happy. */
827 return NULL;
828
829}
830
831/* TODO add check for SRID consistency */
832
842LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
843{
845
846 /* Initialize the state appropriately */
847 s.wkb = wkb;
848 s.wkb_size = wkb_size;
849 s.swap_bytes = LW_FALSE;
850 s.check = check;
851 s.lwtype = 0;
852 s.srid = SRID_UNKNOWN;
853 s.has_z = LW_FALSE;
854 s.has_m = LW_FALSE;
855 s.has_srid = LW_FALSE;
856 s.error = LW_FALSE;
857 s.pos = wkb;
858 s.depth = 1;
859
860 if (!wkb || !wkb_size)
861 return NULL;
862
863 return lwgeom_from_wkb_state(&s);
864}
865
866LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
867{
868 int hexwkb_len;
869 uint8_t *wkb;
870 LWGEOM *lwgeom;
871
872 if ( ! hexwkb )
873 {
874 lwerror("lwgeom_from_hexwkb: null input");
875 return NULL;
876 }
877
878 hexwkb_len = strlen(hexwkb);
879 wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
880 lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
881 lwfree(wkb);
882 return lwgeom;
883}
char * s
Definition cu_in_wkt.c:23
#define LW_PARSER_CHECK_ODD
Definition liblwgeom.h:2145
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define IS_BIG_ENDIAN
Definition liblwgeom.h:326
#define WKBMOFFSET
Definition liblwgeom.h:125
#define LW_FALSE
Definition liblwgeom.h:94
#define COLLECTIONTYPE
Definition liblwgeom.h:108
#define COMPOUNDTYPE
Definition liblwgeom.h:110
#define LW_PARSER_CHECK_CLOSURE
Definition liblwgeom.h:2146
#define LW_FAILURE
Definition liblwgeom.h:96
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
#define CURVEPOLYTYPE
Definition liblwgeom.h:111
LWCURVEPOLY * lwcurvepoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwcurvepoly.c:35
#define MULTILINETYPE
Definition liblwgeom.h:106
#define LW_PARSER_CHECK_ZCLOSURE
Definition liblwgeom.h:2147
#define MULTISURFACETYPE
Definition liblwgeom.h:113
#define LINETYPE
Definition liblwgeom.h:103
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition lwpoint.c:129
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define WKBSRIDFLAG
Definition liblwgeom.h:126
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:102
void * lwalloc(size_t size)
Definition lwutil.c:227
#define TINTYPE
Definition liblwgeom.h:116
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
void lwfree(void *mem)
Definition lwutil.c:248
#define POLYGONTYPE
Definition liblwgeom.h:104
#define POLYHEDRALSURFACETYPE
Definition liblwgeom.h:114
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:109
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition ptarray.c:736
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:2144
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:112
#define TRIANGLETYPE
Definition liblwgeom.h:115
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:710
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
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:215
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:124
LWTRIANGLE * lwtriangle_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwtriangle.c:40
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:339
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 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:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
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:413
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:285
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:347
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:317
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:502
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:648
static char byte_from_wkb_state(wkb_parse_state *s)
Byte Read a byte and advance the parse state forward.
Definition lwin_wkb.c:264
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:538
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition lwin_wkb.c:866
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:603
static LWCOLLECTION * lwcollection_from_wkb_state(wkb_parse_state *s)
POLYHEDRALSURFACETYPE.
Definition lwin_wkb.c:693
LWGEOM * lwgeom_from_wkb_state(wkb_parse_state *s)
Internal function declarations.
Definition lwin_wkb.c:743
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:471
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:842
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:97
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
uint32_t npoints
Definition liblwgeom.h:427
uint8_t * serialized_pointlist
Definition liblwgeom.h:434
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