tikhomirov@115: /*
tikhomirov@115:  * Copyright (c) 2011 TMate Software Ltd
tikhomirov@115:  *  
tikhomirov@115:  * This program is free software; you can redistribute it and/or modify
tikhomirov@115:  * it under the terms of the GNU General Public License as published by
tikhomirov@115:  * the Free Software Foundation; version 2 of the License.
tikhomirov@115:  *
tikhomirov@115:  * This program is distributed in the hope that it will be useful,
tikhomirov@115:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
tikhomirov@115:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
tikhomirov@115:  * GNU General Public License for more details.
tikhomirov@115:  *
tikhomirov@115:  * For information on how to redistribute this software under
tikhomirov@115:  * the terms of a license other than GNU General Public License
tikhomirov@130:  * contact TMate Software at support@hg4j.com
tikhomirov@115:  */
tikhomirov@115: package org.tmatesoft.hg.internal;
tikhomirov@115: 
tikhomirov@115: import java.nio.ByteBuffer;
tikhomirov@115: import java.util.LinkedList;
tikhomirov@115: import java.util.List;
tikhomirov@115: 
tikhomirov@115: import org.tmatesoft.hg.util.ByteChannel;
tikhomirov@115: 
tikhomirov@115: /**
tikhomirov@115:  *
tikhomirov@115:  * @author Artem Tikhomirov
tikhomirov@115:  * @author TMate Software Ltd.
tikhomirov@115:  */
tikhomirov@115: public class ByteArrayChannel implements ByteChannel {
tikhomirov@115: 	private final List<ByteBuffer> buffers;
tikhomirov@115: 	private ByteBuffer target;
tikhomirov@115: 	private byte[] result;
tikhomirov@115: 	
tikhomirov@115: 	public ByteArrayChannel() {
tikhomirov@115: 		this(-1);
tikhomirov@115: 	}
tikhomirov@115: 	
tikhomirov@115: 	public ByteArrayChannel(int size) {
tikhomirov@115: 		if (size == -1) {
tikhomirov@115: 			buffers = new LinkedList<ByteBuffer>();
tikhomirov@115: 		} else {
tikhomirov@115: 			if (size < 0) {
tikhomirov@115: 				throw new IllegalArgumentException(String.valueOf(size));
tikhomirov@115: 			}
tikhomirov@115: 			buffers = null;
tikhomirov@115: 			target = ByteBuffer.allocate(size);
tikhomirov@115: 		}
tikhomirov@115: 	}
tikhomirov@115: 
tikhomirov@115: 	// TODO document what happens on write after toArray() in each case
tikhomirov@148: 	public int write(ByteBuffer buffer) {
tikhomirov@115: 		int rv = buffer.remaining();
tikhomirov@115: 		if (buffers == null) {
tikhomirov@115: 			target.put(buffer);
tikhomirov@115: 		} else {
tikhomirov@115: 			ByteBuffer copy = ByteBuffer.allocate(rv);
tikhomirov@115: 			copy.put(buffer);
tikhomirov@115: 			buffers.add(copy);
tikhomirov@115: 		}
tikhomirov@115: 		return rv;
tikhomirov@115: 	}
tikhomirov@115: 
tikhomirov@115: 	public byte[] toArray() {
tikhomirov@115: 		if (result != null) {
tikhomirov@115: 			return result;
tikhomirov@115: 		}
tikhomirov@115: 		if (buffers == null) {
tikhomirov@115: 			assert target.hasArray();
tikhomirov@115: 			// int total = target.position();
tikhomirov@115: 			// System.arraycopy(target.array(), new byte[total]);
tikhomirov@115: 			// I don't want to duplicate byte[] for now
tikhomirov@115: 			// although correct way of doing things is to make a copy and discard target
tikhomirov@115: 			return target.array();
tikhomirov@115: 		} else {
tikhomirov@115: 			int total = 0;
tikhomirov@115: 			for (ByteBuffer bb : buffers) {
tikhomirov@115: 				bb.flip();
tikhomirov@115: 				total += bb.limit();
tikhomirov@115: 			}
tikhomirov@115: 			result = new byte[total];
tikhomirov@115: 			int off = 0;
tikhomirov@115: 			for (ByteBuffer bb : buffers) {
tikhomirov@115: 				bb.get(result, off, bb.limit());
tikhomirov@115: 				off += bb.limit();
tikhomirov@115: 			}
tikhomirov@115: 			buffers.clear();
tikhomirov@115: 			return result;
tikhomirov@115: 		}
tikhomirov@115: 	}
tikhomirov@115: }