1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
#pragma once
#include "Runtime/mecanim/defs.h"
#include "Runtime/mecanim/types.h"
#include "Runtime/mecanim/string.h"
namespace mecanim
{
template < std::size_t Bits > struct reflector
{
typedef typename mecanim::uint_t<Bits>::value_type value_type;
static value_type reflect( value_type x );
};
// Function that reflects its argument
template < std::size_t Bits > typename reflector<Bits>::value_type reflector<Bits>::reflect( typename reflector<Bits>::value_type x)
{
value_type reflection = 0;
value_type const one = 1;
for ( std::size_t i = 0 ; i < Bits ; ++i, x >>= 1 )
{
if ( x & one )
{
reflection |= ( one << (Bits - 1u - i) );
}
}
return reflection;
}
template <uint32_t TruncPoly> struct crc32_table_t
{
static const uint32_t byte_combos = (1ul << CHAR_BIT);
typedef uint32_t value_type;
typedef value_type table_type[byte_combos];
static void init_table();
static table_type table;
static bool isInitialized;
};
template <uint32_t TruncPoly> typename crc32_table_t<TruncPoly>::table_type crc32_table_t<TruncPoly>::table = { 0 };
template <uint32_t TruncPoly> bool crc32_table_t<TruncPoly>::isInitialized = false;
// Populate CRC lookup table
template<uint32_t TruncPoly> void crc32_table_t<TruncPoly>::init_table()
{
// factor-out constants to avoid recalculation
value_type const fast_hi_bit = 1ul << ( 32 - 1u );
unsigned char const byte_hi_bit = 1u << (CHAR_BIT - 1u);
// loop over every possible dividend value
unsigned char dividend = 0;
do
{
value_type remainder = 0;
// go through all the dividend's bits
for ( unsigned char mask = byte_hi_bit ; mask ; mask >>= 1 )
{
// check if divisor fits
if ( dividend & mask )
{
remainder ^= fast_hi_bit;
}
// do polynominal division
if ( remainder & fast_hi_bit )
{
remainder <<= 1;
remainder ^= TruncPoly;
}
else
{
remainder <<= 1;
}
}
table[ reflector<CHAR_BIT>::reflect(dividend) ] = reflector<32>::reflect( remainder );
}
while ( ++dividend );
isInitialized = true;
}
class crc32
{
public:
// Type
typedef uint32_t value_type;
// Constants for the template parameters
static const std::size_t bit_count = 32;
static const value_type truncated_polynominal = 0x04C11DB7;
static const value_type initial_remainder = 0xFFFFFFFF;
static const value_type final_xor_value = 0xFFFFFFFF;
// Constructor
explicit crc32( value_type init_rem = crc32::initial_remainder ):rem(reflector<bit_count>::reflect(init_rem)){}
inline void process_block(void const *bytes_begin, void const *bytes_end);
inline void process_block_skip2(void const * bytes_begin, void const * bytes_end);
inline void process_bytes(void const *buffer, std::size_t byte_count );
inline void process_bytes_skip2(void const * buffer, std::size_t byte_count);
inline value_type checksum() const;
typedef crc32_table_t<truncated_polynominal> crc32_table_type;
protected:
inline value_type get_truncated_polynominal() const{ return truncated_polynominal; }
inline value_type get_initial_remainder() const{return initial_remainder;}
inline value_type get_final_xor_value() const{return final_xor_value;}
static unsigned char index( value_type rem, unsigned char x ){ return static_cast<unsigned char>(x ^ rem); }
// Shift out the remainder's highest byte
static value_type shift( value_type rem ){ return rem >> CHAR_BIT; }
// Member data
value_type rem;
};
inline void crc32::process_block(void const * bytes_begin, void const * bytes_end)
{
Assert(crc32_table_type::isInitialized);
// Recompute the CRC for each byte passed
for ( unsigned char const * p = static_cast<unsigned char const *>(bytes_begin) ; p < bytes_end ; ++p )
{
// Compare the new byte with the remainder's higher bits to
// get the new bits, shift out the remainder's current higher
// bits, and update the remainder with the polynominal division
// of the new bits.
unsigned char const byte_index = index( rem, *p );
rem = shift( rem );
rem ^= crc32_table_type::table[ byte_index ];
}
}
inline void crc32::process_block_skip2(void const * bytes_begin, void const * bytes_end)
{
Assert(crc32_table_type::isInitialized);
unsigned char const * p;
#if UNITY_BIG_ENDIAN
p = static_cast<unsigned char const *>(bytes_begin) + 1;
#else
p = static_cast<unsigned char const *>(bytes_begin);
#endif
// Recompute the CRC for every second byte passed. This is useful for hashing a UTF16 string that is known to actually be an ascii string.
for ( ; p < bytes_end ; p += 2 )
{
// Compare the new byte with the remainder's higher bits to
// get the new bits, shift out the remainder's current higher
// bits, and update the remainder with the polynominal division
// of the new bits.
unsigned char const byte_index = index( rem, *p );
rem = shift( rem );
rem ^= crc32_table_type::table[ byte_index ];
}
}
inline void crc32::process_bytes(void const * buffer, std::size_t byte_count)
{
unsigned char const * const b = static_cast<unsigned char const *>( buffer );
process_block( b, b + byte_count );
}
inline void crc32::process_bytes_skip2(void const * buffer, std::size_t byte_count)
{
unsigned char const * const b = static_cast<unsigned char const *>( buffer );
process_block_skip2( b, b + byte_count );
}
inline crc32::value_type crc32::checksum() const
{
return ( rem ^ get_final_xor_value() );
}
static inline int processCRC32(String const& string)
{
crc32 result;
result.process_bytes(string.c_str(), string.size());
return result.checksum();
}
static inline int processCRC32(char const* string)
{
crc32 result;
result.process_bytes(string, strlen(string));
return result.checksum();
}
static inline int processCRC32UTF16Ascii(unsigned short const* string, std::size_t stringLength)
{
crc32 result;
result.process_bytes_skip2(string, stringLength * 2);
return result.checksum();
}
}
|