ctf: do not assume endianness of integers for singletons
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / event / types / IntegerDeclaration.java
CommitLineData
866e5b51 1/*******************************************************************************
0f231de2 2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
866e5b51
FC
3 *
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
8 *
4311ac8b
MAL
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 * Simon Marchi - Initial API and implementation
12 * Marc-Andre Laperle - Add min/maximum for validation
866e5b51
FC
13 *******************************************************************************/
14
f357bcd4 15package org.eclipse.tracecompass.ctf.core.event.types;
866e5b51 16
5db5a3a4
AM
17import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
18
4311ac8b 19import java.math.BigInteger;
866e5b51
FC
20import java.nio.ByteOrder;
21
a4fa4e36
MK
22import org.eclipse.jdt.annotation.NonNullByDefault;
23import org.eclipse.jdt.annotation.Nullable;
680f9173 24import org.eclipse.tracecompass.ctf.core.CTFException;
f357bcd4
AM
25import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
26import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
a4fa4e36 27
866e5b51 28/**
d37aaa7f 29 * A CTF integer declaration.
4311ac8b 30 *
d37aaa7f
FC
31 * The declaration of a integer basic data type.
32 *
33 * @version 1.0
34 * @author Matthew Khouzam
35 * @author Simon Marchi
866e5b51 36 */
a4fa4e36 37@NonNullByDefault
f068c622 38public final class IntegerDeclaration extends Declaration implements ISimpleDatatypeDeclaration {
a4fa4e36
MK
39
40 // ------------------------------------------------------------------------
41 // Helpers
42 // ------------------------------------------------------------------------
43
f068c622
MK
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;
a4fa4e36
MK
52 /**
53 * unsigned int 32 bits big endian
a4fa4e36
MK
54 */
55 public static final IntegerDeclaration UINT_32B_DECL = new IntegerDeclaration(32, false, ByteOrder.BIG_ENDIAN);
56 /**
57 * unsigned int 32 bits little endian
a4fa4e36
MK
58 */
59 public static final IntegerDeclaration UINT_32L_DECL = new IntegerDeclaration(32, false, ByteOrder.LITTLE_ENDIAN);
60 /**
61 * signed int 32 bits big endian
a4fa4e36
MK
62 */
63 public static final IntegerDeclaration INT_32B_DECL = new IntegerDeclaration(32, true, ByteOrder.BIG_ENDIAN);
64 /**
65 * signed int 32 bits little endian
a4fa4e36
MK
66 */
67 public static final IntegerDeclaration INT_32L_DECL = new IntegerDeclaration(32, true, ByteOrder.LITTLE_ENDIAN);
68 /**
69 * unsigned int 32 bits big endian
a4fa4e36
MK
70 */
71 public static final IntegerDeclaration UINT_64B_DECL = new IntegerDeclaration(64, false, ByteOrder.BIG_ENDIAN);
72 /**
73 * unsigned int 64 bits little endian
a4fa4e36
MK
74 */
75 public static final IntegerDeclaration UINT_64L_DECL = new IntegerDeclaration(64, false, ByteOrder.LITTLE_ENDIAN);
76 /**
77 * signed int 64 bits big endian
a4fa4e36
MK
78 */
79 public static final IntegerDeclaration INT_64B_DECL = new IntegerDeclaration(64, true, ByteOrder.BIG_ENDIAN);
80 /**
81 * signed int 64 bits little endian
a4fa4e36
MK
82 */
83 public static final IntegerDeclaration INT_64L_DECL = new IntegerDeclaration(64, true, ByteOrder.LITTLE_ENDIAN);
84 /**
85 * unsigned 8 bit int endianness doesn't matter since it's 8 bits (byte)
a4fa4e36
MK
86 */
87 public static final IntegerDeclaration UINT_8_DECL = new IntegerDeclaration(8, false, ByteOrder.BIG_ENDIAN);
88 /**
89 * signed 8 bit int endianness doesn't matter since it's 8 bits (char)
a4fa4e36
MK
90 */
91 public static final IntegerDeclaration INT_8_DECL = new IntegerDeclaration(8, true, ByteOrder.BIG_ENDIAN);
6c7592e1
MK
92 /**
93 * Unsigned 5 bit int, used for event headers
6c7592e1 94 */
2dd7bd51 95 public static final IntegerDeclaration UINT_5B_DECL = new IntegerDeclaration(5, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1); //$NON-NLS-1$
6c7592e1
MK
96 /**
97 * Unsigned 5 bit int, used for event headers
6c7592e1 98 */
2dd7bd51 99 public static final IntegerDeclaration UINT_5L_DECL = new IntegerDeclaration(5, false, 10, ByteOrder.LITTLE_ENDIAN, Encoding.NONE, "", 1); //$NON-NLS-1$
6c7592e1
MK
100 /**
101 * Unsigned 5 bit int, used for event headers
6c7592e1 102 */
2dd7bd51 103 public static final IntegerDeclaration UINT_27B_DECL = new IntegerDeclaration(27, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1); //$NON-NLS-1$
6c7592e1
MK
104 /**
105 * Unsigned 5 bit int, used for event headers
6c7592e1 106 */
2dd7bd51 107 public static final IntegerDeclaration UINT_27L_DECL = new IntegerDeclaration(27, false, 10, ByteOrder.LITTLE_ENDIAN, Encoding.NONE, "", 1); //$NON-NLS-1$
6c7592e1
MK
108 /**
109 * Unsigned 16 bit int, used for event headers
6c7592e1
MK
110 */
111 public static final IntegerDeclaration UINT_16B_DECL = new IntegerDeclaration(16, false, ByteOrder.BIG_ENDIAN);
112 /**
113 * Unsigned 16 bit int, used for event headers
6c7592e1
MK
114 */
115 public static final IntegerDeclaration UINT_16L_DECL = new IntegerDeclaration(16, false, ByteOrder.LITTLE_ENDIAN);
866e5b51
FC
116 // ------------------------------------------------------------------------
117 // Attributes
118 // ------------------------------------------------------------------------
119
a4fa4e36
MK
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;
866e5b51
FC
127
128 // ------------------------------------------------------------------------
129 // Constructors
130 // ------------------------------------------------------------------------
131
a4fa4e36
MK
132 /**
133 * Factory, some common types cached
134 *
135 * @param len
136 * The length in bits
137 * @param signed
138 * Is the integer signed? false == unsigned
139 * @param base
140 * The base (10-16 are most common)
141 * @param byteOrder
142 * Big-endian little-endian or other
143 * @param encoding
144 * ascii, utf8 or none.
145 * @param clock
146 * The clock path, can be null
147 * @param alignment
148 * The minimum alignment. Should be >= 1
149 * @return the integer declaration
a4fa4e36
MK
150 */
151 public static IntegerDeclaration createDeclaration(int len, boolean signed, int base,
152 @Nullable ByteOrder byteOrder, Encoding encoding, String clock, long alignment) {
cfead27d 153 if (encoding.equals(Encoding.NONE) && (clock.equals("")) && base == BASE_10 && byteOrder != null) { //$NON-NLS-1$
f068c622 154 if (alignment == BYTE_ALIGN) {
2dd7bd51 155 switch (len) {
f068c622 156 case SIZE_8:
2dd7bd51 157 return signed ? INT_8_DECL : UINT_8_DECL;
f068c622 158 case SIZE_16:
2dd7bd51 159 if (!signed) {
f068c622 160 if (isBigEndian(byteOrder)) {
2dd7bd51
MK
161 return UINT_16B_DECL;
162 }
163 return UINT_16L_DECL;
6c7592e1 164 }
2dd7bd51 165 break;
f068c622 166 case SIZE_32:
2dd7bd51 167 if (signed) {
f068c622 168 if (isBigEndian(byteOrder)) {
2dd7bd51
MK
169 return INT_32B_DECL;
170 }
171 return INT_32L_DECL;
6c7592e1 172 }
f068c622 173 if (isBigEndian(byteOrder)) {
2dd7bd51 174 return UINT_32B_DECL;
6c7592e1 175 }
2dd7bd51 176 return UINT_32L_DECL;
f068c622 177 case SIZE_64:
2dd7bd51 178 if (signed) {
f068c622 179 if (isBigEndian(byteOrder)) {
2dd7bd51
MK
180 return INT_64B_DECL;
181 }
182 return INT_64L_DECL;
a4fa4e36 183 }
f068c622 184 if (isBigEndian(byteOrder)) {
2dd7bd51 185 return UINT_64B_DECL;
a4fa4e36 186 }
2dd7bd51 187 return UINT_64L_DECL;
f068c622 188
2dd7bd51 189 default:
f068c622 190
a4fa4e36 191 }
f068c622 192
2dd7bd51
MK
193 } else if (alignment == 1) {
194 switch (len) {
f068c622 195 case SIZE_5:
2dd7bd51 196 if (!signed) {
f068c622 197 if (isBigEndian(byteOrder)) {
2dd7bd51
MK
198 return UINT_5B_DECL;
199 }
200 return UINT_5L_DECL;
201 }
202 break;
f068c622 203 case SIZE_27:
2dd7bd51 204 if (!signed) {
f068c622 205 if (isBigEndian(byteOrder)) {
2dd7bd51
MK
206 return UINT_27B_DECL;
207 }
208 return UINT_27L_DECL;
209 }
210 break;
211 default:
212 break;
a4fa4e36 213 }
a4fa4e36
MK
214 }
215 }
216 return new IntegerDeclaration(len, signed, base, byteOrder, encoding, clock, alignment);
217 }
218
f068c622
MK
219 private static boolean isBigEndian(@Nullable ByteOrder byteOrder) {
220 return (byteOrder != null) && byteOrder.equals(ByteOrder.BIG_ENDIAN);
221 }
222
9ac2eb62 223 /**
a511da0d 224 * Constructor
056ebaf1
AM
225 *
226 * @param len
227 * The length in bits
228 * @param signed
229 * Is the integer signed? false == unsigned
230 * @param base
231 * The base (10-16 are most common)
232 * @param byteOrder
a511da0d 233 * Big-endian little-endian or other
056ebaf1
AM
234 * @param encoding
235 * ascii, utf8 or none.
236 * @param clock
237 * The clock path, can be null
238 * @param alignment
ab04fc6b 239 * The minimum alignment. Should be ≥ 1
9ac2eb62 240 */
a4fa4e36
MK
241 private IntegerDeclaration(int len, boolean signed, int base,
242 @Nullable ByteOrder byteOrder, Encoding encoding, String clock, long alignment) {
a4fa4e36
MK
243 fLength = len;
244 fSigned = signed;
245 fBase = base;
1cd75eda 246 fByteOrder = (byteOrder == null) ? ByteOrder.nativeOrder() : byteOrder;
a4fa4e36
MK
247 fEncoding = encoding;
248 fClock = clock;
249 fAlignment = Math.max(alignment, 1);
250 }
251
252 private IntegerDeclaration(int len, boolean signed, @Nullable ByteOrder byteOrder) {
f068c622 253 this(len, signed, BASE_10, byteOrder, Encoding.NONE, "", BYTE_ALIGN); //$NON-NLS-1$
866e5b51
FC
254 }
255
256 // ------------------------------------------------------------------------
a511da0d 257 // Getters/Setters/Predicates
866e5b51
FC
258 // ------------------------------------------------------------------------
259
9ac2eb62
MK
260 /**
261 * Is the integer signed?
bdc1590e 262 *
9ac2eb62
MK
263 * @return the is the integer signed
264 */
866e5b51 265 public boolean isSigned() {
a4fa4e36 266 return fSigned;
866e5b51
FC
267 }
268
9ac2eb62 269 /**
a511da0d 270 * Get the integer base commonly decimal or hex
bdc1590e 271 *
9ac2eb62
MK
272 * @return the integer base
273 */
866e5b51 274 public int getBase() {
a4fa4e36 275 return fBase;
866e5b51
FC
276 }
277
9ac2eb62 278 /**
bdc1590e
EB
279 * Get the byte order
280 *
9ac2eb62
MK
281 * @return the byte order
282 */
866e5b51 283 public ByteOrder getByteOrder() {
a4fa4e36 284 return fByteOrder;
866e5b51
FC
285 }
286
9ac2eb62 287 /**
a511da0d 288 * Get encoding, chars are 8 bit ints
bdc1590e 289 *
9ac2eb62
MK
290 * @return the encoding
291 */
866e5b51 292 public Encoding getEncoding() {
a4fa4e36 293 return fEncoding;
866e5b51
FC
294 }
295
9ac2eb62 296 /**
a511da0d 297 * Is the integer a character (8 bits and encoded?)
bdc1590e 298 *
9ac2eb62
MK
299 * @return is the integer a char
300 */
bdc1590e 301 public boolean isCharacter() {
f068c622 302 return (fLength == SIZE_8) && (fEncoding != Encoding.NONE);
866e5b51
FC
303 }
304
7b4f13e6
MK
305 /**
306 * Is the integer an unsigned byte (8 bits and no sign)?
307 *
308 * @return is the integer an unsigned byte
7b4f13e6
MK
309 */
310 public boolean isUnsignedByte() {
f068c622 311 return (fLength == SIZE_8) && (!fSigned);
7b4f13e6
MK
312 }
313
bdc1590e
EB
314 /**
315 * Get the length in bits for this integer
316 *
317 * @return the length of the integer
318 */
866e5b51 319 public int getLength() {
a4fa4e36 320 return fLength;
866e5b51
FC
321 }
322
07002e0a 323 @Override
6f04e06c 324 public long getAlignment() {
a4fa4e36 325 return fAlignment;
fd74e6c1
MK
326 }
327
9ac2eb62
MK
328 /**
329 * The integer's clock, since timestamps are stored in ints
bdc1590e 330 *
9ac2eb62
MK
331 * @return the integer's clock, can be null. (most often it is)
332 */
6f04e06c 333 public String getClock() {
a4fa4e36
MK
334 return fClock;
335 }
336
a4fa4e36
MK
337 @Override
338 public int getMaximumSize() {
339 return fLength;
fd74e6c1 340 }
bdc1590e 341
866e5b51
FC
342 // ------------------------------------------------------------------------
343 // Operations
344 // ------------------------------------------------------------------------
345
346 @Override
a4fa4e36 347 public IntegerDefinition createDefinition(@Nullable IDefinitionScope definitionScope,
680f9173 348 String fieldName, BitBuffer input) throws CTFException {
733c614c
MK
349 ByteOrder byteOrder = input.getByteOrder();
350 input.setByteOrder(fByteOrder);
a4fa4e36 351 long value = read(input);
733c614c 352 input.setByteOrder(byteOrder);
a4fa4e36 353 return new IntegerDefinition(this, definitionScope, fieldName, value);
866e5b51
FC
354 }
355
356 @Override
357 public String toString() {
2dd7bd51 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$
866e5b51
FC
359 }
360
4311ac8b 361 /**
a4fa4e36 362 * Get the maximum value for this integer declaration.
4311ac8b
MAL
363 *
364 * @return The maximum value for this integer declaration
4311ac8b
MAL
365 */
366 public BigInteger getMaxValue() {
bdc1590e
EB
367 /*
368 * Compute the number of bits able to represent an unsigned number,
369 * ignoring sign bit.
370 */
a4fa4e36 371 int significantBits = fLength - (fSigned ? 1 : 0);
bdc1590e 372 /*
a4fa4e36
MK
373 * For a given N significant bits, compute the maximal value which is (1
374 * << N) - 1.
bdc1590e 375 */
5db5a3a4 376 return checkNotNull(BigInteger.ONE.shiftLeft(significantBits).subtract(BigInteger.ONE));
4311ac8b
MAL
377 }
378
379 /**
a4fa4e36 380 * Get the minimum value for this integer declaration.
4311ac8b
MAL
381 *
382 * @return The minimum value for this integer declaration
4311ac8b
MAL
383 */
384 public BigInteger getMinValue() {
a4fa4e36 385 if (!fSigned) {
5db5a3a4 386 return checkNotNull(BigInteger.ZERO);
4311ac8b
MAL
387 }
388
bdc1590e
EB
389 /*
390 * Compute the number of bits able to represent an unsigned number,
391 * without the sign bit.
392 */
a4fa4e36
MK
393 int significantBits = fLength - 1;
394 /*
395 * For a given N significant bits, compute the minimal value which is -
396 * (1 << N).
397 */
5db5a3a4 398 return checkNotNull(BigInteger.ONE.shiftLeft(significantBits).negate());
a4fa4e36
MK
399 }
400
680f9173 401 private long read(BitBuffer input) throws CTFException {
a4fa4e36
MK
402 /* Offset the buffer position wrt the current alignment */
403 alignRead(input);
404
405 boolean signed = isSigned();
406 int length = getLength();
407 long bits = 0;
408
409 /*
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
413 */
414 ByteOrder previousByteOrder = input.getByteOrder();
415 if ((getByteOrder() != input.getByteOrder())) {
416 input.setByteOrder(getByteOrder());
417 }
418
f068c622 419 if (length > SIZE_64) {
680f9173 420 throw new CTFException("Cannot read an integer with over 64 bits. Length given: " + length); //$NON-NLS-1$
a4fa4e36
MK
421 }
422
423 bits = input.get(length, signed);
424
bdc1590e 425 /*
a4fa4e36 426 * Put the input buffer's endianness back to original if it was changed
bdc1590e 427 */
a4fa4e36
MK
428 if (previousByteOrder != input.getByteOrder()) {
429 input.setByteOrder(previousByteOrder);
430 }
431
432 return bits;
4311ac8b
MAL
433 }
434
e00e6663
MK
435 @Override
436 public int hashCode() {
437 final int prime = 31;
438 int result = 1;
439 result = prime * result + (int) (fAlignment ^ (fAlignment >>> 32));
440 result = prime * result + fBase;
f068c622
MK
441 result = prime * result + fByteOrder.toString().hashCode();
442 result = prime * result + fClock.hashCode();
443 result = prime * result + fEncoding.hashCode();
e00e6663
MK
444 result = prime * result + fLength;
445 result = prime * result + (fSigned ? 1231 : 1237);
446 return result;
447 }
448
449 @Override
450 public boolean equals(@Nullable Object obj) {
451 if (this == obj) {
452 return true;
453 }
454 if (obj == null) {
455 return false;
456 }
457 if (getClass() != obj.getClass()) {
458 return false;
459 }
460 IntegerDeclaration other = (IntegerDeclaration) obj;
f068c622 461 if (!isBinaryEquivalent(other)) {
e00e6663
MK
462 return false;
463 }
464 if (!fByteOrder.equals(other.fByteOrder)) {
465 return false;
466 }
467 if (!fClock.equals(other.fClock)) {
468 return false;
469 }
470 if (fEncoding != other.fEncoding) {
471 return false;
472 }
f068c622 473 if (fBase != other.fBase) {
e00e6663
MK
474 return false;
475 }
476 return true;
477 }
478
66aa25f0
MK
479 @Override
480 public boolean isBinaryEquivalent(@Nullable IDeclaration obj) {
481 if (this == obj) {
482 return true;
483 }
484 if (obj == null) {
485 return false;
486 }
487 if (getClass() != obj.getClass()) {
488 return false;
489 }
490 IntegerDeclaration other = (IntegerDeclaration) obj;
f068c622
MK
491 return isBinaryEquivalent(other);
492 }
493
494 private boolean isBinaryEquivalent(IntegerDeclaration other) {
66aa25f0
MK
495 if (fAlignment != other.fAlignment) {
496 return false;
497 }
498 if (fLength != other.fLength) {
499 return false;
500 }
501 if (fSigned != other.fSigned) {
502 return false;
503 }
504 // no need for base
505 // no need for encoding
506 // no need for clock
507 // byte inversion is ok on byte order if the element is one byte long
f068c622 508 if ((fLength != BYTE_ALIGN) && !fByteOrder.equals(other.fByteOrder)) {
66aa25f0
MK
509 return false;
510 }
511 return true;
512 }
513
866e5b51 514}
This page took 0.093737 seconds and 5 git commands to generate.