Esempio n. 1
0
/*
 *              /// <summary>Compresses input buffer into self-contained package.</summary>
 *              /// <param name="source">Input buffer.</param>
 *              /// <param name="level">Compression level.</param>
 *              /// <returns>Output buffer.</returns>
 *              public static unsafe byte[] Pickle(
 *                      ReadOnlySpan<byte> source, LZ4Level level = LZ4Level.L00_FAST)
 *              {
 *                      var sourceLength = source.Length;
 *                      if (sourceLength <= 0)
 *                              return Mem.Empty;
 *
 *                      fixed (byte* sourceP = &MemoryMarshal.GetReference(source))
 *                              return Pickle(sourceP, sourceLength, level);
 *              }
 */

        /// <summary>Compresses input buffer into self-contained package.</summary>
        /// <param name="source">Input buffer.</param>
        /// <param name="sourceLength">Length of input data.</param>
        /// <param name="level">Compression level.</param>
        /// <returns>Output buffer.</returns>
        public static unsafe byte[] Pickle(
            byte *source, int sourceLength, LZ4Level level = LZ4Level.L00_FAST)
        {
            if (sourceLength <= 0)
            {
                return(Mem.Empty);
            }

            var targetLength = sourceLength - 1;
            var target       = (byte *)Mem.Alloc(sourceLength);

            try
            {
                var encodedLength = LZ4Codec.Encode(
                    source, sourceLength, target, targetLength, level);

                return(encodedLength <= 0
                                        ? PickleV0(source, sourceLength, sourceLength)
                                        : PickleV0(target, encodedLength, sourceLength));
            }
            finally
            {
                Mem.Free(target);
            }
        }
        /// <summary>Compresses input buffer into self-contained package.</summary>
        /// <param name="source">Input buffer.</param>
        /// <param name="writer">Where the compressed data is written.</param>
        /// <param name="level">Compression level.</param>
        /// <returns>Output buffer.</returns>
        public static void Pickle(
            ReadOnlySpan <byte> source, IBufferWriter <byte> writer,
            LZ4Level level = LZ4Level.L00_FAST)
        {
            if (writer is null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            var sourceLength = source.Length;

            if (sourceLength == 0)
            {
                return;
            }

            // this might be an argument at some point
            const int version = 0;

            // number of bytes is not decided on diff but rather of full length
            // although, diff would never be greater than full length
            var headerSize = GetPessimisticHeaderSize(version, sourceLength);
            var target     = writer.GetSpan(headerSize + sourceLength);

            var encodedLength = LZ4Codec.Encode(
                source, target.Slice(headerSize, sourceLength), level);

            if (encodedLength <= 0 || encodedLength >= sourceLength)
            {
                var offset = EncodeUncompressedHeader(target, version, sourceLength);
                source.CopyTo(target.Slice(offset));
                writer.Advance(offset + sourceLength);
            }
            else
            {
                var offset = EncodeCompressedHeader(
                    target, version, headerSize, sourceLength, encodedLength);
                Debug.Assert(headerSize == offset, "Unexpected header size");
                writer.Advance(offset + encodedLength);
            }
        }