001: package org.bouncycastle.crypto.tls;
002:
003: /**
004: * A queue for bytes.
005: * <p/>
006: * This file could be more optimized.
007: * </p>
008: */
009: public class ByteQueue {
010:
011: /**
012: * @return The smallest number which can be written as 2^x which is
013: * bigger than i.
014: */
015: public static final int nextTwoPow(int i) {
016: /*
017: * This code is based of a lot of code I found on the Internet
018: * which mostly referenced a book called "Hacking delight".
019: *
020: */
021: i |= (i >> 1);
022: i |= (i >> 2);
023: i |= (i >> 4);
024: i |= (i >> 8);
025: i |= (i >> 16);
026: return i + 1;
027: }
028:
029: /**
030: * The initial size for our buffer.
031: */
032: private static final int INITBUFSIZE = 1024;
033:
034: /**
035: * The buffer where we store our data.
036: */
037: private byte[] databuf = new byte[ByteQueue.INITBUFSIZE];
038:
039: /**
040: * How many bytes at the beginning of the buffer are skipped.
041: */
042: private int skipped = 0;
043:
044: /**
045: * How many bytes in the buffer are valid data.
046: */
047: private int available = 0;
048:
049: /**
050: * Read data from the buffer.
051: *
052: * @param buf The buffer where the read data will be copied to.
053: * @param offset How many bytes to skip at the beginning of buf.
054: * @param len How many bytes to read at all.
055: * @param skip How many bytes from our data to skip.
056: */
057: public void read(byte[] buf, int offset, int len, int skip) {
058: if ((available - skip) < len) {
059: throw new TlsRuntimeException("Not enough data to read");
060: }
061: if ((buf.length - offset) < len) {
062: throw new TlsRuntimeException("Buffer size of "
063: + buf.length + " is too small for a read of " + len
064: + " bytes");
065: }
066: System.arraycopy(databuf, skipped + skip, buf, offset, len);
067: return;
068: }
069:
070: /**
071: * Add some data to our buffer.
072: *
073: * @param data A byte-array to read data from.
074: * @param offset How many bytes to skip at the beginning of the array.
075: * @param len How many bytes to read from the array.
076: */
077: public void addData(byte[] data, int offset, int len) {
078: if ((skipped + available + len) > databuf.length) {
079: byte[] tmp = new byte[ByteQueue.nextTwoPow(data.length)];
080: System.arraycopy(databuf, skipped, tmp, 0, available);
081: skipped = 0;
082: databuf = tmp;
083: }
084: System.arraycopy(data, offset, databuf, skipped + available,
085: len);
086: available += len;
087: }
088:
089: /**
090: * Remove some bytes from our data from the beginning.
091: *
092: * @param i How many bytes to remove.
093: */
094: public void removeData(int i) {
095: if (i > available) {
096: throw new TlsRuntimeException("Cannot remove " + i
097: + " bytes, only got " + available);
098: }
099:
100: /*
101: * Skip the data.
102: */
103: available -= i;
104: skipped += i;
105:
106: /*
107: * If more than half of our data is skipped, we will move the data
108: * in the buffer.
109: */
110: if (skipped > (databuf.length / 2)) {
111: System.arraycopy(databuf, skipped, databuf, 0, available);
112: skipped = 0;
113: }
114: }
115:
116: /**
117: * @return The number of bytes which are available in this buffer.
118: */
119: public int size() {
120: return available;
121: }
122:
123: }
|