001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mq.il.uil2.msgs;
023:
024: /** A circular byte[] buffer capable of expanding its capacity
025: *
026: * @author Scott.Stark@jboss.org
027: */
028: public class DynCircularBuffer {
029: byte[] buffer;
030: int pos;
031: int end;
032: boolean isFull;
033:
034: /** Creates a new instance of DynCircularBuffer */
035: public DynCircularBuffer() {
036: this (1024);
037: }
038:
039: public DynCircularBuffer(int capacity) {
040: buffer = new byte[capacity];
041: pos = 0;
042: end = 0;
043: }
044:
045: public synchronized void clear() {
046: pos = 0;
047: end = 0;
048: isFull = false;
049: }
050:
051: public synchronized void fill(byte[] data) {
052: fill(data, data.length);
053: }
054:
055: public synchronized void fill(byte[] data, int length) {
056: int freeSpace = getFreeSpace();
057: int currentLength = getSize();
058: if (freeSpace < length) {
059: int newSize = buffer.length + length - freeSpace;
060: byte[] tmp = new byte[newSize];
061: for (int i = 0; i < currentLength; i++) {
062: tmp[i] = buffer[pos];
063: pos++;
064: if (pos == buffer.length)
065: pos = 0;
066: }
067: buffer = tmp;
068: pos = 0;
069: end = currentLength;
070: }
071: // Copy the data in
072: for (int i = 0; i < length; i++) {
073: buffer[end] = data[i];
074: end++;
075: if (end == buffer.length)
076: end = 0;
077: }
078: if (end == pos)
079: isFull = true;
080: }
081:
082: public synchronized int get() {
083: if (pos == end && isFull == false)
084: return -1;
085:
086: int b = buffer[pos] & 0xff;
087: pos++;
088: if (pos == buffer.length)
089: pos = 0;
090: isFull = false;
091: return b;
092: }
093:
094: public synchronized int get(byte b[], int off, int length) {
095: if (pos == end && isFull == false)
096: return -1;
097:
098: int getSize = Math.min(getSize(), length);
099: for (int i = 0; i < getSize; i++) {
100: b[off + i] = buffer[pos];
101: pos++;
102: if (pos == buffer.length)
103: pos = 0;
104: }
105: isFull = isFull ? getSize == 0 : false;
106: return getSize;
107: }
108:
109: /** Get the amount of used space in the buffer
110: */
111: public synchronized int getSize() {
112: int length = buffer.length - getFreeSpace();
113: return length;
114: }
115:
116: /** Get the amount of free space left in the buffer
117: */
118: public synchronized int getFreeSpace() {
119: int available = 0;
120: if (pos == end) {
121: if (isFull == true)
122: available = 0;
123: else
124: available = buffer.length;
125: } else if (pos < end)
126: available = buffer.length - end + pos;
127: else
128: available = pos - end;
129: return available;
130: }
131:
132: /** Unit test driver for the buffer
133: */
134: public static void main(String[] args) throws Exception {
135: DynCircularBuffer dcb = new DynCircularBuffer(16);
136: if (dcb.getFreeSpace() != 16)
137: throw new IllegalStateException("dcb.getFreeSpace() != 16");
138: if (dcb.getSize() != 0)
139: throw new IllegalStateException("dcb.getSize() != 0");
140: byte[] tst = { '1', '2', '3', '4', '5', '6', '7', '8', '9',
141: 'a', 'b', 'c', 'd', 'e', 'f' };
142: dcb.fill(tst);
143: if (dcb.getFreeSpace() != 1)
144: throw new IllegalStateException("dcb.getFreeSpace() != 1, "
145: + dcb.getFreeSpace());
146: if (dcb.getSize() != 15)
147: throw new IllegalStateException("dcb.getSize() != 15");
148:
149: byte[] tst2 = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
150: '9', 'a', 'b', 'c', 'd', 'e', 'f' };
151: dcb.clear();
152: dcb.fill(tst2);
153: if (dcb.getFreeSpace() != 0)
154: throw new IllegalStateException("dcb.getFreeSpace() != 0, "
155: + dcb.getFreeSpace());
156: if (dcb.getSize() != 16)
157: throw new IllegalStateException("dcb.getSize() != 16");
158:
159: dcb.clear();
160: dcb.fill(tst);
161: dcb.fill(tst2);
162: if (dcb.getFreeSpace() != 0)
163: throw new IllegalStateException("dcb.getFreeSpace() != 0, "
164: + dcb.getFreeSpace());
165: if (dcb.getSize() != 31)
166: throw new IllegalStateException("dcb.getSize() != 31, "
167: + dcb.getSize());
168:
169: for (int i = 0; i < tst.length; i++) {
170: int b = dcb.get();
171: if (b != tst[i])
172: throw new IllegalStateException("tst[" + i + ","
173: + tst[i] + "] != " + b);
174: }
175: for (int i = 0; i < tst2.length; i++) {
176: int b = dcb.get();
177: if (b != tst2[i])
178: throw new IllegalStateException("tst2[" + i + ","
179: + tst2[i] + "] != " + b);
180: }
181: if (dcb.get() != -1)
182: throw new IllegalStateException("dcb.get() != -1");
183:
184: dcb.fill(tst);
185: byte[] out = new byte[128];
186: int bytes = dcb.get(out, 0, 128);
187: if (bytes != 15)
188: throw new IllegalStateException(
189: "dcb.get(out, 0, 128) != 15, " + bytes);
190: if (dcb.getFreeSpace() != 31)
191: throw new IllegalStateException(
192: "dcb.getFreeSpace() != 31, " + dcb.getFreeSpace());
193: if (dcb.getSize() != 0)
194: throw new IllegalStateException("dcb.getSize() != 0, "
195: + dcb.getSize());
196:
197: dcb.clear();
198: for (int n = 0; n < 32; n++) {
199: dcb.fill(tst);
200: if (dcb.getFreeSpace() != 16)
201: throw new IllegalStateException(n
202: + ", dcb.getFreeSpace() != 16, "
203: + dcb.getFreeSpace());
204: if (dcb.getSize() != 15)
205: throw new IllegalStateException(n
206: + "dcb.getSize() != 15");
207: for (int i = 0; i < tst.length; i++) {
208: int b = dcb.get();
209: if (b != tst[i])
210: throw new IllegalStateException(n + "tst[" + i
211: + "," + tst[i] + "] != " + b);
212: }
213: if (dcb.get() != -1)
214: throw new IllegalStateException(n + "dcb.get() != -1");
215: if (dcb.getFreeSpace() != 31)
216: throw new IllegalStateException(n
217: + ", dcb.getFreeSpace() != 31, "
218: + dcb.getFreeSpace());
219: }
220:
221: byte[] tst3 = new byte[tst.length + tst2.length];
222: System.arraycopy(tst, 0, tst3, 0, tst.length);
223: System.arraycopy(tst2, 0, tst3, tst.length, tst2.length);
224: dcb.clear();
225: dcb.fill(tst3);
226: if (dcb.getFreeSpace() != 0)
227: throw new IllegalStateException("dcb.getFreeSpace() != 0, "
228: + dcb.getFreeSpace());
229: if (dcb.getSize() != 31)
230: throw new IllegalStateException("dcb.getSize() != 31, "
231: + dcb.getSize());
232: dcb.fill(tst);
233: if (dcb.getFreeSpace() != 0)
234: throw new IllegalStateException("dcb.getFreeSpace() != 0, "
235: + dcb.getFreeSpace());
236: if (dcb.getSize() != 46)
237: throw new IllegalStateException("dcb.getSize() != 46, "
238: + dcb.getSize());
239: for (int i = 0; i < tst.length; i++) {
240: int b = dcb.get();
241: if (b != tst[i])
242: throw new IllegalStateException("tst[" + i + ","
243: + tst[i] + "] != " + b);
244: }
245: for (int i = 0; i < tst2.length; i++) {
246: int b = dcb.get();
247: if (b != tst2[i])
248: throw new IllegalStateException("tst2[" + i + ","
249: + tst2[i] + "] != " + b);
250: }
251: for (int i = 0; i < tst.length; i++) {
252: int b = dcb.get();
253: if (b != tst[i])
254: throw new IllegalStateException("tst[" + i + ","
255: + tst[i] + "] != " + b);
256: }
257:
258: System.out.println("Done");
259: }
260: }
|