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}