Commit | Line | Data |
---|---|---|
8c8bf09f | 1 | /******************************************************************************* |
5179fc01 | 2 | * Copyright (c) 2009, 2010, 2012 Ericsson |
8c8bf09f ASL |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made 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: | |
1f506a43 | 10 | * Francois Chouinard - Initial API and implementation |
023761c4 | 11 | * Thomas Gatterweh - Updated scaling / synchronization |
5179fc01 | 12 | * Francois Chouinard - Refactoring to align with TMF Event Model 1.0 |
8c8bf09f ASL |
13 | *******************************************************************************/ |
14 | ||
6c13869b | 15 | package org.eclipse.linuxtools.tmf.core.event; |
8c8bf09f | 16 | |
8c8bf09f ASL |
17 | /** |
18 | * <b><u>TmfTimestamp</u></b> | |
19 | * <p> | |
5179fc01 | 20 | * A generic implementation of ITmfTimestamp. |
8c8bf09f | 21 | */ |
4df4581d | 22 | public class TmfTimestamp implements ITmfTimestamp { |
8c8bf09f | 23 | |
5179fc01 | 24 | // ------------------------------------------------------------------------ |
8c8bf09f | 25 | // Constants |
5179fc01 | 26 | // ------------------------------------------------------------------------ |
8c8bf09f | 27 | |
d7dbf09a FC |
28 | /** |
29 | * The beginning of time | |
30 | */ | |
085d898f | 31 | public static final ITmfTimestamp BIG_BANG = |
d7dbf09a FC |
32 | new TmfTimestamp(Long.MIN_VALUE, Integer.MAX_VALUE, 0); |
33 | ||
34 | /** | |
35 | * The end of time | |
36 | */ | |
085d898f | 37 | public static final ITmfTimestamp BIG_CRUNCH = |
d7dbf09a | 38 | new TmfTimestamp(Long.MAX_VALUE, Integer.MAX_VALUE, 0); |
085d898f | 39 | |
d7dbf09a FC |
40 | /** |
41 | * Zero | |
42 | */ | |
085d898f | 43 | public static final ITmfTimestamp ZERO = |
d7dbf09a | 44 | new TmfTimestamp(0, 0, 0); |
5179fc01 FC |
45 | |
46 | // ------------------------------------------------------------------------ | |
47 | // Attributes | |
48 | // ------------------------------------------------------------------------ | |
8c8bf09f | 49 | |
d7dbf09a FC |
50 | /** |
51 | * The timestamp raw value (mantissa) | |
52 | */ | |
53 | protected long fValue; | |
54 | ||
55 | /** | |
56 | * The timestamp scale (magnitude) | |
57 | */ | |
58 | protected int fScale; | |
59 | ||
60 | /** | |
61 | * The value precision (tolerance) | |
62 | */ | |
63 | protected int fPrecision; | |
5179fc01 FC |
64 | |
65 | // ------------------------------------------------------------------------ | |
8c8bf09f | 66 | // Constructors |
5179fc01 | 67 | // ------------------------------------------------------------------------ |
8c8bf09f ASL |
68 | |
69 | /** | |
28b94d61 | 70 | * Default constructor |
8c8bf09f ASL |
71 | */ |
72 | public TmfTimestamp() { | |
5179fc01 | 73 | this(0, 0, 0); |
8c8bf09f ASL |
74 | } |
75 | ||
1f506a43 | 76 | /** |
5179fc01 FC |
77 | * Simple constructor (scale = precision = 0) |
78 | * | |
79 | * @param value the timestamp value | |
1f506a43 | 80 | */ |
085d898f | 81 | public TmfTimestamp(final long value) { |
5179fc01 | 82 | this(value, 0, 0); |
1f506a43 FC |
83 | } |
84 | ||
8c8bf09f | 85 | /** |
5179fc01 | 86 | * Simple constructor (precision = 0) |
8c8bf09f | 87 | * |
5179fc01 FC |
88 | * @param value the timestamp value |
89 | * @param scale the timestamp scale | |
8c8bf09f | 90 | */ |
085d898f | 91 | public TmfTimestamp(final long value, final int scale) { |
8c8bf09f ASL |
92 | this(value, scale, 0); |
93 | } | |
94 | ||
95 | /** | |
5179fc01 | 96 | * Full constructor |
8c8bf09f | 97 | * |
5179fc01 FC |
98 | * @param value the timestamp value |
99 | * @param scale the timestamp scale | |
100 | * @param precision the timestamp precision | |
8c8bf09f | 101 | */ |
085d898f | 102 | public TmfTimestamp(final long value, final int scale, final int precision) { |
8c8bf09f ASL |
103 | fValue = value; |
104 | fScale = scale; | |
105 | fPrecision = Math.abs(precision); | |
106 | } | |
107 | ||
108 | /** | |
28b94d61 | 109 | * Copy constructor |
8c8bf09f | 110 | * |
5179fc01 | 111 | * @param timestamp the timestamp to copy |
8c8bf09f | 112 | */ |
085d898f | 113 | public TmfTimestamp(final ITmfTimestamp timestamp) { |
5179fc01 FC |
114 | if (timestamp == null) |
115 | throw new IllegalArgumentException(); | |
4df4581d | 116 | fValue = timestamp.getValue(); |
117 | fScale = timestamp.getScale(); | |
118 | fPrecision = timestamp.getPrecision(); | |
8c8bf09f ASL |
119 | } |
120 | ||
5179fc01 FC |
121 | // ------------------------------------------------------------------------ |
122 | // ITmfTimestamp | |
123 | // ------------------------------------------------------------------------ | |
8c8bf09f | 124 | |
d7dbf09a FC |
125 | /* (non-Javadoc) |
126 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getValue() | |
127 | */ | |
128 | @Override | |
8c8bf09f ASL |
129 | public long getValue() { |
130 | return fValue; | |
131 | } | |
132 | ||
d7dbf09a FC |
133 | /* (non-Javadoc) |
134 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getScale() | |
135 | */ | |
136 | @Override | |
5179fc01 | 137 | public int getScale() { |
8c8bf09f ASL |
138 | return fScale; |
139 | } | |
140 | ||
d7dbf09a FC |
141 | /* (non-Javadoc) |
142 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getPrecision() | |
143 | */ | |
144 | @Override | |
5179fc01 | 145 | public int getPrecision() { |
8c8bf09f ASL |
146 | return fPrecision; |
147 | } | |
148 | ||
5179fc01 FC |
149 | private static final long scalingFactors[] = new long[] { |
150 | 1L, | |
151 | 10L, | |
152 | 100L, | |
153 | 1000L, | |
154 | 10000L, | |
155 | 100000L, | |
156 | 1000000L, | |
157 | 10000000L, | |
158 | 100000000L, | |
159 | 1000000000L, | |
160 | 10000000000L, | |
161 | 100000000000L, | |
162 | 1000000000000L, | |
163 | 10000000000000L, | |
164 | 100000000000000L, | |
165 | 1000000000000000L, | |
166 | 10000000000000000L, | |
167 | 100000000000000000L, | |
168 | 1000000000000000000L, | |
169 | }; | |
4ab33d2b | 170 | |
d7dbf09a FC |
171 | /* (non-Javadoc) |
172 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#normalize(long, int) | |
173 | */ | |
174 | @Override | |
085d898f | 175 | public ITmfTimestamp normalize(final long offset, final int scale) throws ArithmeticException { |
8c8bf09f | 176 | |
5179fc01 FC |
177 | long value = fValue; |
178 | int precision = fPrecision; | |
8c8bf09f | 179 | |
5179fc01 FC |
180 | // Handle the trivial case |
181 | if (fScale == scale && offset == 0) | |
182 | return new TmfTimestamp(this); | |
183 | ||
184 | // First, scale the timestamp | |
185 | if (fScale != scale) { | |
085d898f FC |
186 | final int scaleDiff = Math.abs(fScale - scale); |
187 | if (scaleDiff >= scalingFactors.length) | |
3b38ea61 | 188 | throw new ArithmeticException("Scaling exception"); //$NON-NLS-1$ |
5179fc01 | 189 | |
085d898f | 190 | final long scalingFactor = scalingFactors[scaleDiff]; |
5179fc01 FC |
191 | if (scale < fScale) { |
192 | value *= scalingFactor; | |
193 | precision *= scalingFactor; | |
8c8bf09f | 194 | } else { |
5179fc01 FC |
195 | value /= scalingFactor; |
196 | precision /= scalingFactor; | |
8c8bf09f ASL |
197 | } |
198 | } | |
199 | ||
5179fc01 | 200 | // Then, apply the offset |
085d898f | 201 | if (offset < 0) |
5179fc01 | 202 | value = (value < Long.MIN_VALUE - offset) ? Long.MIN_VALUE : value + offset; |
085d898f | 203 | else |
5179fc01 | 204 | value = (value > Long.MAX_VALUE - offset) ? Long.MAX_VALUE : value + offset; |
023761c4 | 205 | |
5179fc01 | 206 | return new TmfTimestamp(value, scale, precision); |
8c8bf09f ASL |
207 | } |
208 | ||
d7dbf09a FC |
209 | /* (non-Javadoc) |
210 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp, boolean) | |
211 | */ | |
212 | @Override | |
085d898f | 213 | public int compareTo(final ITmfTimestamp ts, final boolean withinPrecision) { |
023761c4 | 214 | |
5179fc01 FC |
215 | // Check the corner cases (we can't use equals() because it uses compareTo()...) |
216 | if (this == ts || (fValue == ts.getValue() && fScale == ts.getScale())) | |
217 | return 0; | |
a4115405 | 218 | if ((fValue == BIG_BANG.getValue() && fScale == BIG_BANG.getScale()) || (ts.getValue() == BIG_CRUNCH.getValue() && ts.getScale() == BIG_CRUNCH.getScale())) |
5179fc01 | 219 | return -1; |
a4115405 | 220 | if ((fValue == BIG_CRUNCH.getValue() && fScale == BIG_CRUNCH.getScale()) || (ts.getValue() == BIG_BANG.getValue() && ts.getScale() == BIG_BANG.getScale())) |
5179fc01 | 221 | return 1; |
085d898f | 222 | |
5179fc01 | 223 | try { |
085d898f FC |
224 | final ITmfTimestamp nts = ts.normalize(0, fScale); |
225 | final long delta = fValue - nts.getValue(); | |
226 | if ((delta == 0) || (withinPrecision && (Math.abs(delta) <= (fPrecision + nts.getPrecision())))) | |
5179fc01 | 227 | return 0; |
5179fc01 FC |
228 | return (delta > 0) ? 1 : -1; |
229 | } | |
085d898f | 230 | catch (final ArithmeticException e) { |
5179fc01 FC |
231 | // Scaling error. We can figure it out nonetheless. |
232 | ||
233 | // First, look at the sign of the mantissa | |
085d898f | 234 | final long value = ts.getValue(); |
5179fc01 FC |
235 | if (fValue == 0 && value == 0) |
236 | return 0; | |
237 | if (fValue < 0 && value >= 0) | |
238 | return -1; | |
f2dd0808 | 239 | if (fValue >= 0 && value < 0) |
5179fc01 FC |
240 | return 1; |
241 | ||
242 | // Otherwise, just compare the scales | |
085d898f FC |
243 | final int scale = ts.getScale(); |
244 | return (fScale > scale) ? (fValue >= 0) ? 1 : -1 : (fValue >= 0) ? -1 : 1; | |
5179fc01 | 245 | } |
8c8bf09f ASL |
246 | } |
247 | ||
d7dbf09a FC |
248 | /* (non-Javadoc) |
249 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getDelta(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp) | |
250 | */ | |
5179fc01 | 251 | @Override |
085d898f FC |
252 | public ITmfTimestamp getDelta(final ITmfTimestamp ts) { |
253 | final ITmfTimestamp nts = ts.normalize(0, fScale); | |
254 | final long value = fValue - nts.getValue(); | |
5179fc01 | 255 | return new TmfTimestamp(value, fScale, fPrecision + nts.getPrecision()); |
73005152 BH |
256 | } |
257 | ||
5179fc01 FC |
258 | // ------------------------------------------------------------------------ |
259 | // Cloneable | |
260 | // ------------------------------------------------------------------------ | |
261 | ||
d7dbf09a FC |
262 | /* (non-Javadoc) |
263 | * @see java.lang.Object#clone() | |
264 | */ | |
5179fc01 | 265 | @Override |
8c149234 | 266 | public TmfTimestamp clone() { |
5179fc01 FC |
267 | TmfTimestamp clone = null; |
268 | try { | |
269 | clone = (TmfTimestamp) super.clone(); | |
270 | clone.fValue = fValue; | |
271 | clone.fScale = fScale; | |
272 | clone.fPrecision = fPrecision; | |
085d898f | 273 | } catch (final CloneNotSupportedException e) { |
5179fc01 FC |
274 | } |
275 | return clone; | |
8c8bf09f ASL |
276 | } |
277 | ||
5179fc01 FC |
278 | // ------------------------------------------------------------------------ |
279 | // Comparable | |
280 | // ------------------------------------------------------------------------ | |
023761c4 | 281 | |
d7dbf09a FC |
282 | /* (non-Javadoc) |
283 | * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp) | |
284 | */ | |
5179fc01 | 285 | @Override |
085d898f | 286 | public int compareTo(final ITmfTimestamp ts) { |
4df4581d | 287 | return compareTo(ts, false); |
5179fc01 | 288 | } |
f3a4c7f4 | 289 | |
5179fc01 | 290 | // ------------------------------------------------------------------------ |
cbd4ad82 | 291 | // Object |
5179fc01 | 292 | // ------------------------------------------------------------------------ |
28b94d61 | 293 | |
d7dbf09a FC |
294 | /* (non-Javadoc) |
295 | * @see java.lang.Object#hashCode() | |
296 | */ | |
8c8bf09f | 297 | @Override |
cbd4ad82 | 298 | public int hashCode() { |
5179fc01 FC |
299 | final int prime = 31; |
300 | int result = 1; | |
301 | result = prime * result + (int) (fValue ^ (fValue >>> 32)); | |
302 | result = prime * result + fScale; | |
303 | result = prime * result + fPrecision; | |
cbd4ad82 FC |
304 | return result; |
305 | } | |
306 | ||
d7dbf09a FC |
307 | /* (non-Javadoc) |
308 | * @see java.lang.Object#equals(java.lang.Object) | |
309 | */ | |
5179fc01 | 310 | @Override |
085d898f | 311 | public boolean equals(final Object other) { |
5179fc01 FC |
312 | if (this == other) |
313 | return true; | |
314 | if (other == null) | |
315 | return false; | |
cbd4ad82 | 316 | if (!(other instanceof TmfTimestamp)) |
5179fc01 | 317 | return false; |
085d898f | 318 | final TmfTimestamp ts = (TmfTimestamp) other; |
5179fc01 | 319 | return compareTo(ts, false) == 0; |
8c8bf09f ASL |
320 | } |
321 | ||
d7dbf09a FC |
322 | /* (non-Javadoc) |
323 | * @see java.lang.Object#toString() | |
324 | */ | |
1f506a43 | 325 | @Override |
3b38ea61 | 326 | @SuppressWarnings("nls") |
1f506a43 | 327 | public String toString() { |
5179fc01 | 328 | return "TmfTimestamp [fValue=" + fValue + ", fScale=" + fScale + ", fPrecision=" + fPrecision + "]"; |
ff4ed569 FC |
329 | } |
330 | ||
023761c4 | 331 | } |