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