Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/sandbox/chromium/base/time/time.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#include "base/time/time.h"
6
7
#include <cmath>
8
#include <ios>
9
#include <limits>
10
#include <ostream>
11
#include <sstream>
12
13
#include "base/lazy_instance.h"
14
#include "base/logging.h"
15
#include "base/macros.h"
16
#include "base/strings/stringprintf.h"
17
#include "base/third_party/nspr/prtime.h"
18
#include "build/build_config.h"
19
20
namespace base {
21
22
// TimeDelta ------------------------------------------------------------------
23
24
0
int TimeDelta::InDays() const {
25
0
  if (is_max()) {
26
0
    // Preserve max to prevent overflow.
27
0
    return std::numeric_limits<int>::max();
28
0
  }
29
0
  return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
30
0
}
31
32
0
int TimeDelta::InHours() const {
33
0
  if (is_max()) {
34
0
    // Preserve max to prevent overflow.
35
0
    return std::numeric_limits<int>::max();
36
0
  }
37
0
  return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
38
0
}
39
40
0
int TimeDelta::InMinutes() const {
41
0
  if (is_max()) {
42
0
    // Preserve max to prevent overflow.
43
0
    return std::numeric_limits<int>::max();
44
0
  }
45
0
  return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
46
0
}
47
48
0
double TimeDelta::InSecondsF() const {
49
0
  if (is_max()) {
50
0
    // Preserve max to prevent overflow.
51
0
    return std::numeric_limits<double>::infinity();
52
0
  }
53
0
  return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
54
0
}
55
56
0
int64_t TimeDelta::InSeconds() const {
57
0
  if (is_max()) {
58
0
    // Preserve max to prevent overflow.
59
0
    return std::numeric_limits<int64_t>::max();
60
0
  }
61
0
  return delta_ / Time::kMicrosecondsPerSecond;
62
0
}
63
64
0
double TimeDelta::InMillisecondsF() const {
65
0
  if (is_max()) {
66
0
    // Preserve max to prevent overflow.
67
0
    return std::numeric_limits<double>::infinity();
68
0
  }
69
0
  return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
70
0
}
71
72
0
int64_t TimeDelta::InMilliseconds() const {
73
0
  if (is_max()) {
74
0
    // Preserve max to prevent overflow.
75
0
    return std::numeric_limits<int64_t>::max();
76
0
  }
77
0
  return delta_ / Time::kMicrosecondsPerMillisecond;
78
0
}
79
80
0
int64_t TimeDelta::InMillisecondsRoundedUp() const {
81
0
  if (is_max()) {
82
0
    // Preserve max to prevent overflow.
83
0
    return std::numeric_limits<int64_t>::max();
84
0
  }
85
0
  return (delta_ + Time::kMicrosecondsPerMillisecond - 1) /
86
0
      Time::kMicrosecondsPerMillisecond;
87
0
}
88
89
0
int64_t TimeDelta::InMicroseconds() const {
90
0
  if (is_max()) {
91
0
    // Preserve max to prevent overflow.
92
0
    return std::numeric_limits<int64_t>::max();
93
0
  }
94
0
  return delta_;
95
0
}
96
97
0
int64_t TimeDelta::InNanoseconds() const {
98
0
  if (is_max()) {
99
0
    // Preserve max to prevent overflow.
100
0
    return std::numeric_limits<int64_t>::max();
101
0
  }
102
0
  return delta_ * Time::kNanosecondsPerMicrosecond;
103
0
}
104
105
namespace time_internal {
106
107
0
int64_t SaturatedAdd(TimeDelta delta, int64_t value) {
108
0
  CheckedNumeric<int64_t> rv(delta.delta_);
109
0
  rv += value;
110
0
  if (rv.IsValid())
111
0
    return rv.ValueOrDie();
112
0
  // Positive RHS overflows. Negative RHS underflows.
113
0
  if (value < 0)
114
0
    return std::numeric_limits<int64_t>::min();
115
0
  return std::numeric_limits<int64_t>::max();
116
0
}
117
118
0
int64_t SaturatedSub(TimeDelta delta, int64_t value) {
119
0
  CheckedNumeric<int64_t> rv(delta.delta_);
120
0
  rv -= value;
121
0
  if (rv.IsValid())
122
0
    return rv.ValueOrDie();
123
0
  // Negative RHS overflows. Positive RHS underflows.
124
0
  if (value < 0)
125
0
    return std::numeric_limits<int64_t>::max();
126
0
  return std::numeric_limits<int64_t>::min();
127
0
}
128
129
}  // namespace time_internal
130
131
0
std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
132
0
  return os << time_delta.InSecondsF() << " s";
133
0
}
134
135
// Time -----------------------------------------------------------------------
136
137
// static
138
0
Time Time::FromTimeT(time_t tt) {
139
0
  if (tt == 0)
140
0
    return Time();  // Preserve 0 so we can tell it doesn't exist.
141
0
  if (tt == std::numeric_limits<time_t>::max())
142
0
    return Max();
143
0
  return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt);
