`
bbwang8088
  • 浏览: 43956 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java 版本循环链表

阅读更多
/**
 * Circular chained byte array
 * 
 * @author bbwang8088@126.com
 */
public class CircularChainedBuffer {

	enum ACTION {
		WAIT, READ, WRITE
	}

	private ACTION lastAction = ACTION.WAIT;
	// current write position
	private int wPos = 0;
	// current read position
	private int rPos = 0;
	// byte array
	private byte[] buffer = null;
	// byte array length
	private int length = 0;

	public CircularChainedBuffer(int size) {
		this.length = size;
		init();
	}

	/**
	 * initialize method
	 */
	private void init() {
		this.buffer = new byte[this.length];
		this.wPos = 0;
		this.rPos = 0;
		this.lastAction = ACTION.WAIT;
	}

	/**
	 * reset method
	 */
	public void reset() {
		init();
	}

	/**
	 * Get current writable data size.
	 * 
	 * @return
	 */
	public int getWritableSize() {

		int ret = 0;

		// if initialize, return length of buffer array.
		if (this.wPos == 0 && this.rPos == 0) {
			return this.length;
		}

		ret = this.wPos - this.rPos;

		// normal case.
		if (ret > 0) {
			ret = this.length - ret;
		}
		// same position of read and write.
		else if (ret == 0) {
			// write to same position,then cann't write any more.
			if (this.lastAction == ACTION.WRITE) {
				ret = 0;
			}
			// read to same position,then cann't read any more, array is empty.
			else if (this.lastAction == ACTION.READ) {
				ret = this.length;
			}
		}
		// if read position before write position, then calculate against.
		else {
			ret = this.rPos - this.wPos;
		}

		return ret;
	}

	/**
	 * Get current readable data size.
	 * 
	 * @return
	 */
	public int getReadableSize() {

		return this.length - this.getWritableSize();
	}

	/**
	 * Try to write some data, if cann't write all, then write a part, if buffer
	 * is filled, then return 0.
	 * 
	 * @param data
	 * @return return size of wrote data
	 */
	public synchronized int tryWrite(byte[] data) {

		int retValue = 0;
		int tmpWritableSize = this.getWritableSize();

		// if current writable size is 0, then return 0.
		if (tmpWritableSize == 0) {
			return 0;
		}

		int copyLength = 0;

		if (data.length > tmpWritableSize) {
			copyLength = tmpWritableSize;
		} else {
			copyLength = data.length;
		}

		// write position after read position.
		if (this.wPos >= this.rPos) {
			// all data can write from current write position to end of array,
			// no need to write data back to head of buffer array.
			if ((this.wPos + copyLength) <= this.length) {
				// copy all data of parameter array to buffer array.
				System.arraycopy(data, 0, this.buffer, this.wPos, copyLength);
				// move write position.
				this.wPos += copyLength;
			}
			// copy part of parameter array full fill buffer array from write
			// position,
			// then copy left part of parameter array from head of buffer array.
			else {
				int partA = (this.length - this.wPos);
				int partB = copyLength - partA;
				// copy part of parameter array full fill buffer array from
				// write position
				System.arraycopy(data, 0, this.buffer, this.wPos, partA);
				// copy left part of parameter array from head of buffer array
				System.arraycopy(data, partA, this.buffer, 0, partB);
				// move write position
				this.wPos = partB;
			}
		}
		// read position after write position
		else {
			// can only write data between write position and read position
			System.arraycopy(data, 0, this.buffer, this.wPos, copyLength);
			// move write position
			this.wPos += copyLength;
		}
		retValue = copyLength;
		this.lastAction = ACTION.WRITE;

		return retValue;
	}

	/**
	 * Try to read size of data,return real read data, if no data can read then
	 * return null.
	 * 
	 * @param size
	 * @return return byte array of read data
	 */
	public synchronized byte[] tryRead(int size) {

		byte[] ret = null;
		int tmpReadableSize = this.getReadableSize();

		if (tmpReadableSize == 0 || size <= 0) {
			return new byte[0];
		}

		int realReadLength = 0;

		if (size > tmpReadableSize) {
			realReadLength = tmpReadableSize;
		} else {
			realReadLength = size;
		}

		ret = new byte[realReadLength];

		// write position after read position.
		if (this.rPos < this.wPos) {

			System.arraycopy(this.buffer, this.rPos, ret, 0, realReadLength);
			this.rPos += realReadLength;
		}
		// read position after write position
		else {
			if( (this.rPos +realReadLength ) <= this.length){
				System.arraycopy(this.buffer, this.rPos, ret, 0, realReadLength);
				this.rPos += realReadLength;
			}else{
				int partA = (this.length - this.rPos);
				int partB = realReadLength - partA;
				
				//Log.d(this.getClass().getSimpleName(),"size:"+size+" realReadLength"+realReadLength+" this.length:"+this.length+" this.rPos:"+this.rPos+" this.wPos:"+this.wPos+" partA:"+partA+" partB:"+partB);
				// copy part of parameter array full fill buffer array from write
				// position
				System.arraycopy(this.buffer, this.rPos, ret, 0, partA);
				// copy left part of parameter array from head of buffer array
				System.arraycopy(this.buffer, 0, ret, partA, partB);
				// move write position
				this.rPos = partB;
			}

		}

		this.lastAction = ACTION.READ;

		return ret;
	}

	/**
	 * Attation: this method will not move read position. Try to read size of
	 * data,return real read data, if no data can read then return null.
	 * 
	 * @param size
	 * @return return byte array of read data
	 */
	public synchronized byte[] pretendRead(int size) {

		byte[] ret = null;
		int tmpReadableSize = this.getReadableSize();

		if (tmpReadableSize == 0) {
			return new byte[0];
		}

		int realReadLength = 0;

		if (size > tmpReadableSize) {
			realReadLength = tmpReadableSize;
		} else {
			realReadLength = size;
		}

		ret = new byte[realReadLength];

		// write position after read position.
		if (this.rPos < this.wPos) {

			System.arraycopy(this.buffer, this.rPos, ret, 0, realReadLength);
			// this.rPos += realReadLength;
		}
		// read position after write position
		else {
			int partA = (this.length - this.rPos);
			int partB = realReadLength - partA;
			// copy part of parameter array full fill buffer array from write
			// position
			System.arraycopy(this.buffer, this.rPos, ret, 0, partA);
			// copy left part of parameter array from head of buffer array
			System.arraycopy(this.buffer, 0, ret, partA, partB);
			// move write position
			// this.rPos = partB;
		}

		// this.lastAction = ACTION.READ;

		return ret;
	}

	public synchronized byte[] pretendReadAll() {
		return this.pretendRead(this.getReadableSize());
	}

	/**
	 * Attation: this method will not move read position. Try to read size of
	 * data,return real read data, if no data can read then return null.
	 * 
	 * @param size
	 * @return return byte array of read data
	 */
	public synchronized byte[] pretendRead(int offset, int size) {
		byte[] data = new byte[size];
		System.arraycopy(pretendReadAll(), offset, data, 0, size);
		return data;
	}

	public synchronized byte[] readAll() {
		return this.tryRead(this.getReadableSize());
	}

	public String toString() {

		StringBuffer sb = new StringBuffer();
		for (byte b : this.buffer) {
			sb.append(" " + Integer.toHexString(b & 0xFF));
		}
		return sb.toString();
	}
}

 

import static org.junit.Assert.*;

import org.junit.Test;

/**
 * Tester for Circular chained byte array
 * 
 * @author bbwang8088@126.com
 */
public class TestCycleByteArray {

	@Test
	public void TestGetWritableSize() {
		int size = 4096;
		CircularChainedBuffer buffer = new CircularChainedBuffer(size);
		assertEquals(buffer.getWritableSize(), size);

		byte[] data1_size10 = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
		byte[] data2_size10 = { (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa,
				(byte) 0xaa };
//		byte[] data3_size10 = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
//				(byte) 0xff };
		
		buffer.tryWrite(data1_size10);
		assertEquals(size - data1_size10.length, buffer.getWritableSize());
		assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize());
//		System.out.println(buffer.toString());

		buffer.tryWrite(data2_size10);
		assertEquals(size - data2_size10.length * 2, buffer.getWritableSize());
		assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize());
//		System.out.println(buffer.toString());

		byte[] data = buffer.tryRead(data2_size10.length * 2);
//		System.out.println(new String(data));
		assertEquals(size, buffer.getWritableSize());
		assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize());
//		System.out.println(buffer.toString());

		data = buffer.tryRead(data2_size10.length * 2);
		assertEquals(0, data.length);
//		System.out.println(new String(data));
//		System.out.println(buffer.toString());

		for (int i = 0; i < (size / data1_size10.length); i++) {
			assertEquals(data1_size10.length, buffer.tryWrite(data1_size10));// 1
//			System.out.println(buffer.toString());
		}

		assertEquals(size % data1_size10.length, buffer.getWritableSize());
		assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize());

		data = buffer.tryRead(size*2);
		assertEquals(size-size%data1_size10.length, data.length);
		assertEquals(size, buffer.getWritableSize());
		assertEquals(0, buffer.getReadableSize());
		assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize());

		assertEquals(data1_size10.length, buffer.tryWrite(data1_size10));
		assertEquals(data2_size10.length, buffer.tryWrite(data2_size10));
		assertEquals(size - data1_size10.length * 2, buffer.getWritableSize());
		assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize());

		data = buffer.tryRead(data1_size10.length*2);
		assertEquals(data1_size10.length*2, data.length);
		assertEquals(size, buffer.getWritableSize());
		assertEquals(0, buffer.getReadableSize());
		assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize());

		for (int i = 0; i < (size / data1_size10.length); i++) {
			assertEquals(data1_size10.length, buffer.tryWrite(data1_size10));// 1
		}
		

		assertEquals(size % data1_size10.length, buffer.getWritableSize());
		assertEquals(size-size % data1_size10.length, buffer.getReadableSize());
		assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize());

		assertEquals(size % data1_size10.length, buffer.tryWrite(data1_size10));// 1
		data = buffer.readAll();
		assertEquals(size, buffer.getWritableSize());
		assertEquals(0, buffer.getReadableSize());

	}
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics