PostGIS  2.4.9dev-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 
35 typedef struct
36 {
37  const uint8_t *wkb; /* Points to start of WKB */
38  size_t wkb_size; /* Expected size of WKB */
39  int swap_bytes; /* Do an endian flip? */
40  int check; /* Simple validity checks on geometries */
41  uint32_t lwtype; /* Current type we are handling */
42  uint32_t srid; /* Current SRID we are handling */
43  int has_z; /* Z? */
44  int has_m; /* M? */
45  int has_srid; /* SRID? */
46  const uint8_t *pos; /* Current parse position */
48 
49 
54 
55 
56 
57 /**********************************************************************/
58 
59 /* Our static character->number map. Anything > 15 is invalid */
60 static uint8_t hex2char[256] = {
61  /* not Hex characters */
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  /* 0-9 */
66  0,1,2,3,4,5,6,7,8,9,20,20,20,20,20,20,
67  /* A-F */
68  20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
69  /* not Hex characters */
70  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
71  /* a-f */
72  20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
73  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
74  /* not Hex characters (upper 128 characters) */
75  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
76  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
77  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
78  20,20,20,20,20,20,20,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  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
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  };
84 
85 
86 uint8_t* bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
87 {
88  uint8_t *buf = NULL;
89  register uint8_t h1, h2;
90  int i;
91 
92  if( hexsize % 2 )
93  lwerror("Invalid hex string, length (%d) has to be a multiple of two!", hexsize);
94 
95  buf = lwalloc(hexsize/2);
96 
97  if( ! buf )
98  lwerror("Unable to allocate memory buffer.");
99 
100  for( i = 0; i < hexsize/2; i++ )
101  {
102  h1 = hex2char[(int)hexbuf[2*i]];
103  h2 = hex2char[(int)hexbuf[2*i+1]];
104  if( h1 > 15 )
105  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i]);
106  if( h2 > 15 )
107  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i+1]);
108  /* First character is high bits, second is low bits */
109  buf[i] = ((h1 & 0x0F) << 4) | (h2 & 0x0F);
110  }
111  return buf;
112 }
113 
114 
115 /**********************************************************************/
116 
117 
118 
119 
120 
125 static inline void wkb_parse_state_check(wkb_parse_state *s, size_t next)
126 {
127  if( (s->pos + next) > (s->wkb + s->wkb_size) )
128  lwerror("WKB structure does not match expected size!");
129 }
130 
137 {
138  uint32_t wkb_simple_type;
139 
140  LWDEBUG(4, "Entered function");
141 
142  s->has_z = LW_FALSE;
143  s->has_m = LW_FALSE;
144  s->has_srid = LW_FALSE;
145 
146  /* If any of the higher bits are set, this is probably an extended type. */
147  if( wkb_type & 0xF0000000 )
148  {
149  if( wkb_type & WKBZOFFSET ) s->has_z = LW_TRUE;
150  if( wkb_type & WKBMOFFSET ) s->has_m = LW_TRUE;
151  if( wkb_type & WKBSRIDFLAG ) s->has_srid = LW_TRUE;
152  LWDEBUGF(4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
153  }
154 
155  /* Mask off the flags */
156  wkb_type = wkb_type & 0x0FFFFFFF;
157  /* Strip out just the type number (1-12) from the ISO number (eg 3001-3012) */
158  wkb_simple_type = wkb_type % 1000;
159 
160  /* Extract the Z/M information from ISO style numbers */
161  if( wkb_type >= 3000 && wkb_type < 4000 )
162  {
163  s->has_z = LW_TRUE;
164  s->has_m = LW_TRUE;
165  }
166  else if ( wkb_type >= 2000 && wkb_type < 3000 )
167  {
168  s->has_m = LW_TRUE;
169  }
170  else if ( wkb_type >= 1000 && wkb_type < 2000 )
171  {
172  s->has_z = LW_TRUE;
173  }
174 
175  switch (wkb_simple_type)
176  {
177  case WKB_POINT_TYPE:
178  s->lwtype = POINTTYPE;
179  break;
180  case WKB_LINESTRING_TYPE:
181  s->lwtype = LINETYPE;
182  break;
183  case WKB_POLYGON_TYPE:
184  s->lwtype = POLYGONTYPE;
185  break;
186  case WKB_MULTIPOINT_TYPE:
187  s->lwtype = MULTIPOINTTYPE;
188  break;
190  s->lwtype = MULTILINETYPE;
191  break;
194  break;
196  s->lwtype = COLLECTIONTYPE;
197  break;
199  s->lwtype = CIRCSTRINGTYPE;
200  break;
202  s->lwtype = COMPOUNDTYPE;
203  break;
205  s->lwtype = CURVEPOLYTYPE;
206  break;
207  case WKB_MULTICURVE_TYPE:
208  s->lwtype = MULTICURVETYPE;
209  break;
212  break;
215  break;
216  case WKB_TIN_TYPE:
217  s->lwtype = TINTYPE;
218  break;
219  case WKB_TRIANGLE_TYPE:
220  s->lwtype = TRIANGLETYPE;
221  break;
222 
223  /* PostGIS 1.5 emits 13, 14 for CurvePolygon, MultiCurve */
224  /* These numbers aren't SQL/MM (numbers currently only */
225  /* go up to 12. We can handle the old data here (for now??) */
226  /* converting them into the lwtypes that are intended. */
227  case WKB_CURVE_TYPE:
228  s->lwtype = CURVEPOLYTYPE;
229  break;
230  case WKB_SURFACE_TYPE:
231  s->lwtype = MULTICURVETYPE;
232  break;
233 
234  default: /* Error! */
235  lwerror("Unknown WKB type (%d)! Full WKB type number was (%d).", wkb_simple_type, wkb_type);
236  break;
237  }
238 
239  LWDEBUGF(4,"Got lwtype %s (%u)", lwtype_name(s->lwtype), s->lwtype);
240 
241  return;
242 }
243 
249 {
250  char char_value = 0;
251  LWDEBUG(4, "Entered function");
252 
254  LWDEBUG(4, "Passed state check");
255 
256  char_value = s->pos[0];
257  LWDEBUGF(4, "Read byte value: %x", char_value);
258  s->pos += WKB_BYTE_SIZE;
259 
260  return char_value;
261 }
262 
268 {
269  uint32_t i = 0;
270 
272 
273  memcpy(&i, s->pos, WKB_INT_SIZE);
274 
275  /* Swap? Copy into a stack-allocated integer. */
276  if( s->swap_bytes )
277  {
278  int j = 0;
279  uint8_t tmp;
280 
281  for( j = 0; j < WKB_INT_SIZE/2; j++ )
282  {
283  tmp = ((uint8_t*)(&i))[j];
284  ((uint8_t*)(&i))[j] = ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1];
285  ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1] = tmp;
286  }
287  }
288 
289  s->pos += WKB_INT_SIZE;
290  return i;
291 }
292 
298 {
299  double d = 0;
300 
302 
303  memcpy(&d, s->pos, WKB_DOUBLE_SIZE);
304 
305  /* Swap? Copy into a stack-allocated integer. */
306  if( s->swap_bytes )
307  {
308  int i = 0;
309  uint8_t tmp;
310 
311  for( i = 0; i < WKB_DOUBLE_SIZE/2; i++ )
312  {
313  tmp = ((uint8_t*)(&d))[i];
314  ((uint8_t*)(&d))[i] = ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1];
315  ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1] = tmp;
316  }
317 
318  }
319 
320  s->pos += WKB_DOUBLE_SIZE;
321  return d;
322 }
323 
330 {
331  POINTARRAY *pa = NULL;
332  size_t pa_size;
333  uint32_t ndims = 2;
334  uint32_t npoints = 0;
335  static uint32_t maxpoints = 4294967295 / WKB_DOUBLE_SIZE / 4;
336 
337  /* Calculate the size of this point array. */
338  npoints = integer_from_wkb_state(s);
339  if (npoints > maxpoints)
340  {
341  lwerror("point array length (%d) is too large");
342  }
343 
344  LWDEBUGF(4,"Pointarray has %d points", npoints);
345 
346  if( s->has_z ) ndims++;
347  if( s->has_m ) ndims++;
348  pa_size = npoints * ndims * WKB_DOUBLE_SIZE;
349 
350  /* Empty! */
351  if( npoints == 0 )
352  return ptarray_construct(s->has_z, s->has_m, npoints);
353 
354  /* Does the data we want to read exist? */
355  wkb_parse_state_check(s, pa_size);
356 
357  /* If we're in a native endianness, we can just copy the data directly! */
358  if( ! s->swap_bytes )
359  {
360  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
361  s->pos += pa_size;
362  }
363  /* Otherwise we have to read each double, separately. */
364  else
365  {
366  int i = 0;
367  double *dlist;
368  pa = ptarray_construct(s->has_z, s->has_m, npoints);
369  dlist = (double*)(pa->serialized_pointlist);
370  for( i = 0; i < npoints * ndims; i++ )
371  {
372  dlist[i] = double_from_wkb_state(s);
373  }
374  }
375 
376  return pa;
377 }
378 
389 {
390  static uint32_t npoints = 1;
391  POINTARRAY *pa = NULL;
392  size_t pa_size;
393  uint32_t ndims = 2;
394  const POINT2D *pt;
395 
396  /* Count the dimensions. */
397  if( s->has_z ) ndims++;
398  if( s->has_m ) ndims++;
399  pa_size = ndims * WKB_DOUBLE_SIZE;
400 
401  /* Does the data we want to read exist? */
402  wkb_parse_state_check(s, pa_size);
403 
404  /* If we're in a native endianness, we can just copy the data directly! */
405  if( ! s->swap_bytes )
406  {
407  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
408  s->pos += pa_size;
409  }
410  /* Otherwise we have to read each double, separately */
411  else
412  {
413  int i = 0;
414  double *dlist;
415  pa = ptarray_construct(s->has_z, s->has_m, npoints);
416  dlist = (double*)(pa->serialized_pointlist);
417  for( i = 0; i < ndims; i++ )
418  {
419  dlist[i] = double_from_wkb_state(s);
420  }
421  }
422 
423  /* Check for POINT(NaN NaN) ==> POINT EMPTY */
424  pt = getPoint2d_cp(pa, 0);
425  if ( isnan(pt->x) && isnan(pt->y) )
426  {
427  ptarray_free(pa);
428  return lwpoint_construct_empty(s->srid, s->has_z, s->has_m);
429  }
430  else
431  {
432  return lwpoint_construct(s->srid, NULL, pa);
433  }
434 }
435 
445 {
447 
448  if( pa == NULL || pa->npoints == 0 )
449  {
450  ptarray_free(pa);
451  return lwline_construct_empty(s->srid, s->has_z, s->has_m);
452  }
453 
454  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
455  {
456  lwerror("%s must have at least two points", lwtype_name(s->lwtype));
457  return NULL;
458  }
459 
460  return lwline_construct(s->srid, NULL, pa);
461 }
462 
473 {
475 
476  if( pa == NULL || pa->npoints == 0 )
477  return lwcircstring_construct_empty(s->srid, s->has_z, s->has_m);
478 
479  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 3 )
480  {
481  lwerror("%s must have at least three points", lwtype_name(s->lwtype));
482  return NULL;
483  }
484 
485  if( s->check & LW_PARSER_CHECK_ODD && ! (pa->npoints % 2) )
486  {
487  lwerror("%s must have an odd number of points", lwtype_name(s->lwtype));
488  return NULL;
489  }
490 
491  return lwcircstring_construct(s->srid, NULL, pa);
492 }
493 
503 {
504  uint32_t nrings = integer_from_wkb_state(s);
505  int i = 0;
506  LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);
507 
508  LWDEBUGF(4,"Polygon has %d rings", nrings);
509 
510  /* Empty polygon? */
511  if( nrings == 0 )
512  return poly;
513 
514  for( i = 0; i < nrings; i++ )
515  {
517  if( pa == NULL )
518  continue;
519 
520  /* Check for at least four points. */
521  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
522  {
523  LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
524  lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
525  return NULL;
526  }
527 
528  /* Check that first and last points are the same. */
530  {
531  LWDEBUGF(2, "%s must have closed rings", lwtype_name(s->lwtype));
532  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
533  return NULL;
534  }
535 
536  /* Add ring to polygon */
537  if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
538  {
539  LWDEBUG(2, "Unable to add ring to polygon");
540  lwerror("Unable to add ring to polygon");
541  }
542 
543  }
544  return poly;
545 }
546 
556 {
557  uint32_t nrings = integer_from_wkb_state(s);
559  POINTARRAY *pa = NULL;
560 
561  /* Empty triangle? */
562  if( nrings == 0 )
563  return tri;
564 
565  /* Should be only one ring. */
566  if ( nrings != 1 )
567  lwerror("Triangle has wrong number of rings: %d", nrings);
568 
569  /* There's only one ring, we hope? */
570  pa = ptarray_from_wkb_state(s);
571 
572  /* If there's no points, return an empty triangle. */
573  if( pa == NULL )
574  return tri;
575 
576  /* Check for at least four points. */
577  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
578  {
579  LWDEBUGF(2, "%s must have at least four points", lwtype_name(s->lwtype));
580  lwerror("%s must have at least four points", lwtype_name(s->lwtype));
581  return NULL;
582  }
583 
585  {
586  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
587  return NULL;
588  }
589 
590  /* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
591  if (tri->points)
592  ptarray_free(tri->points);
593 
594  tri->points = pa;
595  return tri;
596 }
597 
602 {
603  uint32_t ngeoms = integer_from_wkb_state(s);
605  LWGEOM *geom = NULL;
606  int i;
607 
608  /* Empty collection? */
609  if ( ngeoms == 0 )
610  return cp;
611 
612  for ( i = 0; i < ngeoms; i++ )
613  {
614  geom = lwgeom_from_wkb_state(s);
615  if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
616  {
617  lwgeom_free(geom);
618  lwgeom_free((LWGEOM *)cp);
619  lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
620  return NULL;
621  }
622  }
623 
624  return cp;
625 }
626 
637 {
638  uint32_t ngeoms = integer_from_wkb_state(s);
640  LWGEOM *geom = NULL;
641  int i;
642 
643  LWDEBUGF(4,"Collection has %d components", ngeoms);
644 
645  /* Empty collection? */
646  if ( ngeoms == 0 )
647  return col;
648 
649  /* Be strict in polyhedral surface closures */
650  if ( s->lwtype == POLYHEDRALSURFACETYPE )
652 
653  for ( i = 0; i < ngeoms; i++ )
654  {
655  geom = lwgeom_from_wkb_state(s);
656  if ( lwcollection_add_lwgeom(col, geom) == NULL )
657  {
658  lwgeom_free(geom);
659  lwgeom_free((LWGEOM *)col);
660  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
661  return NULL;
662  }
663  }
664 
665  return col;
666 }
667 
668 
677 {
678  char wkb_little_endian;
679  uint32_t wkb_type;
680 
681  LWDEBUG(4,"Entered function");
682 
683  /* Fail when handed incorrect starting byte */
684  wkb_little_endian = byte_from_wkb_state(s);
685  if( wkb_little_endian != 1 && wkb_little_endian != 0 )
686  {
687  LWDEBUG(4,"Leaving due to bad first byte!");
688  lwerror("Invalid endian flag value encountered.");
689  return NULL;
690  }
691 
692  /* Check the endianness of our input */
693  s->swap_bytes = LW_FALSE;
694  if( getMachineEndian() == NDR ) /* Machine arch is little */
695  {
696  if ( ! wkb_little_endian ) /* Data is big! */
697  s->swap_bytes = LW_TRUE;
698  }
699  else /* Machine arch is big */
700  {
701  if ( wkb_little_endian ) /* Data is little! */
702  s->swap_bytes = LW_TRUE;
703  }
704 
705  /* Read the type number */
706  wkb_type = integer_from_wkb_state(s);
707  LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
708  lwtype_from_wkb_state(s, wkb_type);
709 
710  /* Read the SRID, if necessary */
711  if( s->has_srid )
712  {
714  /* TODO: warn on explicit UNKNOWN srid ? */
715  LWDEBUGF(4,"Got SRID: %u", s->srid);
716  }
717 
718  /* Do the right thing */
719  switch( s->lwtype )
720  {
721  case POINTTYPE:
722  return (LWGEOM*)lwpoint_from_wkb_state(s);
723  break;
724  case LINETYPE:
725  return (LWGEOM*)lwline_from_wkb_state(s);
726  break;
727  case CIRCSTRINGTYPE:
729  break;
730  case POLYGONTYPE:
731  return (LWGEOM*)lwpoly_from_wkb_state(s);
732  break;
733  case TRIANGLETYPE:
734  return (LWGEOM*)lwtriangle_from_wkb_state(s);
735  break;
736  case CURVEPOLYTYPE:
738  break;
739  case MULTIPOINTTYPE:
740  case MULTILINETYPE:
741  case MULTIPOLYGONTYPE:
742  case COMPOUNDTYPE:
743  case MULTICURVETYPE:
744  case MULTISURFACETYPE:
746  case TINTYPE:
747  case COLLECTIONTYPE:
749  break;
750 
751  /* Unknown type! */
752  default:
753  lwerror("Unsupported geometry type: %s [%d]", lwtype_name(s->lwtype), s->lwtype);
754  }
755 
756  /* Return value to keep compiler happy. */
757  return NULL;
758 
759 }
760 
761 /* TODO add check for SRID consistency */
762 
772 LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
773 {
775 
776  /* Initialize the state appropriately */
777  s.wkb = wkb;
778  s.wkb_size = wkb_size;
779  s.swap_bytes = LW_FALSE;
780  s.check = check;
781  s.lwtype = 0;
782  s.srid = SRID_UNKNOWN;
783  s.has_z = LW_FALSE;
784  s.has_m = LW_FALSE;
785  s.has_srid = LW_FALSE;
786  s.pos = wkb;
787 
788  /* Hand the check catch-all values */
789  if ( check & LW_PARSER_CHECK_NONE )
790  s.check = 0;
791  else
792  s.check = check;
793 
794  return lwgeom_from_wkb_state(&s);
795 }
796 
797 LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
798 {
799  int hexwkb_len;
800  uint8_t *wkb;
801  LWGEOM *lwgeom;
802 
803  if ( ! hexwkb )
804  {
805  lwerror("lwgeom_from_hexwkb: null input");
806  return NULL;
807  }
808 
809  hexwkb_len = strlen(hexwkb);
810  wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
811  lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
812  lwfree(wkb);
813  return lwgeom;
814 }
#define WKB_SURFACE_TYPE
#define LINETYPE
Definition: liblwgeom.h:86
#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:329
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:380
#define WKB_BYTE_SIZE
#define WKBMOFFSET
Definition: liblwgeom.h:108
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:136
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:797
POINTARRAY * points
Definition: liblwgeom.h:433
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:64
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:555
#define MULTICURVETYPE
Definition: liblwgeom.h:95
uint8_t * serialized_pointlist
Definition: liblwgeom.h:366
static LWCURVEPOLY * lwcurvepoly_from_wkb_state(wkb_parse_state *s)
CURVEPOLYTYPE.
Definition: lwin_wkb.c:601
void lwfree(void *mem)
Definition: lwutil.c:244
LWTRIANGLE * lwtriangle_construct_empty(int srid, char hasz, char hasm)
Definition: lwtriangle.c:58
static char byte_from_wkb_state(wkb_parse_state *s)
Byte Read a byte and advance the parse state forward.
Definition: lwin_wkb.c:248
int npoints
Definition: liblwgeom.h:371
static LWCOLLECTION * lwcollection_from_wkb_state(wkb_parse_state *s)
POLYHEDRALSURFACETYPE.
Definition: lwin_wkb.c:636
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:267
uint8_t * bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
Definition: lwin_wkb.c:86
#define WKB_COMPOUNDCURVE_TYPE
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:2008
#define WKB_POLYHEDRALSURFACE_TYPE
uint32_t lwtype
Definition: lwin_wkb.c:41
#define POLYGONTYPE
Definition: liblwgeom.h:87
#define CURVEPOLYTYPE
Definition: liblwgeom.h:94
#define WKB_TRIANGLE_TYPE
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1099
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:772
#define COMPOUNDTYPE
Definition: liblwgeom.h:93
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
#define WKB_MULTISURFACE_TYPE
#define NDR
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:723
#define WKB_DOUBLE_SIZE
Well-Known Binary (WKB) Output Variant Types.
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define TRIANGLETYPE
Definition: liblwgeom.h:98
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:97
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:502
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:151
const uint8_t * wkb
Definition: lwin_wkb.c:37
#define WKB_MULTICURVE_TYPE
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:697
#define LW_FAILURE
Definition: liblwgeom.h:79
unsigned int uint32_t
Definition: uthash.h:78
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2013
double x
Definition: liblwgeom.h:328
#define LW_PARSER_CHECK_ZCLOSURE
Definition: liblwgeom.h:2011
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:2009
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
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:472
#define WKBZOFFSET
Flags applied in EWKB to indicate Z/M dimensions and presence/absence of SRID and bounding boxes...
Definition: liblwgeom.h:107
size_t wkb_size
Definition: lwin_wkb.c:38
#define WKB_POLYGON_TYPE
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm)
Definition: lwcircstring.c:80
static uint8_t hex2char[256]
Definition: lwin_wkb.c:60
#define LW_FALSE
Definition: liblwgeom.h:77
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:373
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
#define TINTYPE
Definition: liblwgeom.h:99
#define WKBSRIDFLAG
Definition: liblwgeom.h:109
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:36
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:125
#define WKB_POINT_TYPE
Well-Known Binary (WKB) Geometry Types.
double y
Definition: liblwgeom.h:328
char * s
Definition: cu_in_wkt.c:23
#define WKB_LINESTRING_TYPE
char getMachineEndian(void)
Definition: lwutil.c:360
#define WKB_CIRCULARSTRING_TYPE
#define WKB_MULTIPOLYGON_TYPE
#define WKB_CURVEPOLYGON_TYPE
LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:51
#define WKB_MULTILINESTRING_TYPE
#define WKB_TIN_TYPE
LWGEOM * lwgeom_from_wkb_state(wkb_parse_state *s)
Internal function declarations.
Definition: lwin_wkb.c:676
uint32_t srid
Definition: lwin_wkb.c:42
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
#define WKB_CURVE_TYPE
#define MULTISURFACETYPE
Definition: liblwgeom.h:96
Used for passing the parse state between the parsing functions.
Definition: lwin_wkb.c:35
#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:444
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:161
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
Add a ring, allocating extra space if necessary.
Definition: lwcurvepoly.c:72
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:249
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:92
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
void * lwalloc(size_t size)
Definition: lwutil.c:229
#define MULTILINETYPE
Definition: liblwgeom.h:89
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
unsigned char uint8_t
Definition: uthash.h:79
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:388
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
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:297
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
#define LW_PARSER_CHECK_CLOSURE
Definition: liblwgeom.h:2010
const uint8_t * pos
Definition: lwin_wkb.c:46
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
#define WKB_GEOMETRYCOLLECTION_TYPE