PostGIS  2.2.7dev-r@@SVN_REVISION@@
lwin_wkb.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  *
5  * Copyright (C) 2009 Paul Ramsey <pramsey@cleverelephant.ca>
6  *
7  * This is free software; you can redistribute and/or modify it under
8  * the terms of the GNU General Public Licence. See the COPYING file.
9  *
10  **********************************************************************/
11 
12 #include "../postgis_config.h"
13 /*#define POSTGIS_DEBUG_LEVEL 4*/
14 #include "liblwgeom_internal.h" /* NOTE: includes lwgeom_log.h */
15 #include "lwgeom_log.h"
16 #include <math.h>
17 
21 typedef struct
22 {
23  const uint8_t *wkb; /* Points to start of WKB */
24  size_t wkb_size; /* Expected size of WKB */
25  int swap_bytes; /* Do an endian flip? */
26  int check; /* Simple validity checks on geometries */
27  uint32_t lwtype; /* Current type we are handling */
28  uint32_t srid; /* Current SRID we are handling */
29  int has_z; /* Z? */
30  int has_m; /* M? */
31  int has_srid; /* SRID? */
32  const uint8_t *pos; /* Current parse position */
34 
35 
40 
41 
42 
43 /**********************************************************************/
44 
45 /* Our static character->number map. Anything > 15 is invalid */
46 static uint8_t hex2char[256] = {
47  /* not Hex characters */
48  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
49  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
50  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
51  /* 0-9 */
52  0,1,2,3,4,5,6,7,8,9,20,20,20,20,20,20,
53  /* A-F */
54  20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
55  /* not Hex characters */
56  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
57  /* a-f */
58  20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
59  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
60  /* not Hex characters (upper 128 characters) */
61  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
62  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
63  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
64  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
65  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
66  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
67  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
68  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20
69  };
70 
71 
72 uint8_t* bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
73 {
74  uint8_t *buf = NULL;
75  register uint8_t h1, h2;
76  int i;
77 
78  if( hexsize % 2 )
79  lwerror("Invalid hex string, length (%d) has to be a multiple of two!", hexsize);
80 
81  buf = lwalloc(hexsize/2);
82 
83  if( ! buf )
84  lwerror("Unable to allocate memory buffer.");
85 
86  for( i = 0; i < hexsize/2; i++ )
87  {
88  h1 = hex2char[(int)hexbuf[2*i]];
89  h2 = hex2char[(int)hexbuf[2*i+1]];
90  if( h1 > 15 )
91  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i]);
92  if( h2 > 15 )
93  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i+1]);
94  /* First character is high bits, second is low bits */
95  buf[i] = ((h1 & 0x0F) << 4) | (h2 & 0x0F);
96  }
97  return buf;
98 }
99 
100 
101 /**********************************************************************/
102 
103 
104 
105 
106 
111 static inline void wkb_parse_state_check(wkb_parse_state *s, size_t next)
112 {
113  if( (s->pos + next) > (s->wkb + s->wkb_size) )
114  lwerror("WKB structure does not match expected size!");
115 }
116 
122 static void lwtype_from_wkb_state(wkb_parse_state *s, uint32_t wkb_type)
123 {
124  uint32_t wkb_simple_type;
125 
126  LWDEBUG(4, "Entered function");
127 
128  s->has_z = LW_FALSE;
129  s->has_m = LW_FALSE;
130  s->has_srid = LW_FALSE;
131 
132  /* If any of the higher bits are set, this is probably an extended type. */
133  if( wkb_type & 0xF0000000 )
134  {
135  if( wkb_type & WKBZOFFSET ) s->has_z = LW_TRUE;
136  if( wkb_type & WKBMOFFSET ) s->has_m = LW_TRUE;
137  if( wkb_type & WKBSRIDFLAG ) s->has_srid = LW_TRUE;
138  LWDEBUGF(4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
139  }
140 
141  /* Mask off the flags */
142  wkb_type = wkb_type & 0x0FFFFFFF;
143  /* Strip out just the type number (1-12) from the ISO number (eg 3001-3012) */
144  wkb_simple_type = wkb_type % 1000;
145 
146  /* Extract the Z/M information from ISO style numbers */
147  if( wkb_type >= 3000 && wkb_type < 4000 )
148  {
149  s->has_z = LW_TRUE;
150  s->has_m = LW_TRUE;
151  }
152  else if ( wkb_type >= 2000 && wkb_type < 3000 )
153  {
154  s->has_m = LW_TRUE;
155  }
156  else if ( wkb_type >= 1000 && wkb_type < 2000 )
157  {
158  s->has_z = LW_TRUE;
159  }
160 
161  switch (wkb_simple_type)
162  {
163  case WKB_POINT_TYPE:
164  s->lwtype = POINTTYPE;
165  break;
166  case WKB_LINESTRING_TYPE:
167  s->lwtype = LINETYPE;
168  break;
169  case WKB_POLYGON_TYPE:
170  s->lwtype = POLYGONTYPE;
171  break;
172  case WKB_MULTIPOINT_TYPE:
173  s->lwtype = MULTIPOINTTYPE;
174  break;
176  s->lwtype = MULTILINETYPE;
177  break;
180  break;
182  s->lwtype = COLLECTIONTYPE;
183  break;
185  s->lwtype = CIRCSTRINGTYPE;
186  break;
188  s->lwtype = COMPOUNDTYPE;
189  break;
191  s->lwtype = CURVEPOLYTYPE;
192  break;
193  case WKB_MULTICURVE_TYPE:
194  s->lwtype = MULTICURVETYPE;
195  break;
196  case WKB_MULTISURFACE_TYPE:
198  break;
201  break;
202  case WKB_TIN_TYPE:
203  s->lwtype = TINTYPE;
204  break;
205  case WKB_TRIANGLE_TYPE:
206  s->lwtype = TRIANGLETYPE;
207  break;
208 
209  /* PostGIS 1.5 emits 13, 14 for CurvePolygon, MultiCurve */
210  /* These numbers aren't SQL/MM (numbers currently only */
211  /* go up to 12. We can handle the old data here (for now??) */
212  /* converting them into the lwtypes that are intended. */
213  case WKB_CURVE_TYPE:
214  s->lwtype = CURVEPOLYTYPE;
215  break;
216  case WKB_SURFACE_TYPE:
217  s->lwtype = MULTICURVETYPE;
218  break;
219 
220  default: /* Error! */
221  lwerror("Unknown WKB type (%d)! Full WKB type number was (%d).", wkb_simple_type, wkb_type);
222  break;
223  }
224 
225  LWDEBUGF(4,"Got lwtype %s (%u)", lwtype_name(s->lwtype), s->lwtype);
226 
227  return;
228 }
229 
235 {
236  char char_value = 0;
237  LWDEBUG(4, "Entered function");
238 
240  LWDEBUG(4, "Passed state check");
241 
242  char_value = s->pos[0];
243  LWDEBUGF(4, "Read byte value: %x", char_value);
244  s->pos += WKB_BYTE_SIZE;
245 
246  return char_value;
247 }
248 
254 {
255  uint32_t i = 0;
256 
258 
259  memcpy(&i, s->pos, WKB_INT_SIZE);
260 
261  /* Swap? Copy into a stack-allocated integer. */
262  if( s->swap_bytes )
263  {
264  int j = 0;
265  uint8_t tmp;
266 
267  for( j = 0; j < WKB_INT_SIZE/2; j++ )
268  {
269  tmp = ((uint8_t*)(&i))[j];
270  ((uint8_t*)(&i))[j] = ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1];
271  ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1] = tmp;
272  }
273  }
274 
275  s->pos += WKB_INT_SIZE;
276  return i;
277 }
278 
284 {
285  double d = 0;
286 
288 
289  memcpy(&d, s->pos, WKB_DOUBLE_SIZE);
290 
291  /* Swap? Copy into a stack-allocated integer. */
292  if( s->swap_bytes )
293  {
294  int i = 0;
295  uint8_t tmp;
296 
297  for( i = 0; i < WKB_DOUBLE_SIZE/2; i++ )
298  {
299  tmp = ((uint8_t*)(&d))[i];
300  ((uint8_t*)(&d))[i] = ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1];
301  ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1] = tmp;
302  }
303 
304  }
305 
306  s->pos += WKB_DOUBLE_SIZE;
307  return d;
308 }
309 
316 {
317  POINTARRAY *pa = NULL;
318  size_t pa_size;
319  uint32_t ndims = 2;
320  uint32_t npoints = 0;
321  static uint32_t maxpoints = 4294967295 / WKB_DOUBLE_SIZE / 4;
322 
323  /* Calculate the size of this point array. */
324  npoints = integer_from_wkb_state(s);
325  if (npoints > maxpoints)
326  {
327  lwerror("point array length (%d) is too large");
328  }
329 
330  LWDEBUGF(4,"Pointarray has %d points", npoints);
331 
332  if( s->has_z ) ndims++;
333  if( s->has_m ) ndims++;
334  pa_size = npoints * ndims * WKB_DOUBLE_SIZE;
335 
336  /* Empty! */
337  if( npoints == 0 )
338  return ptarray_construct(s->has_z, s->has_m, npoints);
339 
340  /* Does the data we want to read exist? */
341  wkb_parse_state_check(s, pa_size);
342 
343  /* If we're in a native endianness, we can just copy the data directly! */
344  if( ! s->swap_bytes )
345  {
346  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
347  s->pos += pa_size;
348  }
349  /* Otherwise we have to read each double, separately. */
350  else
351  {
352  int i = 0;
353  double *dlist;
354  pa = ptarray_construct(s->has_z, s->has_m, npoints);
355  dlist = (double*)(pa->serialized_pointlist);
356  for( i = 0; i < npoints * ndims; i++ )
357  {
358  dlist[i] = double_from_wkb_state(s);
359  }
360  }
361 
362  return pa;
363 }
364 
375 {
376  static uint32_t npoints = 1;
377  POINTARRAY *pa = NULL;
378  size_t pa_size;
379  uint32_t ndims = 2;
380  const POINT2D *pt;
381 
382  /* Count the dimensions. */
383  if( s->has_z ) ndims++;
384  if( s->has_m ) ndims++;
385  pa_size = ndims * WKB_DOUBLE_SIZE;
386 
387  /* Does the data we want to read exist? */
388  wkb_parse_state_check(s, pa_size);
389 
390  /* If we're in a native endianness, we can just copy the data directly! */
391  if( ! s->swap_bytes )
392  {
393  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
394  s->pos += pa_size;
395  }
396  /* Otherwise we have to read each double, separately */
397  else
398  {
399  int i = 0;
400  double *dlist;
401  pa = ptarray_construct(s->has_z, s->has_m, npoints);
402  dlist = (double*)(pa->serialized_pointlist);
403  for( i = 0; i < ndims; i++ )
404  {
405  dlist[i] = double_from_wkb_state(s);
406  }
407  }
408 
409  /* Check for POINT(NaN NaN) ==> POINT EMPTY */
410  pt = getPoint2d_cp(pa, 0);
411  if ( isnan(pt->x) && isnan(pt->y) )
412  {
413  ptarray_free(pa);
414  return lwpoint_construct_empty(s->srid, s->has_z, s->has_m);
415  }
416  else
417  {
418  return lwpoint_construct(s->srid, NULL, pa);
419  }
420 }
421 
431 {
433 
434  if( pa == NULL || pa->npoints == 0 )
435  return lwline_construct_empty(s->srid, s->has_z, s->has_m);
436 
437  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
438  {
439  lwerror("%s must have at least two points", lwtype_name(s->lwtype));
440  return NULL;
441  }
442 
443  return lwline_construct(s->srid, NULL, pa);
444 }
445 
456 {
458 
459  if( pa == NULL || pa->npoints == 0 )
460  return lwcircstring_construct_empty(s->srid, s->has_z, s->has_m);
461 
462  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 3 )
463  {
464  lwerror("%s must have at least three points", lwtype_name(s->lwtype));
465  return NULL;
466  }
467 
468  if( s->check & LW_PARSER_CHECK_ODD && ! (pa->npoints % 2) )
469  {
470  lwerror("%s must have an odd number of points", lwtype_name(s->lwtype));
471  return NULL;
472  }
473 
474  return lwcircstring_construct(s->srid, NULL, pa);
475 }
476 
486 {
487  uint32_t nrings = integer_from_wkb_state(s);
488  int i = 0;
489  LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);
490 
491  LWDEBUGF(4,"Polygon has %d rings", nrings);
492 
493  /* Empty polygon? */
494  if( nrings == 0 )
495  return poly;
496 
497  for( i = 0; i < nrings; i++ )
498  {
500  if( pa == NULL )
501  continue;
502 
503  /* Check for at least four points. */
504  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
505  {
506  LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
507  lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
508  return NULL;
509  }
510 
511  /* Check that first and last points are the same. */
513  {
514  LWDEBUGF(2, "%s must have closed rings", lwtype_name(s->lwtype));
515  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
516  return NULL;
517  }
518 
519  /* Add ring to polygon */
520  if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
521  {
522  LWDEBUG(2, "Unable to add ring to polygon");
523  lwerror("Unable to add ring to polygon");
524  }
525 
526  }
527  return poly;
528 }
529 
539 {
540  uint32_t nrings = integer_from_wkb_state(s);
542  POINTARRAY *pa = NULL;
543 
544  /* Empty triangle? */
545  if( nrings == 0 )
546  return tri;
547 
548  /* Should be only one ring. */
549  if ( nrings != 1 )
550  lwerror("Triangle has wrong number of rings: %d", nrings);
551 
552  /* There's only one ring, we hope? */
553  pa = ptarray_from_wkb_state(s);
554 
555  /* If there's no points, return an empty triangle. */
556  if( pa == NULL )
557  return tri;
558 
559  /* Check for at least four points. */
560  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
561  {
562  LWDEBUGF(2, "%s must have at least four points", lwtype_name(s->lwtype));
563  lwerror("%s must have at least four points", lwtype_name(s->lwtype));
564  return NULL;
565  }
566 
568  {
569  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
570  return NULL;
571  }
572 
574  {
575  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
576  return NULL;
577  }
578 
579  /* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
580  if (tri->points)
581  ptarray_free(tri->points);
582 
583  tri->points = pa;
584  return tri;
585 }
586 
591 {
592  uint32_t ngeoms = integer_from_wkb_state(s);
594  LWGEOM *geom = NULL;
595  int i;
596 
597  /* Empty collection? */
598  if ( ngeoms == 0 )
599  return cp;
600 
601  for ( i = 0; i < ngeoms; i++ )
602  {
603  geom = lwgeom_from_wkb_state(s);
604  if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
605  lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
606  }
607 
608  return cp;
609 }
610 
621 {
622  uint32_t ngeoms = integer_from_wkb_state(s);
624  LWGEOM *geom = NULL;
625  int i;
626 
627  LWDEBUGF(4,"Collection has %d components", ngeoms);
628 
629  /* Empty collection? */
630  if ( ngeoms == 0 )
631  return col;
632 
633  /* Be strict in polyhedral surface closures */
634  if ( s->lwtype == POLYHEDRALSURFACETYPE )
636 
637  for ( i = 0; i < ngeoms; i++ )
638  {
639  geom = lwgeom_from_wkb_state(s);
640  if ( lwcollection_add_lwgeom(col, geom) == NULL )
641  {
642  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
643  return NULL;
644  }
645  }
646 
647  return col;
648 }
649 
650 
659 {
660  char wkb_little_endian;
661  uint32_t wkb_type;
662 
663  LWDEBUG(4,"Entered function");
664 
665  /* Fail when handed incorrect starting byte */
666  wkb_little_endian = byte_from_wkb_state(s);
667  if( wkb_little_endian != 1 && wkb_little_endian != 0 )
668  {
669  LWDEBUG(4,"Leaving due to bad first byte!");
670  lwerror("Invalid endian flag value encountered.");
671  return NULL;
672  }
673 
674  /* Check the endianness of our input */
675  s->swap_bytes = LW_FALSE;
676  if( getMachineEndian() == NDR ) /* Machine arch is little */
677  {
678  if ( ! wkb_little_endian ) /* Data is big! */
679  s->swap_bytes = LW_TRUE;
680  }
681  else /* Machine arch is big */
682  {
683  if ( wkb_little_endian ) /* Data is little! */
684  s->swap_bytes = LW_TRUE;
685  }
686 
687  /* Read the type number */
688  wkb_type = integer_from_wkb_state(s);
689  LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
690  lwtype_from_wkb_state(s, wkb_type);
691 
692  /* Read the SRID, if necessary */
693  if( s->has_srid )
694  {
696  /* TODO: warn on explicit UNKNOWN srid ? */
697  LWDEBUGF(4,"Got SRID: %u", s->srid);
698  }
699 
700  /* Do the right thing */
701  switch( s->lwtype )
702  {
703  case POINTTYPE:
704  return (LWGEOM*)lwpoint_from_wkb_state(s);
705  break;
706  case LINETYPE:
707  return (LWGEOM*)lwline_from_wkb_state(s);
708  break;
709  case CIRCSTRINGTYPE:
711  break;
712  case POLYGONTYPE:
713  return (LWGEOM*)lwpoly_from_wkb_state(s);
714  break;
715  case TRIANGLETYPE:
716  return (LWGEOM*)lwtriangle_from_wkb_state(s);
717  break;
718  case CURVEPOLYTYPE:
720  break;
721  case MULTIPOINTTYPE:
722  case MULTILINETYPE:
723  case MULTIPOLYGONTYPE:
724  case COMPOUNDTYPE:
725  case MULTICURVETYPE:
726  case MULTISURFACETYPE:
728  case TINTYPE:
729  case COLLECTIONTYPE:
731  break;
732 
733  /* Unknown type! */
734  default:
735  lwerror("Unsupported geometry type: %s [%d]", lwtype_name(s->lwtype), s->lwtype);
736  }
737 
738  /* Return value to keep compiler happy. */
739  return NULL;
740 
741 }
742 
743 /* TODO add check for SRID consistency */
744 
754 LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
755 {
757 
758  /* Initialize the state appropriately */
759  s.wkb = wkb;
760  s.wkb_size = wkb_size;
761  s.swap_bytes = LW_FALSE;
762  s.check = check;
763  s.lwtype = 0;
764  s.srid = SRID_UNKNOWN;
765  s.has_z = LW_FALSE;
766  s.has_m = LW_FALSE;
767  s.has_srid = LW_FALSE;
768  s.pos = wkb;
769 
770  /* Hand the check catch-all values */
771  if ( check & LW_PARSER_CHECK_NONE )
772  s.check = 0;
773  else
774  s.check = check;
775 
776  return lwgeom_from_wkb_state(&s);
777 }
778 
779 LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
780 {
781  int hexwkb_len;
782  uint8_t *wkb;
783  LWGEOM *lwgeom;
784 
785  if ( ! hexwkb )
786  {
787  lwerror("lwgeom_from_hexwkb: null input");
788  return NULL;
789  }
790 
791  hexwkb_len = strlen(hexwkb);
792  wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
793  lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
794  lwfree(wkb);
795  return lwgeom;
796 }
#define WKB_SURFACE_TYPE
#define LINETYPE
Definition: liblwgeom.h:71
#define WKB_INT_SIZE
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:315
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition: lwutil.c:350
#define WKB_BYTE_SIZE
#define WKBMOFFSET
Definition: liblwgeom.h:93
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:62
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:122
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:779
POINTARRAY * points
Definition: liblwgeom.h:417
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:51
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:538
#define MULTICURVETYPE
Definition: liblwgeom.h:80
uint8_t * serialized_pointlist
Definition: liblwgeom.h:350
static LWCURVEPOLY * lwcurvepoly_from_wkb_state(wkb_parse_state *s)
CURVEPOLYTYPE.
Definition: lwin_wkb.c:590
void lwfree(void *mem)
Definition: lwutil.c:214
LWTRIANGLE * lwtriangle_construct_empty(int srid, char hasz, char hasm)
Definition: lwtriangle.c:45
static char byte_from_wkb_state(wkb_parse_state *s)
Byte Read a byte and advance the parse state forward.
Definition: lwin_wkb.c:234
int npoints
Definition: liblwgeom.h:355
static LWCOLLECTION * lwcollection_from_wkb_state(wkb_parse_state *s)
POLYHEDRALSURFACETYPE.
Definition: lwin_wkb.c:620
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:253
uint8_t * bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
Definition: lwin_wkb.c:72
#define WKB_COMPOUNDCURVE_TYPE
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:1864
#define WKB_POLYHEDRALSURFACE_TYPE
uint32_t lwtype
Definition: lwin_wkb.c:27
#define POLYGONTYPE
Definition: liblwgeom.h:72
#define CURVEPOLYTYPE
Definition: liblwgeom.h:79
#define WKB_TRIANGLE_TYPE
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:330
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:754
#define COMPOUNDTYPE
Definition: liblwgeom.h:78
#define MULTIPOINTTYPE
Definition: liblwgeom.h:73
#define WKB_MULTISURFACE_TYPE
#define NDR
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:720
#define WKB_DOUBLE_SIZE
Well-Known Binary (WKB) Output Variant Types.
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
#define TRIANGLETYPE
Definition: liblwgeom.h:83
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:82
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:485
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:120
const uint8_t * wkb
Definition: lwin_wkb.c:23
#define WKB_MULTICURVE_TYPE
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:694
#define LW_FAILURE
Definition: liblwgeom.h:64
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:1869
double x
Definition: liblwgeom.h:312
#define LW_PARSER_CHECK_ZCLOSURE
Definition: liblwgeom.h:1867
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:1865
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:188
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:455
#define WKBZOFFSET
Flags applied in EWKB to indicate Z/M dimensions and presence/absence of SRID and bounding boxes...
Definition: liblwgeom.h:92
size_t wkb_size
Definition: lwin_wkb.c:24
#define WKB_POLYGON_TYPE
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm)
Definition: lwcircstring.c:67
static uint8_t hex2char[256]
Definition: lwin_wkb.c:46
#define LW_FALSE
Definition: liblwgeom.h:62
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:472
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:61
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:172
#define TINTYPE
Definition: liblwgeom.h:84
#define WKBSRIDFLAG
Definition: liblwgeom.h:94
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:309
LWCURVEPOLY * lwcurvepoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwcurvepoly.c:23
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:111
#define WKB_POINT_TYPE
Well-Known Binary (WKB) Geometry Types.
double y
Definition: liblwgeom.h:312
char * s
Definition: cu_in_wkt.c:23
#define WKB_LINESTRING_TYPE
char getMachineEndian(void)
Definition: lwutil.c:330
#define WKB_CIRCULARSTRING_TYPE
#define WKB_MULTIPOLYGON_TYPE
#define WKB_CURVEPOLYGON_TYPE
LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:38
#define WKB_MULTILINESTRING_TYPE
#define WKB_TIN_TYPE
LWGEOM * lwgeom_from_wkb_state(wkb_parse_state *s)
Internal function declarations.
Definition: lwin_wkb.c:658
uint32_t srid
Definition: lwin_wkb.c:28
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:75
#define WKB_CURVE_TYPE
#define MULTISURFACETYPE
Definition: liblwgeom.h:81
Used for passing the parse state between the parsing functions.
Definition: lwin_wkb.c:21
#define WKB_MULTIPOINT_TYPE
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:430
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:70
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:66
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
Add a ring, allocating extra space if necessary.
Definition: lwcurvepoly.c:59
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:154
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:77
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:98
void * lwalloc(size_t size)
Definition: lwutil.c:199
#define MULTILINETYPE
Definition: liblwgeom.h:74
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:81
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
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:374
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:174
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:283
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
#define LW_PARSER_CHECK_CLOSURE
Definition: liblwgeom.h:1866
const uint8_t * pos
Definition: lwin_wkb.c:32
int ptarray_is_closed(const POINTARRAY *pa)
Check for ring closure using whatever dimensionality is declared on the pointarray.
Definition: ptarray.c:680
#define COLLECTIONTYPE
Definition: liblwgeom.h:76
#define WKB_GEOMETRYCOLLECTION_TYPE