/*
 * @(#)CopyingInputStream.java  1.0.1  2008-08-18
 *
 * Copyright (c) 2006-2008 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */

package ch.randelshofer.io;

import java.io.*;

/**
 * Copies all data that has been read through this input stream into an
 * OutputStream.
 *
 * @author Werner Randelshofer
 * @version 1.0.1 2008-08-18 Skip method did not return negative number in case 
 * of EOF.
 * <br>1.0 December 28, 2006 Created.
 */
public class CopyingInputStream extends FilterInputStream {
    private OutputStream out;
    /** We lazily create this skipBuffer for efficient skipping. */
    private byte[] skipBuffer;
    private final static int SKIP_BUFFER_SIZE = 512;
    
    
    /** Creates a new instance. */
    public CopyingInputStream(InputStream in, OutputStream out) {
        super(in);
        this.out = out;
    }
    
    public OutputStream getCopyStream() {
        return out;
    }
    public void setCopyStream(OutputStream out) {
        this.out = out;
    }
    
    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int count;
        
        count = super.read(b, off, len);
        if (count > 0) {
            out.write(b, off, count);
        }
        return count;
    }
    
    @Override
    public int read() throws IOException {
        int retValue;
        
        retValue = super.read();
        if (retValue >= 0) {
            out.write(retValue);
        }
        return retValue;
    }
    
    @Override
    public long skip(long n) throws IOException {
	long remaining = n;
	int nr;
	if (skipBuffer == null)
	    skipBuffer = new byte[SKIP_BUFFER_SIZE];

	byte[] localSkipBuffer = skipBuffer;
		
	if (n <= 0) {
	    return 0;
	}

	while (remaining > 0) {
	    nr = read(localSkipBuffer, 0,
		      (int) Math.min(SKIP_BUFFER_SIZE, remaining));
	    if (nr < 0) {
                if (remaining ==n) return nr;
		break;
	    }
	    remaining -= nr;
	}
	
	return n - remaining;
    }
}
