PostGIS  3.0.6dev-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  /* 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;
189  case WKB_LINESTRING_TYPE:
190  s->lwtype = LINETYPE;
191  break;
192  case WKB_POLYGON_TYPE:
193  s->lwtype = POLYGONTYPE;
194  break;
195  case WKB_MULTIPOINT_TYPE:
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;
216  case WKB_MULTICURVE_TYPE:
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;
228  case WKB_TRIANGLE_TYPE:
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  /* Add ring to polygon */
571  if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
572  {
573  lwpoly_free(poly);
574  LWDEBUG(2, "Unable to add ring to polygon");
575  lwerror("Unable to add ring to polygon");
576  return NULL;
577  }
578 
579  }
580  return poly;
581 }
582 
592 {
593  uint32_t nrings = integer_from_wkb_state(s);
594  if (s->error)
595  return NULL;
596  LWTRIANGLE *tri = lwtriangle_construct_empty(s->srid, s->has_z, s->has_m);
597  POINTARRAY *pa = NULL;
598 
599  /* Empty triangle? */
600  if( nrings == 0 )
601  return tri;
602 
603  /* Should be only one ring. */
604  if ( nrings != 1 )
605  lwerror("Triangle has wrong number of rings: %d", nrings);
606 
607  /* There's only one ring, we hope? */
609 
610  /* If there's no points, return an empty triangle. */
611  if( pa == NULL )
612  return tri;
613 
614  /* Check for at least four points. */
615  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
616  {
617  LWDEBUGF(2, "%s must have at least four points", lwtype_name(s->lwtype));
618  lwerror("%s must have at least four points", lwtype_name(s->lwtype));
619  return NULL;
620  }
621 
622  if( s->check & LW_PARSER_CHECK_ZCLOSURE && ! ptarray_is_closed_z(pa) )
623  {
624  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
625  return NULL;
626  }
627 
628  /* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
629  if (tri->points)
630  ptarray_free(tri->points);
631 
632  tri->points = pa;
633  return tri;
634 }
635 
640 {
641  uint32_t ngeoms = integer_from_wkb_state(s);
642  if (s->error)
643  return NULL;
644  LWCURVEPOLY *cp = lwcurvepoly_construct_empty(s->srid, s->has_z, s->has_m);
645  LWGEOM *geom = NULL;
646  uint32_t i;
647 
648  /* Empty collection? */
649  if ( ngeoms == 0 )
650  return cp;
651 
652  for ( i = 0; i < ngeoms; i++ )
653  {
654  geom = lwgeom_from_wkb_state(s);
655  if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
656  {
657  lwgeom_free(geom);
658  lwgeom_free((LWGEOM *)cp);
659  lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
660  return NULL;
661  }
662  }
663 
664  return cp;
665 }
666 
677 {
678  uint32_t ngeoms = integer_from_wkb_state(s);
679  if (s->error)
680  return NULL;
681  LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, s->srid, s->has_z, s->has_m);
682  LWGEOM *geom = NULL;
683  uint32_t i;
684 
685  LWDEBUGF(4,"Collection has %d components", ngeoms);
686 
687  /* Empty collection? */
688  if ( ngeoms == 0 )
689  return col;
690 
691  /* Be strict in polyhedral surface closures */
692  if ( s->lwtype == POLYHEDRALSURFACETYPE )
693  s->check |= LW_PARSER_CHECK_ZCLOSURE;
694 
695  s->depth++;
696  if (s->depth >= LW_PARSER_MAX_DEPTH)
697  {
698  lwcollection_free(col);
699  lwerror("Geometry has too many chained collections");
700  return NULL;
701  }
702  for ( i = 0; i < ngeoms; i++ )
703  {
704  geom = lwgeom_from_wkb_state(s);
705  if ( lwcollection_add_lwgeom(col, geom) == NULL )
706  {
707  lwgeom_free(geom);
708  lwgeom_free((LWGEOM *)col);
709  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
710  return NULL;
711  }
712  }
713  s->depth--;
714 
715  return col;
716 }
717 
718 
727 {
728  char wkb_little_endian;
729  uint32_t wkb_type;
730 
731  LWDEBUG(4,"Entered function");
732 
733  /* Fail when handed incorrect starting byte */
734  wkb_little_endian = byte_from_wkb_state(s);
735  if (s->error)
736  return NULL;
737  if( wkb_little_endian != 1 && wkb_little_endian != 0 )
738  {
739  LWDEBUG(4,"Leaving due to bad first byte!");
740  lwerror("Invalid endian flag value encountered.");
741  return NULL;
742  }
743 
744  /* Check the endianness of our input */
745  s->swap_bytes = LW_FALSE;
746 
747  /* Machine arch is big endian, request is for little */
748  if (IS_BIG_ENDIAN && wkb_little_endian)
749  s->swap_bytes = LW_TRUE;
750  /* Machine arch is little endian, request is for big */
751  else if ((!IS_BIG_ENDIAN) && (!wkb_little_endian))
752  s->swap_bytes = LW_TRUE;
753 
754  /* Read the type number */
755  wkb_type = integer_from_wkb_state(s);
756  if (s->error)
757  return NULL;
758  LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
759  lwtype_from_wkb_state(s, wkb_type);
760 
761  /* Read the SRID, if necessary */
762  if( s->has_srid )
763  {
765  if (s->error)
766  return NULL;
767  /* TODO: warn on explicit UNKNOWN srid ? */
768  LWDEBUGF(4,"Got SRID: %u", s->srid);
769  }
770 
771  /* Do the right thing */
772  switch( s->lwtype )
773  {
774  case POINTTYPE:
775  return (LWGEOM*)lwpoint_from_wkb_state(s);
776  break;
777  case LINETYPE:
778  return (LWGEOM*)lwline_from_wkb_state(s);
779  break;
780  case CIRCSTRINGTYPE:
782  break;
783  case POLYGONTYPE:
784  return (LWGEOM*)lwpoly_from_wkb_state(s);
785  break;
786  case TRIANGLETYPE:
788  break;
789  case CURVEPOLYTYPE:
791  break;
792  case MULTIPOINTTYPE:
793  case MULTILINETYPE:
794  case MULTIPOLYGONTYPE:
795  case COMPOUNDTYPE:
796  case MULTICURVETYPE:
797  case MULTISURFACETYPE:
799  case TINTYPE:
800  case COLLECTIONTYPE:
802  break;
803 
804  /* Unknown type! */
805  default:
806  lwerror("%s: Unsupported geometry type: %s", __func__, lwtype_name(s->lwtype));
807  }
808 
809  /* Return value to keep compiler happy. */
810  return NULL;
811 
812 }
813 
814 /* TODO add check for SRID consistency */
815 
825 LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
826 {
828 
829  /* Initialize the state appropriately */
830  s.wkb = wkb;
831  s.wkb_size = wkb_size;
832  s.swap_bytes = LW_FALSE;
833  s.check = check;
834  s.lwtype = 0;
835  s.srid = SRID_UNKNOWN;
836  s.has_z = LW_FALSE;
837  s.has_m = LW_FALSE;
838  s.has_srid = LW_FALSE;
839  s.error = LW_FALSE;
840  s.pos = wkb;
841  s.depth = 1;
842 
843  if (!wkb || !wkb_size)
844  return NULL;
845 
846  return lwgeom_from_wkb_state(&s);
847 }
848 
849 LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
850 {
851  int hexwkb_len;
852  uint8_t *wkb;
853  LWGEOM *lwgeom;
854 
855  if ( ! hexwkb )
856  {
857  lwerror("lwgeom_from_hexwkb: null input");
858  return NULL;
859  }
860 
861  hexwkb_len = strlen(hexwkb);
862  wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
863  lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
864  lwfree(wkb);
865  return lwgeom;
866 }
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:2056
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 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
#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
#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
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:116
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:130
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:121
void lwfree(void *mem)
Definition: lwutil.c:242
#define POLYGONTYPE
Definition: liblwgeom.h:118
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
#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
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:719
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:2055
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:319
#define MULTICURVETYPE
Definition: liblwgeom.h:126
#define TRIANGLETYPE
Definition: liblwgeom.h:129
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:693
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
LWCURVEPOLY * lwcurvepoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwcurvepoly.c:35
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:229
#define WKBZOFFSET
Flags applied in EWKB to indicate Z/M dimensions and presence/absence of SRID and bounding boxes.
Definition: liblwgeom.h:138
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
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 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 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 LWCURVEPOLY * lwcurvepoly_from_wkb_state(wkb_parse_state *s)
CURVEPOLYTYPE.
Definition: lwin_wkb.c:639
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:849
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 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
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:310
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 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
static LWCOLLECTION * lwcollection_from_wkb_state(wkb_parse_state *s)
POLYHEDRALSURFACETYPE.
Definition: lwin_wkb.c:676
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 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
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:726
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:825
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:591
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
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