package multimonster.common.pipe; /** * Implementation of a RingBuffer. * * @author Holger Velke (sihovelk) */ class RingBuffer { /* * Let 'size' be the size of the buffer B in bytes. * * Let 'inIndex' be an index into the buffer where the producer will store the * next new byte of data. * * Let 'outIndex' be the index of the next byte that the consumer should remove * from the buffer. * * Let 'used' be the number of unconsumed bytes in the buffer. Define % as the * modulus operator. * * Initially, I = O = N = 0. * * The buffer is full (has no room for new data) when N == S. The available * space (for new data) A = S - N */ private int size; // size of B private int inIndex; // input index private int outIndex; // output ndex private int avalbl; // available (free) space private int used; // number of bytes in B private byte[] buffer; // the buffer /** * Allocate a ring buffer of size s */ public RingBuffer(int size) { this.size = size; this.avalbl = size; this.used = 0; this.inIndex = 0; this.outIndex = 0; buffer = new byte[size]; } /** * Add m bytes of data from buffer D to the buffer B */ public void add(byte[] D, int m) throws Exception { // Check that m <= A (if not an error has occurred) if (m > avalbl) throw new Exception("ringBuffer.add(): insufficient room in buffer"); int j = inIndex; inIndex = (inIndex + m) % size; used += m; for (int q = 0; q < m; q++) buffer[(j + q) % size] = D[q]; // update available space avalbl = size - used; } /** * Get n bytes from the buffer B to buffer 'buf' */ public int get(byte[] buf, int n) { if (used == 0) return 0; // Check that r <= N. If not, adjust r (r = N) int result = n; if (n > used) result = used; int j = outIndex; outIndex = (outIndex + result) % size; used -= result; try { for (int q = 0; q < result; q++) buf[q] = buffer[(j + q) % size]; } catch (Exception x) { System.out.println("ringBuffer " + x.toString()); } // update available space avalbl = size - used; return result; } /** * Return the number of bytes in the buffer. */ public int length() { return used; } /** * Checks if buffer is empty. * * @return */ public boolean isEmpty(){ if (length() == 0) { return true; } else { return false; } } /** * @return */ public int available() { return avalbl; } }