PostGIS  2.1.10dev-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 "liblwgeom_internal.h"
13 #include "lwgeom_log.h"
14 
18 typedef struct
19 {
20  const uint8_t *wkb; /* Points to start of WKB */
21  size_t wkb_size; /* Expected size of WKB */
22  int swap_bytes; /* Do an endian flip? */
23  int check; /* Simple validity checks on geometries */
24  uint32_t lwtype; /* Current type we are handling */
25  uint32_t srid; /* Current SRID we are handling */
26  int has_z; /* Z? */
27  int has_m; /* M? */
28  int has_srid; /* SRID? */
29  const uint8_t *pos; /* Current parse position */
31 
32 
37 
38 
39 
40 /**********************************************************************/
41 
42 /* Our static character->number map. Anything > 15 is invalid */
43 static uint8_t hex2char[256] = {
44  /* not Hex characters */
45  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
46  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
47  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
48  /* 0-9 */
49  0,1,2,3,4,5,6,7,8,9,20,20,20,20,20,20,
50  /* A-F */
51  20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
52  /* not Hex characters */
53  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
54  /* a-f */
55  20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
56  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
57  /* not Hex characters (upper 128 characters) */
58  20,20,20,20,20,20,20,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  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
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  };
67 
68 
69 uint8_t* bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
70 {
71  uint8_t *buf = NULL;
72  register uint8_t h1, h2;
73  int i;
74 
75  if( hexsize % 2 )
76  lwerror("Invalid hex string, length (%d) has to be a multiple of two!", hexsize);
77 
78  buf = lwalloc(hexsize/2);
79 
80  if( ! buf )
81  lwerror("Unable to allocate memory buffer.");
82 
83  for( i = 0; i < hexsize/2; i++ )
84  {
85  h1 = hex2char[(int)hexbuf[2*i]];
86  h2 = hex2char[(int)hexbuf[2*i+1]];
87  if( h1 > 15 )
88  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i]);
89  if( h2 > 15 )
90  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i+1]);
91  /* First character is high bits, second is low bits */
92  buf[i] = ((h1 & 0x0F) << 4) | (h2 & 0x0F);
93  }
94  return buf;
95 }
96 
97 
98 /**********************************************************************/
99 
100 
101 
102 
103 
108 static inline void wkb_parse_state_check(wkb_parse_state *s, size_t next)
109 {
110  if( (s->pos + next) > (s->wkb + s->wkb_size) )
111  lwerror("WKB structure does not match expected size!");
112 }
113 
119 static void lwtype_from_wkb_state(wkb_parse_state *s, uint32_t wkb_type)
120 {
121  uint32_t wkb_simple_type;
122 
123  LWDEBUG(4, "Entered function");
124 
125  s->has_z = LW_FALSE;
126  s->has_m = LW_FALSE;
127  s->has_srid = LW_FALSE;
128 
129  /* If any of the higher bits are set, this is probably an extended type. */
130  if( wkb_type & 0xF0000000 )
131  {
132  if( wkb_type & WKBZOFFSET ) s->has_z = LW_TRUE;
133  if( wkb_type & WKBMOFFSET ) s->has_m = LW_TRUE;
134  if( wkb_type & WKBSRIDFLAG ) s->has_srid = LW_TRUE;
135  LWDEBUGF(4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
136  }
137 
138  /* Mask off the flags */
139  wkb_type = wkb_type & 0x0FFFFFFF;
140  /* Strip out just the type number (1-12) from the ISO number (eg 3001-3012) */
141  wkb_simple_type = wkb_type % 1000;
142 
143  /* Extract the Z/M information from ISO style numbers */
144  if( wkb_type >= 3000 && wkb_type < 4000 )
145  {
146  s->has_z = LW_TRUE;
147  s->has_m = LW_TRUE;
148  }
149  else if ( wkb_type >= 2000 && wkb_type < 3000 )
150  {
151  s->has_m = LW_TRUE;
152  }
153  else if ( wkb_type >= 1000 && wkb_type < 2000 )
154  {
155  s->has_z = LW_TRUE;
156  }
157 
158  switch (wkb_simple_type)
159  {
160  case WKB_POINT_TYPE:
161  s->lwtype = POINTTYPE;
162  break;
163  case WKB_LINESTRING_TYPE:
164  s->lwtype = LINETYPE;
165  break;
166  case WKB_POLYGON_TYPE:
167  s->lwtype = POLYGONTYPE;
168  break;
169  case WKB_MULTIPOINT_TYPE:
170  s->lwtype = MULTIPOINTTYPE;
171  break;
173  s->lwtype = MULTILINETYPE;
174  break;
177  break;
179  s->lwtype = COLLECTIONTYPE;
180  break;
182  s->lwtype = CIRCSTRINGTYPE;
183  break;
185  s->lwtype = COMPOUNDTYPE;
186  break;
188  s->lwtype = CURVEPOLYTYPE;
189  break;
190  case WKB_MULTICURVE_TYPE:
191  s->lwtype = MULTICURVETYPE;
192  break;
193  case WKB_MULTISURFACE_TYPE:
195  break;
198  break;
199  case WKB_TIN_TYPE:
200  s->lwtype = TINTYPE;
201  break;
202  case WKB_TRIANGLE_TYPE:
203  s->lwtype = TRIANGLETYPE;
204  break;
205 
206  /* PostGIS 1.5 emits 13, 14 for CurvePolygon, MultiCurve */
207  /* These numbers aren't SQL/MM (numbers currently only */
208  /* go up to 12. We can handle the old data here (for now??) */
209  /* converting them into the lwtypes that are intended. */
210  case WKB_CURVE_TYPE:
211  s->lwtype = CURVEPOLYTYPE;
212  break;
213  case WKB_SURFACE_TYPE:
214  s->lwtype = MULTICURVETYPE;
215  break;
216 
217  default: /* Error! */
218  lwerror("Unknown WKB type (%d)! Full WKB type number was (%d).", wkb_simple_type, wkb_type);
219  break;
220  }
221 
222  LWDEBUGF(4,"Got lwtype %s (%u)", lwtype_name(s->lwtype), s->lwtype);
223 
224  return;
225 }
226 
232 {
233  char char_value = 0;
234  LWDEBUG(4, "Entered function");
235 
237  LWDEBUG(4, "Passed state check");
238 
239  char_value = s->pos[0];
240  LWDEBUGF(4, "Read byte value: %x", char_value);
241  s->pos += WKB_BYTE_SIZE;
242 
243  return char_value;
244 }
245 
251 {
252  uint32_t i = 0;
253 
255 
256  memcpy(&i, s->pos, WKB_INT_SIZE);
257 
258  /* Swap? Copy into a stack-allocated integer. */
259  if( s->swap_bytes )
260  {
261  int j = 0;
262  uint8_t tmp;
263 
264  for( j = 0; j < WKB_INT_SIZE/2; j++ )
265  {
266  tmp = ((uint8_t*)(&i))[j];
267  ((uint8_t*)(&i))[j] = ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1];
268  ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1] = tmp;
269  }
270  }
271 
272  s->pos += WKB_INT_SIZE;
273  return i;
274 }
275 
281 {
282  double d = 0;
283 
285 
286  memcpy(&d, s->pos, WKB_DOUBLE_SIZE);
287 
288  /* Swap? Copy into a stack-allocated integer. */
289  if( s->swap_bytes )
290  {
291  int i = 0;
292  uint8_t tmp;
293 
294  for( i = 0; i < WKB_DOUBLE_SIZE/2; i++ )
295  {
296  tmp = ((uint8_t*)(&d))[i];
297  ((uint8_t*)(&d))[i] = ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1];
298  ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1] = tmp;
299  }
300 
301  }
302 
303  s->pos += WKB_DOUBLE_SIZE;
304  return d;
305 }
306 
313 {
314  POINTARRAY *pa = NULL;
315  size_t pa_size;
316  uint32_t ndims = 2;
317  uint32_t npoints = 0;
318 
319  /* Calculate the size of this point array. */
320  npoints = integer_from_wkb_state(s);
321  if( s->has_z ) ndims++;
322  if( s->has_m ) ndims++;
323  pa_size = npoints * ndims * WKB_DOUBLE_SIZE;
324 
325  /* Empty! */
326  if( npoints == 0 )
327  return ptarray_construct(s->has_z, s->has_m, npoints);
328 
329  /* Does the data we want to read exist? */
330  wkb_parse_state_check(s, pa_size);
331 
332  /* If we're in a native endianness, we can just copy the data directly! */
333  if( ! s->swap_bytes )
334  {
335  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
336  s->pos += pa_size;
337  }
338  /* Otherwise we have to read each double, separately. */
339  else
340  {
341  int i = 0;
342  double *dlist;
343  pa = ptarray_construct(s->has_z, s->has_m, npoints);
344  dlist = (double*)(pa->serialized_pointlist);
345  for( i = 0; i < npoints * ndims; i++ )
346  {
347  dlist[i] = double_from_wkb_state(s);
348  }
349  }
350 
351  return pa;
352 }
353 
364 {
365  static uint32_t npoints = 1;
366  POINTARRAY *pa = NULL;
367  size_t pa_size;
368  uint32_t ndims = 2;
369 
370  /* Count the dimensions. */
371  if( s->has_z ) ndims++;
372  if( s->has_m ) ndims++;
373  pa_size = ndims * WKB_DOUBLE_SIZE;
374 
375  /* Does the data we want to read exist? */
376  wkb_parse_state_check(s, pa_size);
377 
378  /* If we're in a native endianness, we can just copy the data directly! */
379  if( ! s->swap_bytes )
380  {
381  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
382  s->pos += pa_size;
383  }
384  /* Otherwise we have to read each double, separately */
385  else
386  {
387  int i = 0;
388  double *dlist;
389  pa = ptarray_construct(s->has_z, s->has_m, npoints);
390  dlist = (double*)(pa->serialized_pointlist);
391  for( i = 0; i < ndims; i++ )
392  {
393  dlist[i] = double_from_wkb_state(s);
394  }
395  }
396 
397  return lwpoint_construct(s->srid, NULL, pa);
398 }
399 
409 {
411 
412  if( pa == NULL || pa->npoints == 0 )
413  return lwline_construct_empty(s->srid, s->has_z, s->has_m);
414 
415  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
416  {
417  lwerror("%s must have at least two points", lwtype_name(s->lwtype));
418  return NULL;
419  }
420 
421  return lwline_construct(s->srid, NULL, pa);
422 }
423 
434 {
436 
437  if( pa == NULL || pa->npoints == 0 )
438  return lwcircstring_construct_empty(s->srid, s->has_z, s->has_m);
439 
440  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 3 )
441  {
442  lwerror("%s must have at least three points", lwtype_name(s->lwtype));
443  return NULL;
444  }
445 
446  if( s->check & LW_PARSER_CHECK_ODD && ! (pa->npoints % 2) )
447  {
448  lwerror("%s must have an odd number of points", lwtype_name(s->lwtype));
449  return NULL;
450  }
451 
452  return lwcircstring_construct(s->srid, NULL, pa);
453 }
454 
464 {
465  uint32_t nrings = integer_from_wkb_state(s);
466  int i = 0;
467  LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);
468 
469  /* Empty polygon? */
470  if( nrings == 0 )
471  return poly;
472 
473  for( i = 0; i < nrings; i++ )
474  {
476  if( pa == NULL )
477  continue;
478 
479  /* Check for at least four points. */
480  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
481  {
482  LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
483  lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
484  return NULL;
485  }
486 
487  /* Check that first and last points are the same. */
489  {
490  LWDEBUGF(2, "%s must have closed rings", lwtype_name(s->lwtype));
491  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
492  return NULL;
493  }
494 
495  /* Add ring to polygon */
496  if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
497  {
498  LWDEBUG(2, "Unable to add ring to polygon");
499  lwerror("Unable to add ring to polygon");
500  }
501 
502  }
503  return poly;
504 }
505 
515 {
516  uint32_t nrings = integer_from_wkb_state(s);
518  POINTARRAY *pa = NULL;
519 
520  /* Empty triangle? */
521  if( nrings == 0 )
522  return tri;
523 
524  /* Should be only one ring. */
525  if ( nrings != 1 )
526  lwerror("Triangle has wrong number of rings: %d", nrings);
527 
528  /* There's only one ring, we hope? */
529  pa = ptarray_from_wkb_state(s);
530 
531  /* If there's no points, return an empty triangle. */
532  if( pa == NULL )
533  return tri;
534 
535  /* Check for at least four points. */
536  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
537  {
538  LWDEBUGF(2, "%s must have at least four points", lwtype_name(s->lwtype));
539  lwerror("%s must have at least four points", lwtype_name(s->lwtype));
540  return NULL;
541  }
542 
544  {
545  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
546  return NULL;
547  }
548 
550  {
551  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
552  return NULL;
553  }
554 
555  /* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
556  if ( tri->points)
557  ptarray_free(tri->points);
558 
559  tri->points = pa;
560  return tri;
561 }
562 
567 {
568  uint32_t ngeoms = integer_from_wkb_state(s);
570  LWGEOM *geom = NULL;
571  int i;
572 
573  /* Empty collection? */
574  if ( ngeoms == 0 )
575  return cp;
576 
577  for ( i = 0; i < ngeoms; i++ )
578  {
579  geom = lwgeom_from_wkb_state(s);
580  if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
581  lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
582  }
583 
584  return cp;
585 }
586 
597 {
598  uint32_t ngeoms = integer_from_wkb_state(s);
600  LWGEOM *geom = NULL;
601  int i;
602 
603  /* Empty collection? */
604  if ( ngeoms == 0 )
605  return col;
606 
607  /* Be strict in polyhedral surface closures */
608  if ( s->lwtype == POLYHEDRALSURFACETYPE )
610 
611  for ( i = 0; i < ngeoms; i++ )
612  {
613  geom = lwgeom_from_wkb_state(s);
614  if ( lwcollection_add_lwgeom(col, geom) == NULL )
615  {
616  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
617  return NULL;
618  }
619  }
620 
621  return col;
622 }
623 
624 
633 {
634  char wkb_little_endian;
635  uint32_t wkb_type;
636 
637  LWDEBUG(4,"Entered function");
638 
639  /* Fail when handed incorrect starting byte */
640  wkb_little_endian = byte_from_wkb_state(s);
641  if( wkb_little_endian != 1 && wkb_little_endian != 0 )
642  {
643  LWDEBUG(4,"Leaving due to bad first byte!");
644  lwerror("Invalid endian flag value encountered.");
645  return NULL;
646  }
647 
648  /* Check the endianness of our input */
649  s->swap_bytes = LW_FALSE;
650  if( getMachineEndian() == NDR ) /* Machine arch is little */
651  {
652  if ( ! wkb_little_endian ) /* Data is big! */
653  s->swap_bytes = LW_TRUE;
654  }
655  else /* Machine arch is big */
656  {
657  if ( wkb_little_endian ) /* Data is little! */
658  s->swap_bytes = LW_TRUE;
659  }
660 
661  /* Read the type number */
662  wkb_type = integer_from_wkb_state(s);
663  LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
664  lwtype_from_wkb_state(s, wkb_type);
665 
666  /* Read the SRID, if necessary */
667  if( s->has_srid )
668  {
670  /* TODO: warn on explicit UNKNOWN srid ? */
671  LWDEBUGF(4,"Got SRID: %u", s->srid);
672  }
673 
674  /* Do the right thing */
675  switch( s->lwtype )
676  {
677  case POINTTYPE:
678  return (LWGEOM*)lwpoint_from_wkb_state(s);
679  break;
680  case LINETYPE:
681  return (LWGEOM*)lwline_from_wkb_state(s);
682  break;
683  case CIRCSTRINGTYPE:
685  break;
686  case POLYGONTYPE:
687  return (LWGEOM*)lwpoly_from_wkb_state(s);
688  break;
689  case TRIANGLETYPE:
690  return (LWGEOM*)lwtriangle_from_wkb_state(s);
691  break;
692  case CURVEPOLYTYPE:
694  break;
695  case MULTIPOINTTYPE:
696  case MULTILINETYPE:
697  case MULTIPOLYGONTYPE:
698  case COMPOUNDTYPE:
699  case MULTICURVETYPE:
700  case MULTISURFACETYPE:
702  case TINTYPE:
703  case COLLECTIONTYPE:
705  break;
706 
707  /* Unknown type! */
708  default:
709  lwerror("Unsupported geometry type: %s [%d]", lwtype_name(s->lwtype), s->lwtype);
710  }
711 
712  /* Return value to keep compiler happy. */
713  return NULL;
714 
715 }
716 
717 /* TODO add check for SRID consistency */
718 
728 LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
729 {
731 
732  /* Initialize the state appropriately */
733  s.wkb = wkb;
734  s.wkb_size = wkb_size;
735  s.swap_bytes = LW_FALSE;
736  s.check = check;
737  s.lwtype = 0;
738  s.srid = SRID_UNKNOWN;
739  s.has_z = LW_FALSE;
740  s.has_m = LW_FALSE;
741  s.has_srid = LW_FALSE;
742  s.pos = wkb;
743 
744  /* Hand the check catch-all values */
745  if ( check & LW_PARSER_CHECK_NONE )
746  s.check = 0;
747  else
748  s.check = check;
749 
750  return lwgeom_from_wkb_state(&s);
751 }
752 
753 LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
754 {
755  int hexwkb_len;
756  uint8_t *wkb;
757  LWGEOM *lwgeom;
758 
759  if ( ! hexwkb )
760  {
761  lwerror("lwgeom_from_hexwkb: null input");
762  return NULL;
763  }
764 
765  hexwkb_len = strlen(hexwkb);
766  wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
767  lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
768  lwfree(wkb);
769  return lwgeom;
770 }
#define WKB_SURFACE_TYPE
#define LINETYPE
Definition: liblwgeom.h:61
#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:312
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:326
#define WKB_BYTE_SIZE
#define WKBMOFFSET
Definition: liblwgeom.h:83
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:49
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:119
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:753
POINTARRAY * points
Definition: liblwgeom.h:389
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:514
#define MULTICURVETYPE
Definition: liblwgeom.h:70
uint8_t * serialized_pointlist
Definition: liblwgeom.h:322
static LWCURVEPOLY * lwcurvepoly_from_wkb_state(wkb_parse_state *s)
CURVEPOLYTYPE.
Definition: lwin_wkb.c:566
void lwfree(void *mem)
Definition: lwutil.c:190
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:231
int npoints
Definition: liblwgeom.h:327
static LWCOLLECTION * lwcollection_from_wkb_state(wkb_parse_state *s)
POLYHEDRALSURFACETYPE.
Definition: lwin_wkb.c:596
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:250
uint8_t * bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
Definition: lwin_wkb.c:69
#define WKB_COMPOUNDCURVE_TYPE
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:1701
#define WKB_POLYHEDRALSURFACE_TYPE
uint32_t lwtype
Definition: lwin_wkb.c:24
#define POLYGONTYPE
Definition: liblwgeom.h:62
#define CURVEPOLYTYPE
Definition: liblwgeom.h:69
#define WKB_TRIANGLE_TYPE
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:315
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:728
#define COMPOUNDTYPE
Definition: liblwgeom.h:68
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
#define WKB_MULTISURFACE_TYPE
#define NDR
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:684
#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:73
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:72
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:463
const uint8_t * wkb
Definition: lwin_wkb.c:20
#define WKB_MULTICURVE_TYPE
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:672
#define LW_FAILURE
Definition: liblwgeom.h:54
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:1706
#define LW_PARSER_CHECK_ZCLOSURE
Definition: liblwgeom.h:1704
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:1702
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:164
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:433
#define WKBZOFFSET
Flags applied in EWKB to indicate Z/M dimensions and presence/absence of SRID and bounding boxes...
Definition: liblwgeom.h:82
size_t wkb_size
Definition: lwin_wkb.c:21
#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:43
#define LW_FALSE
Definition: liblwgeom.h:52
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:51
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:154
#define TINTYPE
Definition: liblwgeom.h:74
#define WKBSRIDFLAG
Definition: liblwgeom.h:84
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:294
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:108
#define WKB_POINT_TYPE
Well-Known Binary (WKB) Geometry Types.
char * s
Definition: cu_in_wkt.c:24
#define WKB_LINESTRING_TYPE
char getMachineEndian(void)
Definition: lwutil.c:306
#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:632
uint32_t srid
Definition: lwin_wkb.c:25
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
#define WKB_CURVE_TYPE
#define MULTISURFACETYPE
Definition: liblwgeom.h:71
Used for passing the parse state between the parsing functions.
Definition: lwin_wkb.c:18
#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:408
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
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:67
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:96
void * lwalloc(size_t size)
Definition: lwutil.c:175
#define MULTILINETYPE
Definition: liblwgeom.h:64
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:363
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:280
#define LW_PARSER_CHECK_CLOSURE
Definition: liblwgeom.h:1703
const uint8_t * pos
Definition: lwin_wkb.c:29
int ptarray_is_closed(const POINTARRAY *pa)
Check for ring closure using whatever dimensionality is declared on the pointarray.
Definition: ptarray.c:665
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
#define WKB_GEOMETRYCOLLECTION_TYPE