diff --git a/Zutil.jar b/Zutil.jar index 1f7356d..c545a96 100644 Binary files a/Zutil.jar and b/Zutil.jar differ diff --git a/src/zutil/struct/CircularBuffer.java b/src/zutil/struct/CircularBuffer.java new file mode 100644 index 0000000..dd2005e --- /dev/null +++ b/src/zutil/struct/CircularBuffer.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015 ezivkoc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.struct; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * This class is a first in first out circular buffer with a fixed size. + * If the size is exceed then the oldest item will be removed. + * Created by Ziver on 2015-09-22. + */ +public class CircularBuffer implements Iterable{ + + private Object[] buffer; + private int buffSize; + private int buffPos; + private long addCount; + + /** + * Initiates the buffer with a maximum size of maxSize. + */ + public CircularBuffer(int maxSize){ + buffer = new Object[maxSize]; + buffSize = 0; + buffPos = 0; + } + + public void add(T obj){ + if(buffPos+1 >= buffer.length) + buffPos = 0; + else + ++buffPos; + if(buffSize < buffer.length) + ++buffSize; + buffer[buffPos] = obj; + ++addCount; + } + + public T get(int index) { + if(index >= buffSize) + throw new IndexOutOfBoundsException("Index "+ index +" is larger than actual buffer size "+ buffSize); + int buffIndex = buffPos - index; + if(buffIndex < 0) + buffIndex = buffer.length - Math.abs(buffIndex); + return (T)buffer[buffIndex]; + } + + public int size() { + return buffSize; + } + + /** + * @return the total amount of insertions into the buffer, this value only increments and will never decrease. + */ + public long getInsertionCount() { + return addCount; + } + + @Override + public Iterator iterator() { + return new CircularBufferIterator(); + } + + + protected class CircularBufferIterator implements Iterator { + private int iteratorPos = 0; + + @Override + public boolean hasNext() { + return iteratorPos < buffSize; + } + + @Override + public T next() { + if(iteratorPos >= buffSize) + throw new NoSuchElementException(); + return get(iteratorPos++); + } + + @Override + public void remove() { + throw new NotImplementedException(); + } + } +} diff --git a/src/zutil/test/CircularBufferTest.java b/src/zutil/test/CircularBufferTest.java new file mode 100644 index 0000000..9de3c27 --- /dev/null +++ b/src/zutil/test/CircularBufferTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 ezivkoc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.test; + +import org.junit.Test; +import zutil.struct.CircularBuffer; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static org.junit.Assert.*; + +/** + * Created by Ziver on 2015-09-22. + */ +public class CircularBufferTest { + + @Test + public void addToEmpty() { + CircularBuffer buff = new CircularBuffer(0); + try { + buff.add(10); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) {} + } + + @Test + public void addOneElement() { + CircularBuffer buff = new CircularBuffer(1); + assertEquals(0, buff.size()); + buff.add(10); + assertEquals(1, buff.size()); + assertEquals((Integer) 10, buff.get(0)); + } + + @Test + public void addThreeElements() { + CircularBuffer buff = new CircularBuffer(10); + buff.add(10); + buff.add(11); + buff.add(12); + assertEquals(3, buff.size()); + assertEquals((Integer) 12, buff.get(0)); + assertEquals((Integer) 11, buff.get(1)); + assertEquals((Integer) 10, buff.get(2)); + } + + @Test + public void addOutOfRange() { + CircularBuffer buff = new CircularBuffer(2); + buff.add(10); + buff.add(11); + buff.add(12); + assertEquals(2, buff.size()); + assertEquals((Integer) 12, buff.get(0)); + assertEquals((Integer) 11, buff.get(1)); + try { + buff.get(2); + fail("IndexOutOfBoundsException was not thrown"); + } catch (IndexOutOfBoundsException e) {} + } + + @Test + public void iteratorEmpty() { + CircularBuffer buff = new CircularBuffer(10); + Iterator it = buff.iterator(); + + assert (!it.hasNext()); + try { + it.next(); + fail("NoSuchElementException was not thrown"); + } catch (NoSuchElementException e) {} + } + + @Test + public void iteratorThreeElements() { + CircularBuffer buff = new CircularBuffer(10); + buff.add(10); + buff.add(11); + buff.add(12); + + Iterator it = buff.iterator(); + assert (it.hasNext()); + assertEquals((Integer) 12, it.next()); + assert (it.hasNext()); + assertEquals((Integer) 11, it.next()); + assert (it.hasNext()); + assertEquals((Integer) 10, it.next()); + assert (!it.hasNext()); + + try { + it.next(); + fail("NoSuchElementException was not thrown"); + } catch (NoSuchElementException e) {} + } +}