private static void AssertWritableBuffer(ref LinkedFifoBuffer <T> buffer)
 {
     if (buffer == null)
     {
         buffer = new LinkedFifoBuffer <T>(DefaultCapacity, 0);
     }
     else if (buffer.head >= buffer.data.Length)
     {
         buffer.next = new LinkedFifoBuffer <T>(buffer.data.Length, buffer.offset + buffer.data.Length);
         buffer      = buffer.next;
     }
 }
 /// <summary>Append data to the buffer.</summary>
 /// <exception cref="ArgumentOutOfRangeException">Thrown when one or more arguments are outside the required range.</exception>
 /// <param name="buffer">[in,out] The buffer.</param>
 /// <param name="data">The data.</param>
 /// <param name="index">Zero-based index of the.</param>
 /// <param name="count">Number of data items to write.</param>
 public static void Write(ref LinkedFifoBuffer <T> buffer, T[] data, int index, int count)
 {
     if (count == 0)
     {
         return;
     }
     if (count < 0)
     {
         throw new ArgumentOutOfRangeException(nameof(count));
     }
     do
     {
         AssertWritableBuffer(ref buffer);
         var size = Math.Min(count, buffer.data.Length - buffer.head);
         Debug.Assert(size > 0);
         Array.Copy(data, index, buffer.data, buffer.head, size);
         buffer.head += size;
         index       += size;
         count       -= size;
     } while (count > 0);
 }
        public void Fifo()
        {
            // tiny buffer capacity so that we can test the different methods with buffer breakover
            var buffer   = new LinkedFifoBuffer <byte>(4);
            var position = buffer.HeadPosition;

            for (byte i = 1; i <= 4; i++)
            {
                LinkedFifoBuffer <byte> .Write(ref buffer, i);

                // no breakover
                Assert.Same(position.Buffer, buffer);
            }
            Assert.Equal(4, position.Count());
            Assert.Equal(4, position.AvailableCount());
            LinkedFifoBuffer <byte> .Write(ref buffer, 5);

            Assert.Equal(5, position.Count());
            Assert.Equal(5, position.AvailableCount());
            Assert.NotSame(position.Buffer, buffer);
            Assert.Equal(ByteRange(1, 5), position);
            position = position.Advance(4);
            Assert.NotSame(position.Buffer, buffer);
            Assert.Equal(ByteRange(5, 1), position);
            position = position.Advance(1);
            Assert.Same(position.Buffer, buffer);
            Assert.Empty(position);
            LinkedFifoBuffer <byte> .Write(ref buffer, ByteRange(6, 3));

            Assert.Same(position.Buffer, buffer);
            LinkedFifoBuffer <byte> .Write(ref buffer, ByteRange(9, 10));

            Assert.NotSame(position.Buffer, buffer);
            Assert.Equal(ByteRange(6, 13), position);
            position = position.Advance(12);
            Assert.Same(position.Buffer, buffer);
            Assert.Equal(ByteRange(18, 1), position);
            position = position.Advance(1);
            Assert.Empty(position);
        }
 /// <summary>Constructor.</summary>
 /// <param name="buffer">The buffer.</param>
 /// <param name="index">Zero-based index into the buffer.</param>
 public BufferPosition(LinkedFifoBuffer <T> buffer, int index)
 {
     this.Buffer = buffer;
     this.Index  = index;
 }
 /// <summary>Append data to the buffer.</summary>
 /// <param name="buffer">[in,out] The buffer.</param>
 /// <param name="data">The data.</param>
 public static void Write(ref LinkedFifoBuffer <T> buffer, T data)
 {
     AssertWritableBuffer(ref buffer);
     buffer.data[buffer.head++] = data;
 }
 /// <summary>Append data to the buffer.</summary>
 /// <param name="buffer">[in,out] The buffer.</param>
 /// <param name="data">The data.</param>
 public static void Write(ref LinkedFifoBuffer <T> buffer, T[] data)
 {
     Write(ref buffer, data, 0, data.Length);
 }