LinesImpl.java

    1/*******************************************************************************
    2 * Copyright (c) 2009, 2010 Mountainminds GmbH & Co. KG and Contributors
    3 * All rights reserved. This program and the accompanying materials
    4 * are made available under the terms of the Eclipse Public License v1.0
    5 * which accompanies this distribution, and is available at
    6 * http://www.eclipse.org/legal/epl-v10.html
    7 *
    8 * Contributors:
    9 *    Marc R. Hoffmann - initial API and implementation
   10 *    
   11 * $Id: $
   12 *******************************************************************************/
   13package org.jacoco.core.analysis;
   14
   15/**
   16 * {@link ILines} implementation.
   17 * 
   18 * @author Marc R. Hoffmann
   19 * @version $Revision: $
   20 */
   21public class LinesImpl extends AbstractCounter implements ILines {
   22
   23    /** status for each line */
   24    private byte[] status;
   25
   26    /** first line number in lines */
   27    private int offset;
   28
   29    /**
   30     * Creates an empty line counter.
   31     */
   32    public LinesImpl() {
   33        super(0, 0);
   34        status = null;
   35        offset = -1;
   36    }
   37
   38    /**
   39     * Created a line counter with the given lines
   40     * 
   41     * @param lines
   42     *            line numbers to add
   43     * @param covered
   44     *            <code>true</code> if all lines are covered
   45     * 
   46     */
   47    public LinesImpl(final int[] lines, final boolean covered) {
   48        this();
   49        increment(lines, covered);
   50    }
   51
   52    private void ensureCapacity(final int first, final int last) {
   53        if (status == null) {
   54            offset = first;
   55            status = new byte[last - first + 1];
   56        } else {
   57            final int newFirst = Math.min(getFirstLine(), first);
   58            final int newLast = Math.max(getLastLine(), last);
   59            final int newLength = newLast - newFirst + 1;
   60            if (newLength > status.length) {
   61                final byte[] newStatus = new byte[newLength];
   62                System.arraycopy(status, 0, newStatus, offset - newFirst,
   63                        status.length);
   64                offset = newFirst;
   65                status = newStatus;
   66            }
   67        }
   68    }
   69
   70    /**
   71     * Adds the given lines as fully covered or not covered.
   72     * 
   73     * @param lines
   74     *            line numbers to add
   75     * @param covered
   76     *            <code>true</code> if all lines are covered
   77     * 
   78     */
   79    public void increment(final int[] lines, final boolean covered) {
   80        if (lines.length > 0) {
   81            ensureCapacity(lines[0], lines[lines.length - 1]);
   82            final byte newStatus = covered ? FULLY_COVERED : NOT_COVERED;
   83            for (final int line : lines) {
   84                incrementLine(line, newStatus);
   85            }
   86        }
   87    }
   88
   89    /**
   90     * Adds the lines of the given line counter. The states are updated
   91     * accordingly.
   92     * 
   93     * @param counter
   94     *            line counter to add
   95     */
   96    public void increment(final ILines counter) {
   97        if (counter.getTotalCount() == 0) {
   98            return;
   99        }
  100        ensureCapacity(counter.getFirstLine(), counter.getLastLine());
  101        for (int line = counter.getFirstLine(); line <= counter.getLastLine(); line++) {
  102            incrementLine(line, counter.getStatus(line));
  103        }
  104    }
  105
  106    private void incrementLine(final int line, final byte newStatus) {
  107        final byte oldStatus = status[line - offset];
  108        status[line - offset] = (byte) (oldStatus | newStatus);
  109        if (oldStatus == NO_CODE && newStatus != NO_CODE) {
  110            total++;
  111        }
  112        if ((oldStatus == NO_CODE || oldStatus == NOT_COVERED)
  113                && (newStatus == PARTLY_COVERED || newStatus == FULLY_COVERED)) {
  114            covered++;
  115        }
  116    }
  117
  118    // === ILineCounter ===
  119
  120    public int getFirstLine() {
  121        return offset;
  122    }
  123
  124    public int getLastLine() {
  125        return status == null ? -1 : (offset + status.length - 1);
  126    }
  127
  128    public byte getStatus(final int line) {
  129        if (status == null || line < getFirstLine() || line > getLastLine()) {
  130            return NO_CODE;
  131        }
  132        return status[line - offset];
  133    }
  134
  135}