JASSv2
compress_integer_variable_byte.h
Go to the documentation of this file.
1 /*
2  COMPRESS_INTEGER_VARIABLE_BYTE.H
3  --------------------------------
4  Copyright (c) 2016 Andrew Trotman
5  Released under the 2-clause BSD license (See:https://en.wikipedia.org/wiki/BSD_licenses)
6 */
13 #pragma once
14 
15 #include "compress.h"
16 
17 #define forceinline inline
18 #define JASS_COMPRESS_INTEGER_BITS_PER_INTEGER 32
19 
20  /*
21  CLASS COMPRESS_INTEGER_VARIABLE_BYTE
22  ------------------------------------
23  */
40  {
41  public:
42  typedef uint32_t integer;
43  /*
44  COMPRESS_INTEGER_VARIABLE_BYTE::COMPRESS_INTEGER_VARIABLE_BYTE()
45  ----------------------------------------------------------------
46  */
51  {
52  /* Nothing */
53  }
54 
55  /*
56  COMPRESS_INTEGER_VARIABLE_BYTE::~COMPRESS_INTEGER_VARIABLE_BYTE()
57  -----------------------------------------------------------------
58  */
63  {
64  /* Nothing */
65  }
66 
67  /*
68  COMPRESS_INTEGER_VARIABLE_BYTE::ENCODE()
69  ----------------------------------------
70  */
79  virtual size_t encode(void *encoded, size_t encoded_buffer_length, const integer *source, size_t source_integers);
80 
81  /*
82  COMPRESS_INTEGER_VARIABLE_BYTE::DECODE()
83  ----------------------------------------
84  */
92  virtual void decode(integer *decoded, size_t integers_to_decode, const void *source, size_t source_length)
93  {
94  /*
95  Call through to the static version of this function
96  */
97  static_decode(decoded, integers_to_decode, source, source_length);
98  }
99 
100  /*
101  COMPRESS_INTEGER_VARIABLE_BYTE::STATIC_DECODE()
102  -----------------------------------------------
103  */
111  static inline void static_decode(integer *decoded, size_t integers_to_decode, const void *source_as_void, size_t source_length)
112  {
113  const uint8_t *source = static_cast<const uint8_t *>(source_as_void);
114  const uint8_t *end = source + source_length; // compute the stopping condition
115 
116  while (source < end)
117  {
118  decompress_into(decoded, source);
119  decoded++;
120  }
121  }
122 
123  /*
124  COMPRESS_INTEGER_VARIABLE_BYTE::DECODE_WITH_WRITER()
125  ----------------------------------------------------
126  */
133 #ifdef SIMD_JASS
134  virtual void decode_with_writer(size_t integers_to_decode, const void *source_as_void, size_t source_length)
135  {
136  const uint8_t *source = static_cast<const uint8_t *>(source_as_void);
137  const uint8_t *end = source + source_length; // compute the stopping condition
138 
139  while (source < end)
140  {
141  integer into;
142 
143  decompress_into(&into, source);
144  add_rsv_d1(into);
145  }
146  }
147 #endif
148 
149  /*
150  COMPRESS_INTEGER_VARIABLE_BYTE::BYTES_NEEDED_FOR()
151  --------------------------------------------------
152  */
158  static inline size_t bytes_needed_for(integer value)
159  {
160  /*
161  The size can be computed by compairing to a bunch of constants.
162  */
163  if (value < ((uint64_t)1 << 7))
164  return 1;
165  else if (value < ((uint64_t)1 << 14))
166  return 2;
167  else if (value < ((uint64_t)1 << 21))
168  return 3;
169  else if (value < ((uint64_t)1 << 28))
170  return 4;
171 #if JASS_COMPRESS_INTEGER_BITS_PER_INTEGER == 32
172  else
173  return 5;
174 #else
175  else if (value < ((uint64_t)1 << 35))
176  return 5;
177  else if (value < ((uint64_t)1 << 42))
178  return 6;
179  else if (value < ((uint64_t)1 << 49))
180  return 7;
181  else if (value < ((uint64_t)1 << 56))
182  return 8;
183  else if (value < ((uint64_t)1 << 63))
184  return 9;
185  else
186  return 10;
187 #endif
188  }
189 
190  /*
191  COMPRESS_INTEGER_VARIABLE_BYTE::COMPRESS_INTO()
192  -----------------------------------------------
193  */
199  template <typename DESTINATION>
200  static forceinline void compress_into(DESTINATION &destination, integer value)
201  {
202  /*
203  Work out how many bytes it'll take to encode
204  */
205  if (value < ((uint64_t)1 << 7))
206  goto one;
207  else if (value < ((uint64_t)1 << 14))
208  goto two;
209  else if (value < ((uint64_t)1 << 21))
210  goto three;
211  else if (value < ((uint64_t)1 << 28))
212  goto four;
213 #if JASS_COMPRESS_INTEGER_BITS_PER_INTEGER == 32
214  goto five;
215 #else
216  else if (value < ((uint64_t)1 << 35))
217  goto five;
218  else if (value < ((uint64_t)1 << 42))
219  goto six;
220  else if (value < ((uint64_t)1 << 49))
221  goto seven;
222  else if (value < ((uint64_t)1 << 56))
223  goto eight;
224  else if (value < ((uint64_t)1 << 63))
225  goto nine;
226  else
227  goto ten;
228 #endif
229 
230  /*
231  Now encode byte at a time with fall-through
232  */
233 #if JASS_COMPRESS_INTEGER_BITS_PER_INTEGER == 64
234  ten:
235  *destination = (value >> 63) & 0x7F;
236  ++destination;
237  nine:
238  *destination = (value >> 56) & 0x7F;
239  ++destination;
240  eight:
241  *destination = (value >> 49) & 0x7F;
242  ++destination;
243  seven:
244  *destination = (value >> 42) & 0x7F;
245  ++destination;
246  six:
247  *destination = (value >> 35) & 0x7F;
248  ++destination;
249 #endif
250  five:
251  *destination = (value >> 28) & 0x7F;
252  ++destination;
253  four:
254  *destination = (value >> 21) & 0x7F;
255  ++destination;
256  three:
257  *destination = (value >> 14) & 0x7F;
258  ++destination;
259  two:
260  *destination = (value >> 7) & 0x7F;
261  ++destination;
262  one:
263  *destination = (value & 0x7F) | 0x80;
264  ++destination;
265  }
266 
267 
268  /*
269  COMPRESS_INTEGER_VARIABLE_BYTE::DECOMPRESS_INTO()
270  -------------------------------------------------
271  */
277  template <typename SOURCE>
278  static forceinline void decompress_into(integer *decoded, SOURCE &source)
279  {
280  /*
281  If the high bit is set the sequence is over, otherwise, in an unwound loop, decode the integers one at a time.
282  */
283  if (*source & 0x80)
284  {
285  *decoded = *source & 0x7F;
286  ++source;
287  }
288  else
289  {
290  *decoded = *source;
291  ++source;
292  if (*source & 0x80)
293  {
294  *decoded = (*decoded << 7) | (*source & 0x7F);
295  ++source;
296  }
297  else
298  {
299  *decoded = (*decoded << 7) | *source;
300  ++source;
301  if (*source & 0x80)
302  {
303  *decoded = (*decoded << 7) | (*source & 0x7F);
304  ++source;
305  }
306  else
307  {
308  *decoded = (*decoded << 7) | *source;
309  ++source;
310  if (*source & 0x80)
311  {
312  *decoded = (*decoded << 7) | (*source & 0x7F);
313  ++source;
314  }
315  else
316  {
317  *decoded = (*decoded << 7) | *source;
318  ++source;
319  if (*source & 0x80)
320  {
321  *decoded = (*decoded << 7) | (*source & 0x7F);
322  ++source;
323  }
324  else
325  {
326  #if JASS_COMPRESS_INTEGER_BITS_PER_INTEGER == 64
327  *decoded = (*decoded << 7) | *source;
328  ++source;
329  if (*source & 0x80)
330  {
331  *decoded = (*decoded << 7) | (*source & 0x7F);
332  ++source;
333  }
334  else
335  {
336  *decoded = (*decoded << 7) | *source;
337  ++source;
338  if (*source & 0x80)
339  {
340  *decoded = (*decoded << 7) | (*source & 0x7F);
341  ++source;
342  }
343  else
344  {
345  *decoded = (*decoded << 7) | *source;
346  ++source;
347  if (*source & 0x80)
348  {
349  *decoded = (*decoded << 7) | (*source & 0x7F);
350  ++source;
351  }
352  else
353  {
354  *decoded = (*decoded << 7) | *source;
355  ++source;
356  if (*source & 0x80)
357  {
358  *decoded = (*decoded << 7) | (*source & 0x7F);
359  ++source;
360  }
361  else
362  {
363  *decoded = (*decoded << 7) | *source;
364  ++source;
365  if (*source & 0x80)
366  {
367  *decoded = (*decoded << 7) | (*source & 0x7F);
368  ++source;
369  }
370  else
371  {
372  *decoded = (*decoded << 7) | *source;
373  ++source;
374  }
375  }
376  }
377  }
378  }
379  #endif
380  }
381  }
382  }
383  }
384  }
385  }
386  /*
387  For JASS V1
388  */
389  virtual long long compress(unsigned char *destination, long long destination_length, uint32_t *source, long long source_integers)
390  {
391  return encode(destination, destination_length, source, source_integers);
392  }
393 
394  virtual void decompress(uint32_t *destination, unsigned char *source, long long destination_integers)
395  {
396  /* Nothing */
397  }
398 
399 };
static forceinline void decompress_into(integer *decoded, SOURCE &source)
Decode the given integer placing the encoding into destination (whose size is not validated)...
Definition: compress_integer_variable_byte.h:278
virtual size_t encode(void *encoded, size_t encoded_buffer_length, const integer *source, size_t source_integers)
Encode a sequence of integers returning the number of bytes used for the encoding, or 0 if the encoded sequence doesn&#39;t fit in the buffer.
Definition: compress_integer_variable_byte.cpp:20
Variable byte compression for integer sequences.
Definition: compress_integer_variable_byte.h:39
static void static_decode(integer *decoded, size_t integers_to_decode, const void *source_as_void, size_t source_length)
Decode a sequence of integers encoded with this codex.
Definition: compress_integer_variable_byte.h:111
static forceinline void compress_into(DESTINATION &destination, integer value)
Encode the given integer placing the encoding into destination (whose size is not validated)...
Definition: compress_integer_variable_byte.h:200
virtual void decode(integer *decoded, size_t integers_to_decode, const void *source, size_t source_length)
Decode a sequence of integers encoded with this codex.
Definition: compress_integer_variable_byte.h:92
Definition: compress.h:14
virtual ~compress_integer_variable_byte()
Constructor.
Definition: compress_integer_variable_byte.h:62
compress_integer_variable_byte()
Constructor.
Definition: compress_integer_variable_byte.h:50
static size_t bytes_needed_for(integer value)
Decode a sequence of integers encoded with this codex, calling add_rsv for each SIMD register...
Definition: compress_integer_variable_byte.h:158