PostGIS  2.2.7dev-r@@SVN_REVISION@@
lwin_twkb.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  *
5  * Copyright (C) 2014 Nicklas Avén
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 <math.h>
13 #include "liblwgeom_internal.h"
14 #include "lwgeom_log.h"
15 #include "varint.h"
16 
17 #define TWKB_IN_MAXCOORDS 4
18 
22 typedef struct
23 {
24  /* Pointers to the bytes */
25  uint8_t *twkb; /* Points to start of TWKB */
26  uint8_t *twkb_end; /* Points to end of TWKB */
27  uint8_t *pos; /* Current read position */
28 
29  uint32_t check; /* Simple validity checks on geometries */
30  uint32_t lwtype; /* Current type we are handling */
31 
32  uint8_t has_bbox;
33  uint8_t has_size;
34  uint8_t has_idlist;
35  uint8_t has_z;
36  uint8_t has_m;
37  uint8_t is_empty;
38 
39  /* Precision factors to convert ints to double */
40  double factor;
41  double factor_z;
42  double factor_m;
43 
44  uint64_t size;
45 
46  /* Info about current geometry */
47  uint8_t magic_byte; /* the magic byte contain info about if twkb contain id, size info, bboxes and precision */
48 
49  int ndims; /* Number of dimensions */
50 
51  int64_t *coords; /* An array to keep delta values from 4 dimensions */
52 
54 
55 
60 
61 
62 /**********************************************************************/
63 
68 static inline void twkb_parse_state_advance(twkb_parse_state *s, size_t next)
69 {
70  if( (s->pos + next) > s->twkb_end)
71  {
72  lwerror("%s: TWKB structure does not match expected size!", __func__);
73  // lwnotice("TWKB structure does not match expected size!");
74  }
75 
76  s->pos += next;
77 }
78 
80 {
81  size_t size;
82  int64_t val = varint_s64_decode(s->pos, s->twkb_end, &size);
83  twkb_parse_state_advance(s, size);
84  return val;
85 }
86 
88 {
89  size_t size;
90  uint64_t val = varint_u64_decode(s->pos, s->twkb_end, &size);
91  twkb_parse_state_advance(s, size);
92  return val;
93 }
94 
95 static inline double twkb_parse_state_double(twkb_parse_state *s, double factor)
96 {
97  size_t size;
98  int64_t val = varint_s64_decode(s->pos, s->twkb_end, &size);
99  twkb_parse_state_advance(s, size);
100  return val / factor;
101 }
102 
104 {
105  size_t size = varint_size(s->pos, s->twkb_end);
106 
107  if ( ! size )
108  lwerror("%s: no varint to skip", __func__);
109 
110  twkb_parse_state_advance(s, size);
111  return;
112 }
113 
114 
115 
116 static uint32_t lwtype_from_twkb_type(uint8_t twkb_type)
117 {
118  switch (twkb_type)
119  {
120  case 1:
121  return POINTTYPE;
122  case 2:
123  return LINETYPE;
124  case 3:
125  return POLYGONTYPE;
126  case 4:
127  return MULTIPOINTTYPE;
128  case 5:
129  return MULTILINETYPE;
130  case 6:
131  return MULTIPOLYGONTYPE;
132  case 7:
133  return COLLECTIONTYPE;
134 
135  default: /* Error! */
136  lwerror("Unknown WKB type");
137  return 0;
138  }
139  return 0;
140 }
141 
147 {
148  uint8_t val = *(s->pos);
150  return val;
151 }
152 
153 
159 {
160  POINTARRAY *pa = NULL;
161  uint32_t ndims = s->ndims;
162  int i;
163  double *dlist;
164 
165  LWDEBUG(2,"Entering ptarray_from_twkb_state");
166  LWDEBUGF(4,"Pointarray has %d points", npoints);
167 
168  /* Empty! */
169  if( npoints == 0 )
170  return ptarray_construct_empty(s->has_z, s->has_m, 0);
171 
172  pa = ptarray_construct(s->has_z, s->has_m, npoints);
173  dlist = (double*)(pa->serialized_pointlist);
174  for( i = 0; i < npoints; i++ )
175  {
176  int j = 0;
177  /* X */
178  s->coords[j] += twkb_parse_state_varint(s);
179  dlist[ndims*i + j] = s->coords[j] / s->factor;
180  j++;
181  /* Y */
182  s->coords[j] += twkb_parse_state_varint(s);
183  dlist[ndims*i + j] = s->coords[j] / s->factor;
184  j++;
185  /* Z */
186  if ( s->has_z )
187  {
188  s->coords[j] += twkb_parse_state_varint(s);
189  dlist[ndims*i + j] = s->coords[j] / s->factor_z;
190  j++;
191  }
192  /* M */
193  if ( s->has_m )
194  {
195  s->coords[j] += twkb_parse_state_varint(s);
196  dlist[ndims*i + j] = s->coords[j] / s->factor_m;
197  j++;
198  }
199  }
200 
201  return pa;
202 }
203 
208 {
209  static uint32_t npoints = 1;
210  POINTARRAY *pa;
211 
212  LWDEBUG(2,"Entering lwpoint_from_twkb_state");
213 
214  if ( s->is_empty )
216 
217  pa = ptarray_from_twkb_state(s, npoints);
218  return lwpoint_construct(SRID_UNKNOWN, NULL, pa);
219 }
220 
225 {
226  uint32_t npoints;
227  POINTARRAY *pa;
228 
229  LWDEBUG(2,"Entering lwline_from_twkb_state");
230 
231  if ( s->is_empty )
233 
234  /* Read number of points */
235  npoints = twkb_parse_state_uvarint(s);
236 
237  if ( npoints == 0 )
239 
240  /* Read coordinates */
241  pa = ptarray_from_twkb_state(s, npoints);
242 
243  if( pa == NULL )
245 
246  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 )
247  {
248  lwerror("%s must have at least two points", lwtype_name(s->lwtype));
249  return NULL;
250  }
251 
252  return lwline_construct(SRID_UNKNOWN, NULL, pa);
253 }
254 
259 {
260  uint32_t nrings;
261  int i;
262  LWPOLY *poly;
263 
264  LWDEBUG(2,"Entering lwpoly_from_twkb_state");
265 
266  if ( s->is_empty )
268 
269  /* Read number of rings */
270  nrings = twkb_parse_state_uvarint(s);
271 
272  /* Start w/ empty polygon */
274 
275  LWDEBUGF(4,"Polygon has %d rings", nrings);
276 
277  /* Empty polygon? */
278  if( nrings == 0 )
279  return poly;
280 
281  for( i = 0; i < nrings; i++ )
282  {
283  /* Ret number of points */
284  uint32_t npoints = twkb_parse_state_uvarint(s);
285  POINTARRAY *pa = ptarray_from_twkb_state(s, npoints);
286 
287  /* Skip empty rings */
288  if( pa == NULL )
289  continue;
290 
291  /* Force first and last points to be the same. */
292  if( ! ptarray_is_closed_2d(pa) )
293  {
294  POINT4D pt;
295  getPoint4d_p(pa, 0, &pt);
296  ptarray_append_point(pa, &pt, LW_FALSE);
297  }
298 
299  /* Check for at least four points. */
300  if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
301  {
302  LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype));
303  lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype));
304  return NULL;
305  }
306 
307  /* Add ring to polygon */
308  if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
309  {
310  LWDEBUG(2, "Unable to add ring to polygon");
311  lwerror("Unable to add ring to polygon");
312  }
313 
314  }
315  return poly;
316 }
317 
318 
323 {
324  int ngeoms, i;
325  LWGEOM *geom = NULL;
327 
328  LWDEBUG(2,"Entering lwmultipoint_from_twkb_state");
329 
330  if ( s->is_empty )
331  return col;
332 
333  /* Read number of geometries */
334  ngeoms = twkb_parse_state_uvarint(s);
335  LWDEBUGF(4,"Number of geometries %d", ngeoms);
336 
337  /* It has an idlist, we need to skip that */
338  if ( s->has_idlist )
339  {
340  for ( i = 0; i < ngeoms; i++ )
342  }
343 
344  for ( i = 0; i < ngeoms; i++ )
345  {
347  if ( lwcollection_add_lwgeom(col, geom) == NULL )
348  {
349  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
350  return NULL;
351  }
352  }
353 
354  return col;
355 }
356 
361 {
362  int ngeoms, i;
363  LWGEOM *geom = NULL;
365 
366  LWDEBUG(2,"Entering lwmultilinestring_from_twkb_state");
367 
368  if ( s->is_empty )
369  return col;
370 
371  /* Read number of geometries */
372  ngeoms = twkb_parse_state_uvarint(s);
373 
374  LWDEBUGF(4,"Number of geometries %d",ngeoms);
375 
376  /* It has an idlist, we need to skip that */
377  if ( s->has_idlist )
378  {
379  for ( i = 0; i < ngeoms; i++ )
381  }
382 
383  for ( i = 0; i < ngeoms; i++ )
384  {
386  if ( lwcollection_add_lwgeom(col, geom) == NULL )
387  {
388  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
389  return NULL;
390  }
391  }
392 
393  return col;
394 }
395 
400 {
401  int ngeoms, i;
402  LWGEOM *geom = NULL;
404 
405  LWDEBUG(2,"Entering lwmultipolygon_from_twkb_state");
406 
407  if ( s->is_empty )
408  return col;
409 
410  /* Read number of geometries */
411  ngeoms = twkb_parse_state_uvarint(s);
412  LWDEBUGF(4,"Number of geometries %d",ngeoms);
413 
414  /* It has an idlist, we need to skip that */
415  if ( s->has_idlist )
416  {
417  for ( i = 0; i < ngeoms; i++ )
419  }
420 
421  for ( i = 0; i < ngeoms; i++ )
422  {
424  if ( lwcollection_add_lwgeom(col, geom) == NULL )
425  {
426  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
427  return NULL;
428  }
429  }
430 
431  return col;
432 }
433 
434 
439 {
440  int ngeoms, i;
441  LWGEOM *geom = NULL;
443 
444  LWDEBUG(2,"Entering lwcollection_from_twkb_state");
445 
446  if ( s->is_empty )
447  return col;
448 
449  /* Read number of geometries */
450  ngeoms = twkb_parse_state_uvarint(s);
451 
452  LWDEBUGF(4,"Number of geometries %d",ngeoms);
453 
454  /* It has an idlist, we need to skip that */
455  if ( s->has_idlist )
456  {
457  for ( i = 0; i < ngeoms; i++ )
459  }
460 
461  for ( i = 0; i < ngeoms; i++ )
462  {
463  geom = lwgeom_from_twkb_state(s);
464  if ( lwcollection_add_lwgeom(col, geom) == NULL )
465  {
466  lwerror("Unable to add geometry (%p) to collection (%p)", geom, col);
467  return NULL;
468  }
469  }
470 
471 
472  return col;
473 }
474 
475 
477 {
478  LWDEBUG(2,"Entering magicbyte_from_twkb_state");
479 
480  uint8_t extended_dims;
481 
482  /* Read the first two bytes */
483  uint8_t type_precision = byte_from_twkb_state(s);
484  uint8_t metadata = byte_from_twkb_state(s);
485 
486  /* Strip type and precision out of first byte */
487  uint8_t type = type_precision & 0x0F;
488  int8_t precision = unzigzag8((type_precision & 0xF0) >> 4);
489 
490  /* Convert TWKB type to internal type */
491  s->lwtype = lwtype_from_twkb_type(type);
492 
493  /* Convert the precision into factor */
494  s->factor = pow(10, (double)precision);
495 
496  /* Strip metadata flags out of second byte */
497  s->has_bbox = metadata & 0x01;
498  s->has_size = (metadata & 0x02) >> 1;
499  s->has_idlist = (metadata & 0x04) >> 2;
500  extended_dims = (metadata & 0x08) >> 3;
501  s->is_empty = (metadata & 0x10) >> 4;
502 
503  /* Flag for higher dims means read a third byte */
504  if ( extended_dims )
505  {
506  int8_t precision_z, precision_m;
507 
508  extended_dims = byte_from_twkb_state(s);
509 
510  /* Strip Z/M presence and precision from ext byte */
511  s->has_z = (extended_dims & 0x01);
512  s->has_m = (extended_dims & 0x02) >> 1;
513  precision_z = (extended_dims & 0x1C) >> 2;
514  precision_m = (extended_dims & 0xE0) >> 5;
515 
516  /* Convert the precision into factor */
517  s->factor_z = pow(10, (double)precision_z);
518  s->factor_m = pow(10, (double)precision_m);
519  }
520  else
521  {
522  s->has_z = 0;
523  s->has_m = 0;
524  s->factor_z = 0;
525  s->factor_m = 0;
526  }
527 
528  /* Read the size, if there is one */
529  if ( s->has_size )
530  {
532  }
533 
534  /* Calculate the number of dimensions */
535  s->ndims = 2 + s->has_z + s->has_m;
536 
537  return;
538 }
539 
540 
541 
549 {
550  GBOX bbox;
551  LWGEOM *geom = NULL;
552  uint32_t has_bbox = LW_FALSE;
553  int i;
554 
555  /* Read the first two bytes, and optional */
556  /* extended precision info and optional size info */
558 
559  /* Just experienced a geometry header, so now we */
560  /* need to reset our coordinate deltas */
561  for ( i = 0; i < TWKB_IN_MAXCOORDS; i++ )
562  {
563  s->coords[i] = 0.0;
564  }
565 
566  /* Read the bounding box, is there is one */
567  if ( s->has_bbox )
568  {
569  /* Initialize */
570  has_bbox = s->has_bbox;
571  memset(&bbox, 0, sizeof(GBOX));
572  bbox.flags = gflags(s->has_z, s->has_m, 0);
573 
574  /* X */
575  bbox.xmin = twkb_parse_state_double(s, s->factor);
576  bbox.xmax = bbox.xmin + twkb_parse_state_double(s, s->factor);
577  /* Y */
578  bbox.ymin = twkb_parse_state_double(s, s->factor);
579  bbox.ymax = bbox.ymin + twkb_parse_state_double(s, s->factor);
580  /* Z */
581  if ( s->has_z )
582  {
583  bbox.zmin = twkb_parse_state_double(s, s->factor_z);
584  bbox.zmax = bbox.zmin + twkb_parse_state_double(s, s->factor_z);
585  }
586  /* M */
587  if ( s->has_z )
588  {
589  bbox.mmin = twkb_parse_state_double(s, s->factor_m);
590  bbox.mmax = bbox.mmin + twkb_parse_state_double(s, s->factor_m);
591  }
592  }
593 
594  /* Switch to code for the particular type we're dealing with */
595  switch( s->lwtype )
596  {
597  case POINTTYPE:
599  break;
600  case LINETYPE:
602  break;
603  case POLYGONTYPE:
605  break;
606  case MULTIPOINTTYPE:
608  break;
609  case MULTILINETYPE:
611  break;
612  case MULTIPOLYGONTYPE:
614  break;
615  case COLLECTIONTYPE:
617  break;
618  /* Unknown type! */
619  default:
620  lwerror("Unsupported geometry type: %s [%d]", lwtype_name(s->lwtype), s->lwtype);
621  break;
622  }
623 
624  if ( has_bbox )
625  {
626  geom->bbox = gbox_clone(&bbox);
627  }
628 
629  return geom;
630 }
631 
632 
642 LWGEOM* lwgeom_from_twkb(uint8_t *twkb, size_t twkb_size, char check)
643 {
644  int64_t coords[TWKB_IN_MAXCOORDS] = {0, 0, 0, 0};
646 
647  LWDEBUG(2,"Entering lwgeom_from_twkb");
648  LWDEBUGF(4,"twkb_size: %d",(int) twkb_size);
649 
650  /* Zero out the state */
651  memset(&s, 0, sizeof(twkb_parse_state));
652 
653  /* Initialize the state appropriately */
654  s.twkb = s.pos = twkb;
655  s.twkb_end = twkb + twkb_size;
656  s.check = check;
657  s.coords = coords;
658 
659  /* Handle the check catch-all values */
660  if ( check & LW_PARSER_CHECK_NONE )
661  s.check = 0;
662  else
663  s.check = check;
664 
665 
666  /* Read the rest of the geometry */
667  return lwgeom_from_twkb_state(&s);
668 }
#define LINETYPE
Definition: liblwgeom.h:71
uint8_t has_z
Definition: lwin_twkb.c:35
uint8_t is_empty
Definition: lwin_twkb.c:37
double factor_z
Definition: lwin_twkb.c:41
#define WKB_BYTE_SIZE
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
GBOX * bbox
Definition: liblwgeom.h:382
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:51
uint8_t * serialized_pointlist
Definition: liblwgeom.h:350
uint64_t size
Definition: lwin_twkb.c:44
int npoints
Definition: liblwgeom.h:355
static LWLINE * lwline_from_twkb_state(twkb_parse_state *s)
LINESTRING.
Definition: lwin_twkb.c:224
static LWCOLLECTION * lwcollection_from_twkb_state(twkb_parse_state *s)
COLLECTION, MULTIPOINTTYPE, MULTILINETYPE, MULTIPOLYGONTYPE.
Definition: lwin_twkb.c:438
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:1864
#define POLYGONTYPE
Definition: liblwgeom.h:72
double xmax
Definition: liblwgeom.h:277
uint8_t has_m
Definition: lwin_twkb.c:36
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
#define MULTIPOINTTYPE
Definition: liblwgeom.h:73
uint32_t check
Definition: lwin_twkb.c:29
static LWPOLY * lwpoly_from_twkb_state(twkb_parse_state *s)
POLYGON.
Definition: lwin_twkb.c:258
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
uint8_t has_idlist
Definition: lwin_twkb.c:34
static uint32_t lwtype_from_twkb_type(uint8_t twkb_type)
Definition: lwin_twkb.c:116
uint8_t * pos
Definition: lwin_twkb.c:27
uint8_t * twkb_end
Definition: lwin_twkb.c:26
static POINTARRAY * ptarray_from_twkb_state(twkb_parse_state *s, uint32_t npoints)
POINTARRAY Read a dynamically sized point array and advance the parse state forward.
Definition: lwin_twkb.c:158
size_t varint_size(const uint8_t *the_start, const uint8_t *the_end)
Definition: varint.c:139
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:120
uint8_t has_bbox
Definition: lwin_twkb.c:32
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:694
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:239
static uint8_t byte_from_twkb_state(twkb_parse_state *s)
Byte Read a byte and advance the parse state forward.
Definition: lwin_twkb.c:146
int64_t varint_s64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size)
Definition: varint.c:94
#define LW_FAILURE
Definition: liblwgeom.h:64
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:1869
double zmax
Definition: liblwgeom.h:281
double ymin
Definition: liblwgeom.h:278
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:188
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:249
#define TWKB_IN_MAXCOORDS
Definition: lwin_twkb.c:17
double xmin
Definition: liblwgeom.h:276
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:156
#define LW_FALSE
Definition: liblwgeom.h:62
int64_t * coords
Definition: lwin_twkb.c:51
uint32_t lwtype
Definition: lwin_twkb.c:30
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:172
uint8_t precision
Definition: cu_in_twkb.c:25
double factor_m
Definition: lwin_twkb.c:42
LWGEOM * lwgeom_from_twkb(uint8_t *twkb, size_t twkb_size, char check)
WKB inputs must have a declared size, to prevent malformed WKB from reading off the end of the memory...
Definition: lwin_twkb.c:642
double ymax
Definition: liblwgeom.h:279
static LWCOLLECTION * lwmultipoint_from_twkb_state(twkb_parse_state *s)
MULTIPOINT.
Definition: lwin_twkb.c:322
char * s
Definition: cu_in_wkt.c:23
Used for passing the parse state between the parsing functions.
Definition: lwin_twkb.c:22
static uint64_t twkb_parse_state_uvarint(twkb_parse_state *s)
Definition: lwin_twkb.c:87
uint8_t flags
Definition: liblwgeom.h:275
static LWCOLLECTION * lwmultipoly_from_twkb_state(twkb_parse_state *s)
MULTIPOLYGON.
Definition: lwin_twkb.c:399
uint8_t gflags(int hasz, int hasm, int geodetic)
Construct a new flags char.
Definition: g_util.c:130
static LWPOINT * lwpoint_from_twkb_state(twkb_parse_state *s)
POINT.
Definition: lwin_twkb.c:207
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:75
uint64_t varint_u64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size)
Definition: varint.c:101
static double twkb_parse_state_double(twkb_parse_state *s, double factor)
Definition: lwin_twkb.c:95
double mmin
Definition: liblwgeom.h:282
double zmin
Definition: liblwgeom.h:280
LWGEOM * lwgeom_from_twkb_state(twkb_parse_state *s)
Internal function declarations.
Definition: lwin_twkb.c:548
static void twkb_parse_state_advance(twkb_parse_state *s, size_t next)
Check that we are not about to read off the end of the WKB array.
Definition: lwin_twkb.c:68
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:70
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:66
double mmax
Definition: liblwgeom.h:283
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:254
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:154
GBOX * gbox_clone(const GBOX *gbox)
Definition: g_box.c:41
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:98
static LWCOLLECTION * lwmultiline_from_twkb_state(twkb_parse_state *s)
MULTILINESTRING.
Definition: lwin_twkb.c:360
uint8_t * twkb
Definition: lwin_twkb.c:25
static void header_from_twkb_state(twkb_parse_state *s)
Definition: lwin_twkb.c:476
#define MULTILINETYPE
Definition: liblwgeom.h:74
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:81
static int64_t twkb_parse_state_varint(twkb_parse_state *s)
Definition: lwin_twkb.c:79
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:174
static void twkb_parse_state_varint_skip(twkb_parse_state *s)
Definition: lwin_twkb.c:103
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
uint8_t magic_byte
Definition: lwin_twkb.c:47
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:231
#define COLLECTIONTYPE
Definition: liblwgeom.h:76
uint8_t has_size
Definition: lwin_twkb.c:33
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:219
int8_t unzigzag8(uint8_t val)
Definition: varint.c:195