PostGIS  2.5.0dev-r@@SVN_REVISION@@
lwin_wkb.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2009 Paul Ramsey <pramsey@cleverelephant.ca>
22  *
23  **********************************************************************/
24 
25 
26 #include "../postgis_config.h"
27 /*#define POSTGIS_DEBUG_LEVEL 4*/
28 #include "liblwgeom_internal.h" /* NOTE: includes lwgeom_log.h */
29 #include "lwgeom_log.h"
30 #include <math.h>
31 #include <limits.h>
32 
36 typedef struct
37 {
38  const uint8_t *wkb; /* Points to start of WKB */
39  size_t wkb_size; /* Expected size of WKB */
40  int swap_bytes; /* Do an endian flip? */
41  int check; /* Simple validity checks on geometries */
42  uint32_t lwtype; /* Current type we are handling */
43  uint32_t srid; /* Current SRID we are handling */
44  int has_z; /* Z? */
45  int has_m; /* M? */
46  int has_srid; /* SRID? */
47  const uint8_t *pos; /* Current parse position */
49 
50 
55 
56 
57 
58 /**********************************************************************/
59 
60 /* Our static character->number map. Anything > 15 is invalid */
61 static uint8_t hex2char[256] = {
62  /* not Hex characters */
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  /* 0-9 */
67  0,1,2,3,4,5,6,7,8,9,20,20,20,20,20,20,
68  /* A-F */
69  20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
70  /* not Hex characters */
71  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
72  /* a-f */
73  20,10,11,12,13,14,15,20,20,20,20,20,20,20,20,20,
74  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
75  /* not Hex characters (upper 128 characters) */
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  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20
84  };
85 
86 
87 uint8_t* bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
88 {
89  uint8_t *buf = NULL;
90  register uint8_t h1, h2;
91  uint32_t i;
92 
93  if( hexsize % 2 )
94  lwerror("Invalid hex string, length (%d) has to be a multiple of two!", hexsize);
95 
96  buf = lwalloc(hexsize/2);
97 
98  if( ! buf )
99  lwerror("Unable to allocate memory buffer.");
100 
101  for( i = 0; i < hexsize/2; i++ )
102  {
103  h1 = hex2char[(int)hexbuf[2*i]];
104  h2 = hex2char[(int)hexbuf[2*i+1]];
105  if( h1 > 15 )
106  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i]);
107  if( h2 > 15 )
108  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i+1]);
109  /* First character is high bits, second is low bits */
110  buf[i] = ((h1 & 0x0F) << 4) | (h2 & 0x0F);
111  }
112  return buf;
113 }
114 
115 
116 /**********************************************************************/
117 
118 
119 
120 
121 
126 static inline void wkb_parse_state_check(wkb_parse_state *s, size_t next)
127 {
128  if( (s->pos + next) > (s->wkb + s->wkb_size) )
129  {
130  lwerror("WKB structure does not match expected size!");
131  return;
132  }
133 }
134 
141 {
142  uint32_t wkb_simple_type;
143 
144  LWDEBUG(4, "Entered function");
145 
146  s->has_z = LW_FALSE;
147  s->has_m = LW_FALSE;
148  s->has_srid = LW_FALSE;
149 
150  /* If any of the higher bits are set, this is probably an extended type. */
151  if( wkb_type & 0xF0000000 )
152  {
153  if( wkb_type & WKBZOFFSET ) s->has_z = LW_TRUE;
154  if( wkb_type & WKBMOFFSET ) s->has_m = LW_TRUE;
155  if( wkb_type & WKBSRIDFLAG ) s->has_srid = LW_TRUE;
156  LWDEBUGF(4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
157  }
158 
159  /* Mask off the flags */
160  wkb_type = wkb_type & 0x0FFFFFFF;
161  /* Strip out just the type number (1-12) from the ISO number (eg 3001-3012) */
162  wkb_simple_type = wkb_type % 1000;
163 
164  /* Extract the Z/M information from ISO style numbers */
165  if( wkb_type >= 3000 && wkb_type < 4000 )
166  {
167  s->has_z = LW_TRUE;
168  s->has_m = LW_TRUE;
169  }
170  else if ( wkb_type >= 2000 && wkb_type < 3000 )
171  {
172  s->has_m = LW_TRUE;
173  }
174  else if ( wkb_type >= 1000 && wkb_type < 2000 )
175  {
176  s->has_z = LW_TRUE;
177  }
178 
179  switch (wkb_simple_type)
180  {
181  case WKB_POINT_TYPE:
182  s->lwtype = POINTTYPE;
183  break;
184  case WKB_LINESTRING_TYPE:
185  s->lwtype = LINETYPE;
186  break;
187  case WKB_POLYGON_TYPE:
188  s->lwtype = POLYGONTYPE;
189  break;
190  case WKB_MULTIPOINT_TYPE:
191  s->lwtype = MULTIPOINTTYPE;
192  break;
194  s->lwtype = MULTILINETYPE;
195  break;
198  break;
200  s->lwtype = COLLECTIONTYPE;
201  break;
203  s->lwtype = CIRCSTRINGTYPE;
204  break;
206  s->lwtype = COMPOUNDTYPE;
207  break;
209  s->lwtype = CURVEPOLYTYPE;
210  break;
211  case WKB_MULTICURVE_TYPE:
212  s->lwtype = MULTICURVETYPE;
213  break;
216  break;
219  break;
220  case WKB_TIN_TYPE:
221  s->lwtype = TINTYPE;
222  break;
223  case WKB_TRIANGLE_TYPE:
224  s->lwtype = TRIANGLETYPE;
225  break;
226 
227  /* PostGIS 1.5 emits 13, 14 for CurvePolygon, MultiCurve */
228  /* These numbers aren't SQL/MM (numbers currently only */
229  /* go up to 12. We can handle the old data here (for now??) */
230  /* converting them into the lwtypes that are intended. */
231  case WKB_CURVE_TYPE:
232  s->lwtype = CURVEPOLYTYPE;
233  break;
234  case WKB_SURFACE_TYPE:
235  s->lwtype = MULTICURVETYPE;
236  break;
237 
238  default: /* Error! */
239  lwerror("Unknown WKB type (%d)! Full WKB type number was (%d).", wkb_simple_type, wkb_type);
240  break;
241  }
242 
243  LWDEBUGF(4,"Got lwtype %s (%u)", lwtype_name(s->lwtype), s->lwtype);
244 
245  return;
246 }
247 
253 {
254  char char_value = 0;
255  LWDEBUG(4, "Entered function");
256 
258  LWDEBUG(4, "Passed state check");
259 
260  char_value = s->pos[0];
261  LWDEBUGF(4, "Read byte value: %x", char_value);
262  s->pos += WKB_BYTE_SIZE;
263 
264  return char_value;
265 }
266 
272 {
273  uint32_t i = 0;
274 
276 
277  memcpy(&i, s->pos, WKB_INT_SIZE);
278 
279  /* Swap? Copy into a stack-allocated integer. */
280  if( s->swap_bytes )
281  {
282  int j = 0;
283  uint8_t tmp;
284 
285  for( j = 0; j < WKB_INT_SIZE/2; j++ )
286  {
287  tmp = ((uint8_t*)(&i))[j];
288  ((uint8_t*)(&i))[j] = ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1];
289  ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1] = tmp;
290  }
291  }
292 
293  s->pos += WKB_INT_SIZE;
294  return i;
295 }
296 
302 {
303  double d = 0;
304 
306 
307  memcpy(&d, s->pos, WKB_DOUBLE_SIZE);
308 
309  /* Swap? Copy into a stack-allocated integer. */
310  if( s->swap_bytes )
311  {
312  int i = 0;
313  uint8_t tmp;
314 
315  for( i = 0; i < WKB_DOUBLE_SIZE/2; i++ )
316  {
317  tmp = ((uint8_t*)(&d))[i];
318  ((uint8_t*)(&d))[i] = ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1];
319  ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1] = tmp;
320  }
321 
322  }
323 
324  s->pos += WKB_DOUBLE_SIZE;
325  return d;
326 }
327 
334 {
335  POINTARRAY *pa = NULL;
336  size_t pa_size;
337  uint32_t ndims = 2;
338  uint32_t npoints = 0;
339  static uint32_t maxpoints = UINT_MAX / WKB_DOUBLE_SIZE / 4;
340 
341  /* Calculate the size of this point array. */
342  npoints = integer_from_wkb_state(s);
343  if (npoints > maxpoints)
344  {
345  lwerror("Pointarray length (%d) is too large");
346  return NULL;
347  }
348 
349  LWDEBUGF(4,"Pointarray has %d points", npoints);
350 
351  if( s->has_z ) ndims++;
352  if( s->has_m ) ndims++;
353  pa_size = npoints * ndims * WKB_DOUBLE_SIZE;
354 
355  /* Empty! */
356  if( npoints == 0 )
357  return ptarray_construct(s->has_z, s->has_m, npoints);
358 
359  /* Does the data we want to read exist? */
360  wkb_parse_state_check(s, pa_size);
361 
362  /* If we're in a native endianness, we can just copy the data directly! */
363  if( ! s->swap_bytes )
364  {
365  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
366  s->pos += pa_size;
367  }
368  /* Otherwise we have to read each double, separately. */
369  else
370  {
371  uint32_t i = 0;
372  double *dlist;
373  pa = ptarray_construct(s->has_z, s->has_m, npoints);
374  dlist = (double*)(pa->serialized_pointlist);
375  for( i = 0; i < npoints * ndims; i++ )
376  {
377  dlist[i] = double_from_wkb_state(s);
378  }
379  }
380 
381  return pa;
382 }
383 
394 {
395  static uint32_t npoints = 1;
396  POINTARRAY *pa = NULL;
397  size_t pa_size;
398  uint32_t ndims = 2;
399  const POINT2D *pt;
400 
401  /* Count the dimensions. */
402  if( s->has_z ) ndims++;
403  if( s->has_m ) ndims++;
404  pa_size = ndims * WKB_DOUBLE_SIZE;
405 
406  /* Does the data we want to read exist? */
407  wkb_parse_state_check(s, pa_size);
408 
409  /* If we're in a native endianness, we can just copy the data directly! */
410  if( ! s->swap_bytes )
411  {
412  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
413  s->pos += pa_size;
414  }
415  /* Otherwise we have to read each double, separately */
416  else
417  {
418  uint32_t i = 0;
419  double *dlist;
420  pa = ptarray_construct(s->has_z, s->has_m, npoints);
421  dlist = (double*)(pa->serialized_pointlist);
422  for( i = 0; i < ndims; i++ )
423  {
424  dlist[i] = double_from_wkb_state(s);
425  }
426  }
427 
428  /* Check for POINT(NaN NaN) ==> POINT EMPTY */
429  pt = getPoint2d_cp(pa, 0);
430  if ( isnan(pt->x) && isnan(pt->y) )
431  {
432  ptarray_free(pa);
433  return lwpoint_construct_empty(s->srid, s->has_z, s->has_m);
434  }
435  else
436  {
437  return lwpoint_construct(s->srid, NULL, pa);
438  }
439 }
440 
450 {
452 
453  if( pa == NULL || pa->npoints == 0 )
454  {
455  ptarray_free(pa);
456  return lwline_construct_empty(s->srid, s->has_z, s->has_m);
457  }
458 
459  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
460  {
461  lwerror("%s must have at least two points", lwtype_name(s->lwtype));
462  return NULL;
463  }
464 
465  return lwline_construct(s->srid, NULL, pa);
466 }
467 
478 {
480 
481  if( pa == NULL || pa->npoints == 0 )
482  return lwcircstring_construct_empty(s->srid, s->has_z, s->has_m);
483 
484  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 3 )
485  {
486  lwerror("%s must have at least three points", lwtype_name(s->lwtype));
487  return NULL;
488  }
489 
490  if( s->check & LW_PARSER_CHECK_ODD && ! (pa->npoints % 2) )
491  {
492  lwerror("%s must have an odd number of points", lwtype_name(s->lwtype));
493  return NULL;
494  }
495 
496  return lwcircstring_construct(s->srid, NULL, pa);
497 }
498 
508 {
509  uint32_t nrings = integer_from_wkb_state(s);
510  uint32_t i = 0;
511  LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);
512 
513  LWDEBUGF(4,"Polygon has %d rings", nrings);
514 
515  /* Empty polygon? */
516  if( nrings == 0 )
517  return poly;
518 
519  for( i = 0; i < nrings; i++ )
520  {
522  if( pa == NULL )
523  continue;
524 
525  /* Check for at least four points. */
526  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
527  {
528  LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
529  lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
530  return NULL;
531  }
532 
533  /* Check that first and last points are the same. */
535  {
536  LWDEBUGF(2, "%s must have closed rings", lwtype_name(s->lwtype));
537  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
538  return NULL;
539  }
540 
541  /* Add ring to polygon */
542  if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
543  {
544  LWDEBUG(2, "Unable to add ring to polygon");
545  lwerror("Unable to add ring to polygon");
546  }
547 
548  }
549  return poly;
550 }
551 
561 {
562  uint32_t nrings = integer_from_wkb_state(s);
564  POINTARRAY *pa = NULL;
565 
566  /* Empty triangle? */
567  if( nrings == 0 )
568  return tri;
569 
570  /* Should be only one ring. */
571  if ( nrings != 1 )
572  lwerror("Triangle has wrong number of rings: %d", nrings);
573 
574  /* There's only one ring, we hope? */
575  pa = ptarray_from_wkb_state(s);
576 
577  /* If there's no points, return an empty triangle. */
578  if( pa == NULL )
579  return tri;
580 
581  /* Check for at least four points. */
582  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
583  {
584  LWDEBUGF(2, "%s must have at least four points", lwtype_name(s->lwtype));
585  lwerror("%s must have at least four points", lwtype_name(s->lwtype));
586  return NULL;
587  }
588 
590  {
591  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
592  return NULL;
593  }
594 
595  /* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
596  if (tri->points)
597  ptarray_free(tri->points);
598 
599  tri->points = pa;
600  return tri;
601 }
602 
607 {
608  uint32_t ngeoms = integer_from_wkb_state(s);
610  LWGEOM *geom = NULL;
611  uint32_t i;
612 
613  /* Empty collection? */
614  if ( ngeoms == 0 )
615  return cp;
616 
617  for ( i = 0; i < ngeoms; i++ )
618  {
619  geom = lwgeom_from_wkb_state(s);
620  if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
621  lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
622  }
623 
624  return cp;
625 }
626 
637 {
638  uint32_t ngeoms = integer_from_wkb_state(s);
640  LWGEOM *geom = NULL;
641  uint32_t 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  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
659  return NULL;
660  }
661  }
662 
663  return col;
664 }
665 
666 
675 {
676  char wkb_little_endian;
677  uint32_t wkb_type;
678 
679  LWDEBUG(4,"Entered function");
680 
681  /* Fail when handed incorrect starting byte */
682  wkb_little_endian = byte_from_wkb_state(s);
683  if( wkb_little_endian != 1 && wkb_little_endian != 0 )
684  {
685  LWDEBUG(4,"Leaving due to bad first byte!");
686  lwerror("Invalid endian flag value encountered.");
687  return NULL;
688  }
689 
690  /* Check the endianness of our input */
691  s->swap_bytes = LW_FALSE;
692  if( getMachineEndian() == NDR ) /* Machine arch is little */
693  {
694  if ( ! wkb_little_endian ) /* Data is big! */
695  s->swap_bytes = LW_TRUE;
696  }
697  else /* Machine arch is big */
698  {
699  if ( wkb_little_endian ) /* Data is little! */
700  s->swap_bytes = LW_TRUE;
701  }
702 
703  /* Read the type number */
704  wkb_type = integer_from_wkb_state(s);
705  LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
706  lwtype_from_wkb_state(s, wkb_type);
707 
708  /* Read the SRID, if necessary */
709  if( s->has_srid )
710  {
712  /* TODO: warn on explicit UNKNOWN srid ? */
713  LWDEBUGF(4,"Got SRID: %u", s->srid);
714  }
715 
716  /* Do the right thing */
717  switch( s->lwtype )
718  {
719  case POINTTYPE:
720  return (LWGEOM*)lwpoint_from_wkb_state(s);
721  break;
722  case LINETYPE:
723  return (LWGEOM*)lwline_from_wkb_state(s);
724  break;
725  case CIRCSTRINGTYPE:
727  break;
728  case POLYGONTYPE:
729  return (LWGEOM*)lwpoly_from_wkb_state(s);
730  break;
731  case TRIANGLETYPE:
732  return (LWGEOM*)lwtriangle_from_wkb_state(s);
733  break;
734  case CURVEPOLYTYPE:
736  break;
737  case MULTIPOINTTYPE:
738  case MULTILINETYPE:
739  case MULTIPOLYGONTYPE:
740  case COMPOUNDTYPE:
741  case MULTICURVETYPE:
742  case MULTISURFACETYPE:
744  case TINTYPE:
745  case COLLECTIONTYPE:
747  break;
748 
749  /* Unknown type! */
750  default:
751  lwerror("Unsupported geometry type: %s [%d]", lwtype_name(s->lwtype), s->lwtype);
752  }
753 
754  /* Return value to keep compiler happy. */
755  return NULL;
756 
757 }
758 
759 /* TODO add check for SRID consistency */
760 
770 LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
771 {
773 
774  /* Initialize the state appropriately */
775  s.wkb = wkb;
776  s.wkb_size = wkb_size;
777  s.swap_bytes = LW_FALSE;
778  s.check = check;
779  s.lwtype = 0;
780  s.srid = SRID_UNKNOWN;
781  s.has_z = LW_FALSE;
782  s.has_m = LW_FALSE;
783  s.has_srid = LW_FALSE;
784  s.pos = wkb;
785 
786  return lwgeom_from_wkb_state(&s);
787 }
788 
789 LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
790 {
791  int hexwkb_len;
792  uint8_t *wkb;
793  LWGEOM *lwgeom;
794 
795  if ( ! hexwkb )
796  {
797  lwerror("lwgeom_from_hexwkb: null input");
798  return NULL;
799  }
800 
801  hexwkb_len = strlen(hexwkb);
802  wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
803  lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
804  lwfree(wkb);
805  return lwgeom;
806 }
#define WKB_SURFACE_TYPE
#define LINETYPE
Definition: liblwgeom.h:85
#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:333
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:347
#define WKB_BYTE_SIZE
#define WKBMOFFSET
Definition: liblwgeom.h:107
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:140
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:789
POINTARRAY * points
Definition: liblwgeom.h:432
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:560
#define MULTICURVETYPE
Definition: liblwgeom.h:94
uint8_t * serialized_pointlist
Definition: liblwgeom.h:365
static LWCURVEPOLY * lwcurvepoly_from_wkb_state(wkb_parse_state *s)
CURVEPOLYTYPE.
Definition: lwin_wkb.c:606
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:252
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:271
uint8_t * bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
Definition: lwin_wkb.c:87
#define WKB_COMPOUNDCURVE_TYPE
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:1993
#define WKB_POLYHEDRALSURFACE_TYPE
uint32_t lwtype
Definition: lwin_wkb.c:42
#define POLYGONTYPE
Definition: liblwgeom.h:86
#define CURVEPOLYTYPE
Definition: liblwgeom.h:93
#define WKB_TRIANGLE_TYPE
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:328
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:770
#define COMPOUNDTYPE
Definition: liblwgeom.h:92
#define MULTIPOINTTYPE
Definition: liblwgeom.h:87
#define WKB_MULTISURFACE_TYPE
#define NDR
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:714
#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:97
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:96
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:507
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:151
const uint8_t * wkb
Definition: lwin_wkb.c:38
#define WKB_MULTICURVE_TYPE
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:688
#define LW_FAILURE
Definition: liblwgeom.h:78
unsigned int uint32_t
Definition: uthash.h:78
double x
Definition: liblwgeom.h:327
#define LW_PARSER_CHECK_ZCLOSURE
Definition: liblwgeom.h:1996
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:1994
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:477
#define WKBZOFFSET
Flags applied in EWKB to indicate Z/M dimensions and presence/absence of SRID and bounding boxes...
Definition: liblwgeom.h:106
size_t wkb_size
Definition: lwin_wkb.c:39
#define WKB_POLYGON_TYPE
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm)
Definition: lwcircstring.c:79
static uint8_t hex2char[256]
Definition: lwin_wkb.c:61
#define LW_FALSE
Definition: liblwgeom.h:76
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:187
#define TINTYPE
Definition: liblwgeom.h:98
#define WKBSRIDFLAG
Definition: liblwgeom.h:108
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:307
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:126
#define WKB_POINT_TYPE
Well-Known Binary (WKB) Geometry Types.
double y
Definition: liblwgeom.h:327
char * s
Definition: cu_in_wkt.c:23
#define WKB_LINESTRING_TYPE
char getMachineEndian(void)
Definition: lwutil.c:327
#define WKB_CIRCULARSTRING_TYPE
#define WKB_MULTIPOLYGON_TYPE
#define WKB_CURVEPOLYGON_TYPE
LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:50
#define WKB_MULTILINESTRING_TYPE
#define WKB_TIN_TYPE
LWGEOM * lwgeom_from_wkb_state(wkb_parse_state *s)
Internal function declarations.
Definition: lwin_wkb.c:674
uint32_t srid
Definition: lwin_wkb.c:43
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:89
#define WKB_CURVE_TYPE
#define MULTISURFACETYPE
Definition: liblwgeom.h:95
Used for passing the parse state between the parsing functions.
Definition: lwin_wkb.c:36
#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:449
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:159
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:245
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:91
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:88
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:393
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:301
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:1995
const uint8_t * pos
Definition: lwin_wkb.c:47
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
#define WKB_GEOMETRYCOLLECTION_TYPE
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:364
uint32_t npoints
Definition: liblwgeom.h:370