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}