PostGIS  2.5.7dev-r@@SVN_REVISION@@
lwin_wkb.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2009 Paul Ramsey <pramsey@cleverelephant.ca>
22  *
23  **********************************************************************/
24 
25 
26 #include "../postgis_config.h"
27 /*#define POSTGIS_DEBUG_LEVEL 4*/
28 #include "liblwgeom_internal.h" /* NOTE: includes lwgeom_log.h */
29 #include "lwgeom_log.h"
30 #include <math.h>
31 #include <limits.h>
32 
34 #define LW_PARSER_MAX_DEPTH 200
35 
39 typedef struct
40 {
41  const uint8_t *wkb; /* Points to start of WKB */
42  size_t wkb_size; /* Expected size of WKB */
43  int swap_bytes; /* Do an endian flip? */
44  int check; /* Simple validity checks on geometries */
45  uint32_t lwtype; /* Current type we are handling */
46  uint32_t srid; /* Current SRID we are handling */
47  int has_z; /* Z? */
48  int has_m; /* M? */
49  int has_srid; /* SRID? */
50  uint8_t depth; /* Current recursion level (to prevent stack overflows). Maxes at LW_PARSER_MAX_DEPTH */
51  const uint8_t *pos; /* Current parse position */
53 
54 
59 
60 
61 
62 /**********************************************************************/
63 
64 /* Our static character->number map. Anything > 15 is invalid */
65 static uint8_t hex2char[256] = {
66  /* not Hex characters */
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  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
70  /* 0-9 */
71  0,1,2,3,4,5,6,7,8,9,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  /* not Hex characters */
75  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
76  /* a-f */
77  20,10,11,12,13,14,15,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  /* not Hex characters (upper 128 characters) */
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  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
85  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
86  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
87  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20
88  };
89 
90 
91 uint8_t* bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
92 {
93  uint8_t *buf = NULL;
94  register uint8_t h1, h2;
95  uint32_t i;
96 
97  if( hexsize % 2 )
98  lwerror("Invalid hex string, length (%d) has to be a multiple of two!", hexsize);
99 
100  buf = lwalloc(hexsize/2);
101 
102  if( ! buf )
103  lwerror("Unable to allocate memory buffer.");
104 
105  for( i = 0; i < hexsize/2; i++ )
106  {
107  h1 = hex2char[(int)hexbuf[2*i]];
108  h2 = hex2char[(int)hexbuf[2*i+1]];
109  if( h1 > 15 )
110  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i]);
111  if( h2 > 15 )
112  lwerror("Invalid hex character (%c) encountered", hexbuf[2*i+1]);
113  /* First character is high bits, second is low bits */
114  buf[i] = ((h1 & 0x0F) << 4) | (h2 & 0x0F);
115  }
116  return buf;
117 }
118 
119 
120 /**********************************************************************/
121 
122 
123 
124 
125 
130 static inline void wkb_parse_state_check(wkb_parse_state *s, size_t next)
131 {
132  if( (s->pos + next) > (s->wkb + s->wkb_size) )
133  {
134  lwerror("WKB structure does not match expected size!");
135  return;
136  }
137 }
138 
145 {
146  uint32_t wkb_simple_type;
147 
148  LWDEBUG(4, "Entered function");
149 
150  s->has_z = LW_FALSE;
151  s->has_m = LW_FALSE;
152  s->has_srid = LW_FALSE;
153 
154  /* If any of the higher bits are set, this is probably an extended type. */
155  if( wkb_type & 0xF0000000 )
156  {
157  if( wkb_type & WKBZOFFSET ) s->has_z = LW_TRUE;
158  if( wkb_type & WKBMOFFSET ) s->has_m = LW_TRUE;
159  if( wkb_type & WKBSRIDFLAG ) s->has_srid = LW_TRUE;
160  LWDEBUGF(4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
161  }
162 
163  /* Mask off the flags */
164  wkb_type = wkb_type & 0x0FFFFFFF;
165  /* Strip out just the type number (1-12) from the ISO number (eg 3001-3012) */
166  wkb_simple_type = wkb_type % 1000;
167 
168  /* Extract the Z/M information from ISO style numbers */
169  if( wkb_type >= 3000 && wkb_type < 4000 )
170  {
171  s->has_z = LW_TRUE;
172  s->has_m = LW_TRUE;
173  }
174  else if ( wkb_type >= 2000 && wkb_type < 3000 )
175  {
176  s->has_m = LW_TRUE;
177  }
178  else if ( wkb_type >= 1000 && wkb_type < 2000 )
179  {
180  s->has_z = LW_TRUE;
181  }
182 
183  switch (wkb_simple_type)
184  {
185  case WKB_POINT_TYPE:
186  s->lwtype = POINTTYPE;
187  break;
188  case WKB_LINESTRING_TYPE:
189  s->lwtype = LINETYPE;
190  break;
191  case WKB_POLYGON_TYPE:
192  s->lwtype = POLYGONTYPE;
193  break;
194  case WKB_MULTIPOINT_TYPE:
195  s->lwtype = MULTIPOINTTYPE;
196  break;
198  s->lwtype = MULTILINETYPE;
199  break;
201  s->lwtype = MULTIPOLYGONTYPE;
202  break;
204  s->lwtype = COLLECTIONTYPE;
205  break;
207  s->lwtype = CIRCSTRINGTYPE;
208  break;
210  s->lwtype = COMPOUNDTYPE;
211  break;
213  s->lwtype = CURVEPOLYTYPE;
214  break;
215  case WKB_MULTICURVE_TYPE:
216  s->lwtype = MULTICURVETYPE;
217  break;
219  s->lwtype = MULTISURFACETYPE;
220  break;
222  s->lwtype = POLYHEDRALSURFACETYPE;
223  break;
224  case WKB_TIN_TYPE:
225  s->lwtype = TINTYPE;
226  break;
227  case WKB_TRIANGLE_TYPE:
228  s->lwtype = TRIANGLETYPE;
229  break;
230 
231  /* PostGIS 1.5 emits 13, 14 for CurvePolygon, MultiCurve */
232  /* These numbers aren't SQL/MM (numbers currently only */
233  /* go up to 12. We can handle the old data here (for now??) */
234  /* converting them into the lwtypes that are intended. */
235  case WKB_CURVE_TYPE:
236  s->lwtype = CURVEPOLYTYPE;
237  break;
238  case WKB_SURFACE_TYPE:
239  s->lwtype = MULTICURVETYPE;
240  break;
241 
242  default: /* Error! */
243  lwerror("Unknown WKB type (%d)! Full WKB type number was (%d).", wkb_simple_type, wkb_type);
244  break;
245  }
246 
247  LWDEBUGF(4,"Got lwtype %s (%u)", lwtype_name(s->lwtype), s->lwtype);
248 
249  return;
250 }
251 
257 {
258  char char_value = 0;
259  LWDEBUG(4, "Entered function");
260 
262  LWDEBUG(4, "Passed state check");
263 
264  char_value = s->pos[0];
265  LWDEBUGF(4, "Read byte value: %x", char_value);
266  s->pos += WKB_BYTE_SIZE;
267 
268  return char_value;
269 }
270 
276 {
277  uint32_t i = 0;
278 
280 
281  memcpy(&i, s->pos, WKB_INT_SIZE);
282 
283  /* Swap? Copy into a stack-allocated integer. */
284  if( s->swap_bytes )
285  {
286  int j = 0;
287  uint8_t tmp;
288 
289  for( j = 0; j < WKB_INT_SIZE/2; j++ )
290  {
291  tmp = ((uint8_t*)(&i))[j];
292  ((uint8_t*)(&i))[j] = ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1];
293  ((uint8_t*)(&i))[WKB_INT_SIZE - j - 1] = tmp;
294  }
295  }
296 
297  s->pos += WKB_INT_SIZE;
298  return i;
299 }
300 
306 {
307  double d = 0;
308 
310 
311  memcpy(&d, s->pos, WKB_DOUBLE_SIZE);
312 
313  /* Swap? Copy into a stack-allocated integer. */
314  if( s->swap_bytes )
315  {
316  int i = 0;
317  uint8_t tmp;
318 
319  for( i = 0; i < WKB_DOUBLE_SIZE/2; i++ )
320  {
321  tmp = ((uint8_t*)(&d))[i];
322  ((uint8_t*)(&d))[i] = ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1];
323  ((uint8_t*)(&d))[WKB_DOUBLE_SIZE - i - 1] = tmp;
324  }
325 
326  }
327 
328  s->pos += WKB_DOUBLE_SIZE;
329  return d;
330 }
331 
338 {
339  POINTARRAY *pa = NULL;
340  size_t pa_size;
341  uint32_t ndims = 2;
342  uint32_t npoints = 0;
343  static uint32_t maxpoints = UINT_MAX / WKB_DOUBLE_SIZE / 4;
344 
345  /* Calculate the size of this point array. */
346  npoints = integer_from_wkb_state(s);
347  if (npoints > maxpoints)
348  {
349  lwerror("Pointarray length (%d) is too large");
350  return NULL;
351  }
352 
353  LWDEBUGF(4,"Pointarray has %d points", npoints);
354 
355  if( s->has_z ) ndims++;
356  if( s->has_m ) ndims++;
357  pa_size = npoints * ndims * WKB_DOUBLE_SIZE;
358 
359  /* Empty! */
360  if( npoints == 0 )
361  return ptarray_construct(s->has_z, s->has_m, npoints);
362 
363  /* Does the data we want to read exist? */
364  wkb_parse_state_check(s, pa_size);
365 
366  /* If we're in a native endianness, we can just copy the data directly! */
367  if( ! s->swap_bytes )
368  {
369  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
370  s->pos += pa_size;
371  }
372  /* Otherwise we have to read each double, separately. */
373  else
374  {
375  uint32_t i = 0;
376  double *dlist;
377  pa = ptarray_construct(s->has_z, s->has_m, npoints);
378  dlist = (double*)(pa->serialized_pointlist);
379  for( i = 0; i < npoints * ndims; i++ )
380  {
381  dlist[i] = double_from_wkb_state(s);
382  }
383  }
384 
385  return pa;
386 }
387 
398 {
399  static uint32_t npoints = 1;
400  POINTARRAY *pa = NULL;
401  size_t pa_size;
402  uint32_t ndims = 2;
403  const POINT2D *pt;
404 
405  /* Count the dimensions. */
406  if( s->has_z ) ndims++;
407  if( s->has_m ) ndims++;
408  pa_size = ndims * WKB_DOUBLE_SIZE;
409 
410  /* Does the data we want to read exist? */
411  wkb_parse_state_check(s, pa_size);
412 
413  /* If we're in a native endianness, we can just copy the data directly! */
414  if( ! s->swap_bytes )
415  {
416  pa = ptarray_construct_copy_data(s->has_z, s->has_m, npoints, (uint8_t*)s->pos);
417  s->pos += pa_size;
418  }
419  /* Otherwise we have to read each double, separately */
420  else
421  {
422  uint32_t i = 0;
423  double *dlist;
424  pa = ptarray_construct(s->has_z, s->has_m, npoints);
425  dlist = (double*)(pa->serialized_pointlist);
426  for( i = 0; i < ndims; i++ )
427  {
428  dlist[i] = double_from_wkb_state(s);
429  }
430  }
431 
432  /* Check for POINT(NaN NaN) ==> POINT EMPTY */
433  pt = getPoint2d_cp(pa, 0);
434  if ( isnan(pt->x) && isnan(pt->y) )
435  {
436  ptarray_free(pa);
437  return lwpoint_construct_empty(s->srid, s->has_z, s->has_m);
438  }
439  else
440  {
441  return lwpoint_construct(s->srid, NULL, pa);
442  }
443 }
444 
454 {
456 
457  if( pa == NULL || pa->npoints == 0 )
458  {
459  ptarray_free(pa);
460  return lwline_construct_empty(s->srid, s->has_z, s->has_m);
461  }
462 
463  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
464  {
465  lwerror("%s must have at least two points", lwtype_name(s->lwtype));
466  return NULL;
467  }
468 
469  return lwline_construct(s->srid, NULL, pa);
470 }
471 
482 {
484 
485  if( pa == NULL || pa->npoints == 0 )
486  return lwcircstring_construct_empty(s->srid, s->has_z, s->has_m);
487 
488  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 3 )
489  {
490  lwerror("%s must have at least three points", lwtype_name(s->lwtype));
491  return NULL;
492  }
493 
494  if( s->check & LW_PARSER_CHECK_ODD && ! (pa->npoints % 2) )
495  {
496  lwerror("%s must have an odd number of points", lwtype_name(s->lwtype));
497  return NULL;
498  }
499 
500  return lwcircstring_construct(s->srid, NULL, pa);
501 }
502 
512 {
514  uint32_t i = 0;
515  LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);
516 
517  LWDEBUGF(4,"Polygon has %d rings", nrings);
518 
519  /* Empty polygon? */
520  if( nrings == 0 )
521  return poly;
522 
523  for( i = 0; i < nrings; i++ )
524  {
526  if( pa == NULL )
527  continue;
528 
529  /* Check for at least four points. */
530  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
531  {
532  LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
533  lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
534  return NULL;
535  }
536 
537  /* Check that first and last points are the same. */
538  if( s->check & LW_PARSER_CHECK_CLOSURE && ! ptarray_is_closed_2d(pa) )
539  {
540  LWDEBUGF(2, "%s must have closed rings", lwtype_name(s->lwtype));
541  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
542  return NULL;
543  }
544 
545  /* Add ring to polygon */
546  if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
547  {
548  LWDEBUG(2, "Unable to add ring to polygon");
549  lwerror("Unable to add ring to polygon");
550  }
551 
552  }
553  return poly;
554 }
555 
565 {
567  LWTRIANGLE *tri = lwtriangle_construct_empty(s->srid, s->has_z, s->has_m);
568  POINTARRAY *pa = NULL;
569 
570  /* Empty triangle? */
571  if( nrings == 0 )
572  return tri;
573 
574  /* Should be only one ring. */
575  if ( nrings != 1 )
576  lwerror("Triangle has wrong number of rings: %d", nrings);
577 
578  /* There's only one ring, we hope? */
580 
581  /* If there's no points, return an empty triangle. */
582  if( pa == NULL )
583  return tri;
584 
585  /* Check for at least four points. */
586  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
587  {
588  LWDEBUGF(2, "%s must have at least four points", lwtype_name(s->lwtype));
589  lwerror("%s must have at least four points", lwtype_name(s->lwtype));
590  return NULL;
591  }
592 
593  if( s->check & LW_PARSER_CHECK_ZCLOSURE && ! ptarray_is_closed_z(pa) )
594  {
595  lwerror("%s must have closed rings", lwtype_name(s->lwtype));
596  return NULL;
597  }
598 
599  /* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
600  if (tri->points)
601  ptarray_free(tri->points);
602 
603  tri->points = pa;
604  return tri;
605 }
606 
611 {
613  LWCURVEPOLY *cp = lwcurvepoly_construct_empty(s->srid, s->has_z, s->has_m);
614  LWGEOM *geom = NULL;
615  uint32_t i;
616 
617  /* Empty collection? */
618  if ( ngeoms == 0 )
619  return cp;
620 
621  for ( i = 0; i < ngeoms; i++ )
622  {
623  geom = lwgeom_from_wkb_state(s);
624  if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
625  {
626  lwgeom_free(geom);
627  lwgeom_free((LWGEOM *)cp);
628  lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
629  return NULL;
630  }
631  }
632 
633  return cp;
634 }
635 
646 {
648  LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, s->srid, s->has_z, s->has_m);
649  LWGEOM *geom = NULL;
650  uint32_t i;
651 
652  LWDEBUGF(4,"Collection has %d components", ngeoms);
653 
654  /* Empty collection? */
655  if ( ngeoms == 0 )
656  return col;
657 
658  /* Be strict in polyhedral surface closures */
659  if ( s->lwtype == POLYHEDRALSURFACETYPE )
660  s->check |= LW_PARSER_CHECK_ZCLOSURE;
661 
662  s->depth++;
663  if (s->depth >= LW_PARSER_MAX_DEPTH)
664  {
665  lwcollection_free(col);
666  lwerror("Geometry has too many chained collections");
667  return NULL;
668  }
669  for ( i = 0; i < ngeoms; i++ )
670  {
671  geom = lwgeom_from_wkb_state(s);
672  if ( lwcollection_add_lwgeom(col, geom) == NULL )
673  {
674  lwgeom_free(geom);
675  lwgeom_free((LWGEOM *)col);
676  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
677  return NULL;
678  }
679  }
680  s->depth--;
681 
682  return col;
683 }
684 
685 
694 {
695  char wkb_little_endian;
696  uint32_t wkb_type;
697 
698  LWDEBUG(4,"Entered function");
699 
700  /* Fail when handed incorrect starting byte */
701  wkb_little_endian = byte_from_wkb_state(s);
702  if( wkb_little_endian != 1 && wkb_little_endian != 0 )
703  {
704  LWDEBUG(4,"Leaving due to bad first byte!");
705  lwerror("Invalid endian flag value encountered.");
706  return NULL;
707  }
708 
709  /* Check the endianness of our input */
710  s->swap_bytes = LW_FALSE;
711  if( getMachineEndian() == NDR ) /* Machine arch is little */
712  {
713  if ( ! wkb_little_endian ) /* Data is big! */
714  s->swap_bytes = LW_TRUE;
715  }
716  else /* Machine arch is big */
717  {
718  if ( wkb_little_endian ) /* Data is little! */
719  s->swap_bytes = LW_TRUE;
720  }
721 
722  /* Read the type number */
723  wkb_type = integer_from_wkb_state(s);
724  LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
725  lwtype_from_wkb_state(s, wkb_type);
726 
727  /* Read the SRID, if necessary */
728  if( s->has_srid )
729  {
731  /* TODO: warn on explicit UNKNOWN srid ? */
732  LWDEBUGF(4,"Got SRID: %u", s->srid);
733  }
734 
735  /* Do the right thing */
736  switch( s->lwtype )
737  {
738  case POINTTYPE:
739  return (LWGEOM*)lwpoint_from_wkb_state(s);
740  break;
741  case LINETYPE:
742  return (LWGEOM*)lwline_from_wkb_state(s);
743  break;
744  case CIRCSTRINGTYPE:
746  break;
747  case POLYGONTYPE:
748  return (LWGEOM*)lwpoly_from_wkb_state(s);
749  break;
750  case TRIANGLETYPE:
752  break;
753  case CURVEPOLYTYPE:
755  break;
756  case MULTIPOINTTYPE:
757  case MULTILINETYPE:
758  case MULTIPOLYGONTYPE:
759  case COMPOUNDTYPE:
760  case MULTICURVETYPE:
761  case MULTISURFACETYPE:
763  case TINTYPE:
764  case COLLECTIONTYPE:
766  break;
767 
768  /* Unknown type! */
769  default:
770  lwerror("Unsupported geometry type: %s [%d]", lwtype_name(s->lwtype), s->lwtype);
771  }
772 
773  /* Return value to keep compiler happy. */
774  return NULL;
775 
776 }
777 
778 /* TODO add check for SRID consistency */
779 
789 LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
790 {
792 
793  /* Initialize the state appropriately */
794  s.wkb = wkb;
795  s.wkb_size = wkb_size;
796  s.swap_bytes = LW_FALSE;
797  s.check = check;
798  s.lwtype = 0;
799  s.srid = SRID_UNKNOWN;
800  s.has_z = LW_FALSE;
801  s.has_m = LW_FALSE;
802  s.has_srid = LW_FALSE;
803  s.pos = wkb;
804  s.depth = 1;
805 
806  return lwgeom_from_wkb_state(&s);
807 }
808 
809 LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check)
810 {
811  int hexwkb_len;
812  uint8_t *wkb;
813  LWGEOM *lwgeom;
814 
815  if ( ! hexwkb )
816  {
817  lwerror("lwgeom_from_hexwkb: null input");
818  return NULL;
819  }
820 
821  hexwkb_len = strlen(hexwkb);
822  wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
823  lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
824  lwfree(wkb);
825  return lwgeom;
826 }
char * s
Definition: cu_in_wkt.c:23
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:2001
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
#define WKBMOFFSET
Definition: liblwgeom.h:108
#define LW_FALSE
Definition: liblwgeom.h:77
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
#define COMPOUNDTYPE
Definition: liblwgeom.h:93
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm)
Definition: lwcircstring.c:79
#define LW_PARSER_CHECK_CLOSURE
Definition: liblwgeom.h:2002
LWCURVEPOLY * lwcurvepoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwcurvepoly.c:36
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
#define LW_FAILURE
Definition: liblwgeom.h:79
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
#define CURVEPOLYTYPE
Definition: liblwgeom.h:94
#define MULTILINETYPE
Definition: liblwgeom.h:89
#define LW_PARSER_CHECK_ZCLOSURE
Definition: liblwgeom.h:2003
#define MULTISURFACETYPE
Definition: liblwgeom.h:96
#define LINETYPE
Definition: liblwgeom.h:86
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:64
#define WKBSRIDFLAG
Definition: liblwgeom.h:109
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:247
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition: ptarray.c:62
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
#define TINTYPE
Definition: liblwgeom.h:99
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
void lwfree(void *mem)
Definition: lwutil.c:244
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
#define POLYGONTYPE
Definition: liblwgeom.h:87
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:97
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
Add a ring, allocating extra space if necessary.
Definition: lwcurvepoly.c:72
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:92
LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:50
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:721
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
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:356
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:2000
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:328
#define MULTICURVETYPE
Definition: liblwgeom.h:95
#define TRIANGLETYPE
Definition: liblwgeom.h:98
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
void * lwalloc(size_t size)
Definition: lwutil.c:229
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:695
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:151
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
#define WKBZOFFSET
Flags applied in EWKB to indicate Z/M dimensions and presence/absence of SRID and bounding boxes.
Definition: liblwgeom.h:107
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:161
LWTRIANGLE * lwtriangle_construct_empty(int srid, char hasz, char hasm)
Definition: lwtriangle.c:58
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:374
#define WKB_COMPOUNDCURVE_TYPE
#define WKB_POLYHEDRALSURFACE_TYPE
#define WKB_GEOMETRYCOLLECTION_TYPE
#define WKB_BYTE_SIZE
#define WKB_INT_SIZE
#define WKB_TRIANGLE_TYPE
char getMachineEndian(void)
Definition: lwutil.c:327
#define WKB_MULTIPOLYGON_TYPE
#define WKB_CURVE_TYPE
#define WKB_MULTIPOINT_TYPE
#define WKB_MULTISURFACE_TYPE
#define WKB_CURVEPOLYGON_TYPE
#define WKB_POINT_TYPE
Well-Known Binary (WKB) Geometry Types.
#define WKB_MULTICURVE_TYPE
#define NDR
#define WKB_SURFACE_TYPE
#define WKB_MULTILINESTRING_TYPE
#define WKB_LINESTRING_TYPE
#define WKB_CIRCULARSTRING_TYPE
#define WKB_POLYGON_TYPE
#define WKB_TIN_TYPE
#define WKB_DOUBLE_SIZE
Well-Known Binary (WKB) Output Variant Types.
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static uint32_t integer_from_wkb_state(wkb_parse_state *s)
Int32 Read 4-byte integer and advance the parse state forward.
Definition: lwin_wkb.c:275
static LWCURVEPOLY * lwcurvepoly_from_wkb_state(wkb_parse_state *s)
CURVEPOLYTYPE.
Definition: lwin_wkb.c:610
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:809
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:337
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:130
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:511
uint8_t * bytes_from_hexbytes(const char *hexbuf, size_t hexsize)
Definition: lwin_wkb.c:91
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:305
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:397
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:453
static LWCOLLECTION * lwcollection_from_wkb_state(wkb_parse_state *s)
POLYHEDRALSURFACETYPE.
Definition: lwin_wkb.c:645
static char byte_from_wkb_state(wkb_parse_state *s)
Byte Read a byte and advance the parse state forward.
Definition: lwin_wkb.c:256
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:481
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:144
#define LW_PARSER_MAX_DEPTH
Max depth in a geometry.
Definition: lwin_wkb.c:34
LWGEOM * lwgeom_from_wkb_state(wkb_parse_state *s)
Internal function declarations.
Definition: lwin_wkb.c:693
static uint8_t hex2char[256]
Definition: lwin_wkb.c:65
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:789
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:564
POINTARRAY * points
Definition: liblwgeom.h:436
double y
Definition: liblwgeom.h:331
double x
Definition: liblwgeom.h:331
uint32_t npoints
Definition: liblwgeom.h:374
uint8_t * serialized_pointlist
Definition: liblwgeom.h:369
uint32_t lwtype
Definition: lwin_wkb.c:45
const uint8_t * pos
Definition: lwin_wkb.c:51
uint32_t srid
Definition: lwin_wkb.c:46
const uint8_t * wkb
Definition: lwin_wkb.c:41
uint8_t depth
Definition: lwin_wkb.c:50
size_t wkb_size
Definition: lwin_wkb.c:42
Used for passing the parse state between the parsing functions.
Definition: lwin_wkb.c:40
unsigned int uint32_t
Definition: uthash.h:78
unsigned char uint8_t
Definition: uthash.h:79