My Project
BlockDataCodec.h
1 #pragma once
2 #include <stdint.h>
3 
4 namespace ParaEngine
5 {
7  {
8  public:
9  template<typename VALUE_TYPE>
10  static bool TryDecodeUInt32(CParaFile& source, VALUE_TYPE& value, int& nByteRead)
11  {
12  int b = 0;
13  if (source.read(&b, 1) == 0)
14  return false;
15  ++nByteRead;
16  if ((b & 0x80) == 0)
17  {
18  // single-byte
19  value = (VALUE_TYPE)b;
20  return true;
21  }
22 
23  int shift = 7;
24 
25  value = (VALUE_TYPE)(b & 0x7F);
26  bool keepGoing;
27  int i = 0;
28  do
29  {
30  if (source.read(&b, 1) == 0)
31  return false;
32  ++nByteRead;
33 
34  i++;
35  keepGoing = (b & 0x80) != 0;
36  value |= ((VALUE_TYPE)(b & 0x7F)) << shift;
37  shift += 7;
38  } while (keepGoing && i < 4);
39  if (keepGoing && i == 4)
40  {
41  return false;
42  }
43  return true;
44  }
45 
46  template<typename VALUE_TYPE>
47  static int EncodeUInt32(VALUE_TYPE value, BYTE* buffer, StringBuilder& stream)
48  {
49  int count = 0, index = 0;
50  do
51  {
52  buffer[index++] = (byte)((value & 0x7F) | 0x80);
53  value >>= 7;
54  count++;
55  } while (value != 0);
56  buffer[index - 1] &= 0x7F;
57  stream.append((const char*)buffer, count);
58  return count;
59  }
60 
70  template<typename VALUE_TYPE>
71  static int EncodeSkipOne(StringBuilder& stream, const std::vector<VALUE_TYPE>& data)
72  {
73  int nCount = data.size();
74  if (nCount == 0) return 0;
75  byte buffer[10];
76  int last = -1, len = 0;
77  for (int i = 0; i < nCount;)
78  {
79  int gap = data[i] - 2 - last, size = 0;
80  while (++i < nCount && data[i] == data[i - 1] + 1)
81  size++;
82  last = data[i - 1];
83  len += EncodeUInt32((VALUE_TYPE)gap, buffer, stream)
84  + EncodeUInt32((VALUE_TYPE)size, buffer, stream);
85  }
86  return len;
87  }
88 
90  template<typename VALUE_TYPE>
91  static bool IsSkipOneBetter(const std::vector<VALUE_TYPE>& data)
92  {
93  int nCount = data.size();
94  if (nCount < 2) return false;
95 
96  int nSkipCount = 0;
97  int nHalfCount = nCount >> 1;
98  for (int i = 1; i < nCount && nSkipCount <= nHalfCount; ++i)
99  {
100  if (data[i] == (data[i - 1] + 1))
101  nSkipCount++;
102  }
103  return nSkipCount >= nHalfCount;
104  }
105 
106  template<typename VALUE_TYPE>
107  static void DecodeSkipOne(CParaFile& stream, std::vector<VALUE_TYPE>& list, int nStreamSize = 0xfffffff)
108  {
109  VALUE_TYPE skip, take;
110  int last = 0;
111  int nByteRead = 0;
112  while (nByteRead<nStreamSize && TryDecodeUInt32(stream, skip, nByteRead)
113  && TryDecodeUInt32(stream, take, nByteRead))
114  {
115  last += (int)skip + 1;
116  for (VALUE_TYPE i = 0; i <= take; i++) {
117  list.push_back(last++);
118  }
119  }
120  }
121 
122  template<typename VALUE_TYPE>
123  static int EncodeIntDeltaArray(StringBuilder& stream, const std::vector<VALUE_TYPE>& data)
124  {
125  int nCount = data.size();
126  if (nCount == 0) return 0;
127  int len = 0;
128  byte buffer[10];
129  len += EncodeUInt32((VALUE_TYPE)(data[0]), buffer, stream);
130 
131  for (int i = 1; i < nCount; ++i)
132  {
133  len += EncodeUInt32((VALUE_TYPE)(data[i] - data[i - 1]), buffer, stream);
134  }
135  return len;
136  }
137 
138  template<typename VALUE_TYPE>
139  static void DecodeIntDeltaArray(CParaFile& stream, std::vector<VALUE_TYPE>& list, int nStreamSize = 0xfffffff)
140  {
141  VALUE_TYPE lastValue, delta;
142  int last = 0;
143  int nByteRead = 0;
144 
145  if (nByteRead<nStreamSize && TryDecodeUInt32(stream, lastValue, nByteRead))
146  {
147  list.push_back(lastValue);
148  while (nByteRead<nStreamSize && TryDecodeUInt32(stream, delta, nByteRead))
149  {
150  lastValue += delta;
151  list.push_back(lastValue);
152  }
153  }
154  }
155 
160  template<typename VALUE_TYPE>
161  static int EncodeSameInteger(StringBuilder& stream, const std::vector<VALUE_TYPE>& data)
162  {
163  int nCount = data.size();
164  if (nCount == 0) return 0;
165  byte buffer[10];
166  int len = 0;
167  int last = data[0];
168  uint32_t size = 0;
169  len += EncodeUInt32(last, buffer, stream);
170 
171  for (int i = 0; i < nCount;)
172  {
173  size = 0;
174 
175  VALUE_TYPE cur_last = last;
176  while (++i < nCount && (cur_last = data[i]) == last)
177  size++;
178 
179  len += EncodeUInt32(size, buffer, stream);
180  if (last != cur_last)
181  {
182  last = cur_last;
183  len += EncodeUInt32(last, buffer, stream);
184  }
185  }
186  return len;
187  }
188 
189  template<typename VALUE_TYPE>
190  static void DecodeSameInteger(CParaFile& stream, std::vector<VALUE_TYPE>& list, int nStreamSize = 0xfffffff)
191  {
192  VALUE_TYPE last;
193  uint32_t size = 0;
194  int nByteRead = 0;
195  while (nByteRead<nStreamSize && TryDecodeUInt32(stream, last, nByteRead))
196  {
197  list.push_back(last);
198  size = 0;
199  if (nByteRead<nStreamSize && TryDecodeUInt32(stream, size, nByteRead))
200  {
201  for (uint32_t i = 0; i < size; i++) {
202  list.push_back(last);
203  }
204  }
205  }
206  }
207 
208  template<typename VALUE_TYPE>
209  static bool IsSameIntegerBetter(const std::vector<VALUE_TYPE>& data)
210  {
211  int nCount = data.size();
212  if (nCount == 0)
213  return false;
214  VALUE_TYPE last = data[0];
215  int len = 0;
216  uint32_t size = 0;
217  for (int i = 0; i < nCount && len<nCount;)
218  {
219  size = 0;
220  VALUE_TYPE cur_last = last;
221  while (++i < nCount && (cur_last = data[i]) == last)
222  size++;
223  last = cur_last;
224  len += 2;
225  }
226  return len<nCount;
227  }
228 
229  template<typename VALUE_TYPE>
230  static int EncodeIntArray(StringBuilder& stream, const std::vector<VALUE_TYPE>& data)
231  {
232  int nCount = data.size();
233  if (nCount == 0) return 0;
234  int len = 0;
235  byte buffer[10];
236  for (int i = 0; i < nCount; ++i)
237  {
238  len += EncodeUInt32(data[i], buffer, stream);
239  }
240  return len;
241  }
242 
243  template<typename VALUE_TYPE>
244  static void DecodeIntArray(CParaFile& stream, std::vector<VALUE_TYPE>& list, int nStreamSize = 0xfffffff)
245  {
246  VALUE_TYPE value;
247  int last = 0;
248  int nByteRead = 0;
249  while (nByteRead<nStreamSize && TryDecodeUInt32(stream, value, nByteRead))
250  {
251  list.push_back(value);
252  }
253  }
254  };
255 
260  template<typename VALUE_TYPE>
262  {
263  public:
264  CSameIntegerEncoder(StringBuilder* pStream) :m_pStream(pStream), m_bIsFirst(true), m_nLastValueCount(0), m_nLastValue(0){};
265 
266  void Reset(){
267  m_bIsFirst = true;
268  m_nLastValue = 0;
269  m_nLastValueCount = 0;
270  }
271  void Append(VALUE_TYPE nValue)
272  {
273  if (!m_bIsFirst)
274  {
275  if (m_nLastValue == nValue)
276  {
277  m_nLastValueCount++;
278  }
279  else
280  {
281  Finalize();
282  m_nLastValue = nValue;
283  m_nLastValueCount = 1;
284  }
285  }
286  else
287  {
288  m_nLastValue = nValue;
289  m_nLastValueCount = 1;
290  m_bIsFirst = false;
291  }
292  }
293 
294  /* @param nCount: must be larger than 1*/
295  void Append(VALUE_TYPE nValue, int nCount)
296  {
297  assert(nCount >= 1);
298  if (!m_bIsFirst)
299  {
300  if (m_nLastValue == nValue)
301  {
302  m_nLastValueCount += nCount;
303  }
304  else
305  {
306  Finalize();
307  m_nLastValue = nValue;
308  m_nLastValueCount = nCount;
309  }
310  }
311  else
312  {
313  m_nLastValue = nValue;
314  m_nLastValueCount = nCount;
315  m_bIsFirst = false;
316  }
317  }
318 
320  void Finalize()
321  {
322  if (m_nLastValueCount > 0)
323  {
324  byte buffer[10];
325  CIntegerEncoder::EncodeUInt32(m_nLastValue, buffer, *m_pStream);
326  CIntegerEncoder::EncodeUInt32(m_nLastValueCount - 1, buffer, *m_pStream);
327  }
328  else
329  {
330  OUTPUT_LOG("Error: invalid call to finalize with nothing to finalize\n");
331  assert(false);
332  }
333  }
334  public:
335  StringBuilder* m_pStream;
336  int m_nLastValueCount;
337  VALUE_TYPE m_nLastValue;
338  bool m_bIsFirst;
339  };
340 
341  template<typename VALUE_TYPE>
343  {
344  public:
345  static void DecodeSameIntegerOfCount(CParaFile& stream, std::vector<VALUE_TYPE>& list, int nIntegerCount = 0xfffffff)
346  {
347  VALUE_TYPE last;
348  uint32_t size = 0;
349  int nIntegerRead = 0;
350  int nByteRead = 0;
351  while (nIntegerRead < nIntegerCount && CIntegerEncoder::TryDecodeUInt32(stream, last, nByteRead))
352  {
353  list.push_back(last);
354  size = 0;
355  if (CIntegerEncoder::TryDecodeUInt32(stream, size, nByteRead))
356  {
357  for (uint32_t i = 0; i < size; i++) {
358  list.push_back(last);
359  }
360  }
361  nIntegerRead += (size+1);
362  }
363  }
364  static void SkipDecodeSameIntegerOfCount(CParaFile& stream, int nIntegerCount = 0xfffffff)
365  {
366  VALUE_TYPE last;
367  uint32_t size = 0;
368  int nIntegerRead = 0;
369  int nByteRead = 0;
370  while (nIntegerRead < nIntegerCount && CIntegerEncoder::TryDecodeUInt32(stream, last, nByteRead))
371  {
372  size = 0;
373  CIntegerEncoder::TryDecodeUInt32(stream, size, nByteRead);
374  nIntegerRead += (size + 1);
375  }
376  }
377  };
378 }
static int EncodeSameInteger(StringBuilder &stream, const std::vector< VALUE_TYPE > &data)
Author: LiXizhi if the input array contains, many data of the same value.
Definition: BlockDataCodec.h:161
different physics engine has different winding order.
Definition: EventBinding.h:32
Author: LiXizhi if the input array contains, many data of the same value.
Definition: BlockDataCodec.h:261
PE_CORE_DECL size_t read(void *dest, size_t bytes)
read byte stream from file at its current location.
Definition: ParaFile.cpp:1073
void append(Char c)
Appends a character to the content of the builder.
Definition: StringBuilder.hpp:257
Definition: enum_maker.hpp:46
it presents a real or virtual file in ParaEngine.
Definition: ParaFile.h:31
Definition: BlockDataCodec.h:342
A NON-thread-safe, mutable sequence of characters(Binary is also possible).
Definition: StringBuilder.h:9
Definition: BlockDataCodec.h:6
static int EncodeSkipOne(StringBuilder &stream, const std::vector< VALUE_TYPE > &data)
Author: LiXizhi here we will use skip 1 algorithm to compress the data, since the result is sorted in...
Definition: BlockDataCodec.h:71
static bool IsSkipOneBetter(const std::vector< VALUE_TYPE > &data)
return true, if more than half of the input is continuous integer with step 1.
Definition: BlockDataCodec.h:91
void Finalize()
call this function when last element is added.
Definition: BlockDataCodec.h:320