From 887423b659b91a2f24af17ba2481c6be05df2992 Mon Sep 17 00:00:00 2001 From: Ziver Koc Date: Tue, 22 Sep 2015 14:52:53 +0000 Subject: [PATCH] Added CircularBuffer class --- Zutil.jar | Bin 1217841 -> 1221574 bytes src/zutil/struct/CircularBuffer.java | 108 +++++++++++++++++++++++ src/zutil/test/CircularBufferTest.java | 116 +++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 src/zutil/struct/CircularBuffer.java create mode 100644 src/zutil/test/CircularBufferTest.java diff --git a/Zutil.jar b/Zutil.jar index 1f7356dddc2aa4c0be0ec41e64233e3dfa3174ef..c545a969955551c719e89fcd346635df46c1cd88 100644 GIT binary patch delta 16296 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 Ni8wej^Z+z`{2#MmEz1A^ delta 12641 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 P@ZZGY;i;d7V5k2NT-mPk 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) {} + } +}