blob: a71a65b611282de6a2558532780e68584b05a354 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors: Matthew Khouzam - Initial API and implementation
* Contributors: Simon Marchi - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.internal.ctf.core.utils;
import java.util.UUID;
import org.eclipse.tracecompass.ctf.core.CTFException;
import org.eclipse.tracecompass.ctf.core.event.types.AbstractArrayDefinition;
import org.eclipse.tracecompass.ctf.core.event.types.CompoundDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
/**
* Various utilities.
*
* @version 1.0
* @author Matthew Khouzam
* @author Simon Marchi
*/
public final class Utils {
private Utils() {
}
// ------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------
/**
* CTF magic number. (sort of looks like CTF CTF CT)
*/
public static final int CTF_MAGIC = 0xC1FC1FC1;
/**
* TSDL magic number. (sort of looks like TSDL LSDT)
*/
public static final int TSDL_MAGIC = 0x75D11D57;
/**
* TSDL magic number length in bytes.
*/
public static final int TSDL_MAGIC_LEN = 4;
/**
* Directory separator on the current platform.
*/
public static final String SEPARATOR = System.getProperty("file.separator"); //$NON-NLS-1$
/**
* Length in bytes of a UUID value.
*/
public static final int UUID_LEN = 16;
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
/**
* Performs an unsigned long comparison on two unsigned long numbers.
*
* <strong> As Java does not support unsigned types and arithmetic,
* parameters are received encoded as a signed long (two-complement) but the
* operation is an unsigned comparator.</strong>
*
* @param left
* Left operand of the comparator.
* @param right
* Right operand of the comparator.
* @return -1 if left &lt; right, 1 if left &gt; right, 0 if left == right.
*/
public static int unsignedCompare(long left, long right) {
/*
* This method assumes that the arithmetic overflow on signed integer
* wrap on a circular domain (modulo arithmetic in two-complement),
* which is the defined behavior in Java.
*
* This idea is to rotate the domain by the length of the negative
* space, and then use the signed operator.
*/
final long a = left + Long.MIN_VALUE;
final long b = right + Long.MIN_VALUE;
if (a < b) {
return -1;
} else if (a > b) {
return 1;
}
return 0;
}
/**
* Gets a UUID from an array defintion
*
* @param uuidDef
* the array defintions, must contain integer bytes
* @return the UUID
* @throws CTFException
* if the definition contains less than 16 elements
*/
public static UUID getUUIDfromDefinition(AbstractArrayDefinition uuidDef) throws CTFException {
byte[] uuidArray = new byte[UUID_LEN];
IDeclaration declaration = uuidDef.getDeclaration();
if (!(declaration instanceof CompoundDeclaration)) {
throw new CTFException("UUID must be a sequence of unsigned bytes"); //$NON-NLS-1$
}
CompoundDeclaration uuidDec = (CompoundDeclaration) declaration;
IDeclaration uuidElem = uuidDec.getElementType();
if (!(uuidElem instanceof IntegerDeclaration)) {
throw new CTFException("UUID must be a sequence of unsigned bytes"); //$NON-NLS-1$
}
IntegerDeclaration intUuidElem = (IntegerDeclaration) uuidElem;
if (!intUuidElem.isUnsignedByte()) {
throw new CTFException("UUID must be a sequence of unsigned bytes"); //$NON-NLS-1$
}
return getUUID(uuidDef, uuidArray);
}
private static UUID getUUID(AbstractArrayDefinition uuidDef, byte[] uuidArray) throws CTFException {
for (int i = 0; i < uuidArray.length; i++) {
IntegerDefinition uuidByteDef = (IntegerDefinition) uuidDef.getDefinitions().get(i);
if (uuidByteDef == null) {
throw new CTFException("UUID incomplete, only " + i + " bytes available"); //$NON-NLS-1$ //$NON-NLS-2$
}
uuidArray[i] = (byte) uuidByteDef.getValue();
}
UUID uuid = Utils.makeUUID(uuidArray);
return uuid;
}
/**
* Creates a UUID object from an array of 16 bytes.
*
* @param bytes
* Array of 16 bytes.
* @return A UUID object.
* @throws CTFException
* the byte buffer was the wrong size
*/
public static UUID makeUUID(byte bytes[]) throws CTFException {
long high = 0;
long low = 0;
if (bytes.length < Utils.UUID_LEN) {
throw new CTFException("UUID byte field must be 16 bytes long"); //$NON-NLS-1$
}
final int bitsPerByte = Byte.SIZE;
int bitMask = (1 << bitsPerByte) - 1;
for (int i = 0; i < bitsPerByte; i++) {
low = (low << bitsPerByte) | (bytes[i + bitsPerByte] & bitMask);
high = (high << bitsPerByte) | (bytes[i] & bitMask);
}
return new UUID(high, low);
}
}