1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Matthew Khouzam - Initial API and implementation
11 * Simon Marchi - Initial API and implementation
12 * Marc-Andre Laperle - Add min/maximum for validation
13 *******************************************************************************/
15 package org
.eclipse
.tracecompass
.ctf
.core
.event
.types
;
17 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
19 import java
.math
.BigInteger
;
20 import java
.nio
.ByteOrder
;
22 import org
.eclipse
.jdt
.annotation
.NonNullByDefault
;
23 import org
.eclipse
.jdt
.annotation
.Nullable
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.CTFException
;
25 import org
.eclipse
.tracecompass
.ctf
.core
.event
.io
.BitBuffer
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.event
.scope
.IDefinitionScope
;
29 * A CTF integer declaration.
31 * The declaration of a integer basic data type.
34 * @author Matthew Khouzam
35 * @author Simon Marchi
38 public final class IntegerDeclaration
extends Declaration
implements ISimpleDatatypeDeclaration
{
40 // ------------------------------------------------------------------------
42 // ------------------------------------------------------------------------
44 private static final int SIZE_64
= 64;
45 private static final int SIZE_32
= 32;
46 private static final int SIZE_27
= 27;
47 private static final int SIZE_16
= 16;
48 private static final int SIZE_8
= 8;
49 private static final int SIZE_5
= 5;
50 private static final int BYTE_ALIGN
= 8;
51 private static final int BASE_10
= 10;
53 * unsigned int 32 bits big endian
55 public static final IntegerDeclaration UINT_32B_DECL
= new IntegerDeclaration(32, false, ByteOrder
.BIG_ENDIAN
);
57 * unsigned int 32 bits little endian
59 public static final IntegerDeclaration UINT_32L_DECL
= new IntegerDeclaration(32, false, ByteOrder
.LITTLE_ENDIAN
);
61 * signed int 32 bits big endian
63 public static final IntegerDeclaration INT_32B_DECL
= new IntegerDeclaration(32, true, ByteOrder
.BIG_ENDIAN
);
65 * signed int 32 bits little endian
67 public static final IntegerDeclaration INT_32L_DECL
= new IntegerDeclaration(32, true, ByteOrder
.LITTLE_ENDIAN
);
69 * unsigned int 32 bits big endian
71 public static final IntegerDeclaration UINT_64B_DECL
= new IntegerDeclaration(64, false, ByteOrder
.BIG_ENDIAN
);
73 * unsigned int 64 bits little endian
75 public static final IntegerDeclaration UINT_64L_DECL
= new IntegerDeclaration(64, false, ByteOrder
.LITTLE_ENDIAN
);
77 * signed int 64 bits big endian
79 public static final IntegerDeclaration INT_64B_DECL
= new IntegerDeclaration(64, true, ByteOrder
.BIG_ENDIAN
);
81 * signed int 64 bits little endian
83 public static final IntegerDeclaration INT_64L_DECL
= new IntegerDeclaration(64, true, ByteOrder
.LITTLE_ENDIAN
);
85 * unsigned 8 bit int endianness doesn't matter since it's 8 bits (byte)
87 public static final IntegerDeclaration UINT_8_DECL
= new IntegerDeclaration(8, false, ByteOrder
.BIG_ENDIAN
);
89 * signed 8 bit int endianness doesn't matter since it's 8 bits (char)
91 public static final IntegerDeclaration INT_8_DECL
= new IntegerDeclaration(8, true, ByteOrder
.BIG_ENDIAN
);
93 * Unsigned 5 bit int, used for event headers
95 public static final IntegerDeclaration UINT_5B_DECL
= new IntegerDeclaration(5, false, 10, ByteOrder
.BIG_ENDIAN
, Encoding
.NONE
, "", 1); //$NON-NLS-1$
97 * Unsigned 5 bit int, used for event headers
99 public static final IntegerDeclaration UINT_5L_DECL
= new IntegerDeclaration(5, false, 10, ByteOrder
.LITTLE_ENDIAN
, Encoding
.NONE
, "", 1); //$NON-NLS-1$
101 * Unsigned 5 bit int, used for event headers
103 public static final IntegerDeclaration UINT_27B_DECL
= new IntegerDeclaration(27, false, 10, ByteOrder
.BIG_ENDIAN
, Encoding
.NONE
, "", 1); //$NON-NLS-1$
105 * Unsigned 5 bit int, used for event headers
107 public static final IntegerDeclaration UINT_27L_DECL
= new IntegerDeclaration(27, false, 10, ByteOrder
.LITTLE_ENDIAN
, Encoding
.NONE
, "", 1); //$NON-NLS-1$
109 * Unsigned 16 bit int, used for event headers
111 public static final IntegerDeclaration UINT_16B_DECL
= new IntegerDeclaration(16, false, ByteOrder
.BIG_ENDIAN
);
113 * Unsigned 16 bit int, used for event headers
115 public static final IntegerDeclaration UINT_16L_DECL
= new IntegerDeclaration(16, false, ByteOrder
.LITTLE_ENDIAN
);
116 // ------------------------------------------------------------------------
118 // ------------------------------------------------------------------------
120 private final int fLength
;
121 private final boolean fSigned
;
122 private final int fBase
;
123 private final ByteOrder fByteOrder
;
124 private final Encoding fEncoding
;
125 private final long fAlignment
;
126 private final String fClock
;
128 // ------------------------------------------------------------------------
130 // ------------------------------------------------------------------------
133 * Factory, some common types cached
138 * Is the integer signed? false == unsigned
140 * The base (10-16 are most common)
142 * Big-endian little-endian or other
144 * ascii, utf8 or none.
146 * The clock path, can be null
148 * The minimum alignment. Should be >= 1
149 * @return the integer declaration
151 public static IntegerDeclaration
createDeclaration(int len
, boolean signed
, int base
,
152 @Nullable ByteOrder byteOrder
, Encoding encoding
, String clock
, long alignment
) {
153 if (encoding
.equals(Encoding
.NONE
) && (clock
.equals("")) && base
== BASE_10
&& byteOrder
!= null) { //$NON-NLS-1$
154 if (alignment
== BYTE_ALIGN
) {
157 return signed ? INT_8_DECL
: UINT_8_DECL
;
160 if (isBigEndian(byteOrder
)) {
161 return UINT_16B_DECL
;
163 return UINT_16L_DECL
;
168 if (isBigEndian(byteOrder
)) {
173 if (isBigEndian(byteOrder
)) {
174 return UINT_32B_DECL
;
176 return UINT_32L_DECL
;
179 if (isBigEndian(byteOrder
)) {
184 if (isBigEndian(byteOrder
)) {
185 return UINT_64B_DECL
;
187 return UINT_64L_DECL
;
193 } else if (alignment
== 1) {
197 if (isBigEndian(byteOrder
)) {
205 if (isBigEndian(byteOrder
)) {
206 return UINT_27B_DECL
;
208 return UINT_27L_DECL
;
216 return new IntegerDeclaration(len
, signed
, base
, byteOrder
, encoding
, clock
, alignment
);
219 private static boolean isBigEndian(@Nullable ByteOrder byteOrder
) {
220 return (byteOrder
!= null) && byteOrder
.equals(ByteOrder
.BIG_ENDIAN
);
229 * Is the integer signed? false == unsigned
231 * The base (10-16 are most common)
233 * Big-endian little-endian or other
235 * ascii, utf8 or none.
237 * The clock path, can be null
239 * The minimum alignment. Should be ≥ 1
241 private IntegerDeclaration(int len
, boolean signed
, int base
,
242 @Nullable ByteOrder byteOrder
, Encoding encoding
, String clock
, long alignment
) {
246 fByteOrder
= (byteOrder
== null) ? ByteOrder
.nativeOrder() : byteOrder
;
247 fEncoding
= encoding
;
249 fAlignment
= Math
.max(alignment
, 1);
252 private IntegerDeclaration(int len
, boolean signed
, @Nullable ByteOrder byteOrder
) {
253 this(len
, signed
, BASE_10
, byteOrder
, Encoding
.NONE
, "", BYTE_ALIGN
); //$NON-NLS-1$
256 // ------------------------------------------------------------------------
257 // Getters/Setters/Predicates
258 // ------------------------------------------------------------------------
261 * Is the integer signed?
263 * @return the is the integer signed
265 public boolean isSigned() {
270 * Get the integer base commonly decimal or hex
272 * @return the integer base
274 public int getBase() {
281 * @return the byte order
283 public ByteOrder
getByteOrder() {
288 * Get encoding, chars are 8 bit ints
290 * @return the encoding
292 public Encoding
getEncoding() {
297 * Is the integer a character (8 bits and encoded?)
299 * @return is the integer a char
301 public boolean isCharacter() {
302 return (fLength
== SIZE_8
) && (fEncoding
!= Encoding
.NONE
);
306 * Is the integer an unsigned byte (8 bits and no sign)?
308 * @return is the integer an unsigned byte
310 public boolean isUnsignedByte() {
311 return (fLength
== SIZE_8
) && (!fSigned
);
315 * Get the length in bits for this integer
317 * @return the length of the integer
319 public int getLength() {
324 public long getAlignment() {
329 * The integer's clock, since timestamps are stored in ints
331 * @return the integer's clock, can be null. (most often it is)
333 public String
getClock() {
338 public int getMaximumSize() {
342 // ------------------------------------------------------------------------
344 // ------------------------------------------------------------------------
347 public IntegerDefinition
createDefinition(@Nullable IDefinitionScope definitionScope
,
348 String fieldName
, BitBuffer input
) throws CTFException
{
349 ByteOrder byteOrder
= input
.getByteOrder();
350 input
.setByteOrder(fByteOrder
);
351 long value
= read(input
);
352 input
.setByteOrder(byteOrder
);
353 return new IntegerDefinition(this, definitionScope
, fieldName
, value
);
357 public String
toString() {
358 return "[declaration] integer[length:" + fLength
+ (fSigned ?
" " : " un") + "signed" + " base:" + fBase
+ " byteOrder:" + fByteOrder
+ " encoding:" + fEncoding
+ " alignment:" + fAlignment
+ " clock:" + fClock
+ "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$
362 * Get the maximum value for this integer declaration.
364 * @return The maximum value for this integer declaration
366 public BigInteger
getMaxValue() {
368 * Compute the number of bits able to represent an unsigned number,
371 int significantBits
= fLength
- (fSigned ?
1 : 0);
373 * For a given N significant bits, compute the maximal value which is (1
376 return checkNotNull(BigInteger
.ONE
.shiftLeft(significantBits
).subtract(BigInteger
.ONE
));
380 * Get the minimum value for this integer declaration.
382 * @return The minimum value for this integer declaration
384 public BigInteger
getMinValue() {
386 return checkNotNull(BigInteger
.ZERO
);
390 * Compute the number of bits able to represent an unsigned number,
391 * without the sign bit.
393 int significantBits
= fLength
- 1;
395 * For a given N significant bits, compute the minimal value which is -
398 return checkNotNull(BigInteger
.ONE
.shiftLeft(significantBits
).negate());
401 private long read(BitBuffer input
) throws CTFException
{
402 /* Offset the buffer position wrt the current alignment */
405 boolean signed
= isSigned();
406 int length
= getLength();
410 * Is the endianness of this field the same as the endianness of the
411 * input buffer? If not, then temporarily set the buffer's endianness to
412 * this field's just to read the data
414 ByteOrder previousByteOrder
= input
.getByteOrder();
415 if ((getByteOrder() != input
.getByteOrder())) {
416 input
.setByteOrder(getByteOrder());
419 if (length
> SIZE_64
) {
420 throw new CTFException("Cannot read an integer with over 64 bits. Length given: " + length
); //$NON-NLS-1$
423 bits
= input
.get(length
, signed
);
426 * Put the input buffer's endianness back to original if it was changed
428 if (previousByteOrder
!= input
.getByteOrder()) {
429 input
.setByteOrder(previousByteOrder
);
436 public int hashCode() {
437 final int prime
= 31;
439 result
= prime
* result
+ (int) (fAlignment ^
(fAlignment
>>> 32));
440 result
= prime
* result
+ fBase
;
441 result
= prime
* result
+ fByteOrder
.toString().hashCode();
442 result
= prime
* result
+ fClock
.hashCode();
443 result
= prime
* result
+ fEncoding
.hashCode();
444 result
= prime
* result
+ fLength
;
445 result
= prime
* result
+ (fSigned ?
1231 : 1237);
450 public boolean equals(@Nullable Object obj
) {
457 if (getClass() != obj
.getClass()) {
460 IntegerDeclaration other
= (IntegerDeclaration
) obj
;
461 if (!isBinaryEquivalent(other
)) {
464 if (!fByteOrder
.equals(other
.fByteOrder
)) {
467 if (!fClock
.equals(other
.fClock
)) {
470 if (fEncoding
!= other
.fEncoding
) {
473 if (fBase
!= other
.fBase
) {
480 public boolean isBinaryEquivalent(@Nullable IDeclaration obj
) {
487 if (getClass() != obj
.getClass()) {
490 IntegerDeclaration other
= (IntegerDeclaration
) obj
;
491 return isBinaryEquivalent(other
);
494 private boolean isBinaryEquivalent(IntegerDeclaration other
) {
495 if (fAlignment
!= other
.fAlignment
) {
498 if (fLength
!= other
.fLength
) {
501 if (fSigned
!= other
.fSigned
) {
505 // no need for encoding
507 // byte inversion is ok on byte order if the element is one byte long
508 if ((fLength
!= BYTE_ALIGN
) && !fByteOrder
.equals(other
.fByteOrder
)) {