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