mirror of
https://git.osgeo.org/gitea/postgis/postgis
synced 2024-10-24 17:12:35 +00:00
d273edb148
git-svn-id: http://svn.osgeo.org/postgis/trunk@12907 b70326c6-7e19-0410-871a-916f4a2858ee
158 lines
4.3 KiB
C
158 lines
4.3 KiB
C
/**********************************************************************
|
|
*
|
|
* PostGIS - Spatial Types for PostgreSQL
|
|
* http://postgis.net
|
|
*
|
|
* Copyright (C) 2014 Sandro Santilli <strk@keybit.net>
|
|
* Copyright (C) 2013 Nicklas Avén
|
|
*
|
|
* This is free software; you can redistribute and/or modify it under
|
|
* the terms of the GNU General Public Licence. See the COPYING file.
|
|
*
|
|
**********************************************************************
|
|
*
|
|
* Handle varInt values, as described here:
|
|
* http://developers.google.com/protocol-buffers/docs/encoding#varints
|
|
*
|
|
**********************************************************************/
|
|
|
|
#include "varint.h"
|
|
#include "lwgeom_log.h"
|
|
#include "liblwgeom.h"
|
|
|
|
/**
|
|
* Constants to find the range of Varint.
|
|
* Since Varint only uses 7 bits instead of 8 in each byte a 8 byte varint
|
|
* only uses 56 bits for the number and 8 for telling if next byte is used
|
|
*/
|
|
const int64_t varint_u64_max = ((int64_t) 1<<56) - 1;
|
|
const int64_t varint_s64_min = (int64_t) -1<<55;
|
|
const int64_t varint_s64_max = ((int64_t)1<<55) - 1;
|
|
const int32_t varint_u32_max = ((int32_t) 1<<28) - 1;
|
|
const int32_t varint_s32_min = (int32_t) -1<<27;
|
|
const int32_t varint_s32_max = ((int32_t)1<<27) - 1;
|
|
|
|
static unsigned
|
|
_varint_u64_encoded_size(uint64_t q)
|
|
{
|
|
int n=0;
|
|
while ((q>>(7*(n+1))) >0) ++n;
|
|
return ++n;
|
|
}
|
|
|
|
static int
|
|
_varint_u64_encode_buf(uint64_t val, uint8_t **buf)
|
|
{
|
|
uint8_t grp;
|
|
uint64_t q=val;
|
|
while (1)
|
|
{
|
|
grp=127&q; //We put the 7 least significant bits in grp
|
|
q=q>>7; //We rightshift our input value 7 bits which means that the 7 next least significant bits becomes the 7 least significant
|
|
if(q>0) // Check if, after our rightshifting, we still have anything to read in our input value.
|
|
{
|
|
/*In the next line quite a lot is happening.
|
|
Since there is more to read in our input value we signalize that by setting the most siginicant bit in our byte to 1.
|
|
Then we put that byte in our buffer (**buf) and move the cursor to our buffer (*buf) one step*/
|
|
*((*buf)++)=128^grp;
|
|
}
|
|
else
|
|
{
|
|
/*The same as above, but since there is nothing more to read in our input value we leave the most significant bit unset*/
|
|
*((*buf)++)=grp;
|
|
// printf("grp1:%d\n",(int) grp);
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned
|
|
varint_u32_encoded_size(uint32_t val)
|
|
{
|
|
LWDEBUGF(2, "Entered varint_u32_encoded_size, value %u", val);
|
|
|
|
if( val>varint_u32_max ) {
|
|
lwerror("Value is out of range for unsigned 32bit varint (0 to %ld)",
|
|
varint_u32_max);
|
|
}
|
|
|
|
return _varint_u64_encoded_size(val); /* implicit upcast to 64bit int */
|
|
}
|
|
|
|
int
|
|
varint_u32_encode_buf(uint32_t val, uint8_t **buf)
|
|
{
|
|
LWDEBUGF(2, "Entered varint_u32_encode_buf, value %u", val);
|
|
_varint_u64_encode_buf(val, buf); /* implicit upcast to 64bit */
|
|
return 0;
|
|
}
|
|
|
|
unsigned
|
|
varint_s32_encoded_size(int32_t val)
|
|
{
|
|
LWDEBUGF(2, "Entered varint_s32_encoded_size, value %d", val);
|
|
|
|
if(val<varint_s32_min||val>varint_s32_max) {
|
|
lwerror("Value is out of range for signed 32bit varint (%d to %d)",
|
|
varint_s32_min, varint_s32_max);
|
|
}
|
|
|
|
uint32_t q = (val << 1) ^ (val >> 31); /* zig-zag encode */
|
|
return _varint_u64_encoded_size(q); /* implicit upcast to 64bit int */
|
|
}
|
|
|
|
int
|
|
varint_s32_encode_buf(int32_t val, uint8_t **buf)
|
|
{
|
|
|
|
uint32_t q;
|
|
q = (val << 1) ^ (val >> 31);/* zig-zag encode */
|
|
_varint_u64_encode_buf(q, buf);/* implicit upcast to 64bit */
|
|
return 0;
|
|
}
|
|
|
|
unsigned
|
|
varint_s64_encoded_size(int64_t val)
|
|
{
|
|
LWDEBUGF(2, "Entered varint_s64_encoded_size, value %ld", val);
|
|
|
|
if(val<varint_s64_min||val>varint_s64_max) {
|
|
lwerror("Value is out of range for signed 64bit varint (%ld to %ld)",
|
|
varint_s64_min, varint_s64_max);
|
|
}
|
|
|
|
uint64_t q = (val << 1) ^ (val >> 63); /* zig-zag encode */
|
|
return _varint_u64_encoded_size(q);
|
|
}
|
|
|
|
int
|
|
varint_s64_encode_buf(int64_t val, uint8_t **buf)
|
|
{
|
|
uint64_t q;
|
|
q = (val << 1) ^ (val >> 63);
|
|
varint_u64_encode_buf(q, buf);
|
|
return 0;
|
|
}
|
|
|
|
unsigned
|
|
varint_u64_encoded_size(uint64_t val)
|
|
{
|
|
LWDEBUGF(2, "Entered varint_u64_encoded_size, value %lu", val);
|
|
|
|
if( val>varint_u64_max ) {
|
|
lwerror("Value is out of range for unsigned 64bit varint (0 to %ld)",
|
|
varint_u64_max);
|
|
}
|
|
|
|
return _varint_u64_encoded_size(val);
|
|
}
|
|
|
|
int
|
|
varint_u64_encode_buf(uint64_t val, uint8_t **buf)
|
|
{
|
|
LWDEBUGF(2, "Entered varint_u64_encode_buf, value %lu", val);
|
|
_varint_u64_encode_buf(val, buf);
|
|
return 0;
|
|
}
|