예제 #1
0
 FillInValue(Ice.OutputStream os, int pos, int value) => os.RewriteInt(value, pos);
예제 #2
0
        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();
            }
        }