libosmscout  1.1.1
Number.h
Go to the documentation of this file.
1 #ifndef OSMSCOUT_NUMBER_H
2 #define OSMSCOUT_NUMBER_H
3 
4 /*
5  This source is part of the libosmscout library
6  Copyright (C) 2009 Tim Teulings
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22 
24 
25 #include <array>
26 #include <limits>
27 #include <cstddef>
28 #include <cassert>
29 
31 
32 namespace osmscout {
33 
49  template<typename N>
50  inline unsigned int EncodeNumberSigned(N number,
51  char* buffer)
52  {
53  unsigned int bytes=1;
54  char val;
55 
56  if (number<0) {
57  number^=static_cast<N>(-1);
58  val=static_cast<char>((number & 0x3f) << 1 | 0x01);
59  }
60  else {
61  val=static_cast<char>((number & 0x3f) << 1);
62  }
63 
64  number>>=6;
65 
66  while (number!=0) {
67  *(buffer++)=val | 0x80;
68  val=static_cast<char>(number & 0x7f);
69  number>>=7;
70  bytes++;
71  }
72 
73  *buffer=val;
74  return bytes;
75  }
76 
91  template<typename N>
92  inline unsigned int EncodeNumberUnsigned(N number,
93  char* buffer)
94  {
95  unsigned int bytes=0;
96 
97  while (number>0x7f) {
98  buffer[bytes]=static_cast<char>((number & 0x7f) | 0x80);
99  number>>=7;
100  bytes++;
101  }
102 
103  buffer[bytes]=static_cast<char>(number);
104  bytes++;
105 
106  return bytes;
107  }
108 
109  template<bool is_signed, typename N>
111  {
112  };
113 
114  template<typename N>
115  struct EncodeNumberTemplated<true, N>
116  {
117  static inline unsigned int f(N number,char* buffer)
118  {
119  return EncodeNumberSigned<N>(number,buffer);
120  }
121  };
122 
123  template<typename N>
124  struct EncodeNumberTemplated<false, N>
125  {
126  static inline unsigned int f(N number,char* buffer)
127  {
128  return EncodeNumberUnsigned<N>(number,buffer);
129  }
130  };
131 
144  template<typename N>
145  inline unsigned int EncodeNumber(N number,
146  char* buffer)
147  {
149  ::f(number,buffer);
150  }
151 
164  template<typename N, size_t S>
165  inline unsigned int EncodeNumber(N number,
166  std::array<char, S> &buffer)
167  {
168  if constexpr (std::numeric_limits<N>::is_signed) {
169  static_assert(sizeof(N) * 64 + 7 <= S * 56, "Not enough big buffer for encoding signed number");
170  } else {
171  static_assert(sizeof(N) * 64 <= S * 56, "Not enough big buffer for encoding unsigned number");
172  }
174  ::f(number,buffer.data());
175  assert(dataWritten<=S);
176  return dataWritten;
177  }
178 
186  template<typename N>
187  inline unsigned int DecodeNumberSigned(const char* buffer,
188  N& number)
189  {
190  unsigned int shift=0;
191  unsigned int nextShift=0;
192  unsigned int bytes=1;
193 
194  // negative form
195  if ((*buffer & 0x01)!=0) {
196  N val=(*buffer & 0x7e) >> 1;
197 
198  number=-1;
199  nextShift=6;
200 
201  while ((*(buffer++) & 0x80)!=0) {
202  number^=(val << shift);
203  val=*buffer & 0x7f;
204  shift=nextShift;
205  nextShift+=7;
206  bytes++;
207  }
208 
209  number^=static_cast<N>(val) << shift;
210  }
211  else {
212  N val=(*buffer & 0x7e) >> 1;
213 
214  number=0;
215  nextShift=6;
216 
217  while ((*(buffer++) & 0x80)!=0) {
218  number|=(val << shift);
219  val=*buffer & 0x7f;
220  shift=nextShift;
221  nextShift+=7;
222  bytes++;
223  }
224 
225  number|=static_cast<N>(val) << shift;
226  }
227 
228  return bytes;
229  }
230 
238  template<typename N>
239  inline unsigned int DecodeNumberUnsigned(const char* buffer,
240  N& number)
241  {
242  unsigned int shift=0;
243  unsigned int bytes=1;
244 
245  number=0;
246 
247  while (true) {
248  number|=static_cast<N>(*buffer & 0x7f) << shift;
249 
250  if (((*buffer) & 0x80)==0) {
251  return bytes;
252  }
253 
254  bytes++;
255  buffer++;
256  shift+=7;
257  }
258 
259  // Only for the compiler...
260  return bytes;
261  }
262 
263  template<bool is_signed, typename N>
265  {
266  };
267 
268  template<typename N>
269  struct DecodeNumberTemplated<true, N>
270  {
271  static inline unsigned int f(const char* buffer, N& number)
272  {
273  return DecodeNumberSigned<N>(buffer,number);
274  }
275  };
276 
277  template<typename N>
278  struct DecodeNumberTemplated<false, N>
279  {
280  static inline unsigned int f(const char* buffer, N& number)
281  {
282  return DecodeNumberUnsigned<N>(buffer,number);
283  }
284  };
285 
293  template<typename N>
294  inline unsigned int DecodeNumber(const char* buffer,
295  N& number)
296  {
298  ::f(buffer,number);
299  }
300 
305  template<typename N>
306  inline N BitsToBytes(N bits)
307  {
308  return bits%8==0 ? bits/8 : bits/8+1;
309  }
310 
317  template<typename N>
318  uint8_t BytesNeededToEncodeNumber(N number)
319  {
320  uint8_t bytes=0;
321 
322  while (number!=0) {
323  number=number/256;
324  bytes++;
325  }
326 
327  if (bytes==0) {
328  bytes=1;
329  }
330 
331  return bytes;
332  }
333 
340  template<typename N>
341  uint8_t BitsNeededToEncodeNumber(N number)
342  {
343  uint8_t bits=0;
344 
345  while (number!=0) {
346  number=number/2;
347  bits++;
348  }
349 
350  if (bits==0) {
351  bits=1;
352  }
353 
354  return bits;
355  }
356 
366  extern OSMSCOUT_API uint64_t InterleaveNumbers(uint32_t a,
367  uint32_t b);
368 }
369 
370 #endif
unsigned int DecodeNumberUnsigned(const char *buffer, N &number)
Definition: Number.h:239
unsigned int EncodeNumberUnsigned(N number, char *buffer)
Definition: Number.h:92
static unsigned int f(N number, char *buffer)
Definition: Number.h:126
N BitsToBytes(N bits)
Definition: Number.h:306
uint8_t BytesNeededToEncodeNumber(N number)
Definition: Number.h:318
unsigned int EncodeNumberSigned(N number, char *buffer)
Definition: Number.h:50
unsigned int DecodeNumber(const char *buffer, N &number)
Definition: Number.h:294
static unsigned int f(N number, char *buffer)
Definition: Number.h:117
OSMSCOUT_API uint64_t InterleaveNumbers(uint32_t a, uint32_t b)
Definition: Area.h:38
#define OSMSCOUT_API
Definition: CoreImportExport.h:45
Definition: Number.h:264
unsigned int EncodeNumber(N number, char *buffer)
Definition: Number.h:145
Definition: Number.h:110
static unsigned int f(const char *buffer, N &number)
Definition: Number.h:271
unsigned int DecodeNumberSigned(const char *buffer, N &number)
Definition: Number.h:187
static unsigned int f(const char *buffer, N &number)
Definition: Number.h:280
uint8_t BitsNeededToEncodeNumber(N number)
Definition: Number.h:341