1
1
using System ;
2
+ using System . Runtime . CompilerServices ;
2
3
3
4
namespace ICSharpCode . SharpZipLib . Checksum
4
5
{
@@ -25,9 +26,19 @@ namespace ICSharpCode.SharpZipLib.Checksum
25
26
/// out is a one). We start with the highest power (least significant bit) of
26
27
/// q and repeat for all eight bits of q.
27
28
///
28
- /// The table is simply the CRC of all possible eight bit values. This is all
29
- /// the information needed to generate CRC's on data a byte at a time for all
30
- /// combinations of CRC register values and incoming bytes.
29
+ /// This implementation uses sixteen lookup tables stored in one linear array
30
+ /// to implement the slicing-by-16 algorithm, a variant of the slicing-by-8
31
+ /// algorithm described in this Intel white paper:
32
+ ///
33
+ /// https://web.archive.org/web/20120722193753/http://download.intel.com/technology/comms/perfnet/download/slicing-by-8.pdf
34
+ ///
35
+ /// The first lookup table is simply the CRC of all possible eight bit values.
36
+ /// Each successive lookup table is derived from the original table generated
37
+ /// by Sarwate's algorithm. Slicing a 16-bit input and XORing the outputs
38
+ /// together will produce the same output as a byte-by-byte CRC loop with
39
+ /// fewer arithmetic and bit manipulation operations, at the cost of increased
40
+ /// memory consumed by the lookup tables. (Slicing-by-16 requires a 16KB table,
41
+ /// which is still small enough to fit in most processors' L1 cache.)
31
42
/// </remarks>
32
43
public sealed class BZip2Crc : IChecksum
33
44
{
@@ -36,72 +47,7 @@ public sealed class BZip2Crc : IChecksum
36
47
private const uint crcInit = 0xFFFFFFFF ;
37
48
//const uint crcXor = 0x00000000;
38
49
39
- private static readonly uint [ ] crcTable = {
40
- 0X00000000 , 0X04C11DB7 , 0X09823B6E , 0X0D4326D9 ,
41
- 0X130476DC , 0X17C56B6B , 0X1A864DB2 , 0X1E475005 ,
42
- 0X2608EDB8 , 0X22C9F00F , 0X2F8AD6D6 , 0X2B4BCB61 ,
43
- 0X350C9B64 , 0X31CD86D3 , 0X3C8EA00A , 0X384FBDBD ,
44
- 0X4C11DB70 , 0X48D0C6C7 , 0X4593E01E , 0X4152FDA9 ,
45
- 0X5F15ADAC , 0X5BD4B01B , 0X569796C2 , 0X52568B75 ,
46
- 0X6A1936C8 , 0X6ED82B7F , 0X639B0DA6 , 0X675A1011 ,
47
- 0X791D4014 , 0X7DDC5DA3 , 0X709F7B7A , 0X745E66CD ,
48
- 0X9823B6E0 , 0X9CE2AB57 , 0X91A18D8E , 0X95609039 ,
49
- 0X8B27C03C , 0X8FE6DD8B , 0X82A5FB52 , 0X8664E6E5 ,
50
- 0XBE2B5B58 , 0XBAEA46EF , 0XB7A96036 , 0XB3687D81 ,
51
- 0XAD2F2D84 , 0XA9EE3033 , 0XA4AD16EA , 0XA06C0B5D ,
52
- 0XD4326D90 , 0XD0F37027 , 0XDDB056FE , 0XD9714B49 ,
53
- 0XC7361B4C , 0XC3F706FB , 0XCEB42022 , 0XCA753D95 ,
54
- 0XF23A8028 , 0XF6FB9D9F , 0XFBB8BB46 , 0XFF79A6F1 ,
55
- 0XE13EF6F4 , 0XE5FFEB43 , 0XE8BCCD9A , 0XEC7DD02D ,
56
- 0X34867077 , 0X30476DC0 , 0X3D044B19 , 0X39C556AE ,
57
- 0X278206AB , 0X23431B1C , 0X2E003DC5 , 0X2AC12072 ,
58
- 0X128E9DCF , 0X164F8078 , 0X1B0CA6A1 , 0X1FCDBB16 ,
59
- 0X018AEB13 , 0X054BF6A4 , 0X0808D07D , 0X0CC9CDCA ,
60
- 0X7897AB07 , 0X7C56B6B0 , 0X71159069 , 0X75D48DDE ,
61
- 0X6B93DDDB , 0X6F52C06C , 0X6211E6B5 , 0X66D0FB02 ,
62
- 0X5E9F46BF , 0X5A5E5B08 , 0X571D7DD1 , 0X53DC6066 ,
63
- 0X4D9B3063 , 0X495A2DD4 , 0X44190B0D , 0X40D816BA ,
64
- 0XACA5C697 , 0XA864DB20 , 0XA527FDF9 , 0XA1E6E04E ,
65
- 0XBFA1B04B , 0XBB60ADFC , 0XB6238B25 , 0XB2E29692 ,
66
- 0X8AAD2B2F , 0X8E6C3698 , 0X832F1041 , 0X87EE0DF6 ,
67
- 0X99A95DF3 , 0X9D684044 , 0X902B669D , 0X94EA7B2A ,
68
- 0XE0B41DE7 , 0XE4750050 , 0XE9362689 , 0XEDF73B3E ,
69
- 0XF3B06B3B , 0XF771768C , 0XFA325055 , 0XFEF34DE2 ,
70
- 0XC6BCF05F , 0XC27DEDE8 , 0XCF3ECB31 , 0XCBFFD686 ,
71
- 0XD5B88683 , 0XD1799B34 , 0XDC3ABDED , 0XD8FBA05A ,
72
- 0X690CE0EE , 0X6DCDFD59 , 0X608EDB80 , 0X644FC637 ,
73
- 0X7A089632 , 0X7EC98B85 , 0X738AAD5C , 0X774BB0EB ,
74
- 0X4F040D56 , 0X4BC510E1 , 0X46863638 , 0X42472B8F ,
75
- 0X5C007B8A , 0X58C1663D , 0X558240E4 , 0X51435D53 ,
76
- 0X251D3B9E , 0X21DC2629 , 0X2C9F00F0 , 0X285E1D47 ,
77
- 0X36194D42 , 0X32D850F5 , 0X3F9B762C , 0X3B5A6B9B ,
78
- 0X0315D626 , 0X07D4CB91 , 0X0A97ED48 , 0X0E56F0FF ,
79
- 0X1011A0FA , 0X14D0BD4D , 0X19939B94 , 0X1D528623 ,
80
- 0XF12F560E , 0XF5EE4BB9 , 0XF8AD6D60 , 0XFC6C70D7 ,
81
- 0XE22B20D2 , 0XE6EA3D65 , 0XEBA91BBC , 0XEF68060B ,
82
- 0XD727BBB6 , 0XD3E6A601 , 0XDEA580D8 , 0XDA649D6F ,
83
- 0XC423CD6A , 0XC0E2D0DD , 0XCDA1F604 , 0XC960EBB3 ,
84
- 0XBD3E8D7E , 0XB9FF90C9 , 0XB4BCB610 , 0XB07DABA7 ,
85
- 0XAE3AFBA2 , 0XAAFBE615 , 0XA7B8C0CC , 0XA379DD7B ,
86
- 0X9B3660C6 , 0X9FF77D71 , 0X92B45BA8 , 0X9675461F ,
87
- 0X8832161A , 0X8CF30BAD , 0X81B02D74 , 0X857130C3 ,
88
- 0X5D8A9099 , 0X594B8D2E , 0X5408ABF7 , 0X50C9B640 ,
89
- 0X4E8EE645 , 0X4A4FFBF2 , 0X470CDD2B , 0X43CDC09C ,
90
- 0X7B827D21 , 0X7F436096 , 0X7200464F , 0X76C15BF8 ,
91
- 0X68860BFD , 0X6C47164A , 0X61043093 , 0X65C52D24 ,
92
- 0X119B4BE9 , 0X155A565E , 0X18197087 , 0X1CD86D30 ,
93
- 0X029F3D35 , 0X065E2082 , 0X0B1D065B , 0X0FDC1BEC ,
94
- 0X3793A651 , 0X3352BBE6 , 0X3E119D3F , 0X3AD08088 ,
95
- 0X2497D08D , 0X2056CD3A , 0X2D15EBE3 , 0X29D4F654 ,
96
- 0XC5A92679 , 0XC1683BCE , 0XCC2B1D17 , 0XC8EA00A0 ,
97
- 0XD6AD50A5 , 0XD26C4D12 , 0XDF2F6BCB , 0XDBEE767C ,
98
- 0XE3A1CBC1 , 0XE760D676 , 0XEA23F0AF , 0XEEE2ED18 ,
99
- 0XF0A5BD1D , 0XF464A0AA , 0XF9278673 , 0XFDE69BC4 ,
100
- 0X89B8FD09 , 0X8D79E0BE , 0X803AC667 , 0X84FBDBD0 ,
101
- 0X9ABC8BD5 , 0X9E7D9662 , 0X933EB0BB , 0X97FFAD0C ,
102
- 0XAFB010B1 , 0XAB710D06 , 0XA6322BDF , 0XA2F33668 ,
103
- 0XBCB4666D , 0XB8757BDA , 0XB5365D03 , 0XB1F740B4
104
- } ;
50
+ private static readonly uint [ ] crcTable = CrcUtilities . GenerateSlicingLookupTable ( 0x04C11DB7 , isReversed : false ) ;
105
51
106
52
/// <summary>
107
53
/// The CRC data checksum so far.
@@ -149,6 +95,7 @@ public long Value
149
95
/// the byte is taken as the lower 8 bits of bval
150
96
/// </param>
151
97
/// <remarks>Reversed Data = false</remarks>
98
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
152
99
public void Update ( int bval )
153
100
{
154
101
checkValue = unchecked ( crcTable [ ( byte ) ( ( ( checkValue >> 24 ) & 0xFF ) ^ bval ) ] ^ ( checkValue << 8 ) ) ;
@@ -166,7 +113,7 @@ public void Update(byte[] buffer)
166
113
throw new ArgumentNullException ( nameof ( buffer ) ) ;
167
114
}
168
115
169
- Update ( new ArraySegment < byte > ( buffer , 0 , buffer . Length ) ) ;
116
+ Update ( buffer , 0 , buffer . Length ) ;
170
117
}
171
118
172
119
/// <summary>
@@ -177,11 +124,48 @@ public void Update(byte[] buffer)
177
124
/// </param>
178
125
public void Update ( ArraySegment < byte > segment )
179
126
{
180
- var count = segment . Count ;
181
- var offset = segment . Offset ;
127
+ Update ( segment . Array , segment . Offset , segment . Count ) ;
128
+ }
129
+
130
+ /// <summary>
131
+ /// Internal helper function for updating a block of data using slicing.
132
+ /// </summary>
133
+ /// <param name="data">The array containing the data to add</param>
134
+ /// <param name="offset">Range start for <paramref name="data"/> (inclusive)</param>
135
+ /// <param name="count">The number of bytes to checksum starting from <paramref name="offset"/></param>
136
+ private void Update ( byte [ ] data , int offset , int count )
137
+ {
138
+ int remainder = count % CrcUtilities . SlicingDegree ;
139
+ int end = offset + count - remainder ;
140
+
141
+ while ( offset != end )
142
+ {
143
+ checkValue = CrcUtilities . UpdateDataForNormalPoly ( data , offset , crcTable , checkValue ) ;
144
+ offset += CrcUtilities . SlicingDegree ;
145
+ }
182
146
183
- while ( -- count >= 0 )
184
- Update ( segment . Array [ offset ++ ] ) ;
147
+ if ( remainder != 0 )
148
+ {
149
+ SlowUpdateLoop ( data , offset , end + remainder ) ;
150
+ }
151
+ }
152
+
153
+ /// <summary>
154
+ /// A non-inlined function for updating data that doesn't fit in a 16-byte
155
+ /// block. We don't expect to enter this function most of the time, and when
156
+ /// we do we're not here for long, so disabling inlining here improves
157
+ /// performance overall.
158
+ /// </summary>
159
+ /// <param name="data">The array containing the data to add</param>
160
+ /// <param name="offset">Range start for <paramref name="data"/> (inclusive)</param>
161
+ /// <param name="end">Range end for <paramref name="data"/> (exclusive)</param>
162
+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
163
+ private void SlowUpdateLoop ( byte [ ] data , int offset , int end )
164
+ {
165
+ while ( offset != end )
166
+ {
167
+ Update ( data [ offset ++ ] ) ;
168
+ }
185
169
}
186
170
}
187
171
}
0 commit comments