PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
varint.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) 2014 Sandro Santilli <strk@kbt.io>
22 * Copyright (C) 2013 Nicklas Avén
23 *
24 **********************************************************************/
25
26
27#include "varint.h"
28#include "lwgeom_log.h"
29#include "liblwgeom.h"
30
31/* -------------------------------------------------------------------------------- */
32
33static size_t
34_varint_u64_encode_buf(uint64_t val, uint8_t *buf)
35{
36 uint8_t grp;
37 uint64_t q = val;
38 uint8_t *ptr = buf;
39 while (1)
40 {
41 /* We put the 7 least significant bits in grp */
42 grp = 0x7f & q;
43 /* We rightshift our input value 7 bits */
44 /* which means that the 7 next least significant bits */
45 /* becomes the 7 least significant */
46 q = q >> 7;
47 /* Check if, after our rightshifting, we still have */
48 /* anything to read in our input value. */
49 if ( q > 0 )
50 {
51 /* In the next line quite a lot is happening. */
52 /* Since there is more to read in our input value */
53 /* we signal that by setting the most significant bit */
54 /* in our byte to 1. */
55 /* Then we put that byte in our buffer and move the pointer */
56 /* forward one step */
57 *ptr = 0x80 | grp;
58 ptr++;
59 }
60 else
61 {
62 /* The same as above, but since there is nothing more */
63 /* to read in our input value we leave the most significant bit unset */
64 *ptr = grp;
65 ptr++;
66 return ptr - buf;
67 }
68 }
69 /* This cannot happen */
70 lwerror("%s: Got out of infinite loop. Consciousness achieved.", __func__);
71 return (size_t)0;
72}
73
74
75size_t
76varint_u64_encode_buf(uint64_t val, uint8_t *buf)
77{
78 return _varint_u64_encode_buf(val, buf);
79}
80
81
82size_t
83varint_u32_encode_buf(uint32_t val, uint8_t *buf)
84{
85 return _varint_u64_encode_buf((uint64_t)val, buf);
86}
87
88size_t
89varint_s64_encode_buf(int64_t val, uint8_t *buf)
90{
91 return _varint_u64_encode_buf(zigzag64(val), buf);
92}
93
94size_t
95varint_s32_encode_buf(int32_t val, uint8_t *buf)
96{
97 return _varint_u64_encode_buf((uint64_t)zigzag32(val), buf);
98}
99
100/* Read from signed 64bit varint */
101int64_t
102varint_s64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size)
103{
104 return unzigzag64(varint_u64_decode(the_start, the_end, size));
105}
106
107/* Read from unsigned 64bit varint */
108uint64_t
109varint_u64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size)
110{
111 uint64_t nVal = 0;
112 int nShift = 0;
113 uint8_t nByte;
114 const uint8_t *ptr = the_start;
115
116 /* Check so we don't read beyond the twkb */
117 while( ptr < the_end )
118 {
119 nByte = *ptr;
120 /* Hibit is set, so this isn't the last byte */
121 if (nByte & 0x80)
122 {
123 /* We get here when there is more to read in the input varInt */
124 /* Here we take the least significant 7 bits of the read */
125 /* byte and put it in the most significant place in the result variable. */
126 nVal |= ((uint64_t)(nByte & 0x7f)) << nShift;
127 /* move the "cursor" of the input buffer step (8 bits) */
128 ptr++;
129 /* move the cursor in the resulting variable (7 bits) */
130 nShift += 7;
131 }
132 else
133 {
134 /* move the "cursor" one step */
135 ptr++;
136 /* Move the last read byte to the most significant */
137 /* place in the result and return the whole result */
138 *size = ptr - the_start;
139 return nVal | ((uint64_t)nByte << nShift);
140 }
141 }
142 lwerror("%s: varint extends past end of buffer", __func__);
143 *size = 0;
144 return 0;
145}
146
147size_t
148varint_size(const uint8_t *the_start, const uint8_t *the_end)
149{
150 const uint8_t *ptr = the_start;
151
152 /* Check so we don't read beyond the twkb */
153 while( ptr < the_end )
154 {
155 /* Hibit is set, this isn't the last byte */
156 if (*ptr & 0x80)
157 {
158 ptr++;
159 }
160 else
161 {
162 ptr++;
163 return ptr - the_start;
164 }
165 }
166 return 0;
167}
168
169uint64_t zigzag64(int64_t val)
170{
171 return val >= 0 ?
172 ((uint64_t)val) << 1 :
173 ((((uint64_t)(-1 - val)) << 1) | 0x01);
174}
175
176uint32_t zigzag32(int32_t val)
177{
178 return val >= 0 ?
179 ((uint32_t)val) << 1 :
180 ((((uint32_t)(-1 - val)) << 1) | 0x01);
181}
182
183uint8_t zigzag8(int8_t val)
184{
185 return val >= 0 ?
186 ((uint8_t)val) << 1 :
187 ((((uint8_t)(-1 - val)) << 1) | 0x01);
188}
189
190int64_t unzigzag64(uint64_t val)
191{
192 return !(val & 0x01) ?
193 ((int64_t)(val >> 1)) :
194 (-1 * (int64_t)((val+1) >> 1));
195}
196
197int32_t unzigzag32(uint32_t val)
198{
199 return !(val & 0x01) ?
200 ((int32_t)(val >> 1)) :
201 (-1 * (int32_t)((val+1) >> 1));
202}
203
204int8_t unzigzag8(uint8_t val)
205{
206 return !(val & 0x01) ?
207 ((int8_t)(val >> 1)) :
208 (-1 * (int8_t)((val+1) >> 1));
209}
210
211
This library is the generic geometry handling section of PostGIS.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
int64_t unzigzag64(uint64_t val)
Definition varint.c:190
int32_t unzigzag32(uint32_t val)
Definition varint.c:197
size_t varint_s32_encode_buf(int32_t val, uint8_t *buf)
Definition varint.c:95
size_t varint_size(const uint8_t *the_start, const uint8_t *the_end)
Definition varint.c:148
size_t varint_s64_encode_buf(int64_t val, uint8_t *buf)
Definition varint.c:89
int8_t unzigzag8(uint8_t val)
Definition varint.c:204
size_t varint_u64_encode_buf(uint64_t val, uint8_t *buf)
Definition varint.c:76
int64_t varint_s64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size)
Definition varint.c:102
uint64_t zigzag64(int64_t val)
Definition varint.c:169
uint64_t varint_u64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size)
Definition varint.c:109
uint32_t zigzag32(int32_t val)
Definition varint.c:176
static size_t _varint_u64_encode_buf(uint64_t val, uint8_t *buf)
Definition varint.c:34
uint8_t zigzag8(int8_t val)
Definition varint.c:183
size_t varint_u32_encode_buf(uint32_t val, uint8_t *buf)
Definition varint.c:83