123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- /*
- Copyright (c) 2012, Alex Regueiro
- All rights reserved.
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
- following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the distribution.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Threading;
- namespace OpenSim.Framework
- {
- public class CircularBuffer<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
- {
- private int capacity;
- private int size;
- private int head;
- private int tail;
- private T[] buffer;
- [NonSerialized()]
- private object syncRoot;
- public CircularBuffer(int capacity)
- : this(capacity, false)
- {
- }
- public CircularBuffer(int capacity, bool allowOverflow)
- {
- if (capacity < 0)
- throw new ArgumentException("Needs to have at least 1","capacity");
- this.capacity = capacity;
- size = 0;
- head = 0;
- tail = 0;
- buffer = new T[capacity];
- AllowOverflow = allowOverflow;
- }
- public bool AllowOverflow
- {
- get;
- set;
- }
- public int Capacity
- {
- get { return capacity; }
- set
- {
- if (value == capacity)
- return;
- if (value < size)
- throw new ArgumentOutOfRangeException("value","Capacity is too small.");
- var dst = new T[value];
- if (size > 0)
- CopyTo(dst);
- buffer = dst;
- capacity = value;
- }
- }
- public int Size
- {
- get { return size; }
- }
- public bool Contains(T item)
- {
- int bufferIndex = head;
- var comparer = EqualityComparer<T>.Default;
- for (int i = 0; i < size; i++, bufferIndex++)
- {
- if (bufferIndex == capacity)
- bufferIndex = 0;
- if (item == null && buffer[bufferIndex] == null)
- return true;
- else if ((buffer[bufferIndex] != null) &&
- comparer.Equals(buffer[bufferIndex], item))
- return true;
- }
- return false;
- }
- public void Clear()
- {
- size = 0;
- head = 0;
- tail = 0;
- }
- public int Put(T[] src)
- {
- return Put(src, 0, src.Length);
- }
- public int Put(T[] src, int offset, int count)
- {
- if (!AllowOverflow && count > capacity - size)
- throw new InvalidOperationException("Buffer Overflow");
- int srcIndex = offset;
- for (int i = 0; i < count; i++, tail++, srcIndex++)
- {
- if (tail == capacity)
- tail = 0;
- buffer[tail] = src[srcIndex];
- }
- size = Math.Min(size + count, capacity);
- return count;
- }
- public void Put(T item)
- {
- if (!AllowOverflow && size == capacity)
- throw new InvalidOperationException("Buffer Overflow");
- buffer[tail] = item;
- if (++tail == capacity)
- tail = 0;
- size++;
- }
- public void Skip(int count)
- {
- head += count;
- if (head >= capacity)
- head -= capacity;
- }
- public T[] Get(int count)
- {
- var dst = new T[count];
- Get(dst);
- return dst;
- }
- public int Get(T[] dst)
- {
- return Get(dst, 0, dst.Length);
- }
- public int Get(T[] dst, int offset, int count)
- {
- int realCount = Math.Min(count, size);
- int dstIndex = offset;
- for (int i = 0; i < realCount; i++, head++, dstIndex++)
- {
- if (head == capacity)
- head = 0;
- dst[dstIndex] = buffer[head];
- }
- size -= realCount;
- return realCount;
- }
- public T Get()
- {
- if (size == 0)
- throw new InvalidOperationException("Buffer Empty");
- var item = buffer[head];
- if (++head == capacity)
- head = 0;
- size--;
- return item;
- }
- public void CopyTo(T[] array)
- {
- CopyTo(array, 0);
- }
- public void CopyTo(T[] array, int arrayIndex)
- {
- CopyTo(0, array, arrayIndex, size);
- }
- public void CopyTo(int index, T[] array, int arrayIndex, int count)
- {
- if (count > size)
- throw new ArgumentOutOfRangeException("count", "Count Too Large");
- int bufferIndex = head;
- for (int i = 0; i < count; i++, bufferIndex++, arrayIndex++)
- {
- if (bufferIndex == capacity)
- bufferIndex = 0;
- array[arrayIndex] = buffer[bufferIndex];
- }
- }
- public IEnumerator<T> GetEnumerator()
- {
- int bufferIndex = head;
- for (int i = 0; i < size; i++, bufferIndex++)
- {
- if (bufferIndex == capacity)
- bufferIndex = 0;
- yield return buffer[bufferIndex];
- }
- }
- public T[] GetBuffer()
- {
- return buffer;
- }
- public T[] ToArray()
- {
- var dst = new T[size];
- CopyTo(dst);
- return dst;
- }
- #region ICollection<T> Members
- int ICollection<T>.Count
- {
- get { return Size; }
- }
- bool ICollection<T>.IsReadOnly
- {
- get { return false; }
- }
- void ICollection<T>.Add(T item)
- {
- Put(item);
- }
- bool ICollection<T>.Remove(T item)
- {
- if (size == 0)
- return false;
- Get();
- return true;
- }
- #endregion
- #region IEnumerable<T> Members
- IEnumerator<T> IEnumerable<T>.GetEnumerator()
- {
- return GetEnumerator();
- }
- #endregion
- #region ICollection Members
- int ICollection.Count
- {
- get { return Size; }
- }
- bool ICollection.IsSynchronized
- {
- get { return false; }
- }
- object ICollection.SyncRoot
- {
- get
- {
- if (syncRoot == null)
- Interlocked.CompareExchange(ref syncRoot, new object(), null);
- return syncRoot;
- }
- }
- void ICollection.CopyTo(Array array, int arrayIndex)
- {
- CopyTo((T[])array, arrayIndex);
- }
- #endregion
- #region IEnumerable Members
- IEnumerator IEnumerable.GetEnumerator()
- {
- return (IEnumerator)GetEnumerator();
- }
- #endregion
- }
- }
|