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