144
0
}
145
146
0
time_t Time::ToTimeT() const {
147
0
  if (is_null())
148
0
    return 0;  // Preserve 0 so we can tell it doesn't exist.
149
0
  if (is_max()) {
150
0
    // Preserve max without offset to prevent overflow.
151
0
    return std::numeric_limits<time_t>::max();
152
0
  }
153
0
  if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) {
154
0
    DLOG(WARNING) << "Overflow when converting base::Time with internal " <<
155
0
                     "value " << us_ << " to time_t.";
156
0
    return std::numeric_limits<time_t>::max();
157
0
  }
158
0
  return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
159
0
}
160
161
// static
162
0
Time Time::FromDoubleT(double dt) {
163
0
  if (dt == 0 || std::isnan(dt))
164
0
    return Time();  // Preserve 0 so we can tell it doesn't exist.
165
0
  return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt);
166
0
}
167
168
0
double Time::ToDoubleT() const {
169
0
  if (is_null())
170
0
    return 0;  // Preserve 0 so we can tell it doesn't exist.
171
0
  if (is_max()) {
172
0
    // Preserve max without offset to prevent overflow.
173
0
    return std::numeric_limits<double>::infinity();
174
0
  }
175
0
  return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
176
0
          static_cast<double>(kMicrosecondsPerSecond));
177
0
}
178
179
#if defined(OS_POSIX)
180
// static
181
0
Time Time::FromTimeSpec(const timespec& ts) {
182
0
  return FromDoubleT(ts.tv_sec +
183
0
                     static_cast<double>(ts.tv_nsec) /
184
0
                         base::Time::kNanosecondsPerSecond);
185
0
}
186
#endif
187
188
// static
189
0
Time Time::FromJsTime(double ms_since_epoch) {
190
0
  // The epoch is a valid time, so this constructor doesn't interpret
191
0
  // 0 as the null time.
192
0
  return Time(kTimeTToMicrosecondsOffset) +
193
0
         TimeDelta::FromMillisecondsD(ms_since_epoch);
194
0
}
195
196
0
double Time::ToJsTime() const {
197
0
  if (is_null()) {
198
0
    // Preserve 0 so the invalid result doesn't depend on the platform.
199
0
    return 0;
200
0
  }
201
0
  if (is_max()) {
202
0
    // Preserve max without offset to prevent overflow.
203
0
    return std::numeric_limits<double>::infinity();
204
0
  }
205
0
  return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
206
0
          kMicrosecondsPerMillisecond);
