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 boolean fIsByteOrderSet
;
124 private final ByteOrder fByteOrder
;
125 private final Encoding fEncoding
;
126 private final long fAlignment
;
127 private final String fClock
;
129 // ------------------------------------------------------------------------
131 // ------------------------------------------------------------------------
134 * Factory, some common types cached
139 * Is the integer signed? false == unsigned
141 * The base (10-16 are most common)
143 * Big-endian little-endian or other
145 * ascii, utf8 or none.
147 * The clock path, can be null
149 * The minimum alignment. Should be >= 1
150 * @return the integer declaration
152 public static IntegerDeclaration
createDeclaration(int len
, boolean signed
, int base
,
153 @Nullable ByteOrder byteOrder
, Encoding encoding
, String clock
, long alignment
) {
154 if (encoding
.equals(Encoding
.NONE
) && (clock
.equals("")) && base
== BASE_10
&& byteOrder
!= null) { //$NON-NLS-1$
155 if (alignment
== BYTE_ALIGN
) {
158 return signed ? INT_8_DECL
: UINT_8_DECL
;
161 if (isBigEndian(byteOrder
)) {
162 return UINT_16B_DECL
;
164 return UINT_16L_DECL
;
169 if (isBigEndian(byteOrder
)) {
174 if (isBigEndian(byteOrder
)) {
175 return UINT_32B_DECL
;
177 return UINT_32L_DECL
;
180 if (isBigEndian(byteOrder
)) {
185 if (isBigEndian(byteOrder
)) {
186 return UINT_64B_DECL
;
188 return UINT_64L_DECL
;
194 } else if (alignment
== 1) {
198 if (isBigEndian(byteOrder
)) {
206 if (isBigEndian(byteOrder
)) {
207 return UINT_27B_DECL
;
209 return UINT_27L_DECL
;
217 return new IntegerDeclaration(len
, signed
, base
, byteOrder
, encoding
, clock
, alignment
);
220 private static boolean isBigEndian(@Nullable ByteOrder byteOrder
) {
221 return (byteOrder
!= null) && byteOrder
.equals(ByteOrder
.BIG_ENDIAN
);
230 * Is the integer signed? false == unsigned
232 * The base (10-16 are most common)
234 * Big-endian little-endian or other
236 * ascii, utf8 or none.
238 * The clock path, can be null
240 * The minimum alignment. Should be ≥ 1
242 private IntegerDeclaration(int len
, boolean signed
, int base
,
243 @Nullable ByteOrder byteOrder
, Encoding encoding
, String clock
, long alignment
) {
247 fIsByteOrderSet
= byteOrder
!= null;
248 fByteOrder
= (byteOrder
== null) ? ByteOrder
.nativeOrder() : byteOrder
;
249 fEncoding
= encoding
;
251 fAlignment
= Math
.max(alignment
, 1);
254 private IntegerDeclaration(int len
, boolean signed
, @Nullable ByteOrder byteOrder
) {
255 this(len
, signed
, BASE_10
, byteOrder
, Encoding
.NONE
, "", BYTE_ALIGN
); //$NON-NLS-1$
258 // ------------------------------------------------------------------------
259 // Getters/Setters/Predicates
260 // ------------------------------------------------------------------------
263 * Is the integer signed?
265 * @return the is the integer signed
267 public boolean isSigned() {
272 * Get the integer base commonly decimal or hex
274 * @return the integer base
276 public int getBase() {
284 public boolean isByteOrderSet() {
285 return fIsByteOrderSet
;
289 public ByteOrder
getByteOrder() {
294 * Get encoding, chars are 8 bit ints
296 * @return the encoding
298 public Encoding
getEncoding() {
303 * Is the integer a character (8 bits and encoded?)
305 * @return is the integer a char
307 public boolean isCharacter() {
308 return (fLength
== SIZE_8
) && (fEncoding
!= Encoding
.NONE
);
312 * Is the integer an unsigned byte (8 bits and no sign)?
314 * @return is the integer an unsigned byte
316 public boolean isUnsignedByte() {
317 return (fLength
== SIZE_8
) && (!fSigned
);
321 * Get the length in bits for this integer
323 * @return the length of the integer
325 public int getLength() {
330 public long getAlignment() {
335 * The integer's clock, since timestamps are stored in ints
337 * @return the integer's clock, can be null. (most often it is)
339 public String
getClock() {
344 public int getMaximumSize() {
348 // ------------------------------------------------------------------------
350 // ------------------------------------------------------------------------
353 public IntegerDefinition
createDefinition(@Nullable IDefinitionScope definitionScope
,
354 String fieldName
, BitBuffer input
) throws CTFException
{
355 ByteOrder byteOrder
= input
.getByteOrder();
356 input
.setByteOrder(fByteOrder
);
357 long value
= read(input
);
358 input
.setByteOrder(byteOrder
);
359 return new IntegerDefinition(this, definitionScope
, fieldName
, value
);
363 public String
toString() {
364 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$
368 * Get the maximum value for this integer declaration.
370 * @return The maximum value for this integer declaration
372 public BigInteger
getMaxValue() {
374 * Compute the number of bits able to represent an unsigned number,
377 int significantBits
= fLength
- (fSigned ?
1 : 0);
379 * For a given N significant bits, compute the maximal value which is (1
382 return checkNotNull(BigInteger
.ONE
.shiftLeft(significantBits
).subtract(BigInteger
.ONE
));
386 * Get the minimum value for this integer declaration.
388 * @return The minimum value for this integer declaration
390 public BigInteger
getMinValue() {
392 return checkNotNull(BigInteger
.ZERO
);
396 * Compute the number of bits able to represent an unsigned number,
397 * without the sign bit.
399 int significantBits
= fLength
- 1;
401 * For a given N significant bits, compute the minimal value which is -
404 return checkNotNull(BigInteger
.ONE
.shiftLeft(significantBits
).negate());
407 private long read(BitBuffer input
) throws CTFException
{
408 /* Offset the buffer position wrt the current alignment */
411 boolean signed
= isSigned();
412 int length
= getLength();
416 * Is the endianness of this field the same as the endianness of the
417 * input buffer? If not, then temporarily set the buffer's endianness to
418 * this field's just to read the data
420 ByteOrder previousByteOrder
= input
.getByteOrder();
421 if ((getByteOrder() != input
.getByteOrder())) {
422 input
.setByteOrder(getByteOrder());
425 if (length
> SIZE_64
) {
426 throw new CTFException("Cannot read an integer with over 64 bits. Length given: " + length
); //$NON-NLS-1$
429 bits
= input
.get(length
, signed
);
432 * Put the input buffer's endianness back to original if it was changed
434 if (previousByteOrder
!= input
.getByteOrder()) {
435 input
.setByteOrder(previousByteOrder
);
442 public int hashCode() {
443 final int prime
= 31;
445 result
= prime
* result
+ (int) (fAlignment ^
(fAlignment
>>> 32));
446 result
= prime
* result
+ fBase
;
447 result
= prime
* result
+ fByteOrder
.toString().hashCode();
448 result
= prime
* result
+ fClock
.hashCode();
449 result
= prime
* result
+ fEncoding
.hashCode();
450 result
= prime
* result
+ fLength
;
451 result
= prime
* result
+ (fSigned ?
1231 : 1237);
456 public boolean equals(@Nullable Object obj
) {
463 if (getClass() != obj
.getClass()) {
466 IntegerDeclaration other
= (IntegerDeclaration
) obj
;
467 if (!isBinaryEquivalent(other
)) {
470 if (!fByteOrder
.equals(other
.fByteOrder
)) {
473 if (!fClock
.equals(other
.fClock
)) {
476 if (fEncoding
!= other
.fEncoding
) {
479 if (fBase
!= other
.fBase
) {
486 public boolean isBinaryEquivalent(@Nullable IDeclaration obj
) {
493 if (getClass() != obj
.getClass()) {
496 IntegerDeclaration other
= (IntegerDeclaration
) obj
;
497 return isBinaryEquivalent(other
);
500 private boolean isBinaryEquivalent(IntegerDeclaration other
) {
501 if (fAlignment
!= other
.fAlignment
) {
504 if (fLength
!= other
.fLength
) {
507 if (fSigned
!= other
.fSigned
) {
511 // no need for encoding
513 // byte inversion is ok on byte order if the element is one byte long
514 if ((fLength
!= BYTE_ALIGN
) && !fByteOrder
.equals(other
.fByteOrder
)) {