internal static extern int UnixBZ2_10_bzCompressInit(ref BZStream stream, int blockSize100k, int verbosity, int workFactor);
internal static extern int UnixBZ2_1_bzCompress(ref BZStream stream, int action);
internal static extern int UnixBZ2_1_bzCompressEnd(ref BZStream stream);
internal static extern int WindowsBZ2_bzCompressEnd(ref BZStream stream);
internal static extern int WindowsBZ2_bzCompress(ref BZStream stream, int action);
public static Ice.OutputStream?Compress(Ice.OutputStream stream, int headerSize, int compressionLevel) { Debug.Assert(Supported()); // Compress the message body, but not the header. int uncompressedLen = stream.Size - headerSize; byte[] compressed = new byte[(int)((uncompressedLen * 1.01) + 600)]; // Prevent GC from moving the byte array, this allow to take the object address // and pass it to bzip2 calls. var compressedHandle = GCHandle.Alloc(compressed, GCHandleType.Pinned); var bzStream = new BZStream(compressedHandle.AddrOfPinnedObject(), (uint)compressed.Length); try { _compressInit(ref bzStream, compressionLevel, 0, 0); System.Collections.Generic.IList <ArraySegment <byte> > data = stream.GetUnderlyingBuffer(); Debug.Assert(data[0].Offset == 0); data[0] = data[0].Slice(headerSize); int rc = BzRunOk; for (int i = 0; rc == BzRunOk && i < data.Count; i++) { ArraySegment <byte> segment = data[i]; var segmentHandle = GCHandle.Alloc(segment.Array, GCHandleType.Pinned); bzStream.NextIn = segmentHandle.AddrOfPinnedObject() + segment.Offset; bzStream.AvailIn = (uint)segment.Count; Debug.Assert(bzStream.AvailIn > 0); do { rc = _compress(ref bzStream, BzRun); }while (rc == BzRunOk && bzStream.AvailIn > 0); segmentHandle.Free(); } if (rc != BzRunOk) { throw new Ice.CompressionException($"Bzip2 compress run failed {GetBZ2Error(rc)}"); } do { rc = _compress(ref bzStream, BzFinish); }while (rc == BzFinishOk); if (rc != BzStreamEnd) { throw new Ice.CompressionException($"Bzip2 compress finish failed {GetBZ2Error(rc)}"); } int compressedLen = compressed.Length - (int)bzStream.AvailOut; // Don't bother if the compressed data is larger than the uncompressed data. if (compressedLen >= uncompressedLen) { return(null); } // Copy the header from the uncompressed stream to the compressed one, // we use headerSize + 4 to ensure there is room for the size of the // uncompressed stream in the first segment. Debug.Assert(data.Count > 0 && data[0].Count > headerSize + 4); var r = new Ice.OutputStream(stream.Communicator, stream.Encoding, data[0].Array.AsSpan(0, headerSize + 4).ToArray()); // Add the size of the uncompressed stream before the message body. r.RewriteInt(stream.Size, new Ice.OutputStream.Position(0, headerSize)); r.WritePayload(new ArraySegment <byte>(compressed, 0, compressedLen)); return(r); } finally { _compressEnd(ref bzStream); compressedHandle.Free(); } }
internal static extern int MacOSBZ2_bzCompressEnd(ref BZStream stream);
internal static extern int MacOSBZ2_bzCompress(ref BZStream stream, int action);