207
0
}
208
209
0
Time Time::FromJavaTime(int64_t ms_since_epoch) {
210
0
  return base::Time::UnixEpoch() +
211
0
         base::TimeDelta::FromMilliseconds(ms_since_epoch);
212
0
}
213
214
0
int64_t Time::ToJavaTime() const {
215
0
  if (is_null()) {
216
0
    // Preserve 0 so the invalid result doesn't depend on the platform.
217
0
    return 0;
218
0
  }
219
0
  if (is_max()) {
220
0
    // Preserve max without offset to prevent overflow.
221
0
    return std::numeric_limits<int64_t>::max();
222
0
  }
223
0
  return ((us_ - kTimeTToMicrosecondsOffset) /
224
0
          kMicrosecondsPerMillisecond);
225
0
}
226
227
// static
228
0
Time Time::UnixEpoch() {
229
0
  Time time;
230
0
  time.us_ = kTimeTToMicrosecondsOffset;
231
0
  return time;
232
0
}
233
234
0
Time Time::LocalMidnight() const {
235
0
  Exploded exploded;
236
0
  LocalExplode(&exploded);
237
0
  exploded.hour = 0;
238
0
  exploded.minute = 0;
239
0
  exploded.second = 0;
240
0
  exploded.millisecond = 0;
241
0
  Time out_time;
242
0
  if (FromLocalExploded(exploded, &out_time))
243
0
    return out_time;
244
0
  // This function must not fail.
245
0
  NOTREACHED();
246
0
  return Time();
247
0
}
248
249
#if !defined(MOZ_SANDBOX)
250
// static
251
bool Time::FromStringInternal(const char* time_string,
252
                              bool is_local,
253
                              Time* parsed_time) {
254
  DCHECK((time_string != NULL) && (parsed_time != NULL));
255
256
  if (time_string[0] == '\0')
257
    return false;
258
259
  PRTime result_time = 0;
260
  PRStatus result = PR_ParseTimeString(time_string,
261
                                       is_local ? PR_FALSE : PR_TRUE,
262
                                       &result_time);
263
  if (PR_SUCCESS != result)
264
    return false;
265
266
  result_time += kTimeTToMicrosecondsOffset;
267
  *parsed_time = Time(result_time);
268
  return true;
269
}
270
#endif
271
272
// static
273
0
bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) {
274
0
  return lhs.year == rhs.year && lhs.month == rhs.month &&
275
0
         lhs.day_of_month == rhs.day_of_month && lhs.hour == rhs.hour &&
276
0
         lhs.minute == rhs.minute && lhs.second == rhs.second &&
277
0
         lhs.millisecond == rhs.millisecond;
278
0
}
279
280
0
std::ostream& operator<<(std::ostream& os, Time time) {
281
0
  Time::Exploded exploded;
282
0
  time.UTCExplode(&exploded);
283
0
  // Use StringPrintf because iostreams formatting is painful.
284
0
  return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC",
285
0
                            exploded.year,
286
0
                            exploded.month,
287
0
                            exploded.day_of_month,
288
0
                            exploded.hour,
289
0
                            exploded.minute,
290
0
                            exploded.second,
291
0
                            exploded.millisecond);
292
0
}
293
294
// Local helper class to hold the conversion from Time to TickTime at the
295
// time of the Unix epoch.
296
class UnixEpochSingleton {
297
 public:
298
  UnixEpochSingleton()
299
0
      : unix_epoch_(TimeTicks::Now() - (Time::Now() - Time::UnixEpoch())) {}
300
301
0
  TimeTicks unix_epoch() const { return unix_epoch_; }
302
303
 private:
304
  const TimeTicks unix_epoch_;
305
306
  DISALLOW_COPY_AND_ASSIGN(UnixEpochSingleton);
307
};
308
309
static LazyInstance<UnixEpochSingleton>::Leaky
310
    leaky_unix_epoch_singleton_instance = LAZY_INSTANCE_INITIALIZER;
311
312
// Static
313
0
TimeTicks TimeTicks::UnixEpoch() {
314
0
  return leaky_unix_epoch_singleton_instance.Get().unix_epoch();
315
0
}
316
317
TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
318
0
                                       TimeDelta tick_interval) const {
319
0
  // |interval_offset| is the offset from |this| to the next multiple of
320
0
  // |tick_interval| after |tick_phase|, possibly negative if in the past.
321
0
  TimeDelta interval_offset = (tick_phase - *this) % tick_interval;
322
0
  // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
323
0
  // Otherwise, if |tick_phase| was in the past, adjust forward to the next
324
0
  // tick after |this|.
325
0
  if (!interval_offset.is_zero() && tick_phase < *this)
326
0
    interval_offset += tick_interval;
327
0
  return *this + interval_offset;
328
0
}
329
330
0
std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
331
0
  // This function formats a TimeTicks object as "bogo-microseconds".
332
0
  // The origin and granularity of the count are platform-specific, and may very
333
0
  // from run to run. Although bogo-microseconds usually roughly correspond to
334
0
  // real microseconds, the only real guarantee is that the number never goes
335
0
  // down during a single run.
336
0
  const TimeDelta as_time_delta = time_ticks - TimeTicks();
337
0
  return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
338
0
}
339
340
0
std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
341
0
  const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
342
0
  return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
343
0
}
344
345
// Time::Exploded -------------------------------------------------------------
346
347
0
inline bool is_in_range(int value, int lo, int hi) {
348
0
  return lo <= value && value <= hi;
349
0
}
350
351
0
bool Time::Exploded::HasValidValues() const {
352
0
  return is_in_range(month, 1, 12) &&
353
0
         is_in_range(day_of_week, 0, 6) &&
354
0
         is_in_range(day_of_month, 1, 31) &&
355
0
         is_in_range(hour, 0, 23) &&
356
0
         is_in_range(minute, 0, 59) &&
357
0
         is_in_range(second, 0, 60) &&
358
0
         is_in_range(millisecond, 0, 999);
359
0
}
360
361
}  // namespace base