/*******************************************************************************
* Copyright (c) 2015 Ericsson
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
import org.antlr.runtime.tree.CommonTree;
import org.eclipse.tracecompass.ctf.parser.CTFParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
/**
* Alignment parser, we define byte-packed types as aligned on the byte size,
* namely 8-bit. We define bit-packed types as following on the next bit, as
* defined by the Integers section.
*
* Each basic type must specify its alignment, in bits. Examples of possible
* alignments are: bit-packed (align = 1), byte-packed (align = 8), or
* word-aligned (e.g. align = 32 or align = 64). The choice depends on the
* architecture preference and compactness vs performance trade-offs of the
* implementation. Architectures providing fast unaligned write byte-packed
* basic types to save space, aligning each type on byte boundaries (8-bit).
* Architectures with slow unaligned writes align types on specific alignment
* values. If no specific alignment is declared for a type, it is assumed to be
* bit-packed for integers with size not multiple of 8 bits and for gcc
* bitfields. All other basic types are byte-packed by default. It is however
* recommended to always specify the alignment explicitly. Alignment values must
* be power of two. Compound types are aligned as specified in their individual
* specification.
*
* The base offset used for field alignment is the start of the packet
* containing the field. For instance, a field aligned on 32-bit needs to be at
* an offset multiple of 32-bit from the start of the packet that contains it.
*
* TSDL metadata attribute representation of a specific alignment:
*
* @author Matthew Khouzam
* @author Efficios (javadoc preamble)
*
*/
public final class AlignmentParser implements ICommonTreeParser {
/**
* Alignment parser instance
*/
public static final AlignmentParser INSTANCE = new AlignmentParser();
private static final String INVALID_VALUE_FOR_ALIGNMENT = "Invalid value for alignment"; //$NON-NLS-1$
private AlignmentParser() {
}
/**
* Gets the value of a "align" integer or struct attribute.
* @param tree
* A CTF_RIGHT node or directly an unary integer.
*
* @return The align value.
* @throws ParseException
* Invalid alignment value
*/
@Override
public Long parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException {
/*
* If a CTF_RIGHT node was passed, call getAlignment with the first
* child
*/
if (tree.getType() == CTFParser.CTF_RIGHT) {
if (tree.getChildCount() > 1) {
throw new ParseException(INVALID_VALUE_FOR_ALIGNMENT);
}
return parse((CommonTree) tree.getChild(0), param);
} else if (isUnaryInteger(tree)) {
long alignment = UnaryIntegerParser.INSTANCE.parse(tree, null);
if (!isValidAlignment(alignment)) {
throw new ParseException(INVALID_VALUE_FOR_ALIGNMENT + " : " //$NON-NLS-1$
+ alignment);
}
return alignment;
}
throw new ParseException(INVALID_VALUE_FOR_ALIGNMENT); // $NON-NLS-1$
}
/**
* Determines if the given value is a valid alignment value.
*
* @param alignment
* The value to check.
* @return True if it is valid.
*/
private static boolean isValidAlignment(long alignment) {
return !((alignment <= 0) || ((alignment & (alignment - 1)) != 0));
}
}