LinesImpl.java

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