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