/*******************************************************************************
* Copyright (c) 2006 Mountainminds GmbH & Co. KG
* This software is provided under the terms of the Eclipse Public License v1.0
* See http://www.eclipse.org/legal/epl-v10.html.
*
* $Id: Lines.java 174 2006-11-19 16:22:19Z mtnminds $
******************************************************************************/
package com.mountainminds.eclemma.internal.core.analysis;
import com.mountainminds.eclemma.core.analysis.ILineCoverage;
/**
* ILineCoverage implementation.
*
* @author Marc R. Hoffmann
* @version $Revision: 174 $
*/
public class Lines extends Counter implements ILineCoverage {
/**
* We allways increase the size of the coverage array by multiples of this
* constant. Larger values will require more memory, a lower value will lead
* to repeated memory allocation and copy operations.
*/
private static final int BLOCK_INCREMENT = 64;
/** Array of flags for each line */
private byte[] coverage = null;
private int firstline = 0;
private int lastline = 0;
private int offset = 0;
protected Lines() {
super(0, 0);
}
private int getBlockAlignedOffset(int line) {
return line - (line % BLOCK_INCREMENT);
}
private int getBlockAlignedSize(int size) {
return size + BLOCK_INCREMENT - (size % BLOCK_INCREMENT);
}
/**
* Updates the firstline and lastline property. If the given line falls
* outside the coverage array the array is increased accordingly.
*
* @param line
* line number to check
*/
private void ensureCapacity(int line) {
if (coverage == null) {
firstline = line;
lastline = line;
offset = getBlockAlignedOffset(line);
coverage = new byte[BLOCK_INCREMENT];
return;
}
if (firstline > line) {
firstline = line;
if (offset > line) {
int newoffset = getBlockAlignedOffset(line);
byte[] newcoverage = new byte[coverage.length + offset - newoffset];
System.arraycopy(coverage, 0, newcoverage, offset - newoffset,
coverage.length);
offset = newoffset;
coverage = newcoverage;
}
return;
}
if (lastline < line) {
lastline = line;
if (line - offset >= coverage.length) {
byte[] newcoverage = new byte[getBlockAlignedSize(line - offset)];
System.arraycopy(coverage, 0, newcoverage, 0, coverage.length);
coverage = newcoverage;
}
}
}
public void addLines(int lines[], boolean isCovered) {
for (int i = 0; i < lines.length; i++) {
int line = lines[i];
// Ignore lines marked with line number -1 as these have been filtered
if (line > -1)
{
ensureCapacity(line);
int idx = line - offset;
switch (coverage[idx]) {
case NO_CODE:
total++;
if (isCovered)
covered++;
break;
case NOT_COVERED:
if (isCovered)
covered++;
break;
}
coverage[idx] |= isCovered ? FULLY_COVERED : NOT_COVERED;
}
}
}
public Counter increment(int total, int covered) {
throw new UnsupportedOperationException();
}
// ILineCoverage interface:
public byte[] getCoverage() {
return coverage;
}
public int getFirstLine() {
return firstline;
}
public int getLastLine() {
return lastline;
}
public int getOffset() {
return offset;
}
}