31 using System.Runtime.CompilerServices;
34 using SiliconStudio.Core.LZ4.Services;
36 namespace SiliconStudio.Core.LZ4
46 private static readonly ILZ4Service encoder;
49 private static readonly ILZ4Service encoderHC;
52 private static readonly ILZ4Service decoder;
57 private static ILZ4Service _service_Native32;
58 private static ILZ4Service _service_Native64;
64 #region initialization
73 Try(InitializeLZ4Native);
106 if (encoder == null || decoder == null)
108 throw new NotSupportedException(
"No LZ4 compression service found");
114 private static void Try(Action method)
131 private static ILZ4Service Try<T>()
132 where T: ILZ4Service,
new()
136 return AutoTest(
new T());
147 private static ILZ4Service AutoTest(ILZ4Service service)
149 const string loremIpsum =
150 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut " +
151 "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
152 "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in " +
153 "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat " +
154 "non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
157 const string inputText = loremIpsum + loremIpsum + loremIpsum + loremIpsum + loremIpsum;
158 var original = Encoding.UTF8.GetBytes(inputText);
163 var encoded =
new byte[MaximumOutputLength(original.Length)];
164 var encodedLength = service.Encode(original, 0, original.Length, encoded, 0, encoded.Length);
165 if (encodedLength < 0)
return null;
168 var decoded =
new byte[original.Length];
169 var decodedLength1 = service.Decode(encoded, 0, encodedLength, decoded, 0, decoded.Length,
true);
170 if (decodedLength1 != original.Length)
return null;
171 var outputText1 = Encoding.UTF8.GetString(decoded, 0, decoded.Length);
172 if (outputText1 != inputText)
return null;
175 var decodedLength2 = service.Decode(encoded, 0, encodedLength, decoded, 0, decoded.Length,
false);
176 if (decodedLength2 != original.Length)
return null;
177 var outputText2 = Encoding.UTF8.GetString(decoded, 0, decoded.Length);
178 if (outputText2 != inputText)
return null;
184 var encoded =
new byte[MaximumOutputLength(original.Length)];
185 var encodedLength = service.EncodeHC(original, 0, original.Length, encoded, 0, encoded.Length);
186 if (encodedLength < 0)
return null;
189 var decoded =
new byte[original.Length];
190 var decodedLength1 = service.Decode(encoded, 0, encodedLength, decoded, 0, decoded.Length,
true);
191 if (decodedLength1 != original.Length)
return null;
192 var outputText1 = Encoding.UTF8.GetString(decoded, 0, decoded.Length);
193 if (outputText1 != inputText)
return null;
196 var decodedLength2 = service.Decode(encoded, 0, encodedLength, decoded, 0, decoded.Length,
false);
197 if (decodedLength2 != original.Length)
return null;
198 var outputText2 = Encoding.UTF8.GetString(decoded, 0, decoded.Length);
199 if (outputText2 != inputText)
return null;
208 [MethodImpl(MethodImplOptions.NoInlining)]
209 private static void InitializeLZ4Native()
211 _service_Native32 = Try<Native32LZ4Service>();
212 _service_Native64 = Try<Native64LZ4Service>();
219 #region public interface
223 public static string CodecName
227 return string.Format(
229 encoder == null ?
"<none>" : encoder.CodecName,
230 decoder == null ?
"<none>" : decoder.CodecName,
231 encoderHC == null ?
"<none>" : encoderHC.CodecName);
240 return inputLength + (inputLength/255) + 16;
261 return encoder.Encode(input, inputOffset, inputLength, output, outputOffset, outputLength);
269 public static byte[]
Encode(byte[] input,
int inputOffset,
int inputLength)
271 if (inputLength < 0) inputLength = input.Length - inputOffset;
273 if (input == null)
throw new ArgumentNullException(
"input");
274 if (inputOffset < 0 || inputOffset + inputLength > input.Length)
275 throw new ArgumentException(
"inputOffset and inputLength are invalid for given input");
277 var result =
new byte[MaximumOutputLength(inputLength)];
278 var length = Encode(input, inputOffset, inputLength, result, 0, result.Length);
280 if (length != result.Length)
283 throw new InvalidOperationException(
"Compression has been corrupted");
284 var buffer =
new byte[length];
285 Buffer.BlockCopy(result, 0, buffer, 0, length);
307 return (encoderHC ?? encoder)
308 .EncodeHC(input, inputOffset, inputLength, output, outputOffset, outputLength);
316 public static byte[]
EncodeHC(byte[] input,
int inputOffset,
int inputLength)
318 if (inputLength < 0) inputLength = input.Length - inputOffset;
320 if (input == null)
throw new ArgumentNullException(
"input");
321 if (inputOffset < 0 || inputOffset + inputLength > input.Length)
322 throw new ArgumentException(
"inputOffset and inputLength are invalid for given input");
324 var result =
new byte[MaximumOutputLength(inputLength)];
325 var length = EncodeHC(input, inputOffset, inputLength, result, 0, result.Length);
327 if (length != result.Length)
330 throw new InvalidOperationException(
"Compression has been corrupted");
331 var buffer =
new byte[length];
332 Buffer.BlockCopy(result, 0, buffer, 0, length);
357 int outputLength = 0,
358 bool knownOutputLength =
false)
360 return decoder.Decode(input, inputOffset, inputLength, output, outputOffset, outputLength, knownOutputLength);
369 public static byte[]
Decode(byte[] input,
int inputOffset,
int inputLength,
int outputLength)
371 if (inputLength < 0) inputLength = input.Length - inputOffset;
373 if (input == null)
throw new ArgumentNullException(
"input");
374 if (inputOffset < 0 || inputOffset + inputLength > input.Length)
375 throw new ArgumentException(
"inputOffset and inputLength are invalid for given input");
377 var result =
new byte[outputLength];
378 var length = Decode(input, inputOffset, inputLength, result, 0, outputLength,
true);
379 if (length != outputLength)
380 throw new ArgumentException(
"outputLength is not valid");
static int Decode(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength=0, bool knownOutputLength=false)
Decodes the specified input.
LZ$ codec selecting best implementation depending on platform.
static byte[] EncodeHC(byte[] input, int inputOffset, int inputLength)
Encodes the specified input.
static int EncodeHC(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength)
Encodes the specified input.
static byte[] Encode(byte[] input, int inputOffset, int inputLength)
Encodes the specified input.
static byte[] Decode(byte[] input, int inputOffset, int inputLength, int outputLength)
Decodes the specified input.
static int Encode(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength)
Encodes the specified input.
static int MaximumOutputLength(int inputLength)
Get maximum output length.