11namespace UnityAsset . NET ;
22
3- public static class LZ4
3+ public static unsafe class LZ4
44{
5- public static unsafe int Decode ( ReadOnlySpan < byte > source , Span < byte > target )
5+ // Only about half the speed of K4os.Compression.LZ4
6+
7+ public static int Decode ( ReadOnlySpan < byte > source , Span < byte > target )
68 {
7- int length1 = source . Length ;
8- if ( length1 <= 0 )
9+ int length = source . Length ;
10+ if ( length < 5 )
911 return 0 ;
1012 fixed ( byte * sourcePtr = & source . GetPinnableReference ( ) )
1113 fixed ( byte * targetPtr = & target . GetPinnableReference ( ) )
1214 {
1315 byte * s = sourcePtr ;
1416 byte * t = targetPtr ;
15- byte * sourceEnd = sourcePtr + source . Length ;
17+ byte * sourceEnd = sourcePtr + length ;
1618 while ( s < sourceEnd )
1719 {
1820 byte token = * s ++ ;
@@ -27,13 +29,11 @@ public static unsafe int Decode(ReadOnlySpan<byte> source, Span<byte> target)
2729 literalLength += b ;
2830 } while ( b == 0xFF && s < sourceEnd ) ;
2931 }
30-
3132 Buffer . MemoryCopy ( s , t , literalLength , literalLength ) ;
3233 s += literalLength ;
3334 t += literalLength ;
34-
35- if ( s >= sourceEnd ) break ;
36-
35+ if ( s == sourceEnd && matchLength == 0 ) break ;
36+ if ( s >= sourceEnd ) return - 1 ;
3737 int offset = * s ++ | ( * s ++ << 8 ) ;
3838 if ( matchLength == 0xF )
3939 {
@@ -44,25 +44,126 @@ public static unsafe int Decode(ReadOnlySpan<byte> source, Span<byte> target)
4444 matchLength += b ;
4545 } while ( b == 0xFF && s < sourceEnd ) ;
4646 }
47-
4847 matchLength += 4 ;
49-
5048 while ( matchLength > offset )
5149 {
5250 Buffer . MemoryCopy ( t - offset , t , offset , offset ) ;
5351 t += offset ;
5452 matchLength -= offset ;
5553 }
56-
5754 if ( matchLength > 0 )
5855 {
5956 Buffer . MemoryCopy ( t - offset , t , matchLength , matchLength ) ;
6057 }
61-
6258 t += matchLength ;
6359 }
64-
6560 return ( int ) ( t - targetPtr ) ;
6661 }
6762 }
63+
64+ public static int EncodeFast ( ReadOnlySpan < byte > source , Span < byte > target )
65+ {
66+ int sourceLength = source . Length - 5 ;
67+ if ( sourceLength < 0 )
68+ {
69+ return 0 ;
70+ }
71+ fixed ( byte * sourcePtr = & source . GetPinnableReference ( ) )
72+ fixed ( byte * targetPtr = & target . GetPinnableReference ( ) )
73+ {
74+ byte * anchor = sourcePtr ;
75+ IntPtr [ ] hashTable = new IntPtr [ 1 << 16 ] ;
76+
77+ byte * s = sourcePtr ;
78+ byte * t = targetPtr ;
79+ byte * sourceEnd = sourcePtr + sourceLength ;
80+ while ( s < sourceEnd - 4 )
81+ {
82+ uint data = * ( uint * ) s ;
83+ ushort hash = ( ushort ) ( ( data * 2654435761 ) >> 16 ) ;
84+ if ( hashTable [ hash ] == 0 )
85+ {
86+ hashTable [ hash ] = ( IntPtr ) s ;
87+ s ++ ;
88+ }
89+ else
90+ {
91+ byte * sourceOffset = ( byte * ) hashTable [ hash ] ;
92+ uint oldData = * ( uint * ) sourceOffset ;
93+ if ( oldData != data )
94+ {
95+ hashTable [ hash ] = ( IntPtr ) s ;
96+ s ++ ;
97+ }
98+ else
99+ {
100+ hashTable [ hash ] = ( IntPtr ) s ;
101+ int matchDec = ( int ) ( s - sourceOffset ) ;
102+ if ( matchDec > 0xFFFF )
103+ {
104+ s ++ ;
105+ continue ;
106+ }
107+ int literalLen = ( int ) ( s - anchor ) ;
108+ int matchLen = 4 ;
109+ while ( s + matchLen < sourceEnd && * ( s + matchLen ) == * ( sourceOffset + matchLen ) )
110+ {
111+ matchLen ++ ;
112+ }
113+ int token = Math . Min ( literalLen , 15 ) << 4 | Math . Min ( matchLen - 4 , 15 ) ;
114+ * t ++ = ( byte ) token ;
115+ if ( literalLen > = 15 )
116+ {
117+ int l = literalLen - 15 ;
118+ while ( l >= 0xFF )
119+ {
120+ * t ++ = 0xFF ;
121+ l -= 0xFF ;
122+ }
123+ * t ++ = ( byte ) l ;
124+ }
125+ Buffer. MemoryCopy ( anchor , t , literalLen , literalLen ) ;
126+ t += literalLen;
127+ byte matchDecLow = ( byte ) matchDec ;
128+ byte matchDecHigh = ( byte ) ( matchDec >> 8 ) ;
129+ * t ++ = matchDecLow;
130+ * t ++ = matchDecHigh;
131+ if ( matchLen >= 19 )
132+ {
133+ int l = matchLen - 19 ;
134+ while ( l > = 0xFF )
135+ {
136+ * t ++ = 0xFF ;
137+ l -= 0xFF ;
138+ }
139+ * t ++ = ( byte ) l ;
140+ }
141+ s += matchLen;
142+ anchor = s;
143+ }
144+ }
145+ }
146+ int literalLenFinal = ( int ) ( sourceEnd - anchor + 5 ) ;
147+ int tokenFinal = Math. Min ( literalLenFinal , 15 ) << 4 ;
148+ * t ++ = ( byte ) tokenFinal ;
149+ if ( literalLenFinal > = 15 )
150+ {
151+ int l = literalLenFinal - 15 ;
152+ while ( l >= 255 )
153+ {
154+ * t ++ = 255 ;
155+ l -= 255 ;
156+ }
157+ * t ++ = ( byte ) l ;
158+ }
159+ Buffer. MemoryCopy ( anchor , t , literalLenFinal , literalLenFinal ) ;
160+ t += literalLenFinal ;
161+ return ( int ) ( t - targetPtr ) ;
162+ }
163+ }
164+
165+ public static int MaximumOutputSize ( int inputSize )
166+ {
167+ return inputSize + inputSize / 255 + 16 ;
168+ }
68169}
0 commit comments