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