| /*=============================================================================# |
| # Copyright (c) 2017, 2018 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.rj.server.dbg; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import org.eclipse.statet.jcommons.collections.CollectionUtils; |
| import org.eclipse.statet.jcommons.collections.ImCollections; |
| import org.eclipse.statet.jcommons.lang.NonNull; |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| |
| |
| @NonNullByDefault |
| public final class Tracepoints { |
| |
| |
| public static final Logger LOGGER= Logger.getLogger("org.eclipse.statet.rj.server.dbg"); //$NON-NLS-1$ |
| |
| |
| public static final String TOPLEVEL_ELEMENT_ID= "200:"; //$NON-NLS-1$ |
| |
| |
| public static final int indexOfTracepointById(final List<? extends Tracepoint> entries, |
| final long id) { |
| for (int idx= 0; idx < entries.size(); idx++) { |
| if (entries.get(idx).getId() == id) { |
| return idx; |
| } |
| } |
| return -1; |
| } |
| |
| public static final @Nullable TracepointPosition getPositionById(final List<? extends TracepointPosition> list, |
| final long id) { |
| for (int j= 0; j < list.size(); j++) { |
| final TracepointPosition p= list.get(j); |
| if (p.getId() == id) { |
| return p; |
| } |
| } |
| return null; |
| } |
| |
| public static final boolean containsPositionsById(final List<? extends TracepointPosition> list, |
| final List<? extends TracepointPosition> requiredIds) { |
| if (list == requiredIds) { |
| return true; |
| } |
| final int l= requiredIds.size(); |
| if (list.size() < l) { |
| return false; |
| } |
| ITER_REQUIRED: for (int i= 0, j= 0; i < l; i++) { |
| final long id= requiredIds.get(i).getId(); |
| while (j < list.size()) { |
| if (list.get(j++).getId() == id) { |
| continue ITER_REQUIRED; |
| } |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| public static final boolean equalsPositions( |
| final List<? extends TracepointPosition> list1, final List<? extends TracepointPosition> list2, |
| final List<? extends TracepointPosition> requiredIds) { |
| if (list1 == list2) { |
| return true; |
| } |
| final int l= list1.size(); |
| if (l != list2.size()) { |
| return false; |
| } |
| ITER_REQUIRED: for (int i= 0, j1= 0, j2= 0; i < l; i++) { |
| final long id= requiredIds.get(i).getId(); |
| while (j1 < list1.size()) { |
| final TracepointPosition p1= list1.get(j1++); |
| if (p1.getId() == id) { |
| while (j2 < list2.size()) { |
| final TracepointPosition p2= list1.get(j2++); |
| if (p2.getId() == id) { |
| if (p1.equals(p2)) { |
| continue ITER_REQUIRED; |
| } |
| return false; |
| } |
| } |
| return false; |
| } |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| public static final List<TracepointPosition> filterPositionsByIdRequired(final List<? extends TracepointPosition> list, |
| final List<? extends TracepointPosition> requiredIds) { |
| final int l= requiredIds.size(); |
| if (list.size() == l) { |
| return ImCollections.toList(list); |
| } |
| final TracepointPosition[] array= new @NonNull TracepointPosition[l]; |
| ITER_REQUIRED: for (int i= 0, j= 0; i < l; i++) { |
| final long id= requiredIds.get(i).getId(); |
| while (j < list.size()) { |
| final TracepointPosition p= list.get(j++); |
| if (p.getId() == id) { |
| array[i]= p; |
| continue ITER_REQUIRED; |
| } |
| } |
| throw new IllegalArgumentException("TracepointPosition missing: id= " + id); //$NON-NLS-1$ |
| } |
| return ImCollections.newList(array); |
| } |
| |
| public static final List<TracepointPosition> filterPositionsById(final List<? extends TracepointPosition> list, |
| final List<? extends TracepointPosition> includedIds) { |
| final int l= includedIds.size(); |
| final List<TracepointPosition> intersection= new ArrayList<>(l); |
| ITER_INCLUDED: for (int i= 0, j= 0; i < l; i++) { |
| final long id= includedIds.get(i).getId(); |
| int j0= j; |
| while (j0 < list.size()) { |
| final TracepointPosition p= list.get(j0++); |
| if (p.getId() == id) { |
| intersection.add(p); |
| j= j0; |
| continue ITER_INCLUDED; |
| } |
| } |
| } |
| return intersection; |
| } |
| |
| public static final List<TracepointPosition> filterPositionsById(final List<? extends TracepointPosition> list, |
| final long[] includedIds) { |
| final int l= includedIds.length; |
| final List<TracepointPosition> intersection= new ArrayList<>(l); |
| ITER_INCLUDED: for (int i= 0, j= 0; i < l; i++) { |
| final long id= includedIds[i]; |
| int j0= j; |
| while (j0 < list.size()) { |
| final TracepointPosition p= list.get(j0++); |
| if (p.getId() == id) { |
| intersection.add(p); |
| j= j0; |
| continue ITER_INCLUDED; |
| } |
| } |
| } |
| return intersection; |
| } |
| |
| public static final List<TracepointPosition> filterPositionsBySrcref(final List<? extends TracepointPosition> list, |
| final int[] baseSrcref, final int[] includedSrcref) { |
| final List<TracepointPosition> intersection= new ArrayList<>(list.size()); |
| for (int j= 0; j < list.size(); j++) { |
| final TracepointPosition p= list.get(j); |
| final int [] @Nullable [] srcrefs= p.getSrcrefs(); |
| for (int i= 0; i < srcrefs.length; i++) { |
| if (srcrefs[i] != null |
| && Srcref.equalsStart(Srcref.add(srcrefs[i], baseSrcref), includedSrcref) ) { |
| intersection.add(p); |
| break; |
| } |
| } |
| } |
| return intersection; |
| } |
| |
| public static final int @Nullable [] findIndexBySrcref(final List<? extends TracepointPosition> list, |
| final int[] baseSrcref, final int[] includedSrcref) { |
| for (int j= 0; j < list.size(); j++) { |
| final TracepointPosition p= list.get(j); |
| final int [] @Nullable [] srcrefs= p.getSrcrefs(); |
| for (int depth= 0; depth < srcrefs.length; depth++) { |
| if (srcrefs[depth] != null |
| && Srcref.equalsStart(Srcref.add(srcrefs[depth], baseSrcref), includedSrcref) ) { |
| return Arrays.copyOf(p.getIndex(), depth + 1); |
| } |
| } |
| } |
| return null; |
| } |
| |
| public static final int @Nullable [] findIndexByReference(final List<? extends TracepointPosition> list, |
| final List<? extends TracepointPosition> reference) { |
| if (!list.isEmpty()) { |
| final TracepointPosition p= list.get(0); |
| final TracepointPosition refP= nonNullAssert(getPositionById(reference, p.getId())); |
| final int[] index= p.getIndex(); |
| final int depth= index.length - 1 - refP.getIndex().length; |
| if (depth > 0 && depth < index.length) { |
| return Arrays.copyOf(index, depth + 1); |
| } |
| } |
| return null; |
| } |
| |
| private static final boolean equalsIndex(final int[] index, final int[] included) { |
| if (index.length < included.length) { |
| return false; |
| } |
| for (int i= 0; i < included.length; i++) { |
| if (index[i] != included[i]) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| public static final int @Nullable [] getSrcrefForIndex(final List<? extends TracepointPosition> list, |
| final int[] includedIndex) { |
| final int depth= includedIndex.length - 1; |
| for (int j= 0; j < list.size(); j++) { |
| final TracepointPosition p= list.get(j); |
| final int[] srcref; |
| if (equalsIndex(p.getIndex(), includedIndex) |
| && (srcref= p.getSrcref(depth)) != null ) { |
| return srcref; |
| } |
| } |
| return null; |
| } |
| |
| public static final List<TracepointPosition> rebasePositionsByIndex(final List<? extends TracepointPosition> list, |
| final int[] newBaseIndex) { |
| final int depth= newBaseIndex.length - 1; |
| final List<TracepointPosition> intersection= new ArrayList<>(list.size()); |
| for (int j= 0; j < list.size(); j++) { |
| final TracepointPosition p= list.get(j); |
| final int[] index= p.getIndex(); |
| if (equalsIndex(index, newBaseIndex) |
| && p.getSrcref() != null && p.getSrcref(depth) != null ) { |
| intersection.add(new TracepointPosition(p.getType(), p.getId(), |
| Arrays.copyOfRange(index, depth + 1, index.length), |
| Srcref.substract(p.getSrcref(), p.getSrcref(depth)) )); |
| } |
| } |
| return intersection; |
| } |
| |
| |
| private static final char[] DIGITS= new char[] { |
| '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' |
| }; |
| |
| public static final String toString(long id) { |
| final char[] c= new char[16]; |
| for (int i= 0; i < 16; i++) { |
| c[15 - i]= DIGITS[(int) id & 0xF]; |
| id >>>= 4; |
| } |
| return new String(c, 0, 16); |
| } |
| |
| public static final void append(long id, final StringBuilder sb) { |
| final char[] c= new char[16]; |
| for (int i= 0; i < 16; i++) { |
| c[15 - i]= DIGITS[(int) id & 0xF]; |
| id >>>= 4; |
| } |
| sb.append(c); |
| } |
| |
| |
| public static final String toLogString(final List<? extends TracepointPosition> positions) { |
| final int n= positions.size(); |
| if (n <= 0) { |
| return ""; //$NON-NLS-1$ |
| } |
| if (LOGGER.isLoggable(Level.FINEST)) { |
| return "\n\t\t" + CollectionUtils.toString(positions, "\n\t\t"); |
| } |
| else { |
| final StringBuilder sb= new StringBuilder(n * 18); |
| sb.append(positions.get(0).getId()); |
| for (int i= 1; i < n; i++) { |
| sb.append(", "); |
| append(positions.get(i).getId(), sb); |
| } |
| return sb.toString(); |
| } |
| } |
| |
| |
| private Tracepoints() {} |
| |
| } |