Commit | Line | Data |
---|---|---|
866e5b51 | 1 | /******************************************************************************* |
11252342 | 2 | * Copyright (c) 2011, 2013 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 | * | |
9 | * Contributors: Matthew Khouzam - Initial API and implementation | |
10 | * Contributors: Simon Marchi - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.ctf.core.event.types; | |
14 | ||
3b11ddc7 | 15 | import java.math.BigInteger; |
72dbc4ac MK |
16 | import java.nio.ByteOrder; |
17 | ||
486efb2e | 18 | import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer; |
866e5b51 FC |
19 | |
20 | /** | |
d37aaa7f | 21 | * A CTF integer definition. |
dc209be3 | 22 | * |
3b11ddc7 JCK |
23 | * The definition of a integer basic data type. It will take the data from a |
24 | * trace and store it (and make it fit) as a long. | |
d37aaa7f | 25 | * |
d37aaa7f FC |
26 | * @version 1.0 |
27 | * @author Matthew Khouzam | |
28 | * @author Simon Marchi | |
866e5b51 | 29 | */ |
21fb02fa | 30 | public class IntegerDefinition extends SimpleDatatypeDefinition { |
866e5b51 FC |
31 | |
32 | // ------------------------------------------------------------------------ | |
33 | // Attributes | |
34 | // ------------------------------------------------------------------------ | |
35 | ||
36 | private final IntegerDeclaration declaration; | |
37 | private long value; | |
38 | ||
39 | // ------------------------------------------------------------------------ | |
40 | // Contructors | |
41 | // ------------------------------------------------------------------------ | |
42 | ||
9ac2eb62 MK |
43 | /** |
44 | * Constructor | |
3b11ddc7 JCK |
45 | * |
46 | * @param declaration | |
47 | * the parent declaration | |
48 | * @param definitionScope | |
49 | * the parent scope | |
50 | * @param fieldName | |
51 | * the field name | |
9ac2eb62 | 52 | */ |
866e5b51 FC |
53 | public IntegerDefinition(IntegerDeclaration declaration, |
54 | IDefinitionScope definitionScope, String fieldName) { | |
55 | super(definitionScope, fieldName); | |
56 | this.declaration = declaration; | |
57 | } | |
58 | ||
59 | // ------------------------------------------------------------------------ | |
60 | // Gettters/Setters/Predicates | |
61 | // ------------------------------------------------------------------------ | |
62 | ||
9ac2eb62 MK |
63 | /** |
64 | * Gets the value of the integer | |
3b11ddc7 | 65 | * |
9ac2eb62 MK |
66 | * @return the value of the integer (in long) |
67 | */ | |
866e5b51 FC |
68 | public long getValue() { |
69 | return value; | |
70 | } | |
71 | ||
9ac2eb62 MK |
72 | /** |
73 | * Sets the value of an integer | |
3b11ddc7 JCK |
74 | * |
75 | * @param val | |
76 | * the value | |
9ac2eb62 | 77 | */ |
866e5b51 FC |
78 | public void setValue(long val) { |
79 | value = val; | |
80 | } | |
81 | ||
9ac2eb62 | 82 | @Override |
866e5b51 FC |
83 | public IntegerDeclaration getDeclaration() { |
84 | return declaration; | |
85 | } | |
86 | ||
87 | // ------------------------------------------------------------------------ | |
88 | // Operations | |
89 | // ------------------------------------------------------------------------ | |
90 | ||
21fb02fa MK |
91 | @Override |
92 | public Long getIntegerValue() { | |
93 | return getValue(); | |
94 | } | |
95 | ||
21fb02fa MK |
96 | @Override |
97 | public String getStringValue() { | |
98 | return this.toString(); | |
99 | } | |
100 | ||
866e5b51 FC |
101 | @Override |
102 | public void read(BitBuffer input) { | |
dc209be3 | 103 | final long longNegBit = 0x0000000080000000L; |
9722444c | 104 | /* Offset the buffer position wrt the current alignment */ |
d6205f97 | 105 | alignRead(input, this.declaration); |
9722444c | 106 | |
866e5b51 FC |
107 | boolean signed = declaration.isSigned(); |
108 | int length = declaration.getLength(); | |
109 | long bits = 0; | |
110 | ||
3edb91f3 GB |
111 | /* |
112 | * Is the endianness of this field the same as the endianness of the | |
113 | * input buffer? If not, then temporarily set the buffer's endianness to | |
114 | * this field's just to read the data | |
115 | */ | |
116 | ByteOrder byteOrder = input.getByteOrder(); | |
117 | if ((this.declaration.getByteOrder() != null) && | |
118 | (this.declaration.getByteOrder() != input.getByteOrder())) { | |
119 | input.setByteOrder(this.declaration.getByteOrder()); | |
120 | } | |
866e5b51 | 121 | |
3edb91f3 | 122 | // TODO: use the eventual getLong from BitBuffer |
866e5b51 FC |
123 | if (length == 64) { |
124 | long low = input.getInt(32, false); | |
125 | low = low & 0x00000000FFFFFFFFL; | |
126 | long high = input.getInt(32, false); | |
127 | high = high & 0x00000000FFFFFFFFL; | |
72dbc4ac MK |
128 | if (this.declaration.getByteOrder() != ByteOrder.BIG_ENDIAN) { |
129 | bits = (high << 32) | low; | |
130 | } else { | |
131 | bits = (low << 32) | high; | |
132 | } | |
866e5b51 FC |
133 | } else { |
134 | bits = input.getInt(length, signed); | |
135 | bits = bits & 0x00000000FFFFFFFFL; | |
dc209be3 | 136 | /* |
3edb91f3 GB |
137 | * The previous line loses sign information but is necessary, this |
138 | * fixes the sign for 32 bit numbers. Sorry, in java all 64 bit ints | |
139 | * are signed. | |
dc209be3 | 140 | */ |
3edb91f3 | 141 | if ((longNegBit == (bits & longNegBit)) && signed) { |
dc209be3 MK |
142 | bits |= 0xffffffff00000000L; |
143 | } | |
866e5b51 | 144 | } |
3edb91f3 GB |
145 | /* |
146 | * Put the input buffer's endianness back to original if it was changed | |
147 | */ | |
148 | if (byteOrder != input.getByteOrder()) { | |
149 | input.setByteOrder(byteOrder); | |
150 | } | |
866e5b51 FC |
151 | |
152 | value = bits; | |
153 | } | |
154 | ||
155 | @Override | |
156 | public String toString() { | |
157 | if (declaration.isCharacter()) { | |
158 | char c = (char) value; | |
159 | return Character.toString(c); | |
160 | } | |
3b11ddc7 JCK |
161 | return formatNumber(value, declaration.getBase(), declaration.isSigned()); |
162 | } | |
163 | ||
164 | /** | |
165 | * Print a numeric value as a string in a given base | |
166 | * | |
167 | * @param value | |
168 | * The value to print as string | |
169 | * @param base | |
170 | * The base for this value | |
171 | * @param signed | |
172 | * Is the value signed or not | |
173 | * @return formatted number string | |
174 | * @since 3.0 | |
175 | */ | |
176 | public static final String formatNumber(long value, int base, boolean signed) { | |
177 | String s; | |
178 | /* Format the number correctly according to the integer's base */ | |
179 | switch (base) { | |
180 | case 2: | |
181 | s = "0b" + Long.toBinaryString(value); //$NON-NLS-1$ | |
182 | break; | |
183 | case 8: | |
184 | s = "0" + Long.toOctalString(value); //$NON-NLS-1$ | |
185 | break; | |
186 | case 16: | |
187 | s = "0x" + Long.toHexString(value); //$NON-NLS-1$ | |
188 | break; | |
189 | case 10: | |
190 | default: | |
191 | /* For non-standard base, we'll just print it as a decimal number */ | |
192 | if (!signed && value < 0) { | |
193 | /* | |
194 | * Since there are no 'unsigned long', handle this case with | |
195 | * BigInteger | |
196 | */ | |
197 | BigInteger bigInteger = BigInteger.valueOf(value); | |
198 | /* | |
199 | * we add 2^64 to the negative number to get the real unsigned | |
200 | * value | |
201 | */ | |
202 | bigInteger = bigInteger.add(BigInteger.valueOf(1).shiftLeft(64)); | |
203 | s = bigInteger.toString(); | |
204 | } else { | |
205 | s = Long.toString(value); | |
206 | } | |
207 | break; | |
208 | } | |
209 | return s; | |
866e5b51 FC |
210 | } |
211 | } |