示例#1
0
        public void Resize(uint newSize, byte filler)
        {
            if (m_buffer == null)
            {
                ThrowAlreadyDisposed();
            }
            if (newSize <= m_count)
            {
                m_count = newSize;
            }
            else
            {
                if (newSize > m_buffer.Length)
                {
                    GrowBuffer(newSize);
                }

                // fill the extra space with zeroes
                uint pos = m_count;
                uint r   = checked ((uint)m_buffer.Length - newSize);
                if (r > 0)
                {
                    UnmanagedHelpers.FillUnsafe(this.Data + pos, r, 0);
                }
                m_count = newSize;
            }
        }
        public byte[] GetBytes(uint offset, uint count)
        {
            Contract.Requires(this.Count >= 0);

            if (offset > this.Count)
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if (offset + count >= this.Count)
            {
                throw new ArgumentOutOfRangeException("count");
            }

            var tmp = new byte[count];

            if (count > 0)
            {
                Contract.Assert(this.Data != null);
                fixed(byte *ptr = tmp)
                {
                    UnmanagedHelpers.CopyUnsafe(ptr, this.Data + offset, count);
                }
            }
            return(tmp);
        }
示例#3
0
        private byte *AllocateInternal(uint size, bool zeroed)
        {
            if (m_buffer == null)
            {
                ThrowAlreadyDisposed();
            }
            Contract.Requires(size != 0, "size == 0");

            Contract.Assert(m_buffer != null && m_count <= m_buffer.Length, "Builder is corrupted");
            uint remaining = checked (((uint)m_buffer.Length) - m_count);

            if (remaining < size)
            {
                GrowBuffer(m_count + size);
            }

            uint pos = m_count;

            m_count = pos + size;
            byte *ptr = this.Data + pos;

            if (zeroed)
            {
                UnmanagedHelpers.FillUnsafe(ptr, size, 0);
            }
            return(ptr);
        }
        /// <summary>Return a builder into the pool</summary>
        /// <param name="builder">Builder that is no longer in use</param>
        internal void Return(UnmanagedSliceBuilder builder)
        {
            if (m_disposed || builder == null)
            {
                return;
            }

            lock (m_buckets)
            {
                if (m_disposed)
                {
                    return;
                }

                var size = builder.Capacity;
                Contract.Assert(size == UnmanagedHelpers.NextPowerOfTwo(size), "builder size should always be a power of two");

                Interlocked.Add(ref m_memoryLoaned, -((long)builder.Capacity));
                Contract.Assert(m_memoryUsed >= 0, "m_memoryLoaned desync");

                if (m_buckets.Count < m_maxCount)
                {
                    m_buckets.Push(builder);
                    Interlocked.Add(ref m_memoryUsed, builder.Capacity);
                }
                else
                {
                    builder.Dispose();
                }
            }
        }
示例#5
0
        public UnmanagedSliceBuilder(Slice slice)
        {
            if (slice.Count < 0 || slice.Offset < 0)
            {
                ThrowMalformedManagedSlice();
            }

            uint size = (uint)slice.Count;

            if (size > 0)
            {
                if (slice.Array == null || slice.Array.Length < slice.Offset + slice.Count)
                {
                    ThrowMalformedManagedSlice();
                }
                GrowBuffer(size);

                fixed(byte *ptr = slice.Array)
                {
                    UnmanagedHelpers.CopyUnsafe(this.Data, ptr + slice.Offset, size);
                }

                m_count = size;
            }
        }
示例#6
0
        public void Append(Slice source)
        {
            if (source.Count > 0)
            {
                if (source.Array == null || source.Offset < 0)
                {
                    ThrowInvalidSource();
                }

                var ptr = AllocateInternal((uint)source.Count, zeroed: false);
                Contract.Assert(ptr != null, "AllocateInternal() => null");
                UnmanagedHelpers.CopyUnsafe(ptr, source);
            }
        }
示例#7
0
        public void Set(USlice source)
        {
            m_count = 0;
            if (source.Count > 0)
            {
                if (source.Data == null)
                {
                    ThrowInvalidSource();
                }

                var ptr = AllocateInternal(source.Count, zeroed: false);
                Contract.Assert(ptr != null);
                UnmanagedHelpers.CopyUnsafe(ptr, source);
            }
        }
        public byte[] GetBytes()
        {
            Contract.Requires(this.Count >= 0);
            var tmp = new byte[this.Count];

            if (this.Count > 0)
            {
                Contract.Assert(this.Data != null);
                fixed(byte *ptr = tmp)
                {
                    UnmanagedHelpers.CopyUnsafe(ptr, this.Data, this.Count);
                }
            }
            return(tmp);
        }
