SmallNumberCoder.h
Go to the documentation of this file.
1 #pragma once
2 
4 {
5 private:
6  char *m_pBuffer;
7  int m_BufferSize;
8  int m_Offset;
9 
10  void *m_RefPointA, *m_RefPointB;
11 
12 private:
13  static inline int IsSignedIntConstrained(int value, int bits)
14  {
15  int mask = -1 << bits;
16  int refVal = ~(((value >> (bits - 1)) & 1) - 1);
17  return (value & mask) == (refVal & mask);
18  }
19 
20  static inline int IsUnsignedIntConstrained(unsigned value, int bits)
21  {
22  int mask = -1 << bits;
23  return (value & mask) == 0;
24  }
25 
26  inline bool WriteSmallInteger(int value, int byteCount)
27  {
28  if (byteCount > (m_BufferSize - m_Offset))
29  return false;
30 
31 #if defined(ARM_MATH_CM3) || defined(ARM_MATH_CM4)
32  switch (byteCount)
33  {
34  case 1:
35  *((char *)(m_pBuffer + m_Offset)) = (char)value;
36  break;
37  case 2:
38  *((short *)(m_pBuffer + m_Offset)) = (short)value;
39  break;
40  case 4:
41  *((int *)(m_pBuffer + m_Offset)) = (int)value;
42  break;
43  default:
44  return 0;
45  }
46 #else
47  for (int i = 0; i < byteCount; i++)
48  *((char *)(m_pBuffer + m_Offset + i)) = ((char *)&value)[i];
49 #endif
50 
51  m_Offset += byteCount;
52  return byteCount;
53  }
54 
55 public:
56  SmallNumberCoder(void *pBuffer, unsigned size, void *pRefPointA, void *pRefPointB)
57  : m_pBuffer((char *)pBuffer), m_BufferSize(size), m_Offset(0), m_RefPointA(pRefPointA), m_RefPointB(pRefPointB)
58  {
59  }
60 
61  inline bool WriteTinySIntWithFlag(int value, bool flag)
62  {
63  if (IsSignedIntConstrained(value, 6))
64  {
65  unsigned b = value << 2 | (!!flag << 1);
66  return WriteSmallInteger(b, 1);
67  }
68  else if (IsSignedIntConstrained(value, 12))
69  {
70  unsigned w = (value << 4) | (!!flag << 1) | (1 << 2) | 1;
71  return WriteSmallInteger(w, 2);
72  }
73  else if (IsSignedIntConstrained(value, 28))
74  {
75  unsigned dw = (value << 4) | (!!flag << 1) | (2 << 2) | 1;
76  return WriteSmallInteger(dw, 4);
77  }
78  else
79  {
80  unsigned b = (!!flag << 1) | (3 << 2) | 1;
81  if (!WriteSmallInteger(b, 1))
82  return false;
83  if (!WriteSmallInteger(value, 4))
84  return false;
85  return true;
86  }
87  }
88 
89  inline bool WriteTinySInt(int value)
90  {
91  if (IsSignedIntConstrained(value, 7))
92  {
93  unsigned b = (value << 1);
94  return WriteSmallInteger(b, 1);
95  }
96  else if (IsSignedIntConstrained(value, 14))
97  {
98  unsigned w = (value << 2) | 1;
99  return WriteSmallInteger(w, 2);
100  }
101  else
102  {
103  unsigned dw = (value << 2) | 3;
104  return WriteSmallInteger(dw, 4);
105  }
106  }
107 
108  inline bool WriteSmallMostLikelyEvenSInt(int value)
109  {
110  int signBit = (value >> 31) & 1;
111  int permutatedValue = (int)((value & 0xffff0000) | ((value & 0xffff) >> 1) | (((value & 1) ^ signBit) << 15));
112 
113  if (IsSignedIntConstrained(permutatedValue, 15))
114  {
115  unsigned w = permutatedValue << 1;
116  return WriteSmallInteger(w, 2);
117  }
118  else if (IsSignedIntConstrained(permutatedValue, 30))
119  {
120  unsigned dw = (permutatedValue << 2) | 1;
121  return WriteSmallInteger(dw, 4);
122  }
123  else
124  {
125  unsigned b = 0xff;
126  if (!WriteSmallInteger(b, 1))
127  return false;
128  return WriteSmallInteger(permutatedValue, 4);
129  }
130  }
131 
132  inline bool WriteSmallUnsignedInt(unsigned value)
133  {
134  if (IsUnsignedIntConstrained(value, 15))
135  {
136  unsigned w = value << 1;
137  return WriteSmallInteger(w, 2);
138  }
139  else if (IsUnsignedIntConstrained(value, 30))
140  {
141  unsigned dw = (value << 2) | 1;
142  return WriteSmallInteger(dw, 4);
143  }
144  else
145  {
146  unsigned b = 0xff;
147  if (!WriteSmallInteger(b, 1))
148  return false;
149  return WriteSmallInteger(value, 4);
150  }
151  }
152 
153  inline bool WriteSmallUnsignedIntWithFlag(unsigned value, bool flag)
154  {
155  if (IsUnsignedIntConstrained(value, 14))
156  {
157  unsigned w = value << 2 | (!!flag << 1);
158  return WriteSmallInteger(w, 2);
159  }
160  else if (IsUnsignedIntConstrained(value, 29))
161  {
162  unsigned dw = (value << 3) | 1 | (!!flag << 2);
163  return WriteSmallInteger(dw, 4);
164  }
165  else
166  {
167  unsigned b = flag ? 0xff : 0x7f;
168  if (!WriteSmallInteger(b, 1))
169  return false;
170  return WriteSmallInteger(value, 4);
171  }
172  }
173 
174  inline bool WriteSmallSignedIntWithFlag(int value, bool flag)
175  {
176  if (IsSignedIntConstrained(value, 14))
177  {
178  unsigned w = value << 2 | (!!flag << 1);
179  return WriteSmallInteger(w, 2);
180  }
181  else if (IsSignedIntConstrained(value, 29))
182  {
183  unsigned dw = (value << 3) | 1 | (!!flag << 2);
184  return WriteSmallInteger(dw, 4);
185  }
186  else
187  {
188  unsigned b = flag ? 0xff : 0x7f;
189  if (!WriteSmallInteger(b, 1))
190  return false;
191  return WriteSmallInteger(value, 4);
192  }
193  }
194 
195  inline bool WritePackedUIntPair(unsigned short largerInt, unsigned short smallerInt)
196  {
197  if (largerInt < 16 && smallerInt < 14)
198  {
199  unsigned b = largerInt << 4 | smallerInt;
200  return WriteSmallInteger(b, 1);
201  }
202  else if (largerInt < 256 && smallerInt < 256)
203  {
204  if (!WriteSmallInteger(0xFE, 1))
205  return false;
206  if (!WriteSmallInteger(largerInt, 1))
207  return false;
208  if (!WriteSmallInteger(smallerInt, 1))
209  return false;
210  return true;
211  }
212  else
213  {
214  if (!WriteSmallInteger(0xFF, 1))
215  return false;
216  if (!WriteSmallInteger(largerInt, 2))
217  return false;
218  if (!WriteSmallInteger(smallerInt, 2))
219  return false;
220  return true;
221  }
222  }
223 
224  inline bool WriteStackEntry(int indexDelta, void *value, bool useRefPointB)
225  {
226  int dist;
227  if (useRefPointB)
228  {
229  dist = (int)value - (int)m_RefPointB;
230  m_RefPointB = value;
231  }
232  else
233  {
234  dist = (int)value - (int)m_RefPointA;
235  m_RefPointA = value;
236  }
237 
238  if (!WriteTinySIntWithFlag(indexDelta, useRefPointB))
239  return false;
240  return WriteSmallMostLikelyEvenSInt(dist);
241  }
242 
243  int GetOffset()
244  {
245  return m_Offset;
246  }
247 
248  void *GetBuffer()
249  {
250  return m_pBuffer;
251  }
252 
253  void ExportState(void **pRefPointA, void **pRefPointB)
254  {
255  *pRefPointA = m_RefPointA;
256  *pRefPointB = m_RefPointB;
257  }
258 
259  void SetOffset(int offset)
260  {
261  m_Offset = offset;
262  }
263 
264  unsigned RemainingSize()
265  {
266  return m_BufferSize - m_Offset;
267  }
268 };
269 
271 {
272 private:
273  const char *m_pBuffer;
274  int m_BufferSize;
275  int m_Offset;
276 
277  char *m_RefPointA, *m_RefPointB;
278 
279 private:
280  static int SignExtend(int value, int bits)
281  {
282  return ((~(((value >> (bits - 1)) & 1) - 1)) << bits) | value;
283  }
284 
285  inline unsigned PeekInt32(int delta = 0)
286  {
287  int offset = m_Offset + delta;
288 #if defined(ARM_MATH_CM3) || defined(ARM_MATH_CM4)
289  return *((unsigned *)(m_pBuffer + offset));
290 #else
291  return (((unsigned char *)(m_pBuffer + offset))[0] << 0) | (((unsigned char *)(m_pBuffer + offset))[1] << 8) | (((unsigned char *)(m_pBuffer + offset))[2] << 16) | (((unsigned char *)(m_pBuffer + offset))[3] << 24);
292 #endif
293  }
294 
295  inline unsigned PeekInt16(int delta = 0)
296  {
297  int offset = m_Offset + delta;
298 #if defined(ARM_MATH_CM3) || defined(ARM_MATH_CM4)
299  return *((unsigned short *)(m_pBuffer + offset));
300 #else
301  return (((unsigned char *)(m_pBuffer + offset))[0] << 0) | (((unsigned char *)(m_pBuffer + offset))[1] << 8);
302 #endif
303  }
304 
305 public:
306  SmallNumberDecoder(const void *pBuffer, unsigned size, void *pRefPointA, void *pRefPointB)
307  : m_pBuffer((char *)pBuffer), m_BufferSize(size), m_Offset(0), m_RefPointA((char *)pRefPointA), m_RefPointB((char *)pRefPointB)
308  {
309  }
310 
311  inline bool ReadTinySIntWithFlag(int *pValue, bool *pFlag)
312  {
313  if ((m_Offset + 1) > m_BufferSize)
314  return false;
315 
316  unsigned char b = (unsigned char)m_pBuffer[m_Offset];
317 
318  if ((b & 0x01) == 0)
319  {
320  *pValue = SignExtend(b >> 2, 6);
321  *pFlag = (b & 0x02) != 0;
322  m_Offset += 1;
323  return true;
324  }
325  else if (((b >> 2) & 0x03) == 1)
326  {
327  if ((m_Offset + 2) > m_BufferSize)
328  return false;
329  unsigned w = PeekInt16();
330 
331  *pValue = SignExtend(w >> 4, 12);
332  *pFlag = (w & 0x02) != 0;
333  m_Offset += 2;
334  return true;
335  }
336  else if (((b >> 2) & 0x03) == 2)
337  {
338  if ((m_Offset + 4) > m_BufferSize)
339  return false;
340  unsigned dw = PeekInt32();
341 
342  *pValue = SignExtend(dw >> 4, 28);
343  *pFlag = (dw & 0x02) != 0;
344  m_Offset += 4;
345  return true;
346  }
347  else
348  {
349  if ((m_Offset + 5) > m_BufferSize)
350  return false;
351  *pValue = PeekInt32(1);
352  *pFlag = (b & 0x02) != 0;
353  m_Offset += 5;
354  return true;
355  }
356  }
357 
358  bool ReadSmallMostlyEvenSInt(int *pValue)
359  {
360  if ((m_Offset + 1) > m_BufferSize)
361  return false;
362 
363  unsigned char b = (unsigned char)m_pBuffer[m_Offset];
364 
365  int permutatedValue;
366  if ((b & 0x01) == 0)
367  {
368  if ((m_Offset + 2) > m_BufferSize)
369  return false;
370  short w = PeekInt16();
371  permutatedValue = w >> 1;
372  m_Offset += 2;
373  }
374  else if ((b & 0x03) == 0x01)
375  {
376  if ((m_Offset + 4) > m_BufferSize)
377  return false;
378  int dw = PeekInt32();
379  permutatedValue = dw >> 2;
380  m_Offset += 4;
381  }
382  else
383  {
384  if ((m_Offset + 5) > m_BufferSize)
385  return false;
386  int dw = PeekInt32(1);
387  permutatedValue = dw >> 2;
388  m_Offset += 5;
389  }
390 
391  int signBit = (permutatedValue >> 31) & 1;
392  *pValue = (int)(((unsigned)permutatedValue & 0xffff0000) | ((((unsigned)permutatedValue & 0x8000) >> 15) ^ signBit) | (((unsigned)permutatedValue & 0x7fff) << 1));
393  return true;
394  }
395 
396  inline bool ReadStackEntry(void ***pInOutStackAddr, void **pValue)
397  {
398  int dist;
399  bool useRefPointB;
400  int indexDelta = 0;
401 
402  if (!ReadTinySIntWithFlag(&indexDelta, &useRefPointB))
403  return false;
404  if (!ReadSmallMostlyEvenSInt(&dist))
405  return false;
406 
407  if (useRefPointB)
408  *pValue = (m_RefPointB += dist);
409  else
410  *pValue = (m_RefPointA += dist);
411 
412  *pInOutStackAddr += indexDelta;
413 
414  return true;
415  }
416 };
Definition: SmallNumberCoder.h:3
unsigned RemainingSize()
Definition: SmallNumberCoder.h:264
bool WriteTinySIntWithFlag(int value, bool flag)
Definition: SmallNumberCoder.h:61
int GetOffset()
Definition: SmallNumberCoder.h:243
bool ReadSmallMostlyEvenSInt(int *pValue)
Definition: SmallNumberCoder.h:358
bool ReadStackEntry(void ***pInOutStackAddr, void **pValue)
Definition: SmallNumberCoder.h:396
bool WriteSmallMostLikelyEvenSInt(int value)
Definition: SmallNumberCoder.h:108
bool WritePackedUIntPair(unsigned short largerInt, unsigned short smallerInt)
Definition: SmallNumberCoder.h:195
bool WriteSmallUnsignedInt(unsigned value)
Definition: SmallNumberCoder.h:132
bool WriteStackEntry(int indexDelta, void *value, bool useRefPointB)
Definition: SmallNumberCoder.h:224
Definition: SmallNumberCoder.h:270
bool WriteTinySInt(int value)
Definition: SmallNumberCoder.h:89
void ExportState(void **pRefPointA, void **pRefPointB)
Definition: SmallNumberCoder.h:253
bool WriteSmallUnsignedIntWithFlag(unsigned value, bool flag)
Definition: SmallNumberCoder.h:153
SmallNumberCoder(void *pBuffer, unsigned size, void *pRefPointA, void *pRefPointB)
Definition: SmallNumberCoder.h:56
bool WriteSmallSignedIntWithFlag(int value, bool flag)
Definition: SmallNumberCoder.h:174
void * GetBuffer()
Definition: SmallNumberCoder.h:248
void SetOffset(int offset)
Definition: SmallNumberCoder.h:259
bool ReadTinySIntWithFlag(int *pValue, bool *pFlag)
Definition: SmallNumberCoder.h:311
SmallNumberDecoder(const void *pBuffer, unsigned size, void *pRefPointA, void *pRefPointB)
Definition: SmallNumberCoder.h:306