PostGIS  3.4.0dev-r@@SVN_REVISION@@
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 
39 typedef 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 */
66 static 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 
92 uint8_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 
131 static 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 
145 static 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;
196  case WKB_LINESTRING_TYPE:
197  s->lwtype = LINETYPE;
198  break;
199  case WKB_POLYGON_TYPE:
200  s->lwtype = POLYGONTYPE;
201  break;
202  case WKB_MULTIPOINT_TYPE:
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;
223  case WKB_MULTICURVE_TYPE:
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;
235  case WKB_TRIANGLE_TYPE:
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 = 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 
634  if (s->check & LW_PARSER_CHECK_ZCLOSURE && !ptarray_is_closed_z(pa))
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  for ( i = 0; i < ngeoms; i++ )
662  {
663  geom = lwgeom_from_wkb_state(s);
664  if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
665  {
666  lwgeom_free(geom);
667  lwgeom_free((LWGEOM *)cp);
668  lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
669  return NULL;
670  }
671  }
672 
673  return cp;
674 }
675 
686 {
687  uint32_t ngeoms = integer_from_wkb_state(s);
688  if (s->error)
689  return NULL;
690  LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, s->srid, s->has_z, s->has_m);
691  LWGEOM *geom = NULL;
692  uint32_t i;
693 
694  LWDEBUGF(4,"Collection has %d components", ngeoms);
695 
696  /* Empty collection? */
697  if ( ngeoms == 0 )
698  return col;
699 
700  /* Be strict in polyhedral surface closures */
701  if ( s->lwtype == POLYHEDRALSURFACETYPE )
702  s->check |= LW_PARSER_CHECK_ZCLOSURE;
703 
704  s->depth++;
705  if (s->depth >= LW_PARSER_MAX_DEPTH)
706  {
707  lwcollection_free(col);
708  lwerror("Geometry has too many chained collections");
709  return NULL;
710  }
711  for ( i = 0; i < ngeoms; i++ )
712  {
713  geom = lwgeom_from_wkb_state(s);
714  if ( lwcollection_add_lwgeom(col, geom) == NULL )
715  {
716  lwgeom_free(geom);
717  lwgeom_free((LWGEOM *)col);
718  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
719  return NULL;
720  }
721  }
722  s->depth--;
723 
724  return col;
725 }
726 
727 
736 {
737  char wkb_little_endian;
738  uint32_t wkb_type;
739 
740  LWDEBUG(4,"Entered function");
741 
742  /* Fail when handed incorrect starting byte */
743  wkb_little_endian = byte_from_wkb_state(s);
744  if (s->error)
745  return NULL;
746  if( wkb_little_endian != 1 && wkb_little_endian != 0 )
747  {
748  LWDEBUG(4,"Leaving due to bad first byte!");
749  lwerror("Invalid endian flag value encountered.");
750  return NULL;
751  }
752 
753  /* Check the endianness of our input */
754  s->swap_bytes = LW_FALSE;
755 
756  /* Machine arch is big endian, request is for little */
757  if (IS_BIG_ENDIAN && wkb_little_endian)
758  s->swap_bytes = LW_TRUE;
759  /* Machine arch is little endian, request is for big */
760  else if ((!IS_BIG_ENDIAN) && (!wkb_little_endian))
761  s->swap_bytes = LW_TRUE;
762 
763  /* Read the type number */
764  wkb_type = integer_from_wkb_state(s);
765  if (s->error)
766  return NULL;
767  LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
768  lwtype_from_wkb_state(s, wkb_type);
769 
770  /* Read the SRID, if necessary */
771  if( s->has_srid )
772  {
774  if (s->error)
775  return NULL;
776  /* TODO: warn on explicit UNKNOWN srid ? */
777  LWDEBUGF(4,"Got SRID: %u", s->srid);
778  }
779 
780  /* Do the right thing */
781  switch( s->lwtype )
782  {
783  case POINTTYPE:
784  return (LWGEOM*)lwpoint_from_wkb_state(s);
785  break;
786  case LINETYPE:
787  return (LWGEOM*)lwline_from_wkb_state(s);
788  break;
789  case CIRCSTRINGTYPE:
791  break;
792  case POLYGONTYPE:
793  return (LWGEOM*)lwpoly_from_wkb_state(s);
794  break;
795  case TRIANGLETYPE:
797  break;
798  case CURVEPOLYTYPE:
800  break;
801  case MULTIPOINTTYPE:
802  case MULTILINETYPE:
803  case MULTIPOLYGONTYPE:
804  case COMPOUNDTYPE:
805  case MULTICURVETYPE:
806  case MULTISURFACETYPE:
808  case TINTYPE:
809  case COLLECTIONTYPE:
811  break;
812 
813  /* Unknown type! */
814  default:
815  lwerror("%s: Unsupported geometry type: %s", __func__, lwtype_name(s->lwtype));
816  }
817 
818  /* Return value to keep compiler happy. */
819  return NULL;
820 
821 }
822 
823 /* TODO add check for SRID consistency */
824 
834 LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
835 {
837 
838  /* Initialize the state appropriately */
839  s.wkb = wkb;
840  s.wkb_size = wkb_size;
841  s.swap_bytes = LW_FALSE;
842  s.check = check;
843  s.lwtype = 0;
844  s.srid = SRID_UNKNOWN;
845  s.has_z = LW_FALSE;
846  s.has_m = LW_FALSE;
847  s.has_srid = LW_FALSE;
848  s.error = LW_FALSE;
849  s.pos = wkb;
850  s.depth = 1;
851 
852  if (!wkb || !wkb_size)
853  return NULL;
854 
855  return lwgeom_from_wkb_state(&s);
856 }
857 
858 LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
859 {
860  int hexwkb_len;
861  uint8_t *wkb;
862  LWGEOM *lwgeom;
863 
864  if ( ! hexwkb )
865  {
866  lwerror("lwgeom_from_hexwkb: null input");
867  return NULL;
868  }
869 
870  hexwkb_len = strlen(hexwkb);
871  wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
872  lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
873  lwfree(wkb);
874  return lwgeom;
875 }
char * s
Definition: cu_in_wkt.c:23
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoint.c:151
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:2110
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:297
#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:2111
#define LW_FAILURE
Definition: liblwgeom.h:96
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define CURVEPOLYTYPE
Definition: liblwgeom.h:111
#define MULTILINETYPE
Definition: liblwgeom.h:106
#define LW_PARSER_CHECK_ZCLOSURE
Definition: liblwgeom.h:2112
#define MULTISURFACETYPE
Definition: liblwgeom.h:113
#define LINETYPE
Definition: liblwgeom.h:103
#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
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 POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:102
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
LWTRIANGLE * lwtriangle_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwtriangle.c:58
#define TINTYPE
Definition: liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:107
void lwfree(void *mem)
Definition: lwutil.c:242
#define POLYGONTYPE
Definition: liblwgeom.h:104
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
#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
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
Definition: lwcollection.c:92
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:740
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:357
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:2109
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:319
#define MULTICURVETYPE
Definition: liblwgeom.h:112
#define TRIANGLETYPE
Definition: liblwgeom.h:115
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:188
void * lwalloc(size_t size)
Definition: lwutil.c:227
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:714
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:93
LWCURVEPOLY * lwcurvepoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwcurvepoly.c:35
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:215
#define WKBZOFFSET
Flags applied in EWKB to indicate Z/M dimensions and presence/absence of SRID and bounding boxes.
Definition: liblwgeom.h:124
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoly.c:161
LWCIRCSTRING * lwcircstring_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwcircstring.c:79
LWCIRCSTRING * lwcircstring_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:50
LWLINE * lwline_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwline.c:55
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:333
#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: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 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 LWCURVEPOLY * lwcurvepoly_from_wkb_state(wkb_parse_state *s)
CURVEPOLYTYPE.
Definition: lwin_wkb.c:648
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:858
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 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
uint8_t * bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
Definition: lwin_wkb.c:92
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 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 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
static LWCOLLECTION * lwcollection_from_wkb_state(wkb_parse_state *s)
POLYHEDRALSURFACETYPE.
Definition: lwin_wkb.c:685
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 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
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
LWGEOM * lwgeom_from_wkb_state(wkb_parse_state *s)
Internal function declarations.
Definition: lwin_wkb.c:735
static uint8_t hex2char[256]
Definition: lwin_wkb.c:66
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:834
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 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:101
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
int8_t has_z
Definition: lwin_wkb.c:47
const uint8_t * pos
Definition: lwin_wkb.c:52
int8_t has_m
Definition: lwin_wkb.c:48
int8_t swap_bytes
Definition: lwin_wkb.c:44
const uint8_t * wkb
Definition: lwin_wkb.c:41
int8_t check
Definition: lwin_wkb.c:45
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
int8_t error
Definition: lwin_wkb.c:50
Used for passing the parse state between the parsing functions.
Definition: lwin_wkb.c:40