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