LineImpl.java revision 398ee59bebad6835dab57b60157eff16d511709e
1/******************************************************************************* 2 * Copyright (c) 2009, 2015 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.internal.analysis; 13 14import org.jacoco.core.analysis.ICounter; 15import org.jacoco.core.analysis.ILine; 16 17/** 18 * Implementation of {@link ILine}. 19 */ 20public abstract class LineImpl implements ILine { 21 22 /** Max instruction counter value for which singletons are created */ 23 private static final int SINGLETON_INS_LIMIT = 8; 24 25 /** Max branch counter value for which singletons are created */ 26 private static final int SINGLETON_BRA_LIMIT = 4; 27 28 private static final LineImpl[][][][] SINGLETONS = new LineImpl[SINGLETON_INS_LIMIT + 1][][][]; 29 30 static { 31 for (int i = 0; i <= SINGLETON_INS_LIMIT; i++) { 32 SINGLETONS[i] = new LineImpl[SINGLETON_INS_LIMIT + 1][][]; 33 for (int j = 0; j <= SINGLETON_INS_LIMIT; j++) { 34 SINGLETONS[i][j] = new LineImpl[SINGLETON_BRA_LIMIT + 1][]; 35 for (int k = 0; k <= SINGLETON_BRA_LIMIT; k++) { 36 SINGLETONS[i][j][k] = new LineImpl[SINGLETON_BRA_LIMIT + 1]; 37 for (int l = 0; l <= SINGLETON_BRA_LIMIT; l++) { 38 SINGLETONS[i][j][k][l] = new Fix(i, j, k, l); 39 } 40 } 41 } 42 } 43 } 44 45 /** 46 * Empty line without instructions or branches. 47 */ 48 public static final LineImpl EMPTY = SINGLETONS[0][0][0][0]; 49 50 private static LineImpl getInstance(final CounterImpl instructions, 51 final CounterImpl branches) { 52 final int im = instructions.getMissedCount(); 53 final int ic = instructions.getCoveredCount(); 54 final int bm = branches.getMissedCount(); 55 final int bc = branches.getCoveredCount(); 56 if (im <= SINGLETON_INS_LIMIT && ic <= SINGLETON_INS_LIMIT 57 && bm <= SINGLETON_BRA_LIMIT && bc <= SINGLETON_BRA_LIMIT) { 58 return SINGLETONS[im][ic][bm][bc]; 59 } 60 return new Var(instructions, branches); 61 } 62 63 /** 64 * Mutable version. 65 */ 66 private static final class Var extends LineImpl { 67 Var(final CounterImpl instructions, final CounterImpl branches) { 68 super(instructions, branches); 69 } 70 71 @Override 72 public LineImpl increment(final ICounter instructions, 73 final ICounter branches) { 74 this.instructions = this.instructions.increment(instructions); 75 this.branches = this.branches.increment(branches); 76 return this; 77 } 78 } 79 80 /** 81 * Immutable version. 82 */ 83 private static final class Fix extends LineImpl { 84 public Fix(final int im, final int ic, final int bm, final int bc) { 85 super(CounterImpl.getInstance(im, ic), CounterImpl.getInstance(bm, 86 bc)); 87 } 88 89 @Override 90 public LineImpl increment(final ICounter instructions, 91 final ICounter branches) { 92 return getInstance(this.instructions.increment(instructions), 93 this.branches.increment(branches)); 94 } 95 } 96 97 /** instruction counter */ 98 protected CounterImpl instructions; 99 100 /** branch counter */ 101 protected CounterImpl branches; 102 103 private LineImpl(final CounterImpl instructions, final CounterImpl branches) { 104 this.instructions = instructions; 105 this.branches = branches; 106 } 107 108 /** 109 * Adds the given counters to this line. 110 * 111 * @param instructions 112 * instructions to add 113 * @param branches 114 * branches to add 115 * @return instance with new counter values 116 */ 117 public abstract LineImpl increment(final ICounter instructions, 118 final ICounter branches); 119 120 // === ILine implementation === 121 122 public int getStatus() { 123 return instructions.getStatus() | branches.getStatus(); 124 } 125 126 public ICounter getInstructionCounter() { 127 return instructions; 128 } 129 130 public ICounter getBranchCounter() { 131 return branches; 132 } 133 134 @Override 135 public int hashCode() { 136 return 23 * instructions.hashCode() ^ branches.hashCode(); 137 } 138 139 @Override 140 public boolean equals(final Object obj) { 141 if (obj instanceof ILine) { 142 final ILine that = (ILine) obj; 143 return this.instructions.equals(that.getInstructionCounter()) 144 && this.branches.equals(that.getBranchCounter()); 145 } 146 return false; 147 } 148 149} 150