PostGIS  2.5.2dev-r@@SVN_REVISION@@

◆ lwgeom_write_to_buffer()

static int lwgeom_write_to_buffer ( const LWGEOM geom,
TWKB_GLOBALS globals,
TWKB_STATE parent_state 
)
static

Definition at line 407 of file lwout_twkb.c.

References TWKB_STATE::accum_rels, TWKB_STATE::bbox_max, TWKB_STATE::bbox_min, bytebuffer_append_byte(), bytebuffer_append_bytebuffer(), bytebuffer_append_uvarint(), bytebuffer_destroy_buffer(), bytebuffer_getlength(), bytebuffer_init_with_size(), TWKB_GLOBALS::factor, FIRST_BYTE_SET_BBOXES, FIRST_BYTE_SET_EMPTY, FIRST_BYTE_SET_EXTENDED, FIRST_BYTE_SET_IDLIST, FIRST_BYTE_SET_SIZES, TWKB_STATE::geom_buf, TWKB_STATE::header_buf, HIGHER_DIM_SET_HASM, HIGHER_DIM_SET_HASZ, HIGHER_DIM_SET_PRECM, HIGHER_DIM_SET_PRECZ, TWKB_STATE::idlist, LWDEBUG, lwerror(), lwgeom_has_m(), lwgeom_has_z(), lwgeom_is_empty(), lwgeom_ndims(), lwgeom_to_twkb_buf(), lwgeom_twkb_type(), MAX_N_DIMS, TWKB_GLOBALS::prec_m, TWKB_GLOBALS::prec_xy, TWKB_GLOBALS::prec_z, sizeof_bbox(), TWKB_BBOX, TWKB_SIZE, TYPE_PREC_SET_PREC, TYPE_PREC_SET_TYPE, TWKB_GLOBALS::variant, write_bbox(), and zigzag8().

Referenced by lwcollection_to_twkb_buf(), and lwgeom_to_twkb_with_idlist().

408 {
409  int i, is_empty, has_z = 0, has_m = 0, ndims;
410  size_t bbox_size = 0, optional_precision_byte = 0;
411  uint8_t flag = 0, type_prec = 0;
412  bytebuffer_t header_bytebuffer, geom_bytebuffer;
413 
414  TWKB_STATE child_state;
415  memset(&child_state, 0, sizeof(TWKB_STATE));
416  child_state.header_buf = &header_bytebuffer;
417  child_state.geom_buf = &geom_bytebuffer;
418  child_state.idlist = parent_state->idlist;
419 
420  bytebuffer_init_with_size(child_state.header_buf, 16);
421  bytebuffer_init_with_size(child_state.geom_buf, 64);
422 
423  /* Read dimensionality from input */
424  ndims = lwgeom_ndims(geom);
425  is_empty = lwgeom_is_empty(geom);
426  if ( ndims > 2 )
427  {
428  has_z = lwgeom_has_z(geom);
429  has_m = lwgeom_has_m(geom);
430  }
431 
432  /* Do we need extended precision? If we have a Z or M we do. */
433  optional_precision_byte = (has_z || has_m);
434 
435  /* Both X and Y dimension use the same precision */
436  globals->factor[0] = pow(10, globals->prec_xy);
437  globals->factor[1] = globals->factor[0];
438 
439  /* Z and M dimensions have their own precisions */
440  if ( has_z )
441  globals->factor[2] = pow(10, globals->prec_z);
442  if ( has_m )
443  globals->factor[2 + has_z] = pow(10, globals->prec_m);
444 
445  /* Reset stats */
446  for ( i = 0; i < MAX_N_DIMS; i++ )
447  {
448  /* Reset bbox calculation */
449  child_state.bbox_max[i] = INT64_MIN;
450  child_state.bbox_min[i] = INT64_MAX;
451  /* Reset acumulated delta values to get absolute values on next point */
452  child_state.accum_rels[i] = 0;
453  }
454 
455  /* TYPE/PRECISION BYTE */
456  if ( abs(globals->prec_xy) > 7 )
457  lwerror("%s: X/Z precision cannot be greater than 7 or less than -7", __func__);
458 
459  /* Read the TWKB type number from the geometry */
460  TYPE_PREC_SET_TYPE(type_prec, lwgeom_twkb_type(geom));
461  /* Zig-zag the precision value before encoding it since it is a signed value */
462  TYPE_PREC_SET_PREC(type_prec, zigzag8(globals->prec_xy));
463  /* Write the type and precision byte */
464  bytebuffer_append_byte(child_state.header_buf, type_prec);
465 
466  /* METADATA BYTE */
467  /* Set first bit if we are going to store bboxes */
468  FIRST_BYTE_SET_BBOXES(flag, (globals->variant & TWKB_BBOX) && ! is_empty);
469  /* Set second bit if we are going to store resulting size */
470  FIRST_BYTE_SET_SIZES(flag, globals->variant & TWKB_SIZE);
471  /* There will be no ID-list (for now) */
472  FIRST_BYTE_SET_IDLIST(flag, parent_state->idlist && ! is_empty);
473  /* Are there higher dimensions */
474  FIRST_BYTE_SET_EXTENDED(flag, optional_precision_byte);
475  /* Empty? */
476  FIRST_BYTE_SET_EMPTY(flag, is_empty);
477  /* Write the header byte */
478  bytebuffer_append_byte(child_state.header_buf, flag);
479 
480  /* EXTENDED PRECISION BYTE (OPTIONAL) */
481  /* If needed, write the extended dim byte */
482  if( optional_precision_byte )
483  {
484  uint8_t flag = 0;
485 
486  if ( has_z && ( globals->prec_z > 7 || globals->prec_z < 0 ) )
487  lwerror("%s: Z precision cannot be negative or greater than 7", __func__);
488 
489  if ( has_m && ( globals->prec_m > 7 || globals->prec_m < 0 ) )
490  lwerror("%s: M precision cannot be negative or greater than 7", __func__);
491 
492  HIGHER_DIM_SET_HASZ(flag, has_z);
493  HIGHER_DIM_SET_HASM(flag, has_m);
494  HIGHER_DIM_SET_PRECZ(flag, globals->prec_z);
495  HIGHER_DIM_SET_PRECM(flag, globals->prec_m);
496  bytebuffer_append_byte(child_state.header_buf, flag);
497  }
498 
499  /* It the geometry is empty, we're almost done */
500  if ( is_empty )
501  {
502  /* If this output is sized, write the size of */
503  /* all following content, which is zero because */
504  /* there is none */
505  if ( globals->variant & TWKB_SIZE )
506  bytebuffer_append_byte(child_state.header_buf, 0);
507 
508  bytebuffer_append_bytebuffer(parent_state->geom_buf, child_state.header_buf);
510  bytebuffer_destroy_buffer(child_state.geom_buf);
511  return 0;
512  }
513 
514  /* Write the TWKB into the output buffer */
515  lwgeom_to_twkb_buf(geom, globals, &child_state);
516 
517  /*If we have a header_buf, we know that this function is called inside a collection*/
518  /*and then we have to merge the bboxes of the included geometries*/
519  /*and put the result to the parent (the collection)*/
520  if( (globals->variant & TWKB_BBOX) && parent_state->header_buf )
521  {
522  LWDEBUG(4,"Merge bboxes");
523  for ( i = 0; i < ndims; i++ )
524  {
525  if(child_state.bbox_min[i]<parent_state->bbox_min[i])
526  parent_state->bbox_min[i] = child_state.bbox_min[i];
527  if(child_state.bbox_max[i]>parent_state->bbox_max[i])
528  parent_state->bbox_max[i] = child_state.bbox_max[i];
529  }
530  }
531 
532  /* Did we have a box? If so, how big? */
533  bbox_size = 0;
534  if( globals->variant & TWKB_BBOX )
535  {
536  LWDEBUG(4,"We want boxes and will calculate required size");
537  bbox_size = sizeof_bbox(&child_state, ndims);
538  }
539 
540  /* Write the size if wanted */
541  if( globals->variant & TWKB_SIZE )
542  {
543  /* Here we have to add what we know will be written to header */
544  /* buffer after size value is written */
545  size_t size_to_register = bytebuffer_getlength(child_state.geom_buf);
546  size_to_register += bbox_size;
547  bytebuffer_append_uvarint(child_state.header_buf, size_to_register);
548  }
549 
550  if( globals->variant & TWKB_BBOX )
551  write_bbox(&child_state, ndims);
552 
553  bytebuffer_append_bytebuffer(parent_state->geom_buf,child_state.header_buf);
554  bytebuffer_append_bytebuffer(parent_state->geom_buf,child_state.geom_buf);
555 
557  bytebuffer_destroy_buffer(child_state.geom_buf);
558  return 0;
559 }
#define FIRST_BYTE_SET_EMPTY(flag, bool)
Definition: lwout_twkb.h:57
float factor[4]
Definition: lwout_twkb.h:82
#define HIGHER_DIM_SET_PRECM(flag, prec)
Definition: lwout_twkb.h:73
#define TYPE_PREC_SET_TYPE(flag, type)
Macros for manipulating the &#39;type_precision&#39; int.
Definition: lwout_twkb.h:66
void bytebuffer_append_bytebuffer(bytebuffer_t *write_to, bytebuffer_t *write_from)
Writes a uint8_t value to the buffer.
Definition: bytebuffer.c:224
uint8_t variant
Definition: lwout_twkb.h:78
static int lwgeom_to_twkb_buf(const LWGEOM *geom, TWKB_GLOBALS *globals, TWKB_STATE *ts)
Definition: lwout_twkb.c:362
void bytebuffer_append_byte(bytebuffer_t *s, const uint8_t val)
Writes a uint8_t value to the buffer.
Definition: bytebuffer.c:197
static uint8_t lwgeom_twkb_type(const LWGEOM *geom)
Definition: lwout_twkb.c:31
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
static void write_bbox(TWKB_STATE *ts, int ndims)
Writes the bbox in varints in the form: xmin, xdelta, ymin, ydelta.
Definition: lwout_twkb.c:89
#define HIGHER_DIM_SET_HASZ(flag, bool)
Definition: lwout_twkb.h:69
size_t bytebuffer_getlength(const bytebuffer_t *s)
Returns the length of the current buffer.
Definition: bytebuffer.c:373
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:930
int lwgeom_ndims(const LWGEOM *geom)
Return the number of dimensions (2, 3, 4) in a geometry.
Definition: lwgeom.c:944
int8_t prec_z
Definition: lwout_twkb.h:80
uint8_t zigzag8(int8_t val)
Definition: varint.c:182
bytebuffer_t * header_buf
Definition: lwout_twkb.h:88
static size_t sizeof_bbox(TWKB_STATE *ts, int ndims)
Calculates the size of the bbox in varints in the form: xmin, xdelta, ymin, ydelta.
Definition: lwout_twkb.c:72
int64_t accum_rels[MAX_N_DIMS]
Definition: lwout_twkb.h:95
const int64_t * idlist
Definition: lwout_twkb.h:92
#define FIRST_BYTE_SET_SIZES(flag, bool)
Definition: lwout_twkb.h:54
void bytebuffer_append_uvarint(bytebuffer_t *b, const uint64_t val)
Writes a unsigned varInt to the buffer.
Definition: bytebuffer.c:250
int8_t prec_xy
Definition: lwout_twkb.h:79
#define FIRST_BYTE_SET_BBOXES(flag, bool)
Header true/false flags.
Definition: lwout_twkb.h:53
int8_t prec_m
Definition: lwout_twkb.h:81
#define TYPE_PREC_SET_PREC(flag, prec)
Definition: lwout_twkb.h:67
#define MAX_N_DIMS
Definition: lwout_twkb.h:43
#define HIGHER_DIM_SET_PRECZ(flag, prec)
Definition: lwout_twkb.h:72
#define TWKB_BBOX
Definition: liblwgeom.h:2082
void bytebuffer_init_with_size(bytebuffer_t *s, size_t size)
Allocate just the internal buffer of an existing bytebuffer_t struct.
Definition: bytebuffer.c:71
#define FIRST_BYTE_SET_EXTENDED(flag, bool)
Definition: lwout_twkb.h:56
int64_t bbox_max[MAX_N_DIMS]
Definition: lwout_twkb.h:94
#define TWKB_SIZE
Definition: liblwgeom.h:2083
#define HIGHER_DIM_SET_HASM(flag, bool)
Definition: lwout_twkb.h:70
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1393
bytebuffer_t * geom_buf
Definition: lwout_twkb.h:89
unsigned char uint8_t
Definition: uthash.h:79
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:937
#define FIRST_BYTE_SET_IDLIST(flag, bool)
Definition: lwout_twkb.h:55
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
void bytebuffer_destroy_buffer(bytebuffer_t *s)
Free the bytebuffer_t and all memory managed within it.
Definition: bytebuffer.c:104
int64_t bbox_min[MAX_N_DIMS]
Definition: lwout_twkb.h:93
Here is the call graph for this function:
Here is the caller graph for this function: