// Path: src/com/ibm/scan/RepetitionTracker.java
// public class RepetitionTracker {
// 	
// 	//private transient Set<String> uniqueRepetitions = new HashSet<String>();
// 	
// 	private Map<Integer, Tuple<Long, Long>> repetitionsAndRenewalRate = new HashMap<>();
// 	
// 	private Histogram histogram = new IntegersHistogram();
// 	
// 	private Histogram noRepetitionsHistogram = new IntegersHistogram();
// 	
// 	private int lastRepetitionPoint = 0;
// 	
// 	private long repeatedData = 0;
// 	
// 	private long nonRepeatedData = 0;
// 	
// 	/*public void addRepetition(byte [] repetitionBytes) {
// 		addRepetition(new String(repetitionBytes));		
// 	}*/
// 	
// 	/*public void addRepetition(String repetition) {
// 		addRepetition(repetition, repetition.length());		
// 	}*/
// 	
// 	/**
// 	 * @param prev_length
// 	 */
// 	public void addRepetition(int length) {
// 		histogram.add(length);		
// 	}
// 	
// 	/*private void addRepetition(String repetition, int length) {
// 		//If the map does not contain this length, create the tuple
// 		if (!repetitionsAndRenewalRate.containsKey(length)) {
// 			repetitionsAndRenewalRate.put(length, new Tuple<Long, Long>(2L, 1L));
// 		}
// 		Tuple<Long, Long> lengthRepetitions = repetitionsAndRenewalRate.get(length);
// 		//If the sequence is new, increment the unique sequences counter
// 		if (!uniqueRepetitions.contains(repetition)){
// 			uniqueRepetitions.add(repetition); 
// 			lengthRepetitions.y+=1;
// 			lengthRepetitions.x+=2;
// 		}else {
// 			//Increment the all repetition length counter
// 			lengthRepetitions.x+=1;
// 		}
// 		addRepetition(length);
// 		repetitionsAndRenewalRate.put(length,lengthRepetitions);
// 	}*/
// 
// 	/**
// 	 * @return the repetitionsAndRenewalRate
// 	 */
// 	public Map<Integer, Tuple<Long, Long>> getRepetitionsAndRenewalRate() {
// 		return repetitionsAndRenewalRate;
// 	}
// 
// 	//public void finish() {
// 	//	uniqueRepetitions.clear();
// 	//}
// 	/**
// 	 * @return
// 	 */
// 	public Histogram getRepetitionDistribution() {
// 		return histogram;
// 	}
// 
// 	/**
// 	 * @param chunk
// 	 * @return
// 	 */
// 	public long getRenewalRate(int chunk) {
// 		Tuple<Long, Long> lengthRepetitions = repetitionsAndRenewalRate.get(chunk);
// 		return lengthRepetitions.x/lengthRepetitions.y+1;
// 	}
// 	
// 	/**
// 	 * @param strstart
// 	 */
// 	public void addRepetition(int strstart, int length) {
// 		/*System.out.println("Repetition start point: " + strstart);
// 		System.out.println("Repetition length: " + length);
// 		System.out.println("No Repetition length: " + (strstart-lastRepetitionPoint));
// 		System.out.println("-----------------------");*/
// 		if (strstart >= lastRepetitionPoint){
// 			repeatedData += length;
// 			if (strstart-lastRepetitionPoint>=0) {
// 				noRepetitionsHistogram.add(strstart-lastRepetitionPoint);
// 				nonRepeatedData += strstart-lastRepetitionPoint;
// 			}//else System.err.println("Problem with no rep length!");
// 			lastRepetitionPoint = strstart+length;
// 			//if (strstart-lastRepetitionPoint < 0) 
// 				//System.err.print("Bad repetition tracking!!");
// 		}
// 		addRepetition(length);
// 	}
// 
// 	/**
// 	 * @return the noRepetitionsHistogram
// 	 */
// 	public Histogram getNoRepetitionsHistogram() {
// 		return noRepetitionsHistogram;
// 	}
// 
// 	/**
// 	 * @param noRepetitionsHistogram the noRepetitionsHistogram to set
// 	 */
// 	public void setNoRepetitionsHistogram(Histogram noRepetitionsHistogram) {
// 		this.noRepetitionsHistogram = noRepetitionsHistogram;
// 	}
// 	
// 	public double getUniquenessRatio() {
// 		return nonRepeatedData/((double)repeatedData);
// 	}
// }


import java.util.Arrays;
import com.ibm.scan.RepetitionTracker;
	int lit_bufsize;

	int last_lit; // running index in l_buf

	// Buffer for distances. To simplify the code, d_buf and l_buf have
	// the same number of elements. To use different lengths, an extra flag
	// array would be necessary.

	int d_buf; // index of pendig_buf

	int opt_len; // bit length of current block with optimal trees
	int static_len; // bit length of current block with static trees
	int matches; // number of string matches in current block
	int last_eob_len; // bit length of EOB code for last block

	// Output buffer. bits are inserted starting at the bottom (least
	// significant bits).
	short bi_buf;

	// Number of valid bits in bi_buf. All bits above the last valid bit
	// are always zero.
	int bi_valid;

	GZIPHeader gheader = null;

	// ADDED BY Raul Gracia (3/04/2014)
	// Add a list to keep track of the repetition length distribution
	/*private List<Integer> repetitionsDistribution = new ArrayList<Integer>();
	private List<Integer> uniqueRepetitionsDistribution = new ArrayList<Integer>();
	private Set<Integer> uniqueRepetitions = new HashSet<Integer>();*/
// Path: src/com/ibm/scan/RepetitionTracker.java
// public class RepetitionTracker {
// 	
// 	//private transient Set<String> uniqueRepetitions = new HashSet<String>();
// 	
// 	private Map<Integer, Tuple<Long, Long>> repetitionsAndRenewalRate = new HashMap<>();
// 	
// 	private Histogram histogram = new IntegersHistogram();
// 	
// 	private Histogram noRepetitionsHistogram = new IntegersHistogram();
// 	
// 	private int lastRepetitionPoint = 0;
// 	
// 	private long repeatedData = 0;
// 	
// 	private long nonRepeatedData = 0;
// 	
// 	/*public void addRepetition(byte [] repetitionBytes) {
// 		addRepetition(new String(repetitionBytes));		
// 	}*/
// 	
// 	/*public void addRepetition(String repetition) {
// 		addRepetition(repetition, repetition.length());		
// 	}*/
// 	
// 	/**
// 	 * @param prev_length
// 	 */
// 	public void addRepetition(int length) {
// 		histogram.add(length);		
// 	}
// 	
// 	/*private void addRepetition(String repetition, int length) {
// 		//If the map does not contain this length, create the tuple
// 		if (!repetitionsAndRenewalRate.containsKey(length)) {
// 			repetitionsAndRenewalRate.put(length, new Tuple<Long, Long>(2L, 1L));
// 		}
// 		Tuple<Long, Long> lengthRepetitions = repetitionsAndRenewalRate.get(length);
// 		//If the sequence is new, increment the unique sequences counter
// 		if (!uniqueRepetitions.contains(repetition)){
// 			uniqueRepetitions.add(repetition); 
// 			lengthRepetitions.y+=1;
// 			lengthRepetitions.x+=2;
// 		}else {
// 			//Increment the all repetition length counter
// 			lengthRepetitions.x+=1;
// 		}
// 		addRepetition(length);
// 		repetitionsAndRenewalRate.put(length,lengthRepetitions);
// 	}*/
// 
// 	/**
// 	 * @return the repetitionsAndRenewalRate
// 	 */
// 	public Map<Integer, Tuple<Long, Long>> getRepetitionsAndRenewalRate() {
// 		return repetitionsAndRenewalRate;
// 	}
// 
// 	//public void finish() {
// 	//	uniqueRepetitions.clear();
// 	//}
// 	/**
// 	 * @return
// 	 */
// 	public Histogram getRepetitionDistribution() {
// 		return histogram;
// 	}
// 
// 	/**
// 	 * @param chunk
// 	 * @return
// 	 */
// 	public long getRenewalRate(int chunk) {
// 		Tuple<Long, Long> lengthRepetitions = repetitionsAndRenewalRate.get(chunk);
// 		return lengthRepetitions.x/lengthRepetitions.y+1;
// 	}
// 	
// 	/**
// 	 * @param strstart
// 	 */
// 	public void addRepetition(int strstart, int length) {
// 		/*System.out.println("Repetition start point: " + strstart);
// 		System.out.println("Repetition length: " + length);
// 		System.out.println("No Repetition length: " + (strstart-lastRepetitionPoint));
// 		System.out.println("-----------------------");*/
// 		if (strstart >= lastRepetitionPoint){
// 			repeatedData += length;
// 			if (strstart-lastRepetitionPoint>=0) {
// 				noRepetitionsHistogram.add(strstart-lastRepetitionPoint);
// 				nonRepeatedData += strstart-lastRepetitionPoint;
// 			}//else System.err.println("Problem with no rep length!");
// 			lastRepetitionPoint = strstart+length;
// 			//if (strstart-lastRepetitionPoint < 0) 
// 				//System.err.print("Bad repetition tracking!!");
// 		}
// 		addRepetition(length);
// 	}
// 
// 	/**
// 	 * @return the noRepetitionsHistogram
// 	 */
// 	public Histogram getNoRepetitionsHistogram() {
// 		return noRepetitionsHistogram;
// 	}
// 
// 	/**
// 	 * @param noRepetitionsHistogram the noRepetitionsHistogram to set
// 	 */
// 	public void setNoRepetitionsHistogram(Histogram noRepetitionsHistogram) {
// 		this.noRepetitionsHistogram = noRepetitionsHistogram;
// 	}
// 	
// 	public double getUniquenessRatio() {
// 		return nonRepeatedData/((double)repeatedData);
// 	}
// }


// Path: src/com/ibm/compression/jcraft/jzlib/Deflate.java
import java.util.Arrays;
import com.ibm.scan.RepetitionTracker;

	int lit_bufsize;

	int last_lit; // running index in l_buf

	// Buffer for distances. To simplify the code, d_buf and l_buf have
	// the same number of elements. To use different lengths, an extra flag
	// array would be necessary.

	int d_buf; // index of pendig_buf

	int opt_len; // bit length of current block with optimal trees
	int static_len; // bit length of current block with static trees
	int matches; // number of string matches in current block
	int last_eob_len; // bit length of EOB code for last block

	// Output buffer. bits are inserted starting at the bottom (least
	// significant bits).
	short bi_buf;

	// Number of valid bits in bi_buf. All bits above the last valid bit
	// are always zero.
	int bi_valid;

	GZIPHeader gheader = null;

	// ADDED BY Raul Gracia (3/04/2014)
	// Add a list to keep track of the repetition length distribution
	/*private List<Integer> repetitionsDistribution = new ArrayList<Integer>();
	private List<Integer> uniqueRepetitionsDistribution = new ArrayList<Integer>();
	private Set<Integer> uniqueRepetitions = new HashSet<Integer>();*/
	private RepetitionTracker repetitions = new RepetitionTracker();