source: trunk/Mars/mcore/checksum.h@ 17253

Last change on this file since 17253 was 17141, checked in by tbretz, 11 years ago
More inclused to make any include order possible, removed some obsolete cint hacks
File size: 5.7 KB
Line 
1#ifndef MARS_checksum
2#define MARS_checksum
3
4#ifndef __CINT__
5#include <arpa/inet.h>
6#endif
7
8#include <stdint.h>
9
10namespace std
11{
12
13class Checksum
14{
15public:
16 uint64_t buffer;
17
18 void reset() { buffer = 0; }
19 Checksum() : buffer(0) { }
20 Checksum(const Checksum &sum) : buffer(sum.buffer) { }
21 Checksum(uint64_t v) : buffer(((v>>16)&0xffff) | ((v&0xffff)<<32)) { }
22
23 uint32_t val() const { return (((buffer&0xffff)<<16) | ((buffer>>32)&0xffff)); }
24
25 bool valid() const { return buffer==0xffff0000ffff; }
26
27 void HandleCarryBits()
28 {
29 while (1)
30 {
31 const uint64_t carry = ((buffer>>48)&0xffff) | ((buffer&0xffff0000)<<16);
32 if (!carry)
33 break;
34
35 buffer = (buffer&0xffff0000ffff) + carry;
36 }
37 }
38
39 Checksum &operator+=(const Checksum &sum)
40 {
41 buffer += sum.buffer;
42 HandleCarryBits();
43 return *this;
44 }
45 Checksum operator+(Checksum sum) const
46 {
47 return (sum += *this);
48 }
49
50
51 bool add(const char *buf, size_t len, bool big_endian = true)
52 {
53 // Avoid overflows in carry bits
54 if (len>262140) // 2^18-4
55 {
56 add(buf, 262140);
57 return add(buf+262140, len-262140);
58 }
59
60 if (len%4>0)
61 {
62 ostringstream sout;
63 sout << "Length " << len << " not dividable by 4." << endl;
64
65#ifdef __EXCEPTIONS
66 throw runtime_error(sout.str());
67#else
68 gLog << ___err___ << "ERROR - " << sout.str() << endl;
69 return false;
70#endif
71 }
72
73 const uint16_t *sbuf = reinterpret_cast<const uint16_t *>(buf);
74
75 uint32_t *hilo = reinterpret_cast<uint32_t*>(&buffer);
76
77
78 const uint16_t *end = sbuf + len/2;
79
80 if (big_endian)
81 addLoopSwapping(sbuf, end, hilo);
82 else
83 addLoop(sbuf, end, hilo);
84 /*const uint16_t *end = sbuf + len/2;
85 while (1)
86 {
87 if (sbuf==end)
88 break;
89
90 hilo[0] += ntohs(*sbuf++);
91
92 if (sbuf==end)
93 break;
94
95 hilo[1] += ntohs(*sbuf++);
96 }*/
97
98 HandleCarryBits();
99
100 return true;
101 }
102
103 void addLoopSwapping(const uint16_t *sbuf, const uint16_t *end, uint32_t* hilo)
104 {
105 /*
106 for (size_t i = 0; i < len/2; i++)
107 {
108 //swap the bytes of the 32 bits value. but...
109 //the hi and lo values are stored in fits-like order. do not swap them
110 hilo[i%2] += ntohs(sbuf[i]); //(sbuf[i]&0xff00)>>8 | (sbuf[i]&0x00ff)<<8;
111 }*/
112
113 // This is about as twice as fast as the loop above
114 // ntohs is CPU optimized, i%2 doesn't need to be computed
115 while (1)
116 {
117 if (sbuf==end)
118 break;
119
120 hilo[0] += ntohs(*sbuf++);
121
122 if (sbuf==end)
123 break;
124
125 hilo[1] += ntohs(*sbuf++);
126 }
127 }
128
129 void addLoop(const uint16_t *sbuf, const uint16_t *end, uint32_t* hilo)
130 {
131 while (1)
132 {
133 if (sbuf==end)
134 break;
135
136 hilo[0] += ntohs(*sbuf++);
137
138 if (sbuf==end)
139 break;
140
141 hilo[1] += ntohs(*sbuf++);
142 }
143 }
144
145 bool add(const vector<char> &v, bool big_endian = true)
146 {
147 return add(v.data(), v.size(), big_endian);
148 }
149
150 string str(bool complm=true) const
151 {
152 string rc(16,0);
153
154 const uint8_t exclude[13] =
155 {
156 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
157 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60
158 };
159
160 const uint32_t value = complm ? ~val() : val(); // complement each bit of the value
161
162 for (int ii = 0; ii < 4; ii++)
163 {
164 uint8_t byte = (value >> (24 - (8 * ii)));
165
166 const uint8_t quotient = byte / 4 + '0';
167 const uint8_t remainder = byte % 4;
168
169 uint32_t ch[4] = { quotient+remainder, quotient, quotient, quotient };
170
171 // avoid ASCII punctuation
172 while (1)
173 {
174 bool check = false;
175 for (int kk = 0; kk < 13; kk++)
176 {
177 for (int jj = 0; jj < 4; jj += 2)
178 {
179 if (ch[jj] != exclude[kk] && ch[jj+1] != exclude[kk])
180 continue;
181
182 ch[jj]++;
183 ch[jj+1]--;
184 check++;
185 }
186 }
187
188 if (!check)
189 break;
190 }
191
192 for (int jj = 0; jj < 4; jj++) // assign the bytes
193 rc[4*jj+ii] = ch[jj];
194 }
195
196 const char lastChar = rc[15];
197 for (int i=15;i>0;i--)
198 rc[i] = rc[i-1];
199 rc[0] = lastChar;
200 return rc;
201/*
202 uint8_t *p = reinterpret_cast<uint8_t*>(&value);
203 //swap the bytes of the value
204 uint8_t temp;
205 temp = p[0];
206 p[0] = p[3];
207 p[3] = temp;
208 temp = p[1];
209 p[1] = p[2];
210 p[2] = temp;
211
212 for (int i=0; i<4; i++)
213 {
214 rc[i+ 0] = '0' + p[i]/4 + p[i]%4;
215 rc[i+ 4] = '0' + p[i]/4;
216 rc[i+ 8] = '0' + p[i]/4;
217 rc[i+12] = '0' + p[i]/4;
218 }
219
220 while(1)
221 {
222 bool ok = true;
223 for (int i=0; i<16-4; i++)
224 {
225 for (int j=0; j<13; j++)
226 if (rc[i]==exclude[j] || rc[(i+4)%16]==exclude[j])
227 {
228 rc[i]++;
229 rc[(i+4)%16]--;
230 ok = false;
231 }
232 }
233
234 if (ok)
235 break;
236 }
237
238
239 return rc;
240 */
241 }
242};
243}
244
245#endif
Note: See TracBrowser for help on using the repository browser.