示例#9
0
        /// <summary>Copy the content of an unmanaged slice of memory, using a specific alignment</summary>
        /// <param name="data">Slice of unmanaged memory to copy</param>
        /// <param name="align">Required memory alignment. MUST BE A POWER OF 2 !</param>
        /// <returns>New slice pointing to the copied bytes in the allocator memory. The start address should be aligned to either 4 or 8 bytes, depending on the platform architecture.</returns>
        private USlice Memoize(USlice data, uint align)
        {
            if (data.Count == 0)
            {
                return(default(USlice));
            }
            byte *ptr = Allocate(data.Count, align);

            if (ptr == null)
            {
                throw new OutOfMemoryException();
            }
            UnmanagedHelpers.CopyUnsafe(ptr, data);
            return(new USlice(ptr, data.Count));
        }
示例#10
0
        public void Append(USlice source)
        {
            if (source.Count == 0)
            {
                return;
            }
            if (source.Data == null)
            {
                ThrowInvalidSource();
            }

            byte *ptr = AllocateInternal(source.Count, zeroed: false);

            Contract.Assert(ptr != null);
            UnmanagedHelpers.CopyUnsafe(ptr, source);
        }
示例#11
0
        public void Append(byte *source, uint size)
        {
            if (size == 0)
            {
                return;
            }
            if (source == null)
            {
                ThrowInvalidSource();
            }

            byte *ptr = AllocateInternal(size, zeroed: false);

            Contract.Assert(ptr != null, "AllocateInternal() => null");
            UnmanagedHelpers.CopyUnsafe(ptr, source, size);
        }
示例#12
0
            public Page(int id, IntPtr handle, uint size)
            {
                Contract.Requires(handle != IntPtr.Zero && size > 0);

                m_id     = id;
                m_handle = handle;
                m_size   = size;

                m_begin = (byte *)handle;

                // fill with zeroes !
                UnmanagedHelpers.FillUnsafe(m_begin, size, 0);

                GC.AddMemoryPressure(size);

                Contract.Ensures(m_handle != IntPtr.Zero && m_size > 0 && m_nextFree == 0);
            }
        public byte[] ToArray()
        {
            if (m_begin == null)
            {
                ThrowDisposed();
            }
            var tmp = new byte[m_size];

            if (tmp.Length > 0)
            {
                fixed(byte *ptr = tmp)
                {
                    UnmanagedHelpers.CopyUnsafe(ptr, m_begin, (uint)m_size);
                }
            }
            return(tmp);
        }
示例#14
0
 public UnmanagedSliceBuilder(byte *data, uint size)
 {
     if (data == null && size != 0)
     {
         throw new ArgumentNullException("data");
     }
     if (size == 0)
     {
         m_buffer = s_empty;
     }
     else
     {
         GrowBuffer(size);
         UnmanagedHelpers.CopyUnsafe(m_data, data, size);
         m_count = size;
     }
 }
示例#15
0
        /// <summary>Copy a segment of the buffer to an unmanaged pointer, and return the corresponding slice</summary>
        /// <param name="count">Number of bytes to copy</param>
        /// <param name="dest">Destination pointer where the buffer will be copied. Caution: the destination buffer must be large enough!</param>
        /// <returns>Slice that points to the copied segment in the destination buffer</returns>
        internal USlice CopyTo(byte *dest, uint count)
        {
            if (m_buffer == null)
            {
                ThrowAlreadyDisposed();
            }
            if (count == 0)
            {
                return(default(USlice));
            }
            if (count > m_count)
            {
                throw new ArgumentOutOfRangeException("count");
            }

            UnmanagedHelpers.CopyUnsafe(dest, m_data, count);
            return(new USlice(dest, count));
        }
        public bool Equals(USlice other)
        {
            if (this.Count != other.Count)
            {
                return(false);
            }
            if (this.Data == other.Data)
            {
                return(true);
            }
            if (this.Data == null || other.Data == null)
            {
                return(false);
            }

            //TODO: optimize!
            return(0 == UnmanagedHelpers.CompareUnsafe(this.Data, this.Count, other.Data, other.Count));
        }
示例#17
0
        public byte[] GetBytes()
        {
            if (m_buffer == null)
            {
                ThrowAlreadyDisposed();
            }

            var tmp = new byte[m_count];

            if (m_count >= 0)
            {
                fixed(byte *ptr = tmp)
                {
                    UnmanagedHelpers.CopyUnsafe(ptr, m_data, m_count);
                }
            }
            return(tmp);
        }
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (m_begin == null)
            {
                ThrowDisposed();
            }

            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if (count < 0 || offset + count >= buffer.Length)
            {
                throw new ArgumentOutOfRangeException("count");
            }

            uint pos = m_pos;

            if (pos >= m_size)
            {
                return(0);                           // EOF
            }
            uint chunk;

            checked { chunk = (uint)Math.Max(m_size - pos, count); }

            if (chunk > 0)
            {
                fixed(byte *ptr = buffer)
                {
                    UnmanagedHelpers.CopyUnsafe(ptr + offset, m_begin + pos, chunk);
                }

                m_pos = pos + chunk;
            }
            return((int)chunk);
        }
