예제 #1
0
/**
* Writes a uint8_t value to the buffer
*/
void 
bytebuffer_append_bytebuffer(bytebuffer_t *write_to,bytebuffer_t *write_from )
{	
	LWDEBUG(2,"bytebuffer_append_bytebuffer");	
	size_t size = bytebuffer_getlength(write_from);
	bytebuffer_makeroom(write_to, size);
	memcpy(write_to->writecursor, write_from->buf_start, size);
	write_to->writecursor += size;
	return;
}
예제 #2
0
/**
* Returns a new bytebuffer were both ingoing bytebuffers is merged.
* Caller is responsible for freeing both incoming bytefyffers and resulting bytebuffer
*/
bytebuffer_t*
bytebuffer_merge(bytebuffer_t **buff_array, int nbuffers)
{
	size_t total_size = 0, current_size, acc_size = 0;
	int i;
	for ( i = 0; i < nbuffers; i++ )
	{
		total_size += bytebuffer_getlength(buff_array[i]);
	}
		
	bytebuffer_t *res = bytebuffer_create_with_size(total_size);
	for ( i = 0; i < nbuffers; i++)
	{
		current_size = bytebuffer_getlength(buff_array[i]);
		memcpy(res->buf_start+acc_size, buff_array[i]->buf_start, current_size);
		acc_size += current_size;
	}
	res->writecursor = res->buf_start + total_size;
	res->readcursor = res->buf_start;
	return res;
}
예제 #3
0
/**
* Convert LWGEOM to a char* in TWKB format. Caller is responsible for freeing
* the returned array.
*/
uint8_t*
lwgeom_to_twkb_with_idlist(const LWGEOM *geom, int64_t *idlist, uint8_t variant,
               int8_t precision_xy, int8_t precision_z, int8_t precision_m,
               size_t *twkb_size)
{
	LWDEBUGF(2, "Entered %s", __func__);
	LWDEBUGF(2, "variant value %x", variant);

	TWKB_GLOBALS tg;
	TWKB_STATE ts;

	uint8_t *twkb;

	memset(&ts, 0, sizeof(TWKB_STATE));
	memset(&tg, 0, sizeof(TWKB_GLOBALS));
	
	tg.variant = variant;
	tg.prec_xy = precision_xy;
	tg.prec_z = precision_z;
	tg.prec_m = precision_m;

	if ( idlist && ! lwgeom_is_collection(geom) )
	{
		lwerror("Only collections can support ID lists");
		return NULL;
	}

	if ( ! geom )
	{
		LWDEBUG(4,"Cannot convert NULL into TWKB.");
		lwerror("Cannot convert NULL into TWKB");
		return NULL;
	}
	
	ts.idlist = idlist;
	ts.header_buf = NULL;
	ts.geom_buf = bytebuffer_create();
	lwgeom_write_to_buffer(geom, &tg, &ts);

	if ( twkb_size )
		*twkb_size = bytebuffer_getlength(ts.geom_buf);

	twkb = ts.geom_buf->buf_start;
	lwfree(ts.geom_buf);
	return twkb;
}
예제 #4
0
/**
* Free the bytebuffer_t and all memory managed within it.
*/
void 
bytebuffer_destroy(bytebuffer_t *s)
{
	LWDEBUG(2,"Entered bytebuffer_destroy");
	LWDEBUGF(4,"The buffer has used %d bytes",bytebuffer_getlength(s));
	
	if ( s->buf_start ) 
	{
		LWDEBUGF(4,"let's free buf_start %p",s->buf_start);
		lwfree(s->buf_start);
		LWDEBUG(4,"buf_start is freed");
	}
	if ( s ) 
	{
		lwfree(s);		
		LWDEBUG(4,"bytebuffer_t is freed");
	}
	return;
}
예제 #5
0
static int lwgeom_write_to_buffer(const LWGEOM *geom, TWKB_GLOBALS *globals, TWKB_STATE *parent_state)
{
	int i, is_empty, has_z, has_m, ndims;
	size_t bbox_size = 0, optional_precision_byte = 0;
	uint8_t flag = 0, type_prec = 0;

	TWKB_STATE child_state;
	memset(&child_state, 0, sizeof(TWKB_STATE));
	child_state.header_buf = bytebuffer_create_with_size(16);
	child_state.geom_buf = bytebuffer_create_with_size(64);
	child_state.idlist = parent_state->idlist;

	/* Read dimensionality from input */
	has_z = lwgeom_has_z(geom);
	has_m = lwgeom_has_m(geom);
	ndims = lwgeom_ndims(geom);
	is_empty = lwgeom_is_empty(geom);

	/* Do we need extended precision? If we have a Z or M we do. */
	optional_precision_byte = (has_z || has_m);

	/* Both X and Y dimension use the same precision */
	globals->factor[0] = pow(10, globals->prec_xy);
	globals->factor[1] = globals->factor[0];

	/* Z and M dimensions have their own precisions */
	if ( has_z )
		globals->factor[2] = pow(10, globals->prec_z);
	if ( has_m )
		globals->factor[2 + has_z] = pow(10, globals->prec_m);

	/* Reset stats */
	for ( i = 0; i < MAX_N_DIMS; i++ )
	{
		/* Reset bbox calculation */
		child_state.bbox_max[i] = INT64_MIN;
		child_state.bbox_min[i] = INT64_MAX;
		/* Reset acumulated delta values to get absolute values on next point */
		child_state.accum_rels[i] = 0;
	}

	/* TYPE/PRECISION BYTE */
	if ( abs(globals->prec_xy) > 7 )
		lwerror("%s: X/Z precision cannot be greater than 7 or less than -7", __func__);
	
	/* Read the TWKB type number from the geometry */
	TYPE_PREC_SET_TYPE(type_prec, lwgeom_twkb_type(geom));
	/* Zig-zag the precision value before encoding it since it is a signed value */
	TYPE_PREC_SET_PREC(type_prec, zigzag8(globals->prec_xy));
	/* Write the type and precision byte */
	bytebuffer_append_byte(child_state.header_buf, type_prec);

	/* METADATA BYTE */
	/* Set first bit if we are going to store bboxes */
	FIRST_BYTE_SET_BBOXES(flag, (globals->variant & TWKB_BBOX) && ! is_empty);
	/* Set second bit if we are going to store resulting size */
	FIRST_BYTE_SET_SIZES(flag, globals->variant & TWKB_SIZE);
	/* There will be no ID-list (for now) */
	FIRST_BYTE_SET_IDLIST(flag, parent_state->idlist && ! is_empty);
	/* Are there higher dimensions */
	FIRST_BYTE_SET_EXTENDED(flag, optional_precision_byte);
	/* Empty? */
	FIRST_BYTE_SET_EMPTY(flag, is_empty);
	/* Write the header byte */
	bytebuffer_append_byte(child_state.header_buf, flag);

	/* EXTENDED PRECISION BYTE (OPTIONAL) */
	/* If needed, write the extended dim byte */
	if( optional_precision_byte )
	{
		uint8_t flag = 0;

		if ( has_z && ( globals->prec_z > 7 || globals->prec_z < 0 ) )
			lwerror("%s: Z precision cannot be negative or greater than 7", __func__);

		if ( has_m && ( globals->prec_m > 7 || globals->prec_m < 0 ) )
			lwerror("%s: M precision cannot be negative or greater than 7", __func__);

		HIGHER_DIM_SET_HASZ(flag, has_z);
		HIGHER_DIM_SET_HASM(flag, has_m);
		HIGHER_DIM_SET_PRECZ(flag, globals->prec_z);
		HIGHER_DIM_SET_PRECM(flag, globals->prec_m);
		bytebuffer_append_byte(child_state.header_buf, flag);
	}

	/* It the geometry is empty, we're almost done */
	if ( is_empty )
	{
		/* If this output is sized, write the size of */
		/* all following content, which is zero because */
		/* there is none */
		if ( globals->variant & TWKB_SIZE )
			bytebuffer_append_byte(child_state.header_buf, 0);

		bytebuffer_append_bytebuffer(parent_state->geom_buf, child_state.header_buf);
		bytebuffer_destroy(child_state.header_buf);
		bytebuffer_destroy(child_state.geom_buf);
		return 0;
	}

	/* Write the TWKB into the output buffer */
	lwgeom_to_twkb_buf(geom, globals, &child_state);

	/*If we have a header_buf, we know that this function is called inside a collection*/
	/*and then we have to merge the bboxes of the included geometries*/
	/*and put the result to the parent (the collection)*/
	if( (globals->variant & TWKB_BBOX) && parent_state->header_buf )
	{
		LWDEBUG(4,"Merge bboxes");
		for ( i = 0; i < ndims; i++ )
		{
			if(child_state.bbox_min[i]<parent_state->bbox_min[i])
				parent_state->bbox_min[i] = child_state.bbox_min[i];
			if(child_state.bbox_max[i]>parent_state->bbox_max[i])
				parent_state->bbox_max[i] = child_state.bbox_max[i];
		}
	}
	
	/* Did we have a box? If so, how big? */
	bbox_size = 0;
	if( globals->variant & TWKB_BBOX )
	{
		LWDEBUG(4,"We want boxes and will calculate required size");
		bbox_size = sizeof_bbox(&child_state, ndims);
	}

	/* Write the size if wanted */
	if( globals->variant & TWKB_SIZE )
	{
		/* Here we have to add what we know will be written to header */
		/* buffer after size value is written */
		size_t size_to_register = bytebuffer_getlength(child_state.geom_buf);
		size_to_register += bbox_size;
		bytebuffer_append_uvarint(child_state.header_buf, size_to_register);
	}

	if( globals->variant & TWKB_BBOX )
		write_bbox(&child_state, ndims);

	bytebuffer_append_bytebuffer(parent_state->geom_buf,child_state.header_buf);
	bytebuffer_append_bytebuffer(parent_state->geom_buf,child_state.geom_buf);

	bytebuffer_destroy(child_state.header_buf);
	bytebuffer_destroy(child_state.geom_buf);
	return 0;
}