/* * 21.04.2004 Original verion. davagin@udm.ru. *----------------------------------------------------------------------- * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *---------------------------------------------------------------------- */ package davaguine.jmac.tools; /** * Author: Dmitry Vaguine * Date: 06.05.2004 * Time: 21:05:48 */ public class CircleBuffer { // construction / destruction public CircleBuffer() { m_pBuffer = null; m_nTotal = 0; m_nHead = 0; m_nTail = 0; m_nEndCap = 0; m_nMaxDirectWriteBytes = 0; } // create the buffer public void CreateBuffer(int nBytes, int nMaxDirectWriteBytes) { m_nMaxDirectWriteBytes = nMaxDirectWriteBytes; m_nTotal = nBytes + 1 + nMaxDirectWriteBytes; m_pBuffer = new byte[m_nTotal]; byteBuffer = new ByteBuffer(); m_nHead = 0; m_nTail = 0; m_nEndCap = m_nTotal; } // query public int MaxAdd() { int nMaxAdd = (m_nTail >= m_nHead) ? (m_nTotal - 1 - m_nMaxDirectWriteBytes) - (m_nTail - m_nHead) : m_nHead - m_nTail - 1; return nMaxAdd; } public int MaxGet() { return (m_nTail >= m_nHead) ? m_nTail - m_nHead : (m_nEndCap - m_nHead) + m_nTail; } // direct writing public ByteBuffer GetDirectWritePointer() { // return a pointer to the tail -- note that it will always be safe to write // at least m_nMaxDirectWriteBytes since we use an end cap region byteBuffer.reset(m_pBuffer, m_nTail); return byteBuffer; } public void UpdateAfterDirectWrite(int nBytes) { // update the tail m_nTail += nBytes; // if the tail enters the "end cap" area, set the end cap and loop around if (m_nTail >= (m_nTotal - m_nMaxDirectWriteBytes)) { m_nEndCap = m_nTail; m_nTail = 0; } } // get data public int Get(byte[] pBuffer, int index, int nBytes) { int nTotalGetBytes = 0; if (pBuffer != null && nBytes > 0) { int nHeadBytes = Math.min(m_nEndCap - m_nHead, nBytes); int nFrontBytes = nBytes - nHeadBytes; System.arraycopy(m_pBuffer, m_nHead, pBuffer, index, nHeadBytes); nTotalGetBytes = nHeadBytes; if (nFrontBytes > 0) { System.arraycopy(m_pBuffer, 0, pBuffer, index + nHeadBytes, nFrontBytes); nTotalGetBytes += nFrontBytes; } RemoveHead(nBytes); } return nTotalGetBytes; } // remove / empty public void Empty() { m_nHead = 0; m_nTail = 0; m_nEndCap = m_nTotal; } public int RemoveHead(int nBytes) { nBytes = Math.min(MaxGet(), nBytes); m_nHead += nBytes; if (m_nHead >= m_nEndCap) m_nHead -= m_nEndCap; return nBytes; } public int RemoveTail(int nBytes) { nBytes = Math.min(MaxGet(), nBytes); m_nTail -= nBytes; if (m_nTail < 0) m_nTail += m_nEndCap; return nBytes; } private int m_nTotal; private int m_nMaxDirectWriteBytes; private int m_nEndCap; private int m_nHead; private int m_nTail; private byte[] m_pBuffer; private ByteBuffer byteBuffer; }