示例#19
0
 /// <summary>Grow the buffer to be able to hold the specified number of bytes</summary>
 /// <param name="required">Minimum capacity required</param>
 /// <remarks>The buffer may be resize to more than <paramref name="required"/></remarks>
 private void GrowBuffer(uint required)
 {
     try
     { }
     finally
     {
         if (!m_handle.IsAllocated)
         {                 // initial allocation of the buffer
             uint newsize = UnmanagedHelpers.NextPowerOfTwo(Math.Max(required, DEFAULT_CAPACITY));
             var  buffer  = new byte[newsize];
             m_buffer = buffer;
             m_count  = 0;
         }
         else
         {                 // resize an existing buffer
             uint newsize = (uint)m_buffer.Length;
             newsize = UnmanagedHelpers.NextPowerOfTwo(Math.Max(required, newsize << 1));
             if (newsize > int.MaxValue)
             {                     // cannot alloc more than 2GB in managed code!
                 newsize = int.MaxValue;
                 if (newsize < required)
                 {
                     throw new OutOfMemoryException("Cannot grow slice builder above 2GB");
                 }
             }
             // temporary release the handle
             m_data = null;
             m_handle.Free();
             // resize to the new capacity, and re-pin
             Array.Resize(ref m_buffer, (int)newsize);
         }
         m_handle = GCHandle.Alloc(m_buffer, GCHandleType.Pinned);
         m_data   = (byte *)m_handle.AddrOfPinnedObject();
     }
     Contract.Ensures(m_buffer != null && m_handle.IsAllocated && m_data != null && m_count >= 0 && m_count <= m_buffer.Length, "GrowBuffer corruption");
 }
 /// <summary>Lexicographically compare two slices and returns an indication of their relative sort order</summary>
 /// <param name="x">Slice compared with <paramref name="y"/></param>
 /// <param name="y">Slice compared with <paramref name="x"/></param>
 /// <returns>Returns a NEGATIVE value if <paramref name="x"/> is LESS THAN <paramref name="y"/>, ZERO if <paramref name="x"/> is EQUAL TO <paramref name="y"/>, and a POSITIVE value if <paramref name="x"/> is GREATER THAN <paramref name="y"/>.</returns>
 /// <remarks>If both <paramref name="x"/> and <paramref name="y"/> are nil or empty, the comparison will return ZERO. If only <paramref name="y"/> is nil or empty, it will return a NEGATIVE value. If only <paramref name="x"/> is nil or empty, it will return a POSITIVE value.</remarks>
 public int Compare(USlice x, USlice y)
 {
     return(UnmanagedHelpers.CompareUnsafe(x.Data, x.Count, y.Data, y.Count));
 }
 public UnmanagedSliceBuilderPool(uint initialCapacity, int maxCount)
 {
     m_initialCapacity = UnmanagedHelpers.NextPowerOfTwo(Math.Min(initialCapacity, 64));
     m_maxCount        = Math.Max(1, maxCount);
     m_buckets         = new Stack <UnmanagedSliceBuilder>(Math.Max(m_maxCount, 100));
 }
 /// <summary>Checks if two slices are equal.</summary>
 /// <param name="x">Slice compared with <paramref name="y"/></param>
 /// <param name="y">Slice compared with <paramref name="x"/></param>
 /// <returns>true if <paramref name="x"/> and <paramref name="y"/> have the same size and contain the same sequence of bytes; otherwise, false.</returns>
 public bool Equals(USlice x, USlice y)
 {
     return(x.Count == y.Count && 0 == UnmanagedHelpers.CompareUnsafe(x.Data, x.Count, y.Data, y.Count));
 }
 public override int GetHashCode()
 {
     return(UnmanagedHelpers.ComputeHashCode(ref this));
 }
 public int CompareTo(USlice other)
 {
     return(UnmanagedHelpers.CompareUnsafe(this.Data, this.Count, other.Data, other.Count));
 }
 int IComparer <KeyValuePair <USlice, USlice> > .Compare(KeyValuePair <USlice, USlice> x, KeyValuePair <USlice, USlice> y)
 {
     return(UnmanagedHelpers.CompareUnsafe(x.Key.Data, x.Key.Count, y.Key.Data, y.Key.Count));
 }