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
|
#include "stdafx.h"
#include "block_chain.h"
#include <util/system/unaligned_mem.h>
namespace NNetliba {
ui32 CalcChecksum(const void* p, int size) {
//return 0;
//return CalcCrc32(p, size);
i64 sum = 0;
const unsigned char *pp = (const unsigned char*)p, *pend = pp + size;
for (const unsigned char* pend4 = pend - 3; pp < pend4; pp += 4)
sum += *(const ui32*)pp;
ui32 left = 0, pos = 0;
for (; pp < pend; ++pp) {
pos += ((ui32)*pp) << left;
left += 8;
}
sum += pos;
sum = (sum & 0xffffffff) + (sum >> 32);
sum += sum >> 32;
return (ui32)~sum;
}
ui32 CalcChecksum(const TBlockChain& chain) {
TIncrementalChecksumCalcer ics;
AddChain(&ics, chain);
return ics.CalcChecksum();
}
void TIncrementalChecksumCalcer::AddBlock(const void* p, int size) {
ui32 sum = CalcBlockSum(p, size);
AddBlockSum(sum, size);
}
void TIncrementalChecksumCalcer::AddBlockSum(ui32 sum, int size) {
for (int k = 0; k < Offset; ++k)
sum = (sum >> 24) + ((sum & 0xffffff) << 8);
TotalSum += sum;
Offset = (Offset + size) & 3;
}
ui32 TIncrementalChecksumCalcer::CalcBlockSum(const void* p, int size) {
i64 sum = 0;
const unsigned char *pp = (const unsigned char*)p, *pend = pp + size;
for (const unsigned char* pend4 = pend - 3; pp < pend4; pp += 4)
sum += ReadUnaligned<ui32>(pp);
ui32 left = 0, pos = 0;
for (; pp < pend; ++pp) {
pos += ((ui32)*pp) << left;
left += 8;
}
sum += pos;
sum = (sum & 0xffffffff) + (sum >> 32);
sum += sum >> 32;
return (ui32)sum;
}
ui32 TIncrementalChecksumCalcer::CalcChecksum() {
TotalSum = (TotalSum & 0xffffffff) + (TotalSum >> 32);
TotalSum += TotalSum >> 32;
return (ui32)~TotalSum;
}
//void TestChainChecksum()
//{
// TVector<char> data;
// data.resize(10);
// for (int i = 0; i < data.ysize(); ++i)
// data[i] = rand();
// int crc1 = CalcChecksum(&data[0], data.size());
//
// TBlockChain chain;
// TIncrementalChecksumCalcer incCS;
// for (int offset = 0; offset < data.ysize();) {
// int sz = Min(rand() % 10, data.ysize() - offset);
// chain.AddBlock(&data[offset], sz);
// incCS.AddBlock(&data[offset], sz);
// offset += sz;
// }
// int crc2 = CalcChecksum(chain);
// Y_ASSERT(crc1 == crc2);
// int crc3 = incCS.CalcChecksum();
// Y_ASSERT(crc1 == crc3);
//}
}
|