Initial Commit
This commit is contained in:
commit
c2e7548296
238 changed files with 65475 additions and 0 deletions
112
absl/time/BUILD.bazel
Normal file
112
absl/time/BUILD.bazel
Normal file
|
@ -0,0 +1,112 @@
|
|||
#
|
||||
# Copyright 2017 The Abseil Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
load(
|
||||
"//absl:copts.bzl",
|
||||
"ABSL_DEFAULT_COPTS",
|
||||
"ABSL_TEST_COPTS",
|
||||
)
|
||||
load(
|
||||
"//absl:test_dependencies.bzl",
|
||||
"GUNIT_MAIN_DEPS_SELECTOR",
|
||||
)
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
cc_library(
|
||||
name = "time",
|
||||
srcs = [
|
||||
"clock.cc",
|
||||
"duration.cc",
|
||||
"format.cc",
|
||||
"internal/get_current_time_ios.inc",
|
||||
"internal/get_current_time_posix.inc",
|
||||
"internal/get_current_time_windows.inc",
|
||||
"time.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"clock.h",
|
||||
"time.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
deps = [
|
||||
"//absl/base",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/numeric:int128",
|
||||
"@com_googlesource_code_cctz//:civil_time",
|
||||
"@com_googlesource_code_cctz//:time_zone",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "test_util",
|
||||
srcs = [
|
||||
"internal/test_util.cc",
|
||||
"internal/zoneinfo.inc",
|
||||
],
|
||||
hdrs = ["internal/test_util.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
deps = [
|
||||
":time",
|
||||
"//absl/base",
|
||||
"@com_googlesource_code_cctz//:time_zone",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "time_test",
|
||||
srcs = [
|
||||
"clock_test.cc",
|
||||
"duration_test.cc",
|
||||
"format_test.cc",
|
||||
"time_norm_test.cc",
|
||||
"time_test.cc",
|
||||
"time_zone_test.cc",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
tags = [
|
||||
"no_test_android_arm",
|
||||
"no_test_android_arm64",
|
||||
"no_test_android_x86",
|
||||
"no_test_ios_x86_64",
|
||||
"no_test_loonix",
|
||||
"no_test_msvc_x64",
|
||||
],
|
||||
deps = [
|
||||
":test_util",
|
||||
":time",
|
||||
"//absl/base",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@com_googlesource_code_cctz//:time_zone",
|
||||
],
|
||||
)
|
||||
|
||||
# Used by get_current_time_test, which, due to a dependency on commandlineflags
|
||||
# and some required cleanup, is staying back in //base for now.
|
||||
cc_library(
|
||||
name = "get_current_time_for_test",
|
||||
testonly = 1,
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
textual_hdrs = [
|
||||
"clock.cc",
|
||||
"clock.h",
|
||||
],
|
||||
deps = ["//absl/base"],
|
||||
)
|
547
absl/time/clock.cc
Normal file
547
absl/time/clock.cc
Normal file
|
@ -0,0 +1,547 @@
|
|||
#include "absl/time/clock.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cerrno>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <limits>
|
||||
|
||||
#include "absl/base/internal/spinlock.h"
|
||||
#include "absl/base/internal/unscaledcycleclock.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/base/port.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
|
||||
namespace absl {
|
||||
Time Now() {
|
||||
// TODO(bww): Get a timespec instead so we don't have to divide.
|
||||
int64_t n = absl::GetCurrentTimeNanos();
|
||||
if (n >= 0) {
|
||||
return time_internal::FromUnixDuration(
|
||||
time_internal::MakeDuration(n / 1000000000, n % 1000000000 * 4));
|
||||
}
|
||||
return time_internal::FromUnixDuration(absl::Nanoseconds(n));
|
||||
}
|
||||
} // namespace absl
|
||||
|
||||
// Decide if we should use the fast GetCurrentTimeNanos() algorithm
|
||||
// based on the cyclecounter, otherwise just get the time directly
|
||||
// from the OS on every call. This can be chosen at compile-time via
|
||||
// -DABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS=[0|1]
|
||||
#ifndef ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
|
||||
#if ABSL_USE_UNSCALED_CYCLECLOCK
|
||||
#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 1
|
||||
#else
|
||||
#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "absl/time/internal/get_current_time_ios.inc"
|
||||
#elif defined(_WIN32)
|
||||
#include "absl/time/internal/get_current_time_windows.inc"
|
||||
#else
|
||||
#include "absl/time/internal/get_current_time_posix.inc"
|
||||
#endif
|
||||
|
||||
// Allows override by test.
|
||||
#ifndef GET_CURRENT_TIME_NANOS_FROM_SYSTEM
|
||||
#define GET_CURRENT_TIME_NANOS_FROM_SYSTEM() \
|
||||
::absl::time_internal::GetCurrentTimeNanosFromSystem()
|
||||
#endif
|
||||
|
||||
#if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
|
||||
namespace absl {
|
||||
int64_t GetCurrentTimeNanos() {
|
||||
return GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
|
||||
}
|
||||
} // namespace absl
|
||||
#else // Use the cyclecounter-based implementation below.
|
||||
|
||||
// Allows override by test.
|
||||
#ifndef GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW
|
||||
#define GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW() \
|
||||
::absl::time_internal::UnscaledCycleClockWrapperForGetCurrentTime::Now()
|
||||
#endif
|
||||
|
||||
// The following counters are used only by the test code.
|
||||
static int64_t stats_initializations;
|
||||
static int64_t stats_reinitializations;
|
||||
static int64_t stats_calibrations;
|
||||
static int64_t stats_slow_paths;
|
||||
static int64_t stats_fast_slow_paths;
|
||||
|
||||
namespace absl {
|
||||
namespace time_internal {
|
||||
// This is a friend wrapper around UnscaledCycleClock::Now()
|
||||
// (needed to access UnscaledCycleClock).
|
||||
class UnscaledCycleClockWrapperForGetCurrentTime {
|
||||
public:
|
||||
static int64_t Now() { return base_internal::UnscaledCycleClock::Now(); }
|
||||
};
|
||||
} // namespace time_internal
|
||||
|
||||
// uint64_t is used in this module to provide an extra bit in multiplications
|
||||
|
||||
// Return the time in ns as told by the kernel interface. Place in *cycleclock
|
||||
// the value of the cycleclock at about the time of the syscall.
|
||||
// This call represents the time base that this module synchronizes to.
|
||||
// Ensures that *cycleclock does not step back by up to (1 << 16) from
|
||||
// last_cycleclock, to discard small backward counter steps. (Larger steps are
|
||||
// assumed to be complete resyncs, which shouldn't happen. If they do, a full
|
||||
// reinitialization of the outer algorithm should occur.)
|
||||
static int64_t GetCurrentTimeNanosFromKernel(uint64_t last_cycleclock,
|
||||
uint64_t *cycleclock) {
|
||||
// We try to read clock values at about the same time as the kernel clock.
|
||||
// This value gets adjusted up or down as estimate of how long that should
|
||||
// take, so we can reject attempts that take unusually long.
|
||||
static std::atomic<uint64_t> approx_syscall_time_in_cycles{10 * 1000};
|
||||
|
||||
uint64_t local_approx_syscall_time_in_cycles = // local copy
|
||||
approx_syscall_time_in_cycles.load(std::memory_order_relaxed);
|
||||
|
||||
int64_t current_time_nanos_from_system;
|
||||
uint64_t before_cycles;
|
||||
uint64_t after_cycles;
|
||||
uint64_t elapsed_cycles;
|
||||
int loops = 0;
|
||||
do {
|
||||
before_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
|
||||
current_time_nanos_from_system = GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
|
||||
after_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
|
||||
// elapsed_cycles is unsigned, so is large on overflow
|
||||
elapsed_cycles = after_cycles - before_cycles;
|
||||
if (elapsed_cycles >= local_approx_syscall_time_in_cycles &&
|
||||
++loops == 20) { // clock changed frequencies? Back off.
|
||||
loops = 0;
|
||||
if (local_approx_syscall_time_in_cycles < 1000 * 1000) {
|
||||
local_approx_syscall_time_in_cycles =
|
||||
(local_approx_syscall_time_in_cycles + 1) << 1;
|
||||
}
|
||||
approx_syscall_time_in_cycles.store(
|
||||
local_approx_syscall_time_in_cycles,
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
} while (elapsed_cycles >= local_approx_syscall_time_in_cycles ||
|
||||
last_cycleclock - after_cycles < (static_cast<uint64_t>(1) << 16));
|
||||
|
||||
// Number of times in a row we've seen a kernel time call take substantially
|
||||
// less than approx_syscall_time_in_cycles.
|
||||
static std::atomic<uint32_t> seen_smaller{ 0 };
|
||||
|
||||
// Adjust approx_syscall_time_in_cycles to be within a factor of 2
|
||||
// of the typical time to execute one iteration of the loop above.
|
||||
if ((local_approx_syscall_time_in_cycles >> 1) < elapsed_cycles) {
|
||||
// measured time is no smaller than half current approximation
|
||||
seen_smaller.store(0, std::memory_order_relaxed);
|
||||
} else if (seen_smaller.fetch_add(1, std::memory_order_relaxed) >= 3) {
|
||||
// smaller delays several times in a row; reduce approximation by 12.5%
|
||||
const uint64_t new_approximation =
|
||||
local_approx_syscall_time_in_cycles -
|
||||
(local_approx_syscall_time_in_cycles >> 3);
|
||||
approx_syscall_time_in_cycles.store(new_approximation,
|
||||
std::memory_order_relaxed);
|
||||
seen_smaller.store(0, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
*cycleclock = after_cycles;
|
||||
return current_time_nanos_from_system;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// An implementation of reader-write locks that use no atomic ops in the read
|
||||
// case. This is a generalization of Lamport's method for reading a multiword
|
||||
// clock. Increment a word on each write acquisition, using the low-order bit
|
||||
// as a spinlock; the word is the high word of the "clock". Readers read the
|
||||
// high word, then all other data, then the high word again, and repeat the
|
||||
// read if the reads of the high words yields different answers, or an odd
|
||||
// value (either case suggests possible interference from a writer).
|
||||
// Here we use a spinlock to ensure only one writer at a time, rather than
|
||||
// spinning on the bottom bit of the word to benefit from SpinLock
|
||||
// spin-delay tuning.
|
||||
|
||||
// Acquire seqlock (*seq) and return the value to be written to unlock.
|
||||
static inline uint64_t SeqAcquire(std::atomic<uint64_t> *seq) {
|
||||
uint64_t x = seq->fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
// We put a release fence between update to *seq and writes to shared data.
|
||||
// Thus all stores to shared data are effectively release operations and
|
||||
// update to *seq above cannot be re-ordered past any of them. Note that
|
||||
// this barrier is not for the fetch_add above. A release barrier for the
|
||||
// fetch_add would be before it, not after.
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
|
||||
return x + 2; // original word plus 2
|
||||
}
|
||||
|
||||
// Release seqlock (*seq) by writing x to it---a value previously returned by
|
||||
// SeqAcquire.
|
||||
static inline void SeqRelease(std::atomic<uint64_t> *seq, uint64_t x) {
|
||||
// The unlock store to *seq must have release ordering so that all
|
||||
// updates to shared data must finish before this store.
|
||||
seq->store(x, std::memory_order_release); // release lock for readers
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// "nsscaled" is unit of time equal to a (2**kScale)th of a nanosecond.
|
||||
enum { kScale = 30 };
|
||||
|
||||
// The minimum interval between samples of the time base.
|
||||
// We pick enough time to amortize the cost of the sample,
|
||||
// to get a reasonably accurate cycle counter rate reading,
|
||||
// and not so much that calculations will overflow 64-bits.
|
||||
static const uint64_t kMinNSBetweenSamples = 2000 << 20;
|
||||
|
||||
// We require that kMinNSBetweenSamples shifted by kScale
|
||||
// have at least a bit left over for 64-bit calculations.
|
||||
static_assert(((kMinNSBetweenSamples << (kScale + 1)) >> (kScale + 1)) ==
|
||||
kMinNSBetweenSamples,
|
||||
"cannot represent kMaxBetweenSamplesNSScaled");
|
||||
|
||||
// A reader-writer lock protecting the static locations below.
|
||||
// See SeqAcquire() and SeqRelease() above.
|
||||
static absl::base_internal::SpinLock lock(
|
||||
absl::base_internal::kLinkerInitialized);
|
||||
static std::atomic<uint64_t> seq(0);
|
||||
|
||||
// data from a sample of the kernel's time value
|
||||
struct TimeSampleAtomic {
|
||||
std::atomic<uint64_t> raw_ns; // raw kernel time
|
||||
std::atomic<uint64_t> base_ns; // our estimate of time
|
||||
std::atomic<uint64_t> base_cycles; // cycle counter reading
|
||||
std::atomic<uint64_t> nsscaled_per_cycle; // cycle period
|
||||
// cycles before we'll sample again (a scaled reciprocal of the period,
|
||||
// to avoid a division on the fast path).
|
||||
std::atomic<uint64_t> min_cycles_per_sample;
|
||||
};
|
||||
// Same again, but with non-atomic types
|
||||
struct TimeSample {
|
||||
uint64_t raw_ns; // raw kernel time
|
||||
uint64_t base_ns; // our estimate of time
|
||||
uint64_t base_cycles; // cycle counter reading
|
||||
uint64_t nsscaled_per_cycle; // cycle period
|
||||
uint64_t min_cycles_per_sample; // approx cycles before next sample
|
||||
};
|
||||
|
||||
static struct TimeSampleAtomic last_sample; // the last sample; under seq
|
||||
|
||||
static int64_t GetCurrentTimeNanosSlowPath() ABSL_ATTRIBUTE_COLD;
|
||||
|
||||
// Read the contents of *atomic into *sample.
|
||||
// Each field is read atomically, but to maintain atomicity between fields,
|
||||
// the access must be done under a lock.
|
||||
static void ReadTimeSampleAtomic(const struct TimeSampleAtomic *atomic,
|
||||
struct TimeSample *sample) {
|
||||
sample->base_ns = atomic->base_ns.load(std::memory_order_relaxed);
|
||||
sample->base_cycles = atomic->base_cycles.load(std::memory_order_relaxed);
|
||||
sample->nsscaled_per_cycle =
|
||||
atomic->nsscaled_per_cycle.load(std::memory_order_relaxed);
|
||||
sample->min_cycles_per_sample =
|
||||
atomic->min_cycles_per_sample.load(std::memory_order_relaxed);
|
||||
sample->raw_ns = atomic->raw_ns.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Public routine.
|
||||
// Algorithm: We wish to compute real time from a cycle counter. In normal
|
||||
// operation, we construct a piecewise linear approximation to the kernel time
|
||||
// source, using the cycle counter value. The start of each line segment is at
|
||||
// the same point as the end of the last, but may have a different slope (that
|
||||
// is, a different idea of the cycle counter frequency). Every couple of
|
||||
// seconds, the kernel time source is sampled and compared with the current
|
||||
// approximation. A new slope is chosen that, if followed for another couple
|
||||
// of seconds, will correct the error at the current position. The information
|
||||
// for a sample is in the "last_sample" struct. The linear approximation is
|
||||
// estimated_time = last_sample.base_ns +
|
||||
// last_sample.ns_per_cycle * (counter_reading - last_sample.base_cycles)
|
||||
// (ns_per_cycle is actually stored in different units and scaled, to avoid
|
||||
// overflow). The base_ns of the next linear approximation is the
|
||||
// estimated_time using the last approximation; the base_cycles is the cycle
|
||||
// counter value at that time; the ns_per_cycle is the number of ns per cycle
|
||||
// measured since the last sample, but adjusted so that most of the difference
|
||||
// between the estimated_time and the kernel time will be corrected by the
|
||||
// estimated time to the next sample. In normal operation, this algorithm
|
||||
// relies on:
|
||||
// - the cycle counter and kernel time rates not changing a lot in a few
|
||||
// seconds.
|
||||
// - the client calling into the code often compared to a couple of seconds, so
|
||||
// the time to the next correction can be estimated.
|
||||
// Any time ns_per_cycle is not known, a major error is detected, or the
|
||||
// assumption about frequent calls is violated, the implementation returns the
|
||||
// kernel time. It records sufficient data that a linear approximation can
|
||||
// resume a little later.
|
||||
|
||||
int64_t GetCurrentTimeNanos() {
|
||||
// read the data from the "last_sample" struct (but don't need raw_ns yet)
|
||||
// The reads of "seq" and test of the values emulate a reader lock.
|
||||
uint64_t base_ns;
|
||||
uint64_t base_cycles;
|
||||
uint64_t nsscaled_per_cycle;
|
||||
uint64_t min_cycles_per_sample;
|
||||
uint64_t seq_read0;
|
||||
uint64_t seq_read1;
|
||||
|
||||
// If we have enough information to interpolate, the value returned will be
|
||||
// derived from this cycleclock-derived time estimate. On some platforms
|
||||
// (POWER) the function to retrieve this value has enough complexity to
|
||||
// contribute to register pressure - reading it early before initializing
|
||||
// the other pieces of the calculation minimizes spill/restore instructions,
|
||||
// minimizing icache cost.
|
||||
uint64_t now_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
|
||||
|
||||
// Acquire pairs with the barrier in SeqRelease - if this load sees that
|
||||
// store, the shared-data reads necessarily see that SeqRelease's updates
|
||||
// to the same shared data.
|
||||
seq_read0 = seq.load(std::memory_order_acquire);
|
||||
|
||||
base_ns = last_sample.base_ns.load(std::memory_order_relaxed);
|
||||
base_cycles = last_sample.base_cycles.load(std::memory_order_relaxed);
|
||||
nsscaled_per_cycle =
|
||||
last_sample.nsscaled_per_cycle.load(std::memory_order_relaxed);
|
||||
min_cycles_per_sample =
|
||||
last_sample.min_cycles_per_sample.load(std::memory_order_relaxed);
|
||||
|
||||
// This acquire fence pairs with the release fence in SeqAcquire. Since it
|
||||
// is sequenced between reads of shared data and seq_read1, the reads of
|
||||
// shared data are effectively acquiring.
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
|
||||
// The shared-data reads are effectively acquire ordered, and the
|
||||
// shared-data writes are effectively release ordered. Therefore if our
|
||||
// shared-data reads see any of a particular update's shared-data writes,
|
||||
// seq_read1 is guaranteed to see that update's SeqAcquire.
|
||||
seq_read1 = seq.load(std::memory_order_relaxed);
|
||||
|
||||
// Fast path. Return if min_cycles_per_sample has not yet elapsed since the
|
||||
// last sample, and we read a consistent sample. The fast path activates
|
||||
// only when min_cycles_per_sample is non-zero, which happens when we get an
|
||||
// estimate for the cycle time. The predicate will fail if now_cycles <
|
||||
// base_cycles, or if some other thread is in the slow path.
|
||||
//
|
||||
// Since we now read now_cycles before base_ns, it is possible for now_cycles
|
||||
// to be less than base_cycles (if we were interrupted between those loads and
|
||||
// last_sample was updated). This is harmless, because delta_cycles will wrap
|
||||
// and report a time much much bigger than min_cycles_per_sample. In that case
|
||||
// we will take the slow path.
|
||||
uint64_t delta_cycles = now_cycles - base_cycles;
|
||||
if (seq_read0 == seq_read1 && (seq_read0 & 1) == 0 &&
|
||||
delta_cycles < min_cycles_per_sample) {
|
||||
return base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale);
|
||||
}
|
||||
return GetCurrentTimeNanosSlowPath();
|
||||
}
|
||||
|
||||
// Return (a << kScale)/b.
|
||||
// Zero is returned if b==0. Scaling is performed internally to
|
||||
// preserve precision without overflow.
|
||||
static uint64_t SafeDivideAndScale(uint64_t a, uint64_t b) {
|
||||
// Find maximum safe_shift so that
|
||||
// 0 <= safe_shift <= kScale and (a << safe_shift) does not overflow.
|
||||
int safe_shift = kScale;
|
||||
while (((a << safe_shift) >> safe_shift) != a) {
|
||||
safe_shift--;
|
||||
}
|
||||
uint64_t scaled_b = b >> (kScale - safe_shift);
|
||||
uint64_t quotient = 0;
|
||||
if (scaled_b != 0) {
|
||||
quotient = (a << safe_shift) / scaled_b;
|
||||
}
|
||||
return quotient;
|
||||
}
|
||||
|
||||
static uint64_t UpdateLastSample(
|
||||
uint64_t now_cycles, uint64_t now_ns, uint64_t delta_cycles,
|
||||
const struct TimeSample *sample) ABSL_ATTRIBUTE_COLD;
|
||||
|
||||
// The slow path of GetCurrentTimeNanos(). This is taken while gathering
|
||||
// initial samples, when enough time has elapsed since the last sample, and if
|
||||
// any other thread is writing to last_sample.
|
||||
//
|
||||
// Manually mark this 'noinline' to minimize stack frame size of the fast
|
||||
// path. Without this, sometimes a compiler may inline this big block of code
|
||||
// into the fast past. That causes lots of register spills and reloads that
|
||||
// are unnecessary unless the slow path is taken.
|
||||
//
|
||||
// TODO(b/36012148) Remove this attribute when our compiler is smart enough
|
||||
// to do the right thing.
|
||||
ABSL_ATTRIBUTE_NOINLINE
|
||||
static int64_t GetCurrentTimeNanosSlowPath() LOCKS_EXCLUDED(lock) {
|
||||
// Serialize access to slow-path. Fast-path readers are not blocked yet, and
|
||||
// code below must not modify last_sample until the seqlock is acquired.
|
||||
lock.Lock();
|
||||
|
||||
// Sample the kernel time base. This is the definition of
|
||||
// "now" if we take the slow path.
|
||||
static uint64_t last_now_cycles; // protected by lock
|
||||
uint64_t now_cycles;
|
||||
uint64_t now_ns = GetCurrentTimeNanosFromKernel(last_now_cycles, &now_cycles);
|
||||
last_now_cycles = now_cycles;
|
||||
|
||||
uint64_t estimated_base_ns;
|
||||
|
||||
// ----------
|
||||
// Read the "last_sample" values again; this time holding the write lock.
|
||||
struct TimeSample sample;
|
||||
ReadTimeSampleAtomic(&last_sample, &sample);
|
||||
|
||||
// ----------
|
||||
// Try running the fast path again; another thread may have updated the
|
||||
// sample between our run of the fast path and the sample we just read.
|
||||
uint64_t delta_cycles = now_cycles - sample.base_cycles;
|
||||
if (delta_cycles < sample.min_cycles_per_sample) {
|
||||
// Another thread updated the sample. This path does not take the seqlock
|
||||
// so that blocked readers can make progress without blocking new readers.
|
||||
estimated_base_ns = sample.base_ns +
|
||||
((delta_cycles * sample.nsscaled_per_cycle) >> kScale);
|
||||
stats_fast_slow_paths++;
|
||||
} else {
|
||||
estimated_base_ns =
|
||||
UpdateLastSample(now_cycles, now_ns, delta_cycles, &sample);
|
||||
}
|
||||
|
||||
lock.Unlock();
|
||||
|
||||
return estimated_base_ns;
|
||||
}
|
||||
|
||||
// Main part of the algorithm. Locks out readers, updates the approximation
|
||||
// using the new sample from the kernel, and stores the result in last_sample
|
||||
// for readers. Returns the new estimated time.
|
||||
static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,
|
||||
uint64_t delta_cycles,
|
||||
const struct TimeSample *sample)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(lock) {
|
||||
uint64_t estimated_base_ns = now_ns;
|
||||
uint64_t lock_value = SeqAcquire(&seq); // acquire seqlock to block readers
|
||||
|
||||
// The 5s in the next if-statement limits the time for which we will trust
|
||||
// the cycle counter and our last sample to give a reasonable result.
|
||||
// Errors in the rate of the source clock can be multiplied by the ratio
|
||||
// between this limit and kMinNSBetweenSamples.
|
||||
if (sample->raw_ns == 0 || // no recent sample, or clock went backwards
|
||||
sample->raw_ns + static_cast<uint64_t>(5) * 1000 * 1000 * 1000 < now_ns ||
|
||||
now_ns < sample->raw_ns || now_cycles < sample->base_cycles) {
|
||||
// record this sample, and forget any previously known slope.
|
||||
last_sample.raw_ns.store(now_ns, std::memory_order_relaxed);
|
||||
last_sample.base_ns.store(estimated_base_ns, std::memory_order_relaxed);
|
||||
last_sample.base_cycles.store(now_cycles, std::memory_order_relaxed);
|
||||
last_sample.nsscaled_per_cycle.store(0, std::memory_order_relaxed);
|
||||
last_sample.min_cycles_per_sample.store(0, std::memory_order_relaxed);
|
||||
stats_initializations++;
|
||||
} else if (sample->raw_ns + 500 * 1000 * 1000 < now_ns &&
|
||||
sample->base_cycles + 100 < now_cycles) {
|
||||
// Enough time has passed to compute the cycle time.
|
||||
if (sample->nsscaled_per_cycle != 0) { // Have a cycle time estimate.
|
||||
// Compute time from counter reading, but avoiding overflow
|
||||
// delta_cycles may be larger than on the fast path.
|
||||
uint64_t estimated_scaled_ns;
|
||||
int s = -1;
|
||||
do {
|
||||
s++;
|
||||
estimated_scaled_ns = (delta_cycles >> s) * sample->nsscaled_per_cycle;
|
||||
} while (estimated_scaled_ns / sample->nsscaled_per_cycle !=
|
||||
(delta_cycles >> s));
|
||||
estimated_base_ns = sample->base_ns +
|
||||
(estimated_scaled_ns >> (kScale - s));
|
||||
}
|
||||
|
||||
// Compute the assumed cycle time kMinNSBetweenSamples ns into the future
|
||||
// assuming the cycle counter rate stays the same as the last interval.
|
||||
uint64_t ns = now_ns - sample->raw_ns;
|
||||
uint64_t measured_nsscaled_per_cycle = SafeDivideAndScale(ns, delta_cycles);
|
||||
|
||||
uint64_t assumed_next_sample_delta_cycles =
|
||||
SafeDivideAndScale(kMinNSBetweenSamples, measured_nsscaled_per_cycle);
|
||||
|
||||
int64_t diff_ns = now_ns - estimated_base_ns; // estimate low by this much
|
||||
|
||||
// We want to set nsscaled_per_cycle so that our estimate of the ns time
|
||||
// at the assumed cycle time is the assumed ns time.
|
||||
// That is, we want to set nsscaled_per_cycle so:
|
||||
// kMinNSBetweenSamples + diff_ns ==
|
||||
// (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale
|
||||
// But we wish to damp oscillations, so instead correct only most
|
||||
// of our current error, by solving:
|
||||
// kMinNSBetweenSamples + diff_ns - (diff_ns / 16) ==
|
||||
// (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale
|
||||
ns = kMinNSBetweenSamples + diff_ns - (diff_ns / 16);
|
||||
uint64_t new_nsscaled_per_cycle =
|
||||
SafeDivideAndScale(ns, assumed_next_sample_delta_cycles);
|
||||
if (new_nsscaled_per_cycle != 0 &&
|
||||
diff_ns < 100 * 1000 * 1000 && -diff_ns < 100 * 1000 * 1000) {
|
||||
// record the cycle time measurement
|
||||
last_sample.nsscaled_per_cycle.store(
|
||||
new_nsscaled_per_cycle, std::memory_order_relaxed);
|
||||
uint64_t new_min_cycles_per_sample =
|
||||
SafeDivideAndScale(kMinNSBetweenSamples, new_nsscaled_per_cycle);
|
||||
last_sample.min_cycles_per_sample.store(
|
||||
new_min_cycles_per_sample, std::memory_order_relaxed);
|
||||
stats_calibrations++;
|
||||
} else { // something went wrong; forget the slope
|
||||
last_sample.nsscaled_per_cycle.store(0, std::memory_order_relaxed);
|
||||
last_sample.min_cycles_per_sample.store(0, std::memory_order_relaxed);
|
||||
estimated_base_ns = now_ns;
|
||||
stats_reinitializations++;
|
||||
}
|
||||
last_sample.raw_ns.store(now_ns, std::memory_order_relaxed);
|
||||
last_sample.base_ns.store(estimated_base_ns, std::memory_order_relaxed);
|
||||
last_sample.base_cycles.store(now_cycles, std::memory_order_relaxed);
|
||||
} else {
|
||||
// have a sample, but no slope; waiting for enough time for a calibration
|
||||
stats_slow_paths++;
|
||||
}
|
||||
|
||||
SeqRelease(&seq, lock_value); // release the readers
|
||||
|
||||
return estimated_base_ns;
|
||||
}
|
||||
} // namespace absl
|
||||
#endif // ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
|
||||
|
||||
namespace absl {
|
||||
namespace {
|
||||
|
||||
// Returns the maximum duration that SleepOnce() can sleep for.
|
||||
constexpr absl::Duration MaxSleep() {
|
||||
#ifdef _WIN32
|
||||
// Windows _sleep() takes unsigned long argument in milliseconds.
|
||||
return absl::Milliseconds(
|
||||
std::numeric_limits<unsigned long>::max()); // NOLINT(runtime/int)
|
||||
#else
|
||||
return absl::Seconds(std::numeric_limits<time_t>::max());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Sleeps for the given duration.
|
||||
// REQUIRES: to_sleep <= MaxSleep().
|
||||
void SleepOnce(absl::Duration to_sleep) {
|
||||
#ifdef _WIN32
|
||||
_sleep(to_sleep / absl::Milliseconds(1));
|
||||
#else
|
||||
struct timespec sleep_time = absl::ToTimespec(to_sleep);
|
||||
while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {
|
||||
// Ignore signals and wait for the full interval to elapse.
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace absl
|
||||
|
||||
extern "C" {
|
||||
|
||||
ABSL_ATTRIBUTE_WEAK void AbslInternalSleepFor(absl::Duration duration) {
|
||||
while (duration > absl::ZeroDuration()) {
|
||||
absl::Duration to_sleep = std::min(duration, absl::MaxSleep());
|
||||
absl::SleepOnce(to_sleep);
|
||||
duration -= to_sleep;
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
72
absl/time/clock.h
Normal file
72
absl/time/clock.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: clock.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file contains utility functions for working with the system-wide
|
||||
// realtime clock. For descriptions of the main time abstractions used within
|
||||
// this header file, consult the time.h header file.
|
||||
#ifndef ABSL_TIME_CLOCK_H_
|
||||
#define ABSL_TIME_CLOCK_H_
|
||||
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
namespace absl {
|
||||
|
||||
// Now()
|
||||
//
|
||||
// Returns the current time, expressed as an `absl::Time` absolute time value.
|
||||
absl::Time Now();
|
||||
|
||||
// GetCurrentTimeNanos()
|
||||
//
|
||||
// Returns the current time, expressed as a count of nanoseconds since the Unix
|
||||
// Epoch (https://en.wikipedia.org/wiki/Unix_time). Prefer `absl::Now()` instead
|
||||
// for all but the most performance-sensitive cases (i.e. when you are calling
|
||||
// this function hundreds of thousands of times per second).
|
||||
int64_t GetCurrentTimeNanos();
|
||||
|
||||
// SleepFor()
|
||||
//
|
||||
// Sleeps for the specified duration, expressed as an `absl::Duration`.
|
||||
//
|
||||
// Notes:
|
||||
// * Signal interruptions will not reduce the sleep duration.
|
||||
// * Returns immediately when passed a nonpositive duration.
|
||||
void SleepFor(absl::Duration duration);
|
||||
|
||||
} // namespace absl
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation Details
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// In some build configurations we pass --detect-odr-violations to the
|
||||
// gold linker. This causes it to flag weak symbol overrides as ODR
|
||||
// violations. Because ODR only applies to C++ and not C,
|
||||
// --detect-odr-violations ignores symbols not mangled with C++ names.
|
||||
// By changing our extension points to be extern "C", we dodge this
|
||||
// check.
|
||||
extern "C" {
|
||||
void AbslInternalSleepFor(absl::Duration duration);
|
||||
} // extern "C"
|
||||
|
||||
inline void absl::SleepFor(absl::Duration duration) {
|
||||
AbslInternalSleepFor(duration);
|
||||
}
|
||||
|
||||
#endif // ABSL_TIME_CLOCK_H_
|
70
absl/time/clock_test.cc
Normal file
70
absl/time/clock_test.cc
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/time/clock.h"
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#if defined(ABSL_HAVE_ALARM)
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
#error all known Linux and Apple targets have alarm
|
||||
#endif
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(Time, Now) {
|
||||
const absl::Time before = absl::FromUnixNanos(absl::GetCurrentTimeNanos());
|
||||
const absl::Time now = absl::Now();
|
||||
const absl::Time after = absl::FromUnixNanos(absl::GetCurrentTimeNanos());
|
||||
EXPECT_GE(now, before);
|
||||
EXPECT_GE(after, now);
|
||||
}
|
||||
|
||||
TEST(SleepForTest, BasicSanity) {
|
||||
absl::Duration sleep_time = absl::Milliseconds(2500);
|
||||
absl::Time start = absl::Now();
|
||||
absl::SleepFor(sleep_time);
|
||||
absl::Time end = absl::Now();
|
||||
EXPECT_LE(sleep_time - absl::Milliseconds(100), end - start);
|
||||
EXPECT_GE(sleep_time + absl::Milliseconds(100), end - start);
|
||||
}
|
||||
|
||||
#ifdef ABSL_HAVE_ALARM
|
||||
// Helper for test SleepFor.
|
||||
bool alarm_handler_invoked = false;
|
||||
void AlarmHandler(int signo) {
|
||||
ASSERT_EQ(signo, SIGALRM);
|
||||
alarm_handler_invoked = true;
|
||||
}
|
||||
|
||||
TEST(SleepForTest, AlarmSupport) {
|
||||
alarm_handler_invoked = false;
|
||||
sig_t old_alarm = signal(SIGALRM, AlarmHandler);
|
||||
alarm(2);
|
||||
absl::Duration sleep_time = absl::Milliseconds(3500);
|
||||
absl::Time start = absl::Now();
|
||||
absl::SleepFor(sleep_time);
|
||||
absl::Time end = absl::Now();
|
||||
EXPECT_TRUE(alarm_handler_invoked);
|
||||
EXPECT_LE(sleep_time - absl::Milliseconds(100), end - start);
|
||||
EXPECT_GE(sleep_time + absl::Milliseconds(100), end - start);
|
||||
signal(SIGALRM, old_alarm);
|
||||
}
|
||||
#endif // ABSL_HAVE_ALARM
|
||||
|
||||
} // namespace
|
864
absl/time/duration.cc
Normal file
864
absl/time/duration.cc
Normal file
|
@ -0,0 +1,864 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The implementation of the absl::Duration class, which is declared in
|
||||
// //absl/time.h. This class behaves like a numeric type; it has no public
|
||||
// methods and is used only through the operators defined here.
|
||||
//
|
||||
// Implementation notes:
|
||||
//
|
||||
// An absl::Duration is represented as
|
||||
//
|
||||
// rep_hi_ : (int64_t) Whole seconds
|
||||
// rep_lo_ : (uint32_t) Fractions of a second
|
||||
//
|
||||
// The seconds value (rep_hi_) may be positive or negative as appropriate.
|
||||
// The fractional seconds (rep_lo_) is always a positive offset from rep_hi_.
|
||||
// The API for Duration guarantees at least nanosecond resolution, which
|
||||
// means rep_lo_ could have a max value of 1B - 1 if it stored nanoseconds.
|
||||
// However, to utilize more of the available 32 bits of space in rep_lo_,
|
||||
// we instead store quarters of a nanosecond in rep_lo_ resulting in a max
|
||||
// value of 4B - 1. This allows us to correctly handle calculations like
|
||||
// 0.5 nanos + 0.5 nanos = 1 nano. The following example shows the actual
|
||||
// Duration rep using quarters of a nanosecond.
|
||||
//
|
||||
// 2.5 sec = {rep_hi_=2, rep_lo_=2000000000} // lo = 4 * 500000000
|
||||
// -2.5 sec = {rep_hi_=-3, rep_lo_=2000000000}
|
||||
//
|
||||
// Infinite durations are represented as Durations with the rep_lo_ field set
|
||||
// to all 1s.
|
||||
//
|
||||
// +InfiniteDuration:
|
||||
// rep_hi_ : kint64max
|
||||
// rep_lo_ : ~0U
|
||||
//
|
||||
// -InfiniteDuration:
|
||||
// rep_hi_ : kint64min
|
||||
// rep_lo_ : ~0U
|
||||
//
|
||||
// Arithmetic overflows/underflows to +/- infinity and saturates.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "absl/numeric/int128.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
namespace absl {
|
||||
|
||||
namespace {
|
||||
|
||||
using time_internal::kTicksPerNanosecond;
|
||||
using time_internal::kTicksPerSecond;
|
||||
|
||||
constexpr int64_t kint64max = std::numeric_limits<int64_t>::max();
|
||||
constexpr int64_t kint64min = std::numeric_limits<int64_t>::min();
|
||||
|
||||
// Can't use std::isinfinite() because it doesn't exist on windows.
|
||||
inline bool IsFinite(double d) {
|
||||
return d != std::numeric_limits<double>::infinity() &&
|
||||
d != -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
// Can't use std::round() because it is only available in C++11.
|
||||
// Note that we ignore the possibility of floating-point over/underflow.
|
||||
template <typename Double>
|
||||
inline double Round(Double d) {
|
||||
return d < 0 ? std::ceil(d - 0.5) : std::floor(d + 0.5);
|
||||
}
|
||||
|
||||
// *sec may be positive or negative. *ticks must be in the range
|
||||
// -kTicksPerSecond < *ticks < kTicksPerSecond. If *ticks is negative it
|
||||
// will be normalized to a positive value by adjusting *sec accordingly.
|
||||
inline void NormalizeTicks(int64_t* sec, int64_t* ticks) {
|
||||
if (*ticks < 0) {
|
||||
--*sec;
|
||||
*ticks += kTicksPerSecond;
|
||||
}
|
||||
}
|
||||
|
||||
// Makes a uint128 from the absolute value of the given scalar.
|
||||
inline uint128 MakeU128(int64_t a) {
|
||||
uint128 u128 = 0;
|
||||
if (a < 0) {
|
||||
++u128;
|
||||
++a; // Makes it safe to negate 'a'
|
||||
a = -a;
|
||||
}
|
||||
u128 += static_cast<uint64_t>(a);
|
||||
return u128;
|
||||
}
|
||||
|
||||
// Makes a uint128 count of ticks out of the absolute value of the Duration.
|
||||
inline uint128 MakeU128Ticks(Duration d) {
|
||||
int64_t rep_hi = time_internal::GetRepHi(d);
|
||||
uint32_t rep_lo = time_internal::GetRepLo(d);
|
||||
if (rep_hi < 0) {
|
||||
++rep_hi;
|
||||
rep_hi = -rep_hi;
|
||||
rep_lo = kTicksPerSecond - rep_lo;
|
||||
}
|
||||
uint128 u128 = static_cast<uint64_t>(rep_hi);
|
||||
u128 *= static_cast<uint64_t>(kTicksPerSecond);
|
||||
u128 += rep_lo;
|
||||
return u128;
|
||||
}
|
||||
|
||||
// Breaks a uint128 of ticks into a Duration.
|
||||
inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) {
|
||||
int64_t rep_hi;
|
||||
uint32_t rep_lo;
|
||||
const uint64_t h64 = Uint128High64(u128);
|
||||
const uint64_t l64 = Uint128Low64(u128);
|
||||
if (h64 == 0) { // fastpath
|
||||
const uint64_t hi = l64 / kTicksPerSecond;
|
||||
rep_hi = static_cast<int64_t>(hi);
|
||||
rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond);
|
||||
} else {
|
||||
// kMaxRepHi64 is the high 64 bits of (2^63 * kTicksPerSecond).
|
||||
// Any positive tick count whose high 64 bits are >= kMaxRepHi64
|
||||
// is not representable as a Duration. A negative tick count can
|
||||
// have its high 64 bits == kMaxRepHi64 but only when the low 64
|
||||
// bits are all zero, otherwise it is not representable either.
|
||||
const uint64_t kMaxRepHi64 = 0x77359400UL;
|
||||
if (h64 >= kMaxRepHi64) {
|
||||
if (is_neg && h64 == kMaxRepHi64 && l64 == 0) {
|
||||
// Avoid trying to represent -kint64min below.
|
||||
return time_internal::MakeDuration(kint64min);
|
||||
}
|
||||
return is_neg ? -InfiniteDuration() : InfiniteDuration();
|
||||
}
|
||||
const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond);
|
||||
const uint128 hi = u128 / kTicksPerSecond128;
|
||||
rep_hi = static_cast<int64_t>(Uint128Low64(hi));
|
||||
rep_lo =
|
||||
static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128));
|
||||
}
|
||||
if (is_neg) {
|
||||
rep_hi = -rep_hi;
|
||||
if (rep_lo != 0) {
|
||||
--rep_hi;
|
||||
rep_lo = kTicksPerSecond - rep_lo;
|
||||
}
|
||||
}
|
||||
return time_internal::MakeDuration(rep_hi, rep_lo);
|
||||
}
|
||||
|
||||
// Convert int64_t to uint64_t in twos-complement system.
|
||||
inline uint64_t EncodeTwosComp(int64_t v) { return static_cast<uint64_t>(v); }
|
||||
|
||||
// Convert uint64_t to int64_t in twos-complement system.
|
||||
inline int64_t DecodeTwosComp(uint64_t v) {
|
||||
if (v <= kint64max) return static_cast<int64_t>(v);
|
||||
return static_cast<int64_t>(v - kint64max - 1) + kint64min;
|
||||
}
|
||||
|
||||
// Note: The overflow detection in this function is done using greater/less *or
|
||||
// equal* because kint64max/min is too large to be represented exactly in a
|
||||
// double (which only has 53 bits of precision). In order to avoid assigning to
|
||||
// rep->hi a double value that is too large for an int64_t (and therefore is
|
||||
// undefined), we must consider computations that equal kint64max/min as a
|
||||
// double as overflow cases.
|
||||
inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) {
|
||||
double c = a_hi + b_hi;
|
||||
if (c >= kint64max) {
|
||||
*d = InfiniteDuration();
|
||||
return false;
|
||||
}
|
||||
if (c <= kint64min) {
|
||||
*d = -InfiniteDuration();
|
||||
return false;
|
||||
}
|
||||
*d = time_internal::MakeDuration(c, time_internal::GetRepLo(*d));
|
||||
return true;
|
||||
}
|
||||
|
||||
// A functor that's similar to std::multiplies<T>, except this returns the max
|
||||
// T value instead of overflowing. This is only defined for uint128.
|
||||
template <typename Ignored>
|
||||
struct SafeMultiply {
|
||||
uint128 operator()(uint128 a, uint128 b) const {
|
||||
// b hi is always zero because it originated as an int64_t.
|
||||
assert(Uint128High64(b) == 0);
|
||||
// Fastpath to avoid the expensive overflow check with division.
|
||||
if (Uint128High64(a) == 0) {
|
||||
return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0)
|
||||
? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b))
|
||||
: a * b;
|
||||
}
|
||||
return b == 0 ? b : (a > kuint128max / b) ? kuint128max : a * b;
|
||||
}
|
||||
};
|
||||
|
||||
// Scales (i.e., multiplies or divides, depending on the Operation template)
|
||||
// the Duration d by the int64_t r.
|
||||
template <template <typename> class Operation>
|
||||
inline Duration ScaleFixed(Duration d, int64_t r) {
|
||||
const uint128 a = MakeU128Ticks(d);
|
||||
const uint128 b = MakeU128(r);
|
||||
const uint128 q = Operation<uint128>()(a, b);
|
||||
const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0);
|
||||
return MakeDurationFromU128(q, is_neg);
|
||||
}
|
||||
|
||||
// Scales (i.e., multiplies or divides, depending on the Operation template)
|
||||
// the Duration d by the double r.
|
||||
template <template <typename> class Operation>
|
||||
inline Duration ScaleDouble(Duration d, double r) {
|
||||
Operation<double> op;
|
||||
double hi_doub = op(time_internal::GetRepHi(d), r);
|
||||
double lo_doub = op(time_internal::GetRepLo(d), r);
|
||||
|
||||
double hi_int = 0;
|
||||
double hi_frac = std::modf(hi_doub, &hi_int);
|
||||
|
||||
// Moves hi's fractional bits to lo.
|
||||
lo_doub /= kTicksPerSecond;
|
||||
lo_doub += hi_frac;
|
||||
|
||||
double lo_int = 0;
|
||||
double lo_frac = std::modf(lo_doub, &lo_int);
|
||||
|
||||
// Rolls lo into hi if necessary.
|
||||
int64_t lo64 = Round(lo_frac * kTicksPerSecond);
|
||||
|
||||
Duration ans;
|
||||
if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans;
|
||||
int64_t hi64 = time_internal::GetRepHi(ans);
|
||||
if (!SafeAddRepHi(hi64, lo64 / kTicksPerSecond, &ans)) return ans;
|
||||
hi64 = time_internal::GetRepHi(ans);
|
||||
lo64 %= kTicksPerSecond;
|
||||
NormalizeTicks(&hi64, &lo64);
|
||||
return time_internal::MakeDuration(hi64, lo64);
|
||||
}
|
||||
|
||||
// Tries to divide num by den as fast as possible by looking for common, easy
|
||||
// cases. If the division was done, the quotient is in *q and the remainder is
|
||||
// in *rem and true will be returned.
|
||||
inline bool IDivFastPath(const Duration num, const Duration den, int64_t* q,
|
||||
Duration* rem) {
|
||||
// Bail if num or den is an infinity.
|
||||
if (time_internal::IsInfiniteDuration(num) ||
|
||||
time_internal::IsInfiniteDuration(den))
|
||||
return false;
|
||||
|
||||
int64_t num_hi = time_internal::GetRepHi(num);
|
||||
uint32_t num_lo = time_internal::GetRepLo(num);
|
||||
int64_t den_hi = time_internal::GetRepHi(den);
|
||||
uint32_t den_lo = time_internal::GetRepLo(den);
|
||||
|
||||
if (den_hi == 0 && den_lo == kTicksPerNanosecond) {
|
||||
// Dividing by 1ns
|
||||
if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) {
|
||||
*q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond;
|
||||
*rem = time_internal::MakeDuration(0, num_lo % den_lo);
|
||||
return true;
|
||||
}
|
||||
} else if (den_hi == 0 && den_lo == 100 * kTicksPerNanosecond) {
|
||||
// Dividing by 100ns (common when converting to Universal time)
|
||||
if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) {
|
||||
*q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond);
|
||||
*rem = time_internal::MakeDuration(0, num_lo % den_lo);
|
||||
return true;
|
||||
}
|
||||
} else if (den_hi == 0 && den_lo == 1000 * kTicksPerNanosecond) {
|
||||
// Dividing by 1us
|
||||
if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) {
|
||||
*q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond);
|
||||
*rem = time_internal::MakeDuration(0, num_lo % den_lo);
|
||||
return true;
|
||||
}
|
||||
} else if (den_hi == 0 && den_lo == 1000000 * kTicksPerNanosecond) {
|
||||
// Dividing by 1ms
|
||||
if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) {
|
||||
*q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond);
|
||||
*rem = time_internal::MakeDuration(0, num_lo % den_lo);
|
||||
return true;
|
||||
}
|
||||
} else if (den_hi > 0 && den_lo == 0) {
|
||||
// Dividing by positive multiple of 1s
|
||||
if (num_hi >= 0) {
|
||||
if (den_hi == 1) {
|
||||
*q = num_hi;
|
||||
*rem = time_internal::MakeDuration(0, num_lo);
|
||||
return true;
|
||||
}
|
||||
*q = num_hi / den_hi;
|
||||
*rem = time_internal::MakeDuration(num_hi % den_hi, num_lo);
|
||||
return true;
|
||||
}
|
||||
if (num_lo != 0) {
|
||||
num_hi += 1;
|
||||
}
|
||||
int64_t quotient = num_hi / den_hi;
|
||||
int64_t rem_sec = num_hi % den_hi;
|
||||
if (rem_sec > 0) {
|
||||
rem_sec -= den_hi;
|
||||
quotient += 1;
|
||||
}
|
||||
if (num_lo != 0) {
|
||||
rem_sec -= 1;
|
||||
}
|
||||
*q = quotient;
|
||||
*rem = time_internal::MakeDuration(rem_sec, num_lo);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace time_internal {
|
||||
|
||||
// The 'satq' argument indicates whether the quotient should saturate at the
|
||||
// bounds of int64_t. If it does saturate, the difference will spill over to
|
||||
// the remainder. If it does not saturate, the remainder remain accurate,
|
||||
// but the returned quotient will over/underflow int64_t and should not be used.
|
||||
int64_t IDivDuration(bool satq, const Duration num, const Duration den,
|
||||
Duration* rem) {
|
||||
int64_t q = 0;
|
||||
if (IDivFastPath(num, den, &q, rem)) {
|
||||
return q;
|
||||
}
|
||||
|
||||
const bool num_neg = num < ZeroDuration();
|
||||
const bool den_neg = den < ZeroDuration();
|
||||
const bool quotient_neg = num_neg != den_neg;
|
||||
|
||||
if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) {
|
||||
*rem = num_neg ? -InfiniteDuration() : InfiniteDuration();
|
||||
return quotient_neg ? kint64min : kint64max;
|
||||
}
|
||||
if (time_internal::IsInfiniteDuration(den)) {
|
||||
*rem = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint128 a = MakeU128Ticks(num);
|
||||
const uint128 b = MakeU128Ticks(den);
|
||||
uint128 quotient128 = a / b;
|
||||
|
||||
if (satq) {
|
||||
// Limits the quotient to the range of int64_t.
|
||||
if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) {
|
||||
quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min))
|
||||
: uint128(static_cast<uint64_t>(kint64max));
|
||||
}
|
||||
}
|
||||
|
||||
const uint128 remainder128 = a - quotient128 * b;
|
||||
*rem = MakeDurationFromU128(remainder128, num_neg);
|
||||
|
||||
if (!quotient_neg || quotient128 == 0) {
|
||||
return Uint128Low64(quotient128) & kint64max;
|
||||
}
|
||||
// The quotient needs to be negated, but we need to carefully handle
|
||||
// quotient128s with the top bit on.
|
||||
return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1;
|
||||
}
|
||||
|
||||
} // namespace time_internal
|
||||
|
||||
//
|
||||
// Additive operators.
|
||||
//
|
||||
|
||||
Duration& Duration::operator+=(Duration rhs) {
|
||||
if (time_internal::IsInfiniteDuration(*this)) return *this;
|
||||
if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs;
|
||||
const int64_t orig_rep_hi = rep_hi_;
|
||||
rep_hi_ =
|
||||
DecodeTwosComp(EncodeTwosComp(rep_hi_) + EncodeTwosComp(rhs.rep_hi_));
|
||||
if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) {
|
||||
rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) + 1);
|
||||
rep_lo_ -= kTicksPerSecond;
|
||||
}
|
||||
rep_lo_ += rhs.rep_lo_;
|
||||
if (rhs.rep_hi_ < 0 ? rep_hi_ > orig_rep_hi : rep_hi_ < orig_rep_hi) {
|
||||
return *this = rhs.rep_hi_ < 0 ? -InfiniteDuration() : InfiniteDuration();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Duration& Duration::operator-=(Duration rhs) {
|
||||
if (time_internal::IsInfiniteDuration(*this)) return *this;
|
||||
if (time_internal::IsInfiniteDuration(rhs)) {
|
||||
return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration();
|
||||
}
|
||||
const int64_t orig_rep_hi = rep_hi_;
|
||||
rep_hi_ =
|
||||
DecodeTwosComp(EncodeTwosComp(rep_hi_) - EncodeTwosComp(rhs.rep_hi_));
|
||||
if (rep_lo_ < rhs.rep_lo_) {
|
||||
rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) - 1);
|
||||
rep_lo_ += kTicksPerSecond;
|
||||
}
|
||||
rep_lo_ -= rhs.rep_lo_;
|
||||
if (rhs.rep_hi_ < 0 ? rep_hi_ < orig_rep_hi : rep_hi_ > orig_rep_hi) {
|
||||
return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Multiplicative operators.
|
||||
//
|
||||
|
||||
Duration& Duration::operator*=(int64_t r) {
|
||||
if (time_internal::IsInfiniteDuration(*this)) {
|
||||
const bool is_neg = (r < 0) != (rep_hi_ < 0);
|
||||
return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
|
||||
}
|
||||
return *this = ScaleFixed<SafeMultiply>(*this, r);
|
||||
}
|
||||
|
||||
Duration& Duration::operator*=(double r) {
|
||||
if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) {
|
||||
const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
|
||||
return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
|
||||
}
|
||||
return *this = ScaleDouble<std::multiplies>(*this, r);
|
||||
}
|
||||
|
||||
Duration& Duration::operator/=(int64_t r) {
|
||||
if (time_internal::IsInfiniteDuration(*this) || r == 0) {
|
||||
const bool is_neg = (r < 0) != (rep_hi_ < 0);
|
||||
return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
|
||||
}
|
||||
return *this = ScaleFixed<std::divides>(*this, r);
|
||||
}
|
||||
|
||||
Duration& Duration::operator/=(double r) {
|
||||
if (time_internal::IsInfiniteDuration(*this) || r == 0.0) {
|
||||
const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
|
||||
return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
|
||||
}
|
||||
return *this = ScaleDouble<std::divides>(*this, r);
|
||||
}
|
||||
|
||||
Duration& Duration::operator%=(Duration rhs) {
|
||||
time_internal::IDivDuration(false, *this, rhs, this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
double FDivDuration(Duration num, Duration den) {
|
||||
// Arithmetic with infinity is sticky.
|
||||
if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) {
|
||||
return (num < ZeroDuration()) == (den < ZeroDuration())
|
||||
? std::numeric_limits<double>::infinity()
|
||||
: -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (time_internal::IsInfiniteDuration(den)) return 0.0;
|
||||
|
||||
double a =
|
||||
static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond +
|
||||
time_internal::GetRepLo(num);
|
||||
double b =
|
||||
static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond +
|
||||
time_internal::GetRepLo(den);
|
||||
return a / b;
|
||||
}
|
||||
|
||||
//
|
||||
// Trunc/Floor/Ceil.
|
||||
//
|
||||
|
||||
Duration Trunc(Duration d, Duration unit) {
|
||||
return d - (d % unit);
|
||||
}
|
||||
|
||||
Duration Floor(const Duration d, const Duration unit) {
|
||||
const absl::Duration td = Trunc(d, unit);
|
||||
return td <= d ? td : td - AbsDuration(unit);
|
||||
}
|
||||
|
||||
Duration Ceil(const Duration d, const Duration unit) {
|
||||
const absl::Duration td = Trunc(d, unit);
|
||||
return td >= d ? td : td + AbsDuration(unit);
|
||||
}
|
||||
|
||||
//
|
||||
// Factory functions.
|
||||
//
|
||||
|
||||
Duration DurationFromTimespec(timespec ts) {
|
||||
if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) {
|
||||
int64_t ticks = ts.tv_nsec * kTicksPerNanosecond;
|
||||
return time_internal::MakeDuration(ts.tv_sec, ticks);
|
||||
}
|
||||
return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec);
|
||||
}
|
||||
|
||||
Duration DurationFromTimeval(timeval tv) {
|
||||
if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) {
|
||||
int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond;
|
||||
return time_internal::MakeDuration(tv.tv_sec, ticks);
|
||||
}
|
||||
return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec);
|
||||
}
|
||||
|
||||
//
|
||||
// Conversion to other duration types.
|
||||
//
|
||||
|
||||
int64_t ToInt64Nanoseconds(Duration d) {
|
||||
if (time_internal::GetRepHi(d) >= 0 &&
|
||||
time_internal::GetRepHi(d) >> 33 == 0) {
|
||||
return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) +
|
||||
(time_internal::GetRepLo(d) / kTicksPerNanosecond);
|
||||
}
|
||||
return d / Nanoseconds(1);
|
||||
}
|
||||
int64_t ToInt64Microseconds(Duration d) {
|
||||
if (time_internal::GetRepHi(d) >= 0 &&
|
||||
time_internal::GetRepHi(d) >> 43 == 0) {
|
||||
return (time_internal::GetRepHi(d) * 1000 * 1000) +
|
||||
(time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000));
|
||||
}
|
||||
return d / Microseconds(1);
|
||||
}
|
||||
int64_t ToInt64Milliseconds(Duration d) {
|
||||
if (time_internal::GetRepHi(d) >= 0 &&
|
||||
time_internal::GetRepHi(d) >> 53 == 0) {
|
||||
return (time_internal::GetRepHi(d) * 1000) +
|
||||
(time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000));
|
||||
}
|
||||
return d / Milliseconds(1);
|
||||
}
|
||||
int64_t ToInt64Seconds(Duration d) {
|
||||
int64_t hi = time_internal::GetRepHi(d);
|
||||
if (time_internal::IsInfiniteDuration(d)) return hi;
|
||||
if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
|
||||
return hi;
|
||||
}
|
||||
int64_t ToInt64Minutes(Duration d) {
|
||||
int64_t hi = time_internal::GetRepHi(d);
|
||||
if (time_internal::IsInfiniteDuration(d)) return hi;
|
||||
if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
|
||||
return hi / 60;
|
||||
}
|
||||
int64_t ToInt64Hours(Duration d) {
|
||||
int64_t hi = time_internal::GetRepHi(d);
|
||||
if (time_internal::IsInfiniteDuration(d)) return hi;
|
||||
if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
|
||||
return hi / (60 * 60);
|
||||
}
|
||||
|
||||
double ToDoubleNanoseconds(Duration d) {
|
||||
return FDivDuration(d, Nanoseconds(1));
|
||||
}
|
||||
double ToDoubleMicroseconds(Duration d) {
|
||||
return FDivDuration(d, Microseconds(1));
|
||||
}
|
||||
double ToDoubleMilliseconds(Duration d) {
|
||||
return FDivDuration(d, Milliseconds(1));
|
||||
}
|
||||
double ToDoubleSeconds(Duration d) {
|
||||
return FDivDuration(d, Seconds(1));
|
||||
}
|
||||
double ToDoubleMinutes(Duration d) {
|
||||
return FDivDuration(d, Minutes(1));
|
||||
}
|
||||
double ToDoubleHours(Duration d) {
|
||||
return FDivDuration(d, Hours(1));
|
||||
}
|
||||
|
||||
timespec ToTimespec(Duration d) {
|
||||
timespec ts;
|
||||
if (!time_internal::IsInfiniteDuration(d)) {
|
||||
int64_t rep_hi = time_internal::GetRepHi(d);
|
||||
uint32_t rep_lo = time_internal::GetRepLo(d);
|
||||
if (rep_hi < 0) {
|
||||
// Tweak the fields so that unsigned division of rep_lo
|
||||
// maps to truncation (towards zero) for the timespec.
|
||||
rep_lo += kTicksPerNanosecond - 1;
|
||||
if (rep_lo >= kTicksPerSecond) {
|
||||
rep_hi += 1;
|
||||
rep_lo -= kTicksPerSecond;
|
||||
}
|
||||
}
|
||||
ts.tv_sec = rep_hi;
|
||||
if (ts.tv_sec == rep_hi) { // no time_t narrowing
|
||||
ts.tv_nsec = rep_lo / kTicksPerNanosecond;
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
if (d >= ZeroDuration()) {
|
||||
ts.tv_sec = std::numeric_limits<time_t>::max();
|
||||
ts.tv_nsec = 1000 * 1000 * 1000 - 1;
|
||||
} else {
|
||||
ts.tv_sec = std::numeric_limits<time_t>::min();
|
||||
ts.tv_nsec = 0;
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
|
||||
timeval ToTimeval(Duration d) {
|
||||
timeval tv;
|
||||
timespec ts = ToTimespec(d);
|
||||
if (ts.tv_sec < 0) {
|
||||
// Tweak the fields so that positive division of tv_nsec
|
||||
// maps to truncation (towards zero) for the timeval.
|
||||
ts.tv_nsec += 1000 - 1;
|
||||
if (ts.tv_nsec >= 1000 * 1000 * 1000) {
|
||||
ts.tv_sec += 1;
|
||||
ts.tv_nsec -= 1000 * 1000 * 1000;
|
||||
}
|
||||
}
|
||||
tv.tv_sec = ts.tv_sec;
|
||||
if (tv.tv_sec != ts.tv_sec) { // narrowing
|
||||
if (ts.tv_sec < 0) {
|
||||
tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
|
||||
tv.tv_usec = 0;
|
||||
} else {
|
||||
tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();
|
||||
tv.tv_usec = 1000 * 1000 - 1;
|
||||
}
|
||||
return tv;
|
||||
}
|
||||
tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t
|
||||
return tv;
|
||||
}
|
||||
|
||||
//
|
||||
// To/From std::string formatting.
|
||||
//
|
||||
|
||||
namespace {
|
||||
|
||||
// Formats a positive 64-bit integer in the given field width. Note that
|
||||
// it is up to the caller of Format64() to ensure that there is sufficient
|
||||
// space before ep to hold the conversion.
|
||||
char* Format64(char* ep, int width, int64_t v) {
|
||||
do {
|
||||
--width;
|
||||
*--ep = "0123456789"[v % 10];
|
||||
} while (v /= 10);
|
||||
while (--width >= 0) *--ep = '0'; // zero pad
|
||||
return ep;
|
||||
}
|
||||
|
||||
// Helpers for FormatDuration() that format 'n' and append it to 'out'
|
||||
// followed by the given 'unit'. If 'n' formats to "0", nothing is
|
||||
// appended (not even the unit).
|
||||
|
||||
// A type that encapsulates how to display a value of a particular unit. For
|
||||
// values that are displayed with fractional parts, the precision indicates
|
||||
// where to round the value. The precision varies with the display unit because
|
||||
// a Duration can hold only quarters of a nanosecond, so displaying information
|
||||
// beyond that is just noise.
|
||||
//
|
||||
// For example, a microsecond value of 42.00025xxxxx should not display beyond 5
|
||||
// fractional digits, because it is in the noise of what a Duration can
|
||||
// represent.
|
||||
struct DisplayUnit {
|
||||
const char* abbr;
|
||||
int prec;
|
||||
double pow10;
|
||||
};
|
||||
const DisplayUnit kDisplayNano = {"ns", 2, 1e2};
|
||||
const DisplayUnit kDisplayMicro = {"us", 5, 1e5};
|
||||
const DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
|
||||
const DisplayUnit kDisplaySec = {"s", 11, 1e11};
|
||||
const DisplayUnit kDisplayMin = {"m", -1, 0.0}; // prec ignored
|
||||
const DisplayUnit kDisplayHour = {"h", -1, 0.0}; // prec ignored
|
||||
|
||||
void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
|
||||
char buf[sizeof("2562047788015216")]; // hours in max duration
|
||||
char* const ep = buf + sizeof(buf);
|
||||
char* bp = Format64(ep, 0, n);
|
||||
if (*bp != '0' || bp + 1 != ep) {
|
||||
out->append(bp, ep - bp);
|
||||
out->append(unit.abbr);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: unit.prec is limited to double's digits10 value (typically 15) so it
|
||||
// always fits in buf[].
|
||||
void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
|
||||
const int buf_size = std::numeric_limits<double>::digits10;
|
||||
const int prec = std::min(buf_size, unit.prec);
|
||||
char buf[buf_size]; // also large enough to hold integer part
|
||||
char* ep = buf + sizeof(buf);
|
||||
double d = 0;
|
||||
int64_t frac_part = Round(std::modf(n, &d) * unit.pow10);
|
||||
int64_t int_part = d;
|
||||
if (int_part != 0 || frac_part != 0) {
|
||||
char* bp = Format64(ep, 0, int_part); // always < 1000
|
||||
out->append(bp, ep - bp);
|
||||
if (frac_part != 0) {
|
||||
out->push_back('.');
|
||||
bp = Format64(ep, prec, frac_part);
|
||||
while (ep[-1] == '0') --ep;
|
||||
out->append(bp, ep - bp);
|
||||
}
|
||||
out->append(unit.abbr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// From Go's doc at http://golang.org/pkg/time/#Duration.String
|
||||
// [FormatDuration] returns a std::string representing the duration in the
|
||||
// form "72h3m0.5s". Leading zero units are omitted. As a special
|
||||
// case, durations less than one second format use a smaller unit
|
||||
// (milli-, micro-, or nanoseconds) to ensure that the leading digit
|
||||
// is non-zero. The zero duration formats as 0, with no unit.
|
||||
std::string FormatDuration(Duration d) {
|
||||
const Duration min_duration = Seconds(kint64min);
|
||||
if (d == min_duration) {
|
||||
// Avoid needing to negate kint64min by directly returning what the
|
||||
// following code should produce in that case.
|
||||
return "-2562047788015215h30m8s";
|
||||
}
|
||||
std::string s;
|
||||
if (d < ZeroDuration()) {
|
||||
s.append("-");
|
||||
d = -d;
|
||||
}
|
||||
if (d == InfiniteDuration()) {
|
||||
s.append("inf");
|
||||
} else if (d < Seconds(1)) {
|
||||
// Special case for durations with a magnitude < 1 second. The duration
|
||||
// is printed as a fraction of a single unit, e.g., "1.2ms".
|
||||
if (d < Microseconds(1)) {
|
||||
AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano);
|
||||
} else if (d < Milliseconds(1)) {
|
||||
AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro);
|
||||
} else {
|
||||
AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli);
|
||||
}
|
||||
} else {
|
||||
AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour);
|
||||
AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin);
|
||||
AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec);
|
||||
}
|
||||
if (s.empty() || s == "-") {
|
||||
s = "0";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// A helper for ParseDuration() that parses a leading number from the given
|
||||
// std::string and stores the result in *n. The given std::string pointer is modified
|
||||
// to point to the first unconsumed char.
|
||||
bool ConsumeDurationNumber(const char** start, double* n) {
|
||||
const char* s = *start;
|
||||
char* end = nullptr;
|
||||
errno = 0;
|
||||
*n = strtod(s, &end);
|
||||
*start = end;
|
||||
return !std::isspace(*s) && errno == 0 && end != s && *n >= 0;
|
||||
}
|
||||
|
||||
// A helper for ParseDuration() that parses a leading unit designator (e.g.,
|
||||
// ns, us, ms, s, m, h) from the given std::string and stores the resulting unit
|
||||
// in "*unit". The given std::string pointer is modified to point to the first
|
||||
// unconsumed char.
|
||||
bool ConsumeDurationUnit(const char** start, Duration* unit) {
|
||||
const char *s = *start;
|
||||
bool ok = true;
|
||||
if (strncmp(s, "ns", 2) == 0) {
|
||||
s += 2;
|
||||
*unit = Nanoseconds(1);
|
||||
} else if (strncmp(s, "us", 2) == 0) {
|
||||
s += 2;
|
||||
*unit = Microseconds(1);
|
||||
} else if (strncmp(s, "ms", 2) == 0) {
|
||||
s += 2;
|
||||
*unit = Milliseconds(1);
|
||||
} else if (strncmp(s, "s", 1) == 0) {
|
||||
s += 1;
|
||||
*unit = Seconds(1);
|
||||
} else if (strncmp(s, "m", 1) == 0) {
|
||||
s += 1;
|
||||
*unit = Minutes(1);
|
||||
} else if (strncmp(s, "h", 1) == 0) {
|
||||
s += 1;
|
||||
*unit = Hours(1);
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
*start = s;
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// From Go's doc at http://golang.org/pkg/time/#ParseDuration
|
||||
// [ParseDuration] parses a duration std::string. A duration std::string is
|
||||
// a possibly signed sequence of decimal numbers, each with optional
|
||||
// fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
|
||||
// Valid time units are "ns", "us" "ms", "s", "m", "h".
|
||||
bool ParseDuration(const std::string& dur_string, Duration* d) {
|
||||
const char* start = dur_string.c_str();
|
||||
int sign = 1;
|
||||
|
||||
if (*start == '-' || *start == '+') {
|
||||
sign = *start == '-' ? -1 : 1;
|
||||
++start;
|
||||
}
|
||||
|
||||
// Can't parse a duration from an empty std::string.
|
||||
if (*start == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Special case for a std::string of "0".
|
||||
if (*start == '0' && *(start + 1) == '\0') {
|
||||
*d = ZeroDuration();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(start, "inf") == 0) {
|
||||
*d = sign * InfiniteDuration();
|
||||
return true;
|
||||
}
|
||||
|
||||
Duration dur;
|
||||
while (*start != '\0') {
|
||||
double n = 0;
|
||||
Duration unit;
|
||||
if (!ConsumeDurationNumber(&start, &n) ||
|
||||
!ConsumeDurationUnit(&start, &unit)) {
|
||||
return false;
|
||||
}
|
||||
dur += sign * n * unit;
|
||||
}
|
||||
*d = dur;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(b/63899288) copybara strip once dependencies are removed.
|
||||
bool ParseFlag(const std::string& text, Duration* dst, std::string* /* err */) {
|
||||
return ParseDuration(text, dst);
|
||||
}
|
||||
|
||||
std::string UnparseFlag(Duration d) {
|
||||
return FormatDuration(d);
|
||||
}
|
||||
|
||||
} // namespace absl
|
1530
absl/time/duration_test.cc
Normal file
1530
absl/time/duration_test.cc
Normal file
File diff suppressed because it is too large
Load diff
140
absl/time/format.cc
Normal file
140
absl/time/format.cc
Normal file
|
@ -0,0 +1,140 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/time/time.h"
|
||||
#include "cctz/time_zone.h"
|
||||
|
||||
namespace absl {
|
||||
|
||||
extern const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
|
||||
extern const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
|
||||
|
||||
extern const char RFC1123_full[] = "%a, %d %b %E4Y %H:%M:%S %z";
|
||||
extern const char RFC1123_no_wday[] = "%d %b %E4Y %H:%M:%S %z";
|
||||
|
||||
namespace {
|
||||
|
||||
const char kInfiniteFutureStr[] = "infinite-future";
|
||||
const char kInfinitePastStr[] = "infinite-past";
|
||||
|
||||
using cctz_sec = cctz::time_point<cctz::sys_seconds>;
|
||||
using cctz_fem = cctz::detail::femtoseconds;
|
||||
struct cctz_parts {
|
||||
cctz_sec sec;
|
||||
cctz_fem fem;
|
||||
};
|
||||
|
||||
inline cctz_sec unix_epoch() {
|
||||
return std::chrono::time_point_cast<cctz::sys_seconds>(
|
||||
std::chrono::system_clock::from_time_t(0));
|
||||
}
|
||||
|
||||
// Splits a Time into seconds and femtoseconds, which can be used with CCTZ.
|
||||
// Requires that 't' is finite. See duration.cc for details about rep_hi and
|
||||
// rep_lo.
|
||||
cctz_parts Split(absl::Time t) {
|
||||
const auto d = time_internal::ToUnixDuration(t);
|
||||
const int64_t rep_hi = time_internal::GetRepHi(d);
|
||||
const int64_t rep_lo = time_internal::GetRepLo(d);
|
||||
const auto sec = unix_epoch() + cctz::sys_seconds(rep_hi);
|
||||
const auto fem = cctz_fem(rep_lo * (1000 * 1000 / 4));
|
||||
return {sec, fem};
|
||||
}
|
||||
|
||||
// Joins the given seconds and femtoseconds into a Time. See duration.cc for
|
||||
// details about rep_hi and rep_lo.
|
||||
absl::Time Join(const cctz_parts& parts) {
|
||||
const int64_t rep_hi = (parts.sec - unix_epoch()).count();
|
||||
const uint32_t rep_lo = parts.fem.count() / (1000 * 1000 / 4);
|
||||
const auto d = time_internal::MakeDuration(rep_hi, rep_lo);
|
||||
return time_internal::FromUnixDuration(d);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string FormatTime(const std::string& format, absl::Time t, absl::TimeZone tz) {
|
||||
if (t == absl::InfiniteFuture()) return kInfiniteFutureStr;
|
||||
if (t == absl::InfinitePast()) return kInfinitePastStr;
|
||||
const auto parts = Split(t);
|
||||
return cctz::detail::format(format, parts.sec, parts.fem,
|
||||
cctz::time_zone(tz));
|
||||
}
|
||||
|
||||
std::string FormatTime(absl::Time t, absl::TimeZone tz) {
|
||||
return FormatTime(RFC3339_full, t, tz);
|
||||
}
|
||||
|
||||
std::string FormatTime(absl::Time t) {
|
||||
return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone());
|
||||
}
|
||||
|
||||
bool ParseTime(const std::string& format, const std::string& input, absl::Time* time,
|
||||
std::string* err) {
|
||||
return absl::ParseTime(format, input, absl::UTCTimeZone(), time, err);
|
||||
}
|
||||
|
||||
// If the input std::string does not contain an explicit UTC offset, interpret
|
||||
// the fields with respect to the given TimeZone.
|
||||
bool ParseTime(const std::string& format, const std::string& input, absl::TimeZone tz,
|
||||
absl::Time* time, std::string* err) {
|
||||
const char* data = input.c_str();
|
||||
while (std::isspace(*data)) ++data;
|
||||
|
||||
size_t inf_size = strlen(kInfiniteFutureStr);
|
||||
if (strncmp(data, kInfiniteFutureStr, inf_size) == 0) {
|
||||
const char* new_data = data + inf_size;
|
||||
while (std::isspace(*new_data)) ++new_data;
|
||||
if (*new_data == '\0') {
|
||||
*time = InfiniteFuture();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inf_size = strlen(kInfinitePastStr);
|
||||
if (strncmp(data, kInfinitePastStr, inf_size) == 0) {
|
||||
const char* new_data = data + inf_size;
|
||||
while (std::isspace(*new_data)) ++new_data;
|
||||
if (*new_data == '\0') {
|
||||
*time = InfinitePast();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string error;
|
||||
cctz_parts parts;
|
||||
const bool b = cctz::detail::parse(format, input, cctz::time_zone(tz),
|
||||
&parts.sec, &parts.fem, &error);
|
||||
if (b) {
|
||||
*time = Join(parts);
|
||||
} else if (err != nullptr) {
|
||||
*err = error;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
// TODO(b/63899288) copybara strip once dependencies are removed.
|
||||
// Functions required to support absl::Time flags. See go/flags.
|
||||
bool ParseFlag(const std::string& text, absl::Time* t, std::string* error) {
|
||||
return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);
|
||||
}
|
||||
|
||||
std::string UnparseFlag(absl::Time t) {
|
||||
return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone());
|
||||
}
|
||||
|
||||
} // namespace absl
|
430
absl/time/format_test.cc
Normal file
430
absl/time/format_test.cc
Normal file
|
@ -0,0 +1,430 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/internal/test_util.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
using testing::HasSubstr;
|
||||
|
||||
namespace {
|
||||
|
||||
// A helper that tests the given format specifier by itself, and with leading
|
||||
// and trailing characters. For example: TestFormatSpecifier(t, "%a", "Thu").
|
||||
void TestFormatSpecifier(absl::Time t, absl::TimeZone tz, const std::string& fmt,
|
||||
const std::string& ans) {
|
||||
EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));
|
||||
EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz));
|
||||
EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz));
|
||||
EXPECT_EQ("xxx " + ans + " yyy",
|
||||
absl::FormatTime("xxx " + fmt + " yyy", t, tz));
|
||||
}
|
||||
|
||||
//
|
||||
// Testing FormatTime()
|
||||
//
|
||||
|
||||
TEST(FormatTime, Basics) {
|
||||
absl::TimeZone tz = absl::UTCTimeZone();
|
||||
absl::Time t = absl::FromTimeT(0);
|
||||
|
||||
// Starts with a couple basic edge cases.
|
||||
EXPECT_EQ("", absl::FormatTime("", t, tz));
|
||||
EXPECT_EQ(" ", absl::FormatTime(" ", t, tz));
|
||||
EXPECT_EQ(" ", absl::FormatTime(" ", t, tz));
|
||||
EXPECT_EQ("xxx", absl::FormatTime("xxx", t, tz));
|
||||
std::string big(128, 'x');
|
||||
EXPECT_EQ(big, absl::FormatTime(big, t, tz));
|
||||
// Cause the 1024-byte buffer to grow.
|
||||
std::string bigger(100000, 'x');
|
||||
EXPECT_EQ(bigger, absl::FormatTime(bigger, t, tz));
|
||||
|
||||
t += absl::Hours(13) + absl::Minutes(4) + absl::Seconds(5);
|
||||
t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
|
||||
EXPECT_EQ("1970-01-01", absl::FormatTime("%Y-%m-%d", t, tz));
|
||||
EXPECT_EQ("13:04:05", absl::FormatTime("%H:%M:%S", t, tz));
|
||||
EXPECT_EQ("13:04:05.006", absl::FormatTime("%H:%M:%E3S", t, tz));
|
||||
EXPECT_EQ("13:04:05.006007", absl::FormatTime("%H:%M:%E6S", t, tz));
|
||||
EXPECT_EQ("13:04:05.006007008", absl::FormatTime("%H:%M:%E9S", t, tz));
|
||||
}
|
||||
|
||||
TEST(FormatTime, LocaleSpecific) {
|
||||
const absl::TimeZone tz = absl::UTCTimeZone();
|
||||
absl::Time t = absl::FromTimeT(0);
|
||||
|
||||
TestFormatSpecifier(t, tz, "%a", "Thu");
|
||||
TestFormatSpecifier(t, tz, "%A", "Thursday");
|
||||
TestFormatSpecifier(t, tz, "%b", "Jan");
|
||||
TestFormatSpecifier(t, tz, "%B", "January");
|
||||
|
||||
// %c should at least produce the numeric year and time-of-day.
|
||||
const std::string s =
|
||||
absl::FormatTime("%c", absl::FromTimeT(0), absl::UTCTimeZone());
|
||||
EXPECT_THAT(s, HasSubstr("1970"));
|
||||
EXPECT_THAT(s, HasSubstr("00:00:00"));
|
||||
|
||||
TestFormatSpecifier(t, tz, "%p", "AM");
|
||||
TestFormatSpecifier(t, tz, "%x", "01/01/70");
|
||||
TestFormatSpecifier(t, tz, "%X", "00:00:00");
|
||||
}
|
||||
|
||||
TEST(FormatTime, ExtendedSeconds) {
|
||||
const absl::TimeZone tz = absl::UTCTimeZone();
|
||||
|
||||
// No subseconds.
|
||||
absl::Time t = absl::FromTimeT(0) + absl::Seconds(5);
|
||||
EXPECT_EQ("05", absl::FormatTime("%E*S", t, tz));
|
||||
EXPECT_EQ("05.000000000000000", absl::FormatTime("%E15S", t, tz));
|
||||
|
||||
// With subseconds.
|
||||
t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
|
||||
EXPECT_EQ("05.006007008", absl::FormatTime("%E*S", t, tz));
|
||||
EXPECT_EQ("05", absl::FormatTime("%E0S", t, tz));
|
||||
EXPECT_EQ("05.006007008000000", absl::FormatTime("%E15S", t, tz));
|
||||
|
||||
// Times before the Unix epoch.
|
||||
t = absl::FromUnixMicros(-1);
|
||||
EXPECT_EQ("1969-12-31 23:59:59.999999",
|
||||
absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
|
||||
|
||||
// Here is a "%E*S" case we got wrong for a while. While the first
|
||||
// instant below is correctly rendered as "...:07.333304", the second
|
||||
// one used to appear as "...:07.33330499999999999".
|
||||
t = absl::FromUnixMicros(1395024427333304);
|
||||
EXPECT_EQ("2014-03-17 02:47:07.333304",
|
||||
absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
|
||||
t += absl::Microseconds(1);
|
||||
EXPECT_EQ("2014-03-17 02:47:07.333305",
|
||||
absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
|
||||
}
|
||||
|
||||
TEST(FormatTime, RFC1123FormatPadsYear) { // locale specific
|
||||
absl::TimeZone tz = absl::UTCTimeZone();
|
||||
|
||||
// A year of 77 should be padded to 0077.
|
||||
absl::Time t = absl::FromDateTime(77, 6, 28, 9, 8, 7, tz);
|
||||
EXPECT_EQ("Mon, 28 Jun 0077 09:08:07 +0000",
|
||||
absl::FormatTime(absl::RFC1123_full, t, tz));
|
||||
EXPECT_EQ("28 Jun 0077 09:08:07 +0000",
|
||||
absl::FormatTime(absl::RFC1123_no_wday, t, tz));
|
||||
}
|
||||
|
||||
TEST(FormatTime, InfiniteTime) {
|
||||
absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
|
||||
|
||||
// The format and timezone are ignored.
|
||||
EXPECT_EQ("infinite-future",
|
||||
absl::FormatTime("%H:%M blah", absl::InfiniteFuture(), tz));
|
||||
EXPECT_EQ("infinite-past",
|
||||
absl::FormatTime("%H:%M blah", absl::InfinitePast(), tz));
|
||||
}
|
||||
|
||||
//
|
||||
// Testing ParseTime()
|
||||
//
|
||||
|
||||
TEST(ParseTime, Basics) {
|
||||
absl::Time t = absl::FromTimeT(1234567890);
|
||||
std::string err;
|
||||
|
||||
// Simple edge cases.
|
||||
EXPECT_TRUE(absl::ParseTime("", "", &t, &err)) << err;
|
||||
EXPECT_EQ(absl::UnixEpoch(), t); // everything defaulted
|
||||
EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err;
|
||||
EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err;
|
||||
EXPECT_TRUE(absl::ParseTime("x", "x", &t, &err)) << err;
|
||||
EXPECT_TRUE(absl::ParseTime("xxx", "xxx", &t, &err)) << err;
|
||||
|
||||
EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
|
||||
"2013-06-28 19:08:09 -0800", &t, &err))
|
||||
<< err;
|
||||
absl::Time::Breakdown bd = t.In(absl::FixedTimeZone(-8 * 60 * 60));
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -8 * 60 * 60, false,
|
||||
"UTC-8");
|
||||
EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
|
||||
}
|
||||
|
||||
TEST(ParseTime, NullErrorString) {
|
||||
absl::Time t;
|
||||
EXPECT_FALSE(absl::ParseTime("%Q", "invalid format", &t, nullptr));
|
||||
EXPECT_FALSE(absl::ParseTime("%H", "12 trailing data", &t, nullptr));
|
||||
EXPECT_FALSE(
|
||||
absl::ParseTime("%H out of range", "42 out of range", &t, nullptr));
|
||||
}
|
||||
|
||||
TEST(ParseTime, WithTimeZone) {
|
||||
const absl::TimeZone tz =
|
||||
absl::time_internal::LoadTimeZone("America/Los_Angeles");
|
||||
absl::Time t;
|
||||
std::string e;
|
||||
|
||||
// We can parse a std::string without a UTC offset if we supply a timezone.
|
||||
EXPECT_TRUE(
|
||||
absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
|
||||
<< e;
|
||||
absl::Time::Breakdown bd = t.In(tz);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true,
|
||||
"PDT");
|
||||
EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
|
||||
|
||||
// But the timezone is ignored when a UTC offset is present.
|
||||
EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
|
||||
"2013-06-28 19:08:09 +0800", tz, &t, &e))
|
||||
<< e;
|
||||
bd = t.In(absl::FixedTimeZone(8 * 60 * 60));
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, 8 * 60 * 60, false,
|
||||
"UTC+8");
|
||||
EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
|
||||
}
|
||||
|
||||
TEST(ParseTime, ErrorCases) {
|
||||
absl::Time t = absl::FromTimeT(0);
|
||||
std::string err;
|
||||
|
||||
EXPECT_FALSE(absl::ParseTime("%S", "123", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
|
||||
|
||||
// Can't parse an illegal format specifier.
|
||||
err.clear();
|
||||
EXPECT_FALSE(absl::ParseTime("%Q", "x", &t, &err)) << err;
|
||||
// Exact contents of "err" are platform-dependent because of
|
||||
// differences in the strptime implementation between OSX and Linux.
|
||||
EXPECT_FALSE(err.empty());
|
||||
|
||||
// Fails because of trailing, unparsed data "blah".
|
||||
EXPECT_FALSE(absl::ParseTime("%m-%d", "2-3 blah", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
|
||||
|
||||
// Feb 31 requires normalization.
|
||||
EXPECT_FALSE(absl::ParseTime("%m-%d", "2-31", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Out-of-range"));
|
||||
|
||||
// Check that we cannot have spaces in UTC offsets.
|
||||
EXPECT_TRUE(absl::ParseTime("%z", "-0203", &t, &err)) << err;
|
||||
EXPECT_FALSE(absl::ParseTime("%z", "- 2 3", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_TRUE(absl::ParseTime("%Ez", "-02:03", &t, &err)) << err;
|
||||
EXPECT_FALSE(absl::ParseTime("%Ez", "- 2: 3", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
|
||||
// Check that we reject other malformed UTC offsets.
|
||||
EXPECT_FALSE(absl::ParseTime("%Ez", "+-08:00", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_FALSE(absl::ParseTime("%Ez", "-+08:00", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
|
||||
// Check that we do not accept "-0" in fields that allow zero.
|
||||
EXPECT_FALSE(absl::ParseTime("%Y", "-0", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_FALSE(absl::ParseTime("%E4Y", "-0", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_FALSE(absl::ParseTime("%H", "-0", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_FALSE(absl::ParseTime("%M", "-0", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_FALSE(absl::ParseTime("%S", "-0", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_FALSE(absl::ParseTime("%z", "+-000", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_FALSE(absl::ParseTime("%Ez", "+-0:00", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
EXPECT_FALSE(absl::ParseTime("%z", "-00-0", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
|
||||
EXPECT_FALSE(absl::ParseTime("%Ez", "-00:-0", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
|
||||
}
|
||||
|
||||
TEST(ParseTime, ExtendedSeconds) {
|
||||
std::string err;
|
||||
absl::Time t;
|
||||
|
||||
// Here is a "%E*S" case we got wrong for a while. The fractional
|
||||
// part of the first instant is less than 2^31 and was correctly
|
||||
// parsed, while the second (and any subsecond field >=2^31) failed.
|
||||
t = absl::UnixEpoch();
|
||||
EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483647", &t, &err)) << err;
|
||||
EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
|
||||
absl::Nanoseconds(1) / 2,
|
||||
t);
|
||||
t = absl::UnixEpoch();
|
||||
EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483648", &t, &err)) << err;
|
||||
EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
|
||||
absl::Nanoseconds(3) / 4,
|
||||
t);
|
||||
|
||||
// We should also be able to specify long strings of digits far
|
||||
// beyond the current resolution and have them convert the same way.
|
||||
t = absl::UnixEpoch();
|
||||
EXPECT_TRUE(absl::ParseTime(
|
||||
"%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
|
||||
&t, &err))
|
||||
<< err;
|
||||
EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
|
||||
absl::Nanoseconds(3) / 4,
|
||||
t);
|
||||
}
|
||||
|
||||
TEST(ParseTime, ExtendedOffsetErrors) {
|
||||
std::string err;
|
||||
absl::Time t;
|
||||
|
||||
// %z against +-HHMM.
|
||||
EXPECT_FALSE(absl::ParseTime("%z", "-123", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
|
||||
|
||||
// %z against +-HH.
|
||||
EXPECT_FALSE(absl::ParseTime("%z", "-1", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
|
||||
// %Ez against +-HH:MM.
|
||||
EXPECT_FALSE(absl::ParseTime("%Ez", "-12:3", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
|
||||
|
||||
// %Ez against +-HHMM.
|
||||
EXPECT_FALSE(absl::ParseTime("%Ez", "-123", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
|
||||
|
||||
// %Ez against +-HH.
|
||||
EXPECT_FALSE(absl::ParseTime("%Ez", "-1", &t, &err)) << err;
|
||||
EXPECT_THAT(err, HasSubstr("Failed to parse"));
|
||||
}
|
||||
|
||||
TEST(ParseTime, InfiniteTime) {
|
||||
absl::Time t;
|
||||
std::string err;
|
||||
EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future", &t, &err));
|
||||
EXPECT_EQ(absl::InfiniteFuture(), t);
|
||||
|
||||
// Surrounding whitespace.
|
||||
EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-future", &t, &err));
|
||||
EXPECT_EQ(absl::InfiniteFuture(), t);
|
||||
EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future ", &t, &err));
|
||||
EXPECT_EQ(absl::InfiniteFuture(), t);
|
||||
EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-future ", &t, &err));
|
||||
EXPECT_EQ(absl::InfiniteFuture(), t);
|
||||
|
||||
EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past", &t, &err));
|
||||
EXPECT_EQ(absl::InfinitePast(), t);
|
||||
|
||||
// Surrounding whitespace.
|
||||
EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-past", &t, &err));
|
||||
EXPECT_EQ(absl::InfinitePast(), t);
|
||||
EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past ", &t, &err));
|
||||
EXPECT_EQ(absl::InfinitePast(), t);
|
||||
EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-past ", &t, &err));
|
||||
EXPECT_EQ(absl::InfinitePast(), t);
|
||||
|
||||
// "infinite-future" as literal std::string
|
||||
absl::TimeZone tz = absl::UTCTimeZone();
|
||||
EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
|
||||
&t, &err));
|
||||
EXPECT_NE(absl::InfiniteFuture(), t);
|
||||
EXPECT_EQ(3, t.In(tz).hour);
|
||||
EXPECT_EQ(4, t.In(tz).minute);
|
||||
|
||||
// "infinite-past" as literal std::string
|
||||
EXPECT_TRUE(
|
||||
absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
|
||||
EXPECT_NE(absl::InfinitePast(), t);
|
||||
EXPECT_EQ(3, t.In(tz).hour);
|
||||
EXPECT_EQ(4, t.In(tz).minute);
|
||||
|
||||
// The input doesn't match the format.
|
||||
EXPECT_FALSE(absl::ParseTime("infinite-future %H:%M", "03:04", &t, &err));
|
||||
EXPECT_FALSE(absl::ParseTime("infinite-past %H:%M", "03:04", &t, &err));
|
||||
}
|
||||
|
||||
TEST(ParseTime, FailsOnUnrepresentableTime) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
absl::Time t;
|
||||
EXPECT_FALSE(
|
||||
absl::ParseTime("%Y-%m-%d", "-292277022657-01-27", utc, &t, nullptr));
|
||||
EXPECT_TRUE(
|
||||
absl::ParseTime("%Y-%m-%d", "-292277022657-01-28", utc, &t, nullptr));
|
||||
EXPECT_TRUE(
|
||||
absl::ParseTime("%Y-%m-%d", "292277026596-12-04", utc, &t, nullptr));
|
||||
EXPECT_FALSE(
|
||||
absl::ParseTime("%Y-%m-%d", "292277026596-12-05", utc, &t, nullptr));
|
||||
}
|
||||
|
||||
//
|
||||
// Roundtrip test for FormatTime()/ParseTime().
|
||||
//
|
||||
|
||||
TEST(FormatParse, RoundTrip) {
|
||||
const absl::TimeZone gst =
|
||||
absl::time_internal::LoadTimeZone("America/Los_Angeles");
|
||||
const absl::Time in = absl::FromDateTime(1977, 6, 28, 9, 8, 7, gst);
|
||||
const absl::Duration subseconds = absl::Nanoseconds(654321);
|
||||
std::string err;
|
||||
|
||||
// RFC3339, which renders subseconds.
|
||||
{
|
||||
absl::Time out;
|
||||
const std::string s = absl::FormatTime(absl::RFC3339_full, in + subseconds, gst);
|
||||
EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
|
||||
<< s << ": " << err;
|
||||
EXPECT_EQ(in + subseconds, out); // RFC3339_full includes %Ez
|
||||
}
|
||||
|
||||
// RFC1123, which only does whole seconds.
|
||||
{
|
||||
absl::Time out;
|
||||
const std::string s = absl::FormatTime(absl::RFC1123_full, in, gst);
|
||||
EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err))
|
||||
<< s << ": " << err;
|
||||
EXPECT_EQ(in, out); // RFC1123_full includes %z
|
||||
}
|
||||
|
||||
// Even though we don't know what %c will produce, it should roundtrip,
|
||||
// but only in the 0-offset timezone.
|
||||
{
|
||||
absl::Time out;
|
||||
const std::string s = absl::FormatTime("%c", in, absl::UTCTimeZone());
|
||||
EXPECT_TRUE(absl::ParseTime("%c", s, &out, &err)) << s << ": " << err;
|
||||
EXPECT_EQ(in, out);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FormatParse, RoundTripDistantFuture) {
|
||||
const absl::TimeZone tz = absl::UTCTimeZone();
|
||||
const absl::Time in =
|
||||
absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());
|
||||
std::string err;
|
||||
|
||||
absl::Time out;
|
||||
const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
|
||||
EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
|
||||
<< s << ": " << err;
|
||||
EXPECT_EQ(in, out);
|
||||
}
|
||||
|
||||
TEST(FormatParse, RoundTripDistantPast) {
|
||||
const absl::TimeZone tz = absl::UTCTimeZone();
|
||||
const absl::Time in =
|
||||
absl::FromUnixSeconds(std::numeric_limits<int64_t>::min());
|
||||
std::string err;
|
||||
|
||||
absl::Time out;
|
||||
const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
|
||||
EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
|
||||
<< s << ": " << err;
|
||||
EXPECT_EQ(in, out);
|
||||
}
|
||||
} // namespace
|
80
absl/time/internal/get_current_time_ios.inc
Normal file
80
absl/time/internal/get_current_time_ios.inc
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "absl/time/clock.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <ctime>
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
|
||||
// These are not defined in the Xcode 7.3.1 SDK Headers.
|
||||
// Once we are no longer supporting Xcode 7.3.1 we can
|
||||
// remove these.
|
||||
#ifndef __WATCHOS_3_0
|
||||
#define __WATCHOS_3_0 30000
|
||||
#endif
|
||||
|
||||
#ifndef __TVOS_10_0
|
||||
#define __TVOS_10_0 100000
|
||||
#endif
|
||||
|
||||
#ifndef __IPHONE_10_0
|
||||
#define __IPHONE_10_0 100000
|
||||
#endif
|
||||
|
||||
#ifndef __MAC_10_12
|
||||
#define __MAC_10_12 101200
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
namespace time_internal {
|
||||
|
||||
static int64_t GetCurrentTimeNanosFromSystem() {
|
||||
#if (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12) || \
|
||||
(__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0) || \
|
||||
(__WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_3_0) || \
|
||||
(__TV_OS_VERSION_MAX_ALLOWED >= __TVOS_10_0)
|
||||
// clock_gettime_nsec_np is not defined on SDKs before Xcode 8.0.
|
||||
// This preprocessor logic is based upon __CLOCK_AVAILABILITY in
|
||||
// usr/include/time.h. Once we are no longer supporting Xcode 7.3.1 we can
|
||||
// remove this #if.
|
||||
// We must continue to check if it is defined until we are sure that ALL the
|
||||
// platforms we are shipping on support it.
|
||||
// clock_gettime_nsec_np is preferred because it may give higher accuracy than
|
||||
// gettimeofday in future Apple operating systems.
|
||||
// Currently (macOS 10.12/iOS 10.2) clock_gettime_nsec_np accuracy is
|
||||
// microsecond accuracy (i.e. equivalent to gettimeofday).
|
||||
if (&clock_gettime_nsec_np != nullptr) {
|
||||
return clock_gettime_nsec_np(CLOCK_REALTIME);
|
||||
}
|
||||
#endif
|
||||
#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
(__MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_12)) || \
|
||||
(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
|
||||
(__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0)) || \
|
||||
(defined(__WATCH_OS_VERSION_MIN_REQUIRED) && \
|
||||
(__WATCH_OS_VERSION_MIN_REQUIRED < __WATCHOS_3_0)) || \
|
||||
(defined(__TV_OS_VERSION_MIN_REQUIRED) && \
|
||||
(__TV_OS_VERSION_MIN_REQUIRED < __TVOS_10_0))
|
||||
// We need this block in 2 different cases:
|
||||
// a) where we are compiling with Xcode 7 in which case the block above
|
||||
// will not be compiled in, and this is the only block executed.
|
||||
// b) where we are compiling with Xcode 8+ but supporting operating systems
|
||||
// that do not define clock_gettime_nsec_np, so this is in effect
|
||||
// an else block to the block above.
|
||||
// This block will not be compiled if the min supported version is
|
||||
// guaranteed to supply clock_gettime_nsec_np.
|
||||
//
|
||||
// Once we know that clock_gettime_nsec_np is in the SDK *AND* exists on
|
||||
// all the platforms we support, we can remove both this block and alter the
|
||||
// block above to just call clock_gettime_nsec_np directly.
|
||||
const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
|
||||
const int64_t kNanosPerMicrosecond = 1000;
|
||||
struct timeval tp;
|
||||
ABSL_RAW_CHECK(gettimeofday(&tp, nullptr) == 0, "Failed gettimeofday");
|
||||
return (int64_t{tp.tv_sec} * kNanosPerSecond +
|
||||
int64_t{tp.tv_usec} * kNanosPerMicrosecond);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace time_internal
|
||||
} // namespace absl
|
22
absl/time/internal/get_current_time_posix.inc
Normal file
22
absl/time/internal/get_current_time_posix.inc
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "absl/time/clock.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <ctime>
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
|
||||
namespace absl {
|
||||
namespace time_internal {
|
||||
|
||||
static int64_t GetCurrentTimeNanosFromSystem() {
|
||||
const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
|
||||
struct timespec ts;
|
||||
ABSL_RAW_CHECK(clock_gettime(CLOCK_REALTIME, &ts) == 0,
|
||||
"Failed to read real-time clock.");
|
||||
return (int64_t{ts.tv_sec} * kNanosPerSecond +
|
||||
int64_t{ts.tv_nsec});
|
||||
}
|
||||
|
||||
} // namespace time_internal
|
||||
} // namespace absl
|
17
absl/time/internal/get_current_time_windows.inc
Normal file
17
absl/time/internal/get_current_time_windows.inc
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include "absl/time/clock.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
|
||||
namespace absl {
|
||||
namespace time_internal {
|
||||
|
||||
static int64_t GetCurrentTimeNanosFromSystem() {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now() -
|
||||
std::chrono::system_clock::from_time_t(0))
|
||||
.count();
|
||||
}
|
||||
|
||||
} // namespace time_internal
|
||||
} // namespace absl
|
112
absl/time/internal/test_util.cc
Normal file
112
absl/time/internal/test_util.cc
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/time/internal/test_util.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "cctz/zone_info_source.h"
|
||||
|
||||
namespace absl {
|
||||
namespace time_internal {
|
||||
|
||||
TimeZone LoadTimeZone(const std::string& name) {
|
||||
TimeZone tz;
|
||||
ABSL_RAW_CHECK(LoadTimeZone(name, &tz), name.c_str());
|
||||
return tz;
|
||||
}
|
||||
|
||||
} // namespace time_internal
|
||||
} // namespace absl
|
||||
|
||||
namespace cctz_extension {
|
||||
namespace {
|
||||
|
||||
// Embed the zoneinfo data for time zones used during tests and benchmarks.
|
||||
// The data was generated using "xxd -i zoneinfo-file". There is no need
|
||||
// to update the data as long as the tests do not depend on recent changes
|
||||
// (and the past rules remain the same).
|
||||
#include "absl/time/internal/zoneinfo.inc"
|
||||
|
||||
const struct ZoneInfo {
|
||||
const char* name;
|
||||
const char* data;
|
||||
std::size_t length;
|
||||
} kZoneInfo[] = {
|
||||
// The three real time zones used by :time_test and :time_benchmark.
|
||||
{"America/Los_Angeles", //
|
||||
reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len},
|
||||
{"America/New_York", //
|
||||
reinterpret_cast<char*>(America_New_York), America_New_York_len},
|
||||
{"Australia/Sydney", //
|
||||
reinterpret_cast<char*>(Australia_Sydney), Australia_Sydney_len},
|
||||
|
||||
// Other zones named in tests but which should fail to load.
|
||||
{"Invalid/TimeZone", nullptr, 0},
|
||||
{"", nullptr, 0},
|
||||
|
||||
// Also allow for loading the local time zone under TZ=US/Pacific.
|
||||
{"US/Pacific", //
|
||||
reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len},
|
||||
|
||||
// Allows use of the local time zone from a common system-specific location.
|
||||
{"/etc/localtime", //
|
||||
reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len},
|
||||
};
|
||||
|
||||
class TestZoneInfoSource : public cctz::ZoneInfoSource {
|
||||
public:
|
||||
TestZoneInfoSource(const char* data, std::size_t size)
|
||||
: data_(data), end_(data + size) {}
|
||||
|
||||
std::size_t Read(void* ptr, std::size_t size) override {
|
||||
const std::size_t len = std::min<std::size_t>(size, end_ - data_);
|
||||
memcpy(ptr, data_, len);
|
||||
data_ += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
int Skip(std::size_t offset) override {
|
||||
data_ += std::min<std::size_t>(offset, end_ - data_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* data_;
|
||||
const char* const end_;
|
||||
};
|
||||
|
||||
std::unique_ptr<cctz::ZoneInfoSource> TestFactory(
|
||||
const std::string& name,
|
||||
const std::function<std::unique_ptr<cctz::ZoneInfoSource>(
|
||||
const std::string& name)>& /*fallback_factory*/) {
|
||||
for (const ZoneInfo& zoneinfo : kZoneInfo) {
|
||||
if (name == zoneinfo.name) {
|
||||
if (zoneinfo.data == nullptr) return nullptr;
|
||||
return std::unique_ptr<cctz::ZoneInfoSource>(
|
||||
new TestZoneInfoSource(zoneinfo.data, zoneinfo.length));
|
||||
}
|
||||
}
|
||||
ABSL_RAW_LOG(FATAL, "Unexpected time zone \"%s\" in test", name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ZoneInfoSourceFactory zone_info_source_factory = TestFactory;
|
||||
|
||||
} // namespace cctz_extension
|
49
absl/time/internal/test_util.h
Normal file
49
absl/time/internal/test_util.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_TIME_INTERNAL_TEST_UTIL_H_
|
||||
#define ABSL_TIME_INTERNAL_TEST_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/time/time.h"
|
||||
|
||||
// This helper is a macro so that failed expectations show up with the
|
||||
// correct line numbers.
|
||||
//
|
||||
// This is for internal testing of the Base Time library itself. This is not
|
||||
// part of a public API.
|
||||
#define ABSL_INTERNAL_EXPECT_TIME(bd, y, m, d, h, min, s, off, isdst, zone) \
|
||||
do { \
|
||||
EXPECT_EQ(y, bd.year); \
|
||||
EXPECT_EQ(m, bd.month); \
|
||||
EXPECT_EQ(d, bd.day); \
|
||||
EXPECT_EQ(h, bd.hour); \
|
||||
EXPECT_EQ(min, bd.minute); \
|
||||
EXPECT_EQ(s, bd.second); \
|
||||
EXPECT_EQ(off, bd.offset); \
|
||||
EXPECT_EQ(isdst, bd.is_dst); \
|
||||
EXPECT_STREQ(zone, bd.zone_abbr); \
|
||||
} while (0)
|
||||
|
||||
namespace absl {
|
||||
namespace time_internal {
|
||||
|
||||
// Loads the named timezone, but dies on any failure.
|
||||
absl::TimeZone LoadTimeZone(const std::string& name);
|
||||
|
||||
} // namespace time_internal
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_TIME_INTERNAL_TEST_UTIL_H_
|
729
absl/time/internal/zoneinfo.inc
Normal file
729
absl/time/internal/zoneinfo.inc
Normal file
|
@ -0,0 +1,729 @@
|
|||
unsigned char America_Los_Angeles[] = {
|
||||
0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00,
|
||||
0x9e, 0xa6, 0x48, 0xa0, 0x9f, 0xbb, 0x15, 0x90, 0xa0, 0x86, 0x2a, 0xa0,
|
||||
0xa1, 0x9a, 0xf7, 0x90, 0xcb, 0x89, 0x1a, 0xa0, 0xd2, 0x23, 0xf4, 0x70,
|
||||
0xd2, 0x61, 0x26, 0x10, 0xd6, 0xfe, 0x74, 0x5c, 0xd8, 0x80, 0xad, 0x90,
|
||||
0xda, 0xfe, 0xc3, 0x90, 0xdb, 0xc0, 0x90, 0x10, 0xdc, 0xde, 0xa5, 0x90,
|
||||
0xdd, 0xa9, 0xac, 0x90, 0xde, 0xbe, 0x87, 0x90, 0xdf, 0x89, 0x8e, 0x90,
|
||||
0xe0, 0x9e, 0x69, 0x90, 0xe1, 0x69, 0x70, 0x90, 0xe2, 0x7e, 0x4b, 0x90,
|
||||
0xe3, 0x49, 0x52, 0x90, 0xe4, 0x5e, 0x2d, 0x90, 0xe5, 0x29, 0x34, 0x90,
|
||||
0xe6, 0x47, 0x4a, 0x10, 0xe7, 0x12, 0x51, 0x10, 0xe8, 0x27, 0x2c, 0x10,
|
||||
0xe8, 0xf2, 0x33, 0x10, 0xea, 0x07, 0x0e, 0x10, 0xea, 0xd2, 0x15, 0x10,
|
||||
0xeb, 0xe6, 0xf0, 0x10, 0xec, 0xb1, 0xf7, 0x10, 0xed, 0xc6, 0xd2, 0x10,
|
||||
0xee, 0x91, 0xd9, 0x10, 0xef, 0xaf, 0xee, 0x90, 0xf0, 0x71, 0xbb, 0x10,
|
||||
0xf1, 0x8f, 0xd0, 0x90, 0xf2, 0x7f, 0xc1, 0x90, 0xf3, 0x6f, 0xb2, 0x90,
|
||||
0xf4, 0x5f, 0xa3, 0x90, 0xf5, 0x4f, 0x94, 0x90, 0xf6, 0x3f, 0x85, 0x90,
|
||||
0xf7, 0x2f, 0x76, 0x90, 0xf8, 0x28, 0xa2, 0x10, 0xf9, 0x0f, 0x58, 0x90,
|
||||
0xfa, 0x08, 0x84, 0x10, 0xfa, 0xf8, 0x83, 0x20, 0xfb, 0xe8, 0x66, 0x10,
|
||||
0xfc, 0xd8, 0x65, 0x20, 0xfd, 0xc8, 0x48, 0x10, 0xfe, 0xb8, 0x47, 0x20,
|
||||
0xff, 0xa8, 0x2a, 0x10, 0x00, 0x98, 0x29, 0x20, 0x01, 0x88, 0x0c, 0x10,
|
||||
0x02, 0x78, 0x0b, 0x20, 0x03, 0x71, 0x28, 0x90, 0x04, 0x61, 0x27, 0xa0,
|
||||
0x05, 0x51, 0x0a, 0x90, 0x06, 0x41, 0x09, 0xa0, 0x07, 0x30, 0xec, 0x90,
|
||||
0x07, 0x8d, 0x43, 0xa0, 0x09, 0x10, 0xce, 0x90, 0x09, 0xad, 0xbf, 0x20,
|
||||
0x0a, 0xf0, 0xb0, 0x90, 0x0b, 0xe0, 0xaf, 0xa0, 0x0c, 0xd9, 0xcd, 0x10,
|
||||
0x0d, 0xc0, 0x91, 0xa0, 0x0e, 0xb9, 0xaf, 0x10, 0x0f, 0xa9, 0xae, 0x20,
|
||||
0x10, 0x99, 0x91, 0x10, 0x11, 0x89, 0x90, 0x20, 0x12, 0x79, 0x73, 0x10,
|
||||
0x13, 0x69, 0x72, 0x20, 0x14, 0x59, 0x55, 0x10, 0x15, 0x49, 0x54, 0x20,
|
||||
0x16, 0x39, 0x37, 0x10, 0x17, 0x29, 0x36, 0x20, 0x18, 0x22, 0x53, 0x90,
|
||||
0x19, 0x09, 0x18, 0x20, 0x1a, 0x02, 0x35, 0x90, 0x1a, 0xf2, 0x34, 0xa0,
|
||||
0x1b, 0xe2, 0x17, 0x90, 0x1c, 0xd2, 0x16, 0xa0, 0x1d, 0xc1, 0xf9, 0x90,
|
||||
0x1e, 0xb1, 0xf8, 0xa0, 0x1f, 0xa1, 0xdb, 0x90, 0x20, 0x76, 0x2b, 0x20,
|
||||
0x21, 0x81, 0xbd, 0x90, 0x22, 0x56, 0x0d, 0x20, 0x23, 0x6a, 0xda, 0x10,
|
||||
0x24, 0x35, 0xef, 0x20, 0x25, 0x4a, 0xbc, 0x10, 0x26, 0x15, 0xd1, 0x20,
|
||||
0x27, 0x2a, 0x9e, 0x10, 0x27, 0xfe, 0xed, 0xa0, 0x29, 0x0a, 0x80, 0x10,
|
||||
0x29, 0xde, 0xcf, 0xa0, 0x2a, 0xea, 0x62, 0x10, 0x2b, 0xbe, 0xb1, 0xa0,
|
||||
0x2c, 0xd3, 0x7e, 0x90, 0x2d, 0x9e, 0x93, 0xa0, 0x2e, 0xb3, 0x60, 0x90,
|
||||
0x2f, 0x7e, 0x75, 0xa0, 0x30, 0x93, 0x42, 0x90, 0x31, 0x67, 0x92, 0x20,
|
||||
0x32, 0x73, 0x24, 0x90, 0x33, 0x47, 0x74, 0x20, 0x34, 0x53, 0x06, 0x90,
|
||||
0x35, 0x27, 0x56, 0x20, 0x36, 0x32, 0xe8, 0x90, 0x37, 0x07, 0x38, 0x20,
|
||||
0x38, 0x1c, 0x05, 0x10, 0x38, 0xe7, 0x1a, 0x20, 0x39, 0xfb, 0xe7, 0x10,
|
||||
0x3a, 0xc6, 0xfc, 0x20, 0x3b, 0xdb, 0xc9, 0x10, 0x3c, 0xb0, 0x18, 0xa0,
|
||||
0x3d, 0xbb, 0xab, 0x10, 0x3e, 0x8f, 0xfa, 0xa0, 0x3f, 0x9b, 0x8d, 0x10,
|
||||
0x40, 0x6f, 0xdc, 0xa0, 0x41, 0x84, 0xa9, 0x90, 0x42, 0x4f, 0xbe, 0xa0,
|
||||
0x43, 0x64, 0x8b, 0x90, 0x44, 0x2f, 0xa0, 0xa0, 0x45, 0x44, 0x6d, 0x90,
|
||||
0x45, 0xf3, 0xd3, 0x20, 0x47, 0x2d, 0x8a, 0x10, 0x47, 0xd3, 0xb5, 0x20,
|
||||
0x49, 0x0d, 0x6c, 0x10, 0x49, 0xb3, 0x97, 0x20, 0x4a, 0xed, 0x4e, 0x10,
|
||||
0x4b, 0x9c, 0xb3, 0xa0, 0x4c, 0xd6, 0x6a, 0x90, 0x4d, 0x7c, 0x95, 0xa0,
|
||||
0x4e, 0xb6, 0x4c, 0x90, 0x4f, 0x5c, 0x77, 0xa0, 0x50, 0x96, 0x2e, 0x90,
|
||||
0x51, 0x3c, 0x59, 0xa0, 0x52, 0x76, 0x10, 0x90, 0x53, 0x1c, 0x3b, 0xa0,
|
||||
0x54, 0x55, 0xf2, 0x90, 0x54, 0xfc, 0x1d, 0xa0, 0x56, 0x35, 0xd4, 0x90,
|
||||
0x56, 0xe5, 0x3a, 0x20, 0x58, 0x1e, 0xf1, 0x10, 0x58, 0xc5, 0x1c, 0x20,
|
||||
0x59, 0xfe, 0xd3, 0x10, 0x5a, 0xa4, 0xfe, 0x20, 0x5b, 0xde, 0xb5, 0x10,
|
||||
0x5c, 0x84, 0xe0, 0x20, 0x5d, 0xbe, 0x97, 0x10, 0x5e, 0x64, 0xc2, 0x20,
|
||||
0x5f, 0x9e, 0x79, 0x10, 0x60, 0x4d, 0xde, 0xa0, 0x61, 0x87, 0x95, 0x90,
|
||||
0x62, 0x2d, 0xc0, 0xa0, 0x63, 0x67, 0x77, 0x90, 0x64, 0x0d, 0xa2, 0xa0,
|
||||
0x65, 0x47, 0x59, 0x90, 0x65, 0xed, 0x84, 0xa0, 0x67, 0x27, 0x3b, 0x90,
|
||||
0x67, 0xcd, 0x66, 0xa0, 0x69, 0x07, 0x1d, 0x90, 0x69, 0xad, 0x48, 0xa0,
|
||||
0x6a, 0xe6, 0xff, 0x90, 0x6b, 0x96, 0x65, 0x20, 0x6c, 0xd0, 0x1c, 0x10,
|
||||
0x6d, 0x76, 0x47, 0x20, 0x6e, 0xaf, 0xfe, 0x10, 0x6f, 0x56, 0x29, 0x20,
|
||||
0x70, 0x8f, 0xe0, 0x10, 0x71, 0x36, 0x0b, 0x20, 0x72, 0x6f, 0xc2, 0x10,
|
||||
0x73, 0x15, 0xed, 0x20, 0x74, 0x4f, 0xa4, 0x10, 0x74, 0xff, 0x09, 0xa0,
|
||||
0x76, 0x38, 0xc0, 0x90, 0x76, 0xde, 0xeb, 0xa0, 0x78, 0x18, 0xa2, 0x90,
|
||||
0x78, 0xbe, 0xcd, 0xa0, 0x79, 0xf8, 0x84, 0x90, 0x7a, 0x9e, 0xaf, 0xa0,
|
||||
0x7b, 0xd8, 0x66, 0x90, 0x7c, 0x7e, 0x91, 0xa0, 0x7d, 0xb8, 0x48, 0x90,
|
||||
0x7e, 0x5e, 0x73, 0xa0, 0x7f, 0x98, 0x2a, 0x90, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0xff, 0xff, 0x91, 0x26, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x90,
|
||||
0x01, 0x04, 0xff, 0xff, 0x8f, 0x80, 0x00, 0x08, 0xff, 0xff, 0x9d, 0x90,
|
||||
0x01, 0x0c, 0xff, 0xff, 0x9d, 0x90, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00,
|
||||
0x50, 0x44, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00,
|
||||
0x50, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xbb, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x04,
|
||||
0x1a, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x48, 0xa0, 0xff, 0xff,
|
||||
0xff, 0xff, 0x9f, 0xbb, 0x15, 0x90, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86,
|
||||
0x2a, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xf7, 0x90, 0xff, 0xff,
|
||||
0xff, 0xff, 0xcb, 0x89, 0x1a, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x23,
|
||||
0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x61, 0x26, 0x10, 0xff, 0xff,
|
||||
0xff, 0xff, 0xd6, 0xfe, 0x74, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x80,
|
||||
0xad, 0x90, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xc3, 0x90, 0xff, 0xff,
|
||||
0xff, 0xff, 0xdb, 0xc0, 0x90, 0x10, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xde,
|
||||
0xa5, 0x90, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0xac, 0x90, 0xff, 0xff,
|
||||
0xff, 0xff, 0xde, 0xbe, 0x87, 0x90, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x89,
|
||||
0x8e, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x69, 0x90, 0xff, 0xff,
|
||||
0xff, 0xff, 0xe1, 0x69, 0x70, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe2, 0x7e,
|
||||
0x4b, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x52, 0x90, 0xff, 0xff,
|
||||
0xff, 0xff, 0xe4, 0x5e, 0x2d, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x29,
|
||||
0x34, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x4a, 0x10, 0xff, 0xff,
|
||||
0xff, 0xff, 0xe7, 0x12, 0x51, 0x10, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x27,
|
||||
0x2c, 0x10, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xf2, 0x33, 0x10, 0xff, 0xff,
|
||||
0xff, 0xff, 0xea, 0x07, 0x0e, 0x10, 0xff, 0xff, 0xff, 0xff, 0xea, 0xd2,
|
||||
0x15, 0x10, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xf0, 0x10, 0xff, 0xff,
|
||||
0xff, 0xff, 0xec, 0xb1, 0xf7, 0x10, 0xff, 0xff, 0xff, 0xff, 0xed, 0xc6,
|
||||
0xd2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xee, 0x91, 0xd9, 0x10, 0xff, 0xff,
|
||||
0xff, 0xff, 0xef, 0xaf, 0xee, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x71,
|
||||
0xbb, 0x10, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xd0, 0x90, 0xff, 0xff,
|
||||
0xff, 0xff, 0xf2, 0x7f, 0xc1, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x6f,
|
||||
0xb2, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0xa3, 0x90, 0xff, 0xff,
|
||||
0xff, 0xff, 0xf5, 0x4f, 0x94, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x3f,
|
||||
0x85, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x76, 0x90, 0xff, 0xff,
|
||||
0xff, 0xff, 0xf8, 0x28, 0xa2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x0f,
|
||||
0x58, 0x90, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x84, 0x10, 0xff, 0xff,
|
||||
0xff, 0xff, 0xfa, 0xf8, 0x83, 0x20, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe8,
|
||||
0x66, 0x10, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x65, 0x20, 0xff, 0xff,
|
||||
0xff, 0xff, 0xfd, 0xc8, 0x48, 0x10, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb8,
|
||||
0x47, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa8, 0x2a, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x98, 0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88,
|
||||
0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x78, 0x0b, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0x71, 0x28, 0x90, 0x00, 0x00, 0x00, 0x00, 0x04, 0x61,
|
||||
0x27, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x51, 0x0a, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x06, 0x41, 0x09, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x30,
|
||||
0xec, 0x90, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x43, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x09, 0x10, 0xce, 0x90, 0x00, 0x00, 0x00, 0x00, 0x09, 0xad,
|
||||
0xbf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0xb0, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0b, 0xe0, 0xaf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd9,
|
||||
0xcd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x91, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0e, 0xb9, 0xaf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xa9,
|
||||
0xae, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x91, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x11, 0x89, 0x90, 0x20, 0x00, 0x00, 0x00, 0x00, 0x12, 0x79,
|
||||
0x73, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x72, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x14, 0x59, 0x55, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15, 0x49,
|
||||
0x54, 0x20, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x37, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x17, 0x29, 0x36, 0x20, 0x00, 0x00, 0x00, 0x00, 0x18, 0x22,
|
||||
0x53, 0x90, 0x00, 0x00, 0x00, 0x00, 0x19, 0x09, 0x18, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1a, 0x02, 0x35, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xf2,
|
||||
0x34, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe2, 0x17, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1c, 0xd2, 0x16, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xc1,
|
||||
0xf9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xf8, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1f, 0xa1, 0xdb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x20, 0x76,
|
||||
0x2b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0xbd, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x22, 0x56, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x23, 0x6a,
|
||||
0xda, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xef, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x25, 0x4a, 0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x15,
|
||||
0xd1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x9e, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x27, 0xfe, 0xed, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x29, 0x0a,
|
||||
0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xcf, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x2a, 0xea, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xbe,
|
||||
0xb1, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x7e, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x2d, 0x9e, 0x93, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xb3,
|
||||
0x60, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x75, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x30, 0x93, 0x42, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31, 0x67,
|
||||
0x92, 0x20, 0x00, 0x00, 0x00, 0x00, 0x32, 0x73, 0x24, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x33, 0x47, 0x74, 0x20, 0x00, 0x00, 0x00, 0x00, 0x34, 0x53,
|
||||
0x06, 0x90, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x56, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x36, 0x32, 0xe8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x37, 0x07,
|
||||
0x38, 0x20, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x05, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x38, 0xe7, 0x1a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x39, 0xfb,
|
||||
0xe7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xfc, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3b, 0xdb, 0xc9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xb0,
|
||||
0x18, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0xab, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x8f, 0xfa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9b,
|
||||
0x8d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xdc, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x41, 0x84, 0xa9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x4f,
|
||||
0xbe, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x8b, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x44, 0x2f, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x45, 0x44,
|
||||
0x6d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xd3, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x47, 0x2d, 0x8a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47, 0xd3,
|
||||
0xb5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x6c, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x49, 0xb3, 0x97, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xed,
|
||||
0x4e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0xb3, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x4c, 0xd6, 0x6a, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x7c,
|
||||
0x95, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x4c, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x4f, 0x5c, 0x77, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96,
|
||||
0x2e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x59, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x52, 0x76, 0x10, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53, 0x1c,
|
||||
0x3b, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xf2, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x54, 0xfc, 0x1d, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x56, 0x35,
|
||||
0xd4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x3a, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x58, 0x1e, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58, 0xc5,
|
||||
0x1c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xd3, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5a, 0xa4, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xde,
|
||||
0xb5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xe0, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5d, 0xbe, 0x97, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x64,
|
||||
0xc2, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x79, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x60, 0x4d, 0xde, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x61, 0x87,
|
||||
0x95, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0xc0, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x67, 0x77, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0d,
|
||||
0xa2, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x59, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x65, 0xed, 0x84, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x67, 0x27,
|
||||
0x3b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x66, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x69, 0x07, 0x1d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69, 0xad,
|
||||
0x48, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xff, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6b, 0x96, 0x65, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd0,
|
||||
0x1c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x47, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6e, 0xaf, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x56,
|
||||
0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xe0, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x71, 0x36, 0x0b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f,
|
||||
0xc2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xed, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x74, 0x4f, 0xa4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x74, 0xff,
|
||||
0x09, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0xc0, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x76, 0xde, 0xeb, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18,
|
||||
0xa2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xcd, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x79, 0xf8, 0x84, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x9e,
|
||||
0xaf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x66, 0x90, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0x7e, 0x91, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xb8,
|
||||
0x48, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x73, 0xa0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x98, 0x2a, 0x90, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0xff, 0xff, 0x91, 0x26, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x90, 0x01,
|
||||
0x04, 0xff, 0xff, 0x8f, 0x80, 0x00, 0x08, 0xff, 0xff, 0x9d, 0x90, 0x01,
|
||||
0x0c, 0xff, 0xff, 0x9d, 0x90, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, 0x50,
|
||||
0x44, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, 0x50,
|
||||
0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x0a, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x2c, 0x4d, 0x33,
|
||||
0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, 0x2e, 0x31, 0x2e, 0x30,
|
||||
0x0a
|
||||
};
|
||||
unsigned int America_Los_Angeles_len = 2845;
|
||||
unsigned char America_New_York[] = {
|
||||
0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00,
|
||||
0x9e, 0xa6, 0x1e, 0x70, 0x9f, 0xba, 0xeb, 0x60, 0xa0, 0x86, 0x00, 0x70,
|
||||
0xa1, 0x9a, 0xcd, 0x60, 0xa2, 0x65, 0xe2, 0x70, 0xa3, 0x83, 0xe9, 0xe0,
|
||||
0xa4, 0x6a, 0xae, 0x70, 0xa5, 0x35, 0xa7, 0x60, 0xa6, 0x53, 0xca, 0xf0,
|
||||
0xa7, 0x15, 0x89, 0x60, 0xa8, 0x33, 0xac, 0xf0, 0xa8, 0xfe, 0xa5, 0xe0,
|
||||
0xaa, 0x13, 0x8e, 0xf0, 0xaa, 0xde, 0x87, 0xe0, 0xab, 0xf3, 0x70, 0xf0,
|
||||
0xac, 0xbe, 0x69, 0xe0, 0xad, 0xd3, 0x52, 0xf0, 0xae, 0x9e, 0x4b, 0xe0,
|
||||
0xaf, 0xb3, 0x34, 0xf0, 0xb0, 0x7e, 0x2d, 0xe0, 0xb1, 0x9c, 0x51, 0x70,
|
||||
0xb2, 0x67, 0x4a, 0x60, 0xb3, 0x7c, 0x33, 0x70, 0xb4, 0x47, 0x2c, 0x60,
|
||||
0xb5, 0x5c, 0x15, 0x70, 0xb6, 0x27, 0x0e, 0x60, 0xb7, 0x3b, 0xf7, 0x70,
|
||||
0xb8, 0x06, 0xf0, 0x60, 0xb9, 0x1b, 0xd9, 0x70, 0xb9, 0xe6, 0xd2, 0x60,
|
||||
0xbb, 0x04, 0xf5, 0xf0, 0xbb, 0xc6, 0xb4, 0x60, 0xbc, 0xe4, 0xd7, 0xf0,
|
||||
0xbd, 0xaf, 0xd0, 0xe0, 0xbe, 0xc4, 0xb9, 0xf0, 0xbf, 0x8f, 0xb2, 0xe0,
|
||||
0xc0, 0xa4, 0x9b, 0xf0, 0xc1, 0x6f, 0x94, 0xe0, 0xc2, 0x84, 0x7d, 0xf0,
|
||||
0xc3, 0x4f, 0x76, 0xe0, 0xc4, 0x64, 0x5f, 0xf0, 0xc5, 0x2f, 0x58, 0xe0,
|
||||
0xc6, 0x4d, 0x7c, 0x70, 0xc7, 0x0f, 0x3a, 0xe0, 0xc8, 0x2d, 0x5e, 0x70,
|
||||
0xc8, 0xf8, 0x57, 0x60, 0xca, 0x0d, 0x40, 0x70, 0xca, 0xd8, 0x39, 0x60,
|
||||
0xcb, 0x88, 0xf0, 0x70, 0xd2, 0x23, 0xf4, 0x70, 0xd2, 0x60, 0xfb, 0xe0,
|
||||
0xd3, 0x75, 0xe4, 0xf0, 0xd4, 0x40, 0xdd, 0xe0, 0xd5, 0x55, 0xc6, 0xf0,
|
||||
0xd6, 0x20, 0xbf, 0xe0, 0xd7, 0x35, 0xa8, 0xf0, 0xd8, 0x00, 0xa1, 0xe0,
|
||||
0xd9, 0x15, 0x8a, 0xf0, 0xd9, 0xe0, 0x83, 0xe0, 0xda, 0xfe, 0xa7, 0x70,
|
||||
0xdb, 0xc0, 0x65, 0xe0, 0xdc, 0xde, 0x89, 0x70, 0xdd, 0xa9, 0x82, 0x60,
|
||||
0xde, 0xbe, 0x6b, 0x70, 0xdf, 0x89, 0x64, 0x60, 0xe0, 0x9e, 0x4d, 0x70,
|
||||
0xe1, 0x69, 0x46, 0x60, 0xe2, 0x7e, 0x2f, 0x70, 0xe3, 0x49, 0x28, 0x60,
|
||||
0xe4, 0x5e, 0x11, 0x70, 0xe5, 0x57, 0x2e, 0xe0, 0xe6, 0x47, 0x2d, 0xf0,
|
||||
0xe7, 0x37, 0x10, 0xe0, 0xe8, 0x27, 0x0f, 0xf0, 0xe9, 0x16, 0xf2, 0xe0,
|
||||
0xea, 0x06, 0xf1, 0xf0, 0xea, 0xf6, 0xd4, 0xe0, 0xeb, 0xe6, 0xd3, 0xf0,
|
||||
0xec, 0xd6, 0xb6, 0xe0, 0xed, 0xc6, 0xb5, 0xf0, 0xee, 0xbf, 0xd3, 0x60,
|
||||
0xef, 0xaf, 0xd2, 0x70, 0xf0, 0x9f, 0xb5, 0x60, 0xf1, 0x8f, 0xb4, 0x70,
|
||||
0xf2, 0x7f, 0x97, 0x60, 0xf3, 0x6f, 0x96, 0x70, 0xf4, 0x5f, 0x79, 0x60,
|
||||
0xf5, 0x4f, 0x78, 0x70, 0xf6, 0x3f, 0x5b, 0x60, 0xf7, 0x2f, 0x5a, 0x70,
|
||||
0xf8, 0x28, 0x77, 0xe0, 0xf9, 0x0f, 0x3c, 0x70, 0xfa, 0x08, 0x59, 0xe0,
|
||||
0xfa, 0xf8, 0x58, 0xf0, 0xfb, 0xe8, 0x3b, 0xe0, 0xfc, 0xd8, 0x3a, 0xf0,
|
||||
0xfd, 0xc8, 0x1d, 0xe0, 0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xa7, 0xff, 0xe0,
|
||||
0x00, 0x97, 0xfe, 0xf0, 0x01, 0x87, 0xe1, 0xe0, 0x02, 0x77, 0xe0, 0xf0,
|
||||
0x03, 0x70, 0xfe, 0x60, 0x04, 0x60, 0xfd, 0x70, 0x05, 0x50, 0xe0, 0x60,
|
||||
0x06, 0x40, 0xdf, 0x70, 0x07, 0x30, 0xc2, 0x60, 0x07, 0x8d, 0x19, 0x70,
|
||||
0x09, 0x10, 0xa4, 0x60, 0x09, 0xad, 0x94, 0xf0, 0x0a, 0xf0, 0x86, 0x60,
|
||||
0x0b, 0xe0, 0x85, 0x70, 0x0c, 0xd9, 0xa2, 0xe0, 0x0d, 0xc0, 0x67, 0x70,
|
||||
0x0e, 0xb9, 0x84, 0xe0, 0x0f, 0xa9, 0x83, 0xf0, 0x10, 0x99, 0x66, 0xe0,
|
||||
0x11, 0x89, 0x65, 0xf0, 0x12, 0x79, 0x48, 0xe0, 0x13, 0x69, 0x47, 0xf0,
|
||||
0x14, 0x59, 0x2a, 0xe0, 0x15, 0x49, 0x29, 0xf0, 0x16, 0x39, 0x0c, 0xe0,
|
||||
0x17, 0x29, 0x0b, 0xf0, 0x18, 0x22, 0x29, 0x60, 0x19, 0x08, 0xed, 0xf0,
|
||||
0x1a, 0x02, 0x0b, 0x60, 0x1a, 0xf2, 0x0a, 0x70, 0x1b, 0xe1, 0xed, 0x60,
|
||||
0x1c, 0xd1, 0xec, 0x70, 0x1d, 0xc1, 0xcf, 0x60, 0x1e, 0xb1, 0xce, 0x70,
|
||||
0x1f, 0xa1, 0xb1, 0x60, 0x20, 0x76, 0x00, 0xf0, 0x21, 0x81, 0x93, 0x60,
|
||||
0x22, 0x55, 0xe2, 0xf0, 0x23, 0x6a, 0xaf, 0xe0, 0x24, 0x35, 0xc4, 0xf0,
|
||||
0x25, 0x4a, 0x91, 0xe0, 0x26, 0x15, 0xa6, 0xf0, 0x27, 0x2a, 0x73, 0xe0,
|
||||
0x27, 0xfe, 0xc3, 0x70, 0x29, 0x0a, 0x55, 0xe0, 0x29, 0xde, 0xa5, 0x70,
|
||||
0x2a, 0xea, 0x37, 0xe0, 0x2b, 0xbe, 0x87, 0x70, 0x2c, 0xd3, 0x54, 0x60,
|
||||
0x2d, 0x9e, 0x69, 0x70, 0x2e, 0xb3, 0x36, 0x60, 0x2f, 0x7e, 0x4b, 0x70,
|
||||
0x30, 0x93, 0x18, 0x60, 0x31, 0x67, 0x67, 0xf0, 0x32, 0x72, 0xfa, 0x60,
|
||||
0x33, 0x47, 0x49, 0xf0, 0x34, 0x52, 0xdc, 0x60, 0x35, 0x27, 0x2b, 0xf0,
|
||||
0x36, 0x32, 0xbe, 0x60, 0x37, 0x07, 0x0d, 0xf0, 0x38, 0x1b, 0xda, 0xe0,
|
||||
0x38, 0xe6, 0xef, 0xf0, 0x39, 0xfb, 0xbc, 0xe0, 0x3a, 0xc6, 0xd1, 0xf0,
|
||||
0x3b, 0xdb, 0x9e, 0xe0, 0x3c, 0xaf, 0xee, 0x70, 0x3d, 0xbb, 0x80, 0xe0,
|
||||
0x3e, 0x8f, 0xd0, 0x70, 0x3f, 0x9b, 0x62, 0xe0, 0x40, 0x6f, 0xb2, 0x70,
|
||||
0x41, 0x84, 0x7f, 0x60, 0x42, 0x4f, 0x94, 0x70, 0x43, 0x64, 0x61, 0x60,
|
||||
0x44, 0x2f, 0x76, 0x70, 0x45, 0x44, 0x43, 0x60, 0x45, 0xf3, 0xa8, 0xf0,
|
||||
0x47, 0x2d, 0x5f, 0xe0, 0x47, 0xd3, 0x8a, 0xf0, 0x49, 0x0d, 0x41, 0xe0,
|
||||
0x49, 0xb3, 0x6c, 0xf0, 0x4a, 0xed, 0x23, 0xe0, 0x4b, 0x9c, 0x89, 0x70,
|
||||
0x4c, 0xd6, 0x40, 0x60, 0x4d, 0x7c, 0x6b, 0x70, 0x4e, 0xb6, 0x22, 0x60,
|
||||
0x4f, 0x5c, 0x4d, 0x70, 0x50, 0x96, 0x04, 0x60, 0x51, 0x3c, 0x2f, 0x70,
|
||||
0x52, 0x75, 0xe6, 0x60, 0x53, 0x1c, 0x11, 0x70, 0x54, 0x55, 0xc8, 0x60,
|
||||
0x54, 0xfb, 0xf3, 0x70, 0x56, 0x35, 0xaa, 0x60, 0x56, 0xe5, 0x0f, 0xf0,
|
||||
0x58, 0x1e, 0xc6, 0xe0, 0x58, 0xc4, 0xf1, 0xf0, 0x59, 0xfe, 0xa8, 0xe0,
|
||||
0x5a, 0xa4, 0xd3, 0xf0, 0x5b, 0xde, 0x8a, 0xe0, 0x5c, 0x84, 0xb5, 0xf0,
|
||||
0x5d, 0xbe, 0x6c, 0xe0, 0x5e, 0x64, 0x97, 0xf0, 0x5f, 0x9e, 0x4e, 0xe0,
|
||||
0x60, 0x4d, 0xb4, 0x70, 0x61, 0x87, 0x6b, 0x60, 0x62, 0x2d, 0x96, 0x70,
|
||||
0x63, 0x67, 0x4d, 0x60, 0x64, 0x0d, 0x78, 0x70, 0x65, 0x47, 0x2f, 0x60,
|
||||
0x65, 0xed, 0x5a, 0x70, 0x67, 0x27, 0x11, 0x60, 0x67, 0xcd, 0x3c, 0x70,
|
||||
0x69, 0x06, 0xf3, 0x60, 0x69, 0xad, 0x1e, 0x70, 0x6a, 0xe6, 0xd5, 0x60,
|
||||
0x6b, 0x96, 0x3a, 0xf0, 0x6c, 0xcf, 0xf1, 0xe0, 0x6d, 0x76, 0x1c, 0xf0,
|
||||
0x6e, 0xaf, 0xd3, 0xe0, 0x6f, 0x55, 0xfe, 0xf0, 0x70, 0x8f, 0xb5, 0xe0,
|
||||
0x71, 0x35, 0xe0, 0xf0, 0x72, 0x6f, 0x97, 0xe0, 0x73, 0x15, 0xc2, 0xf0,
|
||||
0x74, 0x4f, 0x79, 0xe0, 0x74, 0xfe, 0xdf, 0x70, 0x76, 0x38, 0x96, 0x60,
|
||||
0x76, 0xde, 0xc1, 0x70, 0x78, 0x18, 0x78, 0x60, 0x78, 0xbe, 0xa3, 0x70,
|
||||
0x79, 0xf8, 0x5a, 0x60, 0x7a, 0x9e, 0x85, 0x70, 0x7b, 0xd8, 0x3c, 0x60,
|
||||
0x7c, 0x7e, 0x67, 0x70, 0x7d, 0xb8, 0x1e, 0x60, 0x7e, 0x5e, 0x49, 0x70,
|
||||
0x7f, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x04,
|
||||
0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x0c,
|
||||
0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, 0x45, 0x44,
|
||||
0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x57, 0x54, 0x00, 0x45, 0x50,
|
||||
0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x03, 0xf0, 0x90,
|
||||
0xff, 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x1e, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0x9f, 0xba, 0xeb, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, 0x00, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xcd, 0x60, 0xff, 0xff, 0xff, 0xff,
|
||||
0xa2, 0x65, 0xe2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x83, 0xe9, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xa4, 0x6a, 0xae, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0xa5, 0x35, 0xa7, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa6, 0x53, 0xca, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xa7, 0x15, 0x89, 0x60, 0xff, 0xff, 0xff, 0xff,
|
||||
0xa8, 0x33, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xfe, 0xa5, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xaa, 0x13, 0x8e, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xaa, 0xde, 0x87, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xf3, 0x70, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xac, 0xbe, 0x69, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xad, 0xd3, 0x52, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xae, 0x9e, 0x4b, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xaf, 0xb3, 0x34, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xb0, 0x7e, 0x2d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x9c, 0x51, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xb2, 0x67, 0x4a, 0x60, 0xff, 0xff, 0xff, 0xff,
|
||||
0xb3, 0x7c, 0x33, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x47, 0x2c, 0x60,
|
||||
0xff, 0xff, 0xff, 0xff, 0xb5, 0x5c, 0x15, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0xb6, 0x27, 0x0e, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x3b, 0xf7, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xb8, 0x06, 0xf0, 0x60, 0xff, 0xff, 0xff, 0xff,
|
||||
0xb9, 0x1b, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xe6, 0xd2, 0x60,
|
||||
0xff, 0xff, 0xff, 0xff, 0xbb, 0x04, 0xf5, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xbb, 0xc6, 0xb4, 0x60, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe4, 0xd7, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xbd, 0xaf, 0xd0, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xbe, 0xc4, 0xb9, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x8f, 0xb2, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xc0, 0xa4, 0x9b, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xc1, 0x6f, 0x94, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x84, 0x7d, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xc3, 0x4f, 0x76, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xc4, 0x64, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x2f, 0x58, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xc6, 0x4d, 0x7c, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0xc7, 0x0f, 0x3a, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x2d, 0x5e, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xc8, 0xf8, 0x57, 0x60, 0xff, 0xff, 0xff, 0xff,
|
||||
0xca, 0x0d, 0x40, 0x70, 0xff, 0xff, 0xff, 0xff, 0xca, 0xd8, 0x39, 0x60,
|
||||
0xff, 0xff, 0xff, 0xff, 0xcb, 0x88, 0xf0, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0xd2, 0x23, 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x60, 0xfb, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xd3, 0x75, 0xe4, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xd4, 0x40, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x55, 0xc6, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xd6, 0x20, 0xbf, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xd7, 0x35, 0xa8, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0xa1, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xd9, 0x15, 0x8a, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xd9, 0xe0, 0x83, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xa7, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xdb, 0xc0, 0x65, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xdc, 0xde, 0x89, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0x82, 0x60,
|
||||
0xff, 0xff, 0xff, 0xff, 0xde, 0xbe, 0x6b, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0xdf, 0x89, 0x64, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x4d, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xe1, 0x69, 0x46, 0x60, 0xff, 0xff, 0xff, 0xff,
|
||||
0xe2, 0x7e, 0x2f, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x28, 0x60,
|
||||
0xff, 0xff, 0xff, 0xff, 0xe4, 0x5e, 0x11, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0xe5, 0x57, 0x2e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x2d, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xe7, 0x37, 0x10, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xe8, 0x27, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x16, 0xf2, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xea, 0x06, 0xf1, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xea, 0xf6, 0xd4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xd3, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xec, 0xd6, 0xb6, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xed, 0xc6, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xee, 0xbf, 0xd3, 0x60,
|
||||
0xff, 0xff, 0xff, 0xff, 0xef, 0xaf, 0xd2, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf0, 0x9f, 0xb5, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xb4, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf2, 0x7f, 0x97, 0x60, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf3, 0x6f, 0x96, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0x79, 0x60,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf5, 0x4f, 0x78, 0x70, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf6, 0x3f, 0x5b, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x5a, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf8, 0x28, 0x77, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf9, 0x0f, 0x3c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x59, 0xe0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xfa, 0xf8, 0x58, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfb, 0xe8, 0x3b, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x3a, 0xf0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xfd, 0xc8, 0x1d, 0xe0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xff, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, 0xe0, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x03, 0x70, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x60, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0xe0, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x06, 0x40, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x07, 0x30, 0xc2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x19, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x09, 0x10, 0xa4, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0xad, 0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x86, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0b, 0xe0, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0xd9, 0xa2, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x67, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0e, 0xb9, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0f, 0xa9, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x66, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x11, 0x89, 0x65, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x12, 0x79, 0x48, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x47, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x14, 0x59, 0x2a, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x15, 0x49, 0x29, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x0c, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x17, 0x29, 0x0b, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x22, 0x29, 0x60, 0x00, 0x00, 0x00, 0x00, 0x19, 0x08, 0xed, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x0b, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1a, 0xf2, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0xed, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1c, 0xd1, 0xec, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1d, 0xc1, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xce, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1f, 0xa1, 0xb1, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x20, 0x76, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x93, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x22, 0x55, 0xe2, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x23, 0x6a, 0xaf, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xc4, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x25, 0x4a, 0x91, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x26, 0x15, 0xa6, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x73, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x27, 0xfe, 0xc3, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, 0x0a, 0x55, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xa5, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2a, 0xea, 0x37, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2b, 0xbe, 0x87, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x54, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2d, 0x9e, 0x69, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2e, 0xb3, 0x36, 0x60, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x4b, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x30, 0x93, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x31, 0x67, 0x67, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xfa, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x47, 0x49, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x34, 0x52, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x2b, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x36, 0x32, 0xbe, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x37, 0x07, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0xda, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x38, 0xe6, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x39, 0xfb, 0xbc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xd1, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3b, 0xdb, 0x9e, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3c, 0xaf, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x80, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3e, 0x8f, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3f, 0x9b, 0x62, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb2, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x41, 0x84, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x42, 0x4f, 0x94, 0x70, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x61, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x44, 0x2f, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x45, 0x44, 0x43, 0x60, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xa8, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x2d, 0x5f, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x47, 0xd3, 0x8a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x41, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x49, 0xb3, 0x6c, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4a, 0xed, 0x23, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0x89, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x4c, 0xd6, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4d, 0x7c, 0x6b, 0x70, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x22, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x4f, 0x5c, 0x4d, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x50, 0x96, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x2f, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x52, 0x75, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x53, 0x1c, 0x11, 0x70, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xc8, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x54, 0xfb, 0xf3, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x56, 0x35, 0xaa, 0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x0f, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x58, 0x1e, 0xc6, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x58, 0xc4, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xa8, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x5a, 0xa4, 0xd3, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5b, 0xde, 0x8a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xb5, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x5d, 0xbe, 0x6c, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5e, 0x64, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x4e, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x60, 0x4d, 0xb4, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x61, 0x87, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0x96, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x63, 0x67, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x64, 0x0d, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x2f, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x65, 0xed, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x67, 0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x3c, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x69, 0x06, 0xf3, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x69, 0xad, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xd5, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6b, 0x96, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6c, 0xcf, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x1c, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6e, 0xaf, 0xd3, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6f, 0x55, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xb5, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x71, 0x35, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x72, 0x6f, 0x97, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xc2, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x74, 0x4f, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x74, 0xfe, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0x96, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x76, 0xde, 0xc1, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x78, 0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xa3, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x79, 0xf8, 0x5a, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7a, 0x9e, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x3c, 0x60,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7c, 0x7e, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7d, 0xb8, 0x1e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x49, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x98, 0x00, 0x60, 0x00, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff,
|
||||
0xff, 0xc7, 0xc0, 0x01, 0x04, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff,
|
||||
0xff, 0xc7, 0xc0, 0x01, 0x0c, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c,
|
||||
0x4d, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45,
|
||||
0x57, 0x54, 0x00, 0x45, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44,
|
||||
0x54, 0x2c, 0x4d, 0x33, 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31,
|
||||
0x2e, 0x31, 0x2e, 0x30, 0x0a
|
||||
};
|
||||
unsigned int America_New_York_len = 3545;
|
||||
unsigned char Australia_Sydney[] = {
|
||||
0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0e, 0x80, 0x00, 0x00, 0x00,
|
||||
0x9c, 0x4e, 0xa6, 0x9c, 0x9c, 0xbc, 0x20, 0xf0, 0xcb, 0x54, 0xb3, 0x00,
|
||||
0xcb, 0xc7, 0x57, 0x70, 0xcc, 0xb7, 0x56, 0x80, 0xcd, 0xa7, 0x39, 0x70,
|
||||
0xce, 0xa0, 0x73, 0x00, 0xcf, 0x87, 0x1b, 0x70, 0x03, 0x70, 0x39, 0x80,
|
||||
0x04, 0x0d, 0x1c, 0x00, 0x05, 0x50, 0x1b, 0x80, 0x05, 0xf6, 0x38, 0x80,
|
||||
0x07, 0x2f, 0xfd, 0x80, 0x07, 0xd6, 0x1a, 0x80, 0x09, 0x0f, 0xdf, 0x80,
|
||||
0x09, 0xb5, 0xfc, 0x80, 0x0a, 0xef, 0xc1, 0x80, 0x0b, 0x9f, 0x19, 0x00,
|
||||
0x0c, 0xd8, 0xde, 0x00, 0x0d, 0x7e, 0xfb, 0x00, 0x0e, 0xb8, 0xc0, 0x00,
|
||||
0x0f, 0x5e, 0xdd, 0x00, 0x10, 0x98, 0xa2, 0x00, 0x11, 0x3e, 0xbf, 0x00,
|
||||
0x12, 0x78, 0x84, 0x00, 0x13, 0x1e, 0xa1, 0x00, 0x14, 0x58, 0x66, 0x00,
|
||||
0x14, 0xfe, 0x83, 0x00, 0x16, 0x38, 0x48, 0x00, 0x17, 0x0c, 0x89, 0x80,
|
||||
0x18, 0x21, 0x64, 0x80, 0x18, 0xc7, 0x81, 0x80, 0x1a, 0x01, 0x46, 0x80,
|
||||
0x1a, 0xa7, 0x63, 0x80, 0x1b, 0xe1, 0x28, 0x80, 0x1c, 0x87, 0x45, 0x80,
|
||||
0x1d, 0xc1, 0x0a, 0x80, 0x1e, 0x79, 0x9c, 0x80, 0x1f, 0x97, 0xb2, 0x00,
|
||||
0x20, 0x59, 0x7e, 0x80, 0x21, 0x80, 0xce, 0x80, 0x22, 0x42, 0x9b, 0x00,
|
||||
0x23, 0x69, 0xeb, 0x00, 0x24, 0x22, 0x7d, 0x00, 0x25, 0x49, 0xcd, 0x00,
|
||||
0x25, 0xef, 0xea, 0x00, 0x27, 0x29, 0xaf, 0x00, 0x27, 0xcf, 0xcc, 0x00,
|
||||
0x29, 0x09, 0x91, 0x00, 0x29, 0xaf, 0xae, 0x00, 0x2a, 0xe9, 0x73, 0x00,
|
||||
0x2b, 0x98, 0xca, 0x80, 0x2c, 0xd2, 0x8f, 0x80, 0x2d, 0x78, 0xac, 0x80,
|
||||
0x2e, 0xb2, 0x71, 0x80, 0x2f, 0x58, 0x8e, 0x80, 0x30, 0x92, 0x53, 0x80,
|
||||
0x31, 0x5d, 0x5a, 0x80, 0x32, 0x72, 0x35, 0x80, 0x33, 0x3d, 0x3c, 0x80,
|
||||
0x34, 0x52, 0x17, 0x80, 0x35, 0x1d, 0x1e, 0x80, 0x36, 0x31, 0xf9, 0x80,
|
||||
0x36, 0xfd, 0x00, 0x80, 0x38, 0x1b, 0x16, 0x00, 0x38, 0xdc, 0xe2, 0x80,
|
||||
0x39, 0xa7, 0xe9, 0x80, 0x3a, 0xbc, 0xc4, 0x80, 0x3b, 0xda, 0xda, 0x00,
|
||||
0x3c, 0xa5, 0xe1, 0x00, 0x3d, 0xba, 0xbc, 0x00, 0x3e, 0x85, 0xc3, 0x00,
|
||||
0x3f, 0x9a, 0x9e, 0x00, 0x40, 0x65, 0xa5, 0x00, 0x41, 0x83, 0xba, 0x80,
|
||||
0x42, 0x45, 0x87, 0x00, 0x43, 0x63, 0x9c, 0x80, 0x44, 0x2e, 0xa3, 0x80,
|
||||
0x45, 0x43, 0x7e, 0x80, 0x46, 0x05, 0x4b, 0x00, 0x47, 0x23, 0x60, 0x80,
|
||||
0x47, 0xf7, 0xa2, 0x00, 0x48, 0xe7, 0x93, 0x00, 0x49, 0xd7, 0x84, 0x00,
|
||||
0x4a, 0xc7, 0x75, 0x00, 0x4b, 0xb7, 0x66, 0x00, 0x4c, 0xa7, 0x57, 0x00,
|
||||
0x4d, 0x97, 0x48, 0x00, 0x4e, 0x87, 0x39, 0x00, 0x4f, 0x77, 0x2a, 0x00,
|
||||
0x50, 0x70, 0x55, 0x80, 0x51, 0x60, 0x46, 0x80, 0x52, 0x50, 0x37, 0x80,
|
||||
0x53, 0x40, 0x28, 0x80, 0x54, 0x30, 0x19, 0x80, 0x55, 0x20, 0x0a, 0x80,
|
||||
0x56, 0x0f, 0xfb, 0x80, 0x56, 0xff, 0xec, 0x80, 0x57, 0xef, 0xdd, 0x80,
|
||||
0x58, 0xdf, 0xce, 0x80, 0x59, 0xcf, 0xbf, 0x80, 0x5a, 0xbf, 0xb0, 0x80,
|
||||
0x5b, 0xb8, 0xdc, 0x00, 0x5c, 0xa8, 0xcd, 0x00, 0x5d, 0x98, 0xbe, 0x00,
|
||||
0x5e, 0x88, 0xaf, 0x00, 0x5f, 0x78, 0xa0, 0x00, 0x60, 0x68, 0x91, 0x00,
|
||||
0x61, 0x58, 0x82, 0x00, 0x62, 0x48, 0x73, 0x00, 0x63, 0x38, 0x64, 0x00,
|
||||
0x64, 0x28, 0x55, 0x00, 0x65, 0x18, 0x46, 0x00, 0x66, 0x11, 0x71, 0x80,
|
||||
0x67, 0x01, 0x62, 0x80, 0x67, 0xf1, 0x53, 0x80, 0x68, 0xe1, 0x44, 0x80,
|
||||
0x69, 0xd1, 0x35, 0x80, 0x6a, 0xc1, 0x26, 0x80, 0x6b, 0xb1, 0x17, 0x80,
|
||||
0x6c, 0xa1, 0x08, 0x80, 0x6d, 0x90, 0xf9, 0x80, 0x6e, 0x80, 0xea, 0x80,
|
||||
0x6f, 0x70, 0xdb, 0x80, 0x70, 0x6a, 0x07, 0x00, 0x71, 0x59, 0xf8, 0x00,
|
||||
0x72, 0x49, 0xe9, 0x00, 0x73, 0x39, 0xda, 0x00, 0x74, 0x29, 0xcb, 0x00,
|
||||
0x75, 0x19, 0xbc, 0x00, 0x76, 0x09, 0xad, 0x00, 0x76, 0xf9, 0x9e, 0x00,
|
||||
0x77, 0xe9, 0x8f, 0x00, 0x78, 0xd9, 0x80, 0x00, 0x79, 0xc9, 0x71, 0x00,
|
||||
0x7a, 0xb9, 0x62, 0x00, 0x7b, 0xb2, 0x8d, 0x80, 0x7c, 0xa2, 0x7e, 0x80,
|
||||
0x7d, 0x92, 0x6f, 0x80, 0x7e, 0x82, 0x60, 0x80, 0x7f, 0x72, 0x51, 0x80,
|
||||
0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
|
||||
0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x00, 0x00,
|
||||
0x8d, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xb0, 0x01, 0x04, 0x00, 0x00,
|
||||
0x8c, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x9a, 0xb0, 0x01, 0x04, 0x00, 0x00,
|
||||
0x8c, 0xa0, 0x00, 0x09, 0x4c, 0x4d, 0x54, 0x00, 0x41, 0x45, 0x44, 0x54,
|
||||
0x00, 0x41, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0e,
|
||||
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x73, 0x16, 0x7f, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x9c, 0x4e, 0xa6, 0x9c,
|
||||
0xff, 0xff, 0xff, 0xff, 0x9c, 0xbc, 0x20, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xcb, 0x54, 0xb3, 0x00, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xc7, 0x57, 0x70,
|
||||
0xff, 0xff, 0xff, 0xff, 0xcc, 0xb7, 0x56, 0x80, 0xff, 0xff, 0xff, 0xff,
|
||||
0xcd, 0xa7, 0x39, 0x70, 0xff, 0xff, 0xff, 0xff, 0xce, 0xa0, 0x73, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xcf, 0x87, 0x1b, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x70, 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0d, 0x1c, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0x1b, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0xf6, 0x38, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x2f, 0xfd, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x07, 0xd6, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0x0f, 0xdf, 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xb5, 0xfc, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0a, 0xef, 0xc1, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x9f, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd8, 0xde, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0d, 0x7e, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0e, 0xb8, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x5e, 0xdd, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x98, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x11, 0x3e, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x78, 0x84, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x13, 0x1e, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x14, 0x58, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xfe, 0x83, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x16, 0x38, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x17, 0x0c, 0x89, 0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x21, 0x64, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0xc7, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1a, 0x01, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xa7, 0x63, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0x28, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x87, 0x45, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xc1, 0x0a, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1e, 0x79, 0x9c, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1f, 0x97, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x59, 0x7e, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x21, 0x80, 0xce, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x22, 0x42, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x69, 0xeb, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x24, 0x22, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x25, 0x49, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xef, 0xea, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x27, 0x29, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x27, 0xcf, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x09, 0x91, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x29, 0xaf, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2a, 0xe9, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x98, 0xca, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2c, 0xd2, 0x8f, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2d, 0x78, 0xac, 0x80, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xb2, 0x71, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2f, 0x58, 0x8e, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x30, 0x92, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5d, 0x5a, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0x35, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x3d, 0x3c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52, 0x17, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x1e, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x36, 0x31, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x36, 0xfd, 0x00, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x38, 0xdc, 0xe2, 0x80, 0x00, 0x00, 0x00, 0x00, 0x39, 0xa7, 0xe9, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3a, 0xbc, 0xc4, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3b, 0xda, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xa5, 0xe1, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3d, 0xba, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3e, 0x85, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9a, 0x9e, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x65, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x41, 0x83, 0xba, 0x80, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0x87, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x43, 0x63, 0x9c, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x44, 0x2e, 0xa3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x45, 0x43, 0x7e, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x47, 0x23, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x47, 0xf7, 0xa2, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x48, 0xe7, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x49, 0xd7, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xc7, 0x75, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x4b, 0xb7, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4c, 0xa7, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x97, 0x48, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x4e, 0x87, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4f, 0x77, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x70, 0x55, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x51, 0x60, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x52, 0x50, 0x37, 0x80, 0x00, 0x00, 0x00, 0x00, 0x53, 0x40, 0x28, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x54, 0x30, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x55, 0x20, 0x0a, 0x80, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0f, 0xfb, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x56, 0xff, 0xec, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x57, 0xef, 0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x58, 0xdf, 0xce, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x59, 0xcf, 0xbf, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5a, 0xbf, 0xb0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xb8, 0xdc, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x5c, 0xa8, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5d, 0x98, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x88, 0xaf, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x5f, 0x78, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x60, 0x68, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x58, 0x82, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x62, 0x48, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x63, 0x38, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0x55, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x65, 0x18, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x66, 0x11, 0x71, 0x80, 0x00, 0x00, 0x00, 0x00, 0x67, 0x01, 0x62, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x67, 0xf1, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x68, 0xe1, 0x44, 0x80, 0x00, 0x00, 0x00, 0x00, 0x69, 0xd1, 0x35, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6a, 0xc1, 0x26, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6b, 0xb1, 0x17, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xa1, 0x08, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6d, 0x90, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6e, 0x80, 0xea, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0xdb, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x70, 0x6a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x71, 0x59, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x49, 0xe9, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x73, 0x39, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x74, 0x29, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x19, 0xbc, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x76, 0x09, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x76, 0xf9, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xe9, 0x8f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x78, 0xd9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x79, 0xc9, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xb9, 0x62, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7b, 0xb2, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7c, 0xa2, 0x7e, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x92, 0x6f, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7e, 0x82, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7f, 0x72, 0x51, 0x80, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
||||
0x01, 0x02, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
|
||||
0x03, 0x04, 0x03, 0x00, 0x00, 0x8d, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x9a,
|
||||
0xb0, 0x01, 0x04, 0x00, 0x00, 0x8c, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x9a,
|
||||
0xb0, 0x01, 0x04, 0x00, 0x00, 0x8c, 0xa0, 0x00, 0x09, 0x4c, 0x4d, 0x54,
|
||||
0x00, 0x41, 0x45, 0x44, 0x54, 0x00, 0x41, 0x45, 0x53, 0x54, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x45,
|
||||
0x53, 0x54, 0x2d, 0x31, 0x30, 0x41, 0x45, 0x44, 0x54, 0x2c, 0x4d, 0x31,
|
||||
0x30, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x4d, 0x34, 0x2e, 0x31, 0x2e, 0x30,
|
||||
0x2f, 0x33, 0x0a
|
||||
};
|
||||
unsigned int Australia_Sydney_len = 2223;
|
370
absl/time/time.cc
Normal file
370
absl/time/time.cc
Normal file
|
@ -0,0 +1,370 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The implementation of the absl::Time class, which is declared in
|
||||
// //absl/time.h.
|
||||
//
|
||||
// The representation for a absl::Time is a absl::Duration offset from the
|
||||
// epoch. We use the traditional Unix epoch (1970-01-01 00:00:00 +0000)
|
||||
// for convenience, but this is not exposed in the API and could be changed.
|
||||
//
|
||||
// NOTE: To keep type verbosity to a minimum, the following variable naming
|
||||
// conventions are used throughout this file.
|
||||
//
|
||||
// cz: A cctz::time_zone
|
||||
// tz: A absl::TimeZone
|
||||
// cl: A cctz::time_zone::civil_lookup
|
||||
// al: A cctz::time_zone::absolute_lookup
|
||||
// cd: A cctz::civil_day
|
||||
// cs: A cctz::civil_second
|
||||
// bd: A absl::Time::Breakdown
|
||||
|
||||
#include "absl/time/time.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <limits>
|
||||
|
||||
#include "cctz/civil_time.h"
|
||||
#include "cctz/time_zone.h"
|
||||
namespace absl {
|
||||
|
||||
namespace {
|
||||
|
||||
inline cctz::time_point<cctz::sys_seconds> unix_epoch() {
|
||||
return std::chrono::time_point_cast<cctz::sys_seconds>(
|
||||
std::chrono::system_clock::from_time_t(0));
|
||||
}
|
||||
|
||||
// Floors d to the next unit boundary closer to negative infinity.
|
||||
inline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) {
|
||||
absl::Duration rem;
|
||||
int64_t q = absl::IDivDuration(d, unit, &rem);
|
||||
return (q > 0 ||
|
||||
rem >= ZeroDuration() ||
|
||||
q == std::numeric_limits<int64_t>::min()) ? q : q - 1;
|
||||
}
|
||||
|
||||
inline absl::Time::Breakdown InfiniteFutureBreakdown() {
|
||||
absl::Time::Breakdown bd;
|
||||
bd.year = std::numeric_limits<int64_t>::max();
|
||||
bd.month = 12;
|
||||
bd.day = 31;
|
||||
bd.hour = 23;
|
||||
bd.minute = 59;
|
||||
bd.second = 59;
|
||||
bd.subsecond = absl::InfiniteDuration();
|
||||
bd.weekday = 4;
|
||||
bd.yearday = 365;
|
||||
bd.offset = 0;
|
||||
bd.is_dst = false;
|
||||
bd.zone_abbr = "-0000";
|
||||
return bd;
|
||||
}
|
||||
|
||||
inline Time::Breakdown InfinitePastBreakdown() {
|
||||
Time::Breakdown bd;
|
||||
bd.year = std::numeric_limits<int64_t>::min();
|
||||
bd.month = 1;
|
||||
bd.day = 1;
|
||||
bd.hour = 0;
|
||||
bd.minute = 0;
|
||||
bd.second = 0;
|
||||
bd.subsecond = -absl::InfiniteDuration();
|
||||
bd.weekday = 7;
|
||||
bd.yearday = 1;
|
||||
bd.offset = 0;
|
||||
bd.is_dst = false;
|
||||
bd.zone_abbr = "-0000";
|
||||
return bd;
|
||||
}
|
||||
|
||||
inline absl::TimeConversion InfiniteFutureTimeConversion() {
|
||||
absl::TimeConversion tc;
|
||||
tc.pre = tc.trans = tc.post = absl::InfiniteFuture();
|
||||
tc.kind = absl::TimeConversion::UNIQUE;
|
||||
tc.normalized = true;
|
||||
return tc;
|
||||
}
|
||||
|
||||
inline TimeConversion InfinitePastTimeConversion() {
|
||||
absl::TimeConversion tc;
|
||||
tc.pre = tc.trans = tc.post = absl::InfinitePast();
|
||||
tc.kind = absl::TimeConversion::UNIQUE;
|
||||
tc.normalized = true;
|
||||
return tc;
|
||||
}
|
||||
|
||||
// Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as
|
||||
// necessary. If sec is min/max, then consult cs+tz to check for overlow.
|
||||
Time MakeTimeWithOverflow(const cctz::time_point<cctz::sys_seconds>& sec,
|
||||
const cctz::civil_second& cs,
|
||||
const cctz::time_zone& tz,
|
||||
bool* normalized = nullptr) {
|
||||
const auto max = cctz::time_point<cctz::sys_seconds>::max();
|
||||
const auto min = cctz::time_point<cctz::sys_seconds>::min();
|
||||
if (sec == max) {
|
||||
const auto al = tz.lookup(max);
|
||||
if (cs > al.cs) {
|
||||
if (normalized) *normalized = true;
|
||||
return absl::InfiniteFuture();
|
||||
}
|
||||
}
|
||||
if (sec == min) {
|
||||
const auto al = tz.lookup(min);
|
||||
if (cs < al.cs) {
|
||||
if (normalized) *normalized = true;
|
||||
return absl::InfinitePast();
|
||||
}
|
||||
}
|
||||
const auto hi = (sec - unix_epoch()).count();
|
||||
return time_internal::FromUnixDuration(time_internal::MakeDuration(hi));
|
||||
}
|
||||
|
||||
inline absl::TimeConversion::Kind MapKind(
|
||||
const cctz::time_zone::civil_lookup::civil_kind& kind) {
|
||||
switch (kind) {
|
||||
case cctz::time_zone::civil_lookup::UNIQUE:
|
||||
return absl::TimeConversion::UNIQUE;
|
||||
case cctz::time_zone::civil_lookup::SKIPPED:
|
||||
return absl::TimeConversion::SKIPPED;
|
||||
case cctz::time_zone::civil_lookup::REPEATED:
|
||||
return absl::TimeConversion::REPEATED;
|
||||
}
|
||||
return absl::TimeConversion::UNIQUE;
|
||||
}
|
||||
|
||||
// Returns Mon=1..Sun=7.
|
||||
inline int MapWeekday(const cctz::weekday& wd) {
|
||||
switch (wd) {
|
||||
case cctz::weekday::monday:
|
||||
return 1;
|
||||
case cctz::weekday::tuesday:
|
||||
return 2;
|
||||
case cctz::weekday::wednesday:
|
||||
return 3;
|
||||
case cctz::weekday::thursday:
|
||||
return 4;
|
||||
case cctz::weekday::friday:
|
||||
return 5;
|
||||
case cctz::weekday::saturday:
|
||||
return 6;
|
||||
case cctz::weekday::sunday:
|
||||
return 7;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
absl::Time::Breakdown Time::In(absl::TimeZone tz) const {
|
||||
if (*this == absl::InfiniteFuture()) return absl::InfiniteFutureBreakdown();
|
||||
if (*this == absl::InfinitePast()) return absl::InfinitePastBreakdown();
|
||||
|
||||
const auto tp =
|
||||
unix_epoch() + cctz::sys_seconds(time_internal::GetRepHi(rep_));
|
||||
const auto al = cctz::time_zone(tz).lookup(tp);
|
||||
const auto cs = al.cs;
|
||||
const auto cd = cctz::civil_day(cs);
|
||||
|
||||
absl::Time::Breakdown bd;
|
||||
bd.year = cs.year();
|
||||
bd.month = cs.month();
|
||||
bd.day = cs.day();
|
||||
bd.hour = cs.hour();
|
||||
bd.minute = cs.minute();
|
||||
bd.second = cs.second();
|
||||
bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_));
|
||||
bd.weekday = MapWeekday(get_weekday(cd));
|
||||
bd.yearday = get_yearday(cd);
|
||||
bd.offset = al.offset;
|
||||
bd.is_dst = al.is_dst;
|
||||
bd.zone_abbr = al.abbr;
|
||||
return bd;
|
||||
}
|
||||
|
||||
absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
|
||||
const auto cz = cctz::time_zone(tz);
|
||||
const auto cs =
|
||||
cctz::civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
const auto cl = cz.lookup(cs);
|
||||
const auto tp = tm.tm_isdst == 0 ? cl.post : cl.pre;
|
||||
return MakeTimeWithOverflow(tp, cs, cz);
|
||||
}
|
||||
|
||||
struct tm ToTM(absl::Time t, absl::TimeZone tz) {
|
||||
const absl::Time::Breakdown bd = t.In(tz);
|
||||
struct tm tm;
|
||||
std::memset(&tm, 0, sizeof(tm));
|
||||
tm.tm_sec = bd.second;
|
||||
tm.tm_min = bd.minute;
|
||||
tm.tm_hour = bd.hour;
|
||||
tm.tm_mday = bd.day;
|
||||
tm.tm_mon = bd.month - 1;
|
||||
|
||||
// Saturates tm.tm_year in cases of over/underflow, accounting for the fact
|
||||
// that tm.tm_year is years since 1900.
|
||||
if (bd.year < std::numeric_limits<int>::min() + 1900) {
|
||||
tm.tm_year = std::numeric_limits<int>::min();
|
||||
} else if (bd.year > std::numeric_limits<int>::max()) {
|
||||
tm.tm_year = std::numeric_limits<int>::max() - 1900;
|
||||
} else {
|
||||
tm.tm_year = static_cast<int>(bd.year - 1900);
|
||||
}
|
||||
|
||||
tm.tm_wday = bd.weekday % 7;
|
||||
tm.tm_yday = bd.yearday - 1;
|
||||
tm.tm_isdst = bd.is_dst ? 1 : 0;
|
||||
|
||||
return tm;
|
||||
}
|
||||
|
||||
//
|
||||
// Factory functions.
|
||||
//
|
||||
|
||||
absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
|
||||
int min, int sec, TimeZone tz) {
|
||||
// Avoids years that are too extreme for civil_second to normalize.
|
||||
if (year > 300000000000) return InfiniteFutureTimeConversion();
|
||||
if (year < -300000000000) return InfinitePastTimeConversion();
|
||||
const auto cz = cctz::time_zone(tz);
|
||||
const auto cs = cctz::civil_second(year, mon, day, hour, min, sec);
|
||||
absl::TimeConversion tc;
|
||||
tc.normalized = year != cs.year() || mon != cs.month() || day != cs.day() ||
|
||||
hour != cs.hour() || min != cs.minute() || sec != cs.second();
|
||||
const auto cl = cz.lookup(cs);
|
||||
// Converts the civil_lookup struct to a TimeConversion.
|
||||
tc.pre = MakeTimeWithOverflow(cl.pre, cs, cz, &tc.normalized);
|
||||
tc.trans = MakeTimeWithOverflow(cl.trans, cs, cz, &tc.normalized);
|
||||
tc.post = MakeTimeWithOverflow(cl.post, cs, cz, &tc.normalized);
|
||||
tc.kind = MapKind(cl.kind);
|
||||
return tc;
|
||||
}
|
||||
|
||||
absl::Time FromDateTime(int64_t year, int mon, int day, int hour, int min,
|
||||
int sec, TimeZone tz) {
|
||||
if (year > 300000000000) return InfiniteFuture();
|
||||
if (year < -300000000000) return InfinitePast();
|
||||
const auto cz = cctz::time_zone(tz);
|
||||
const auto cs = cctz::civil_second(year, mon, day, hour, min, sec);
|
||||
const auto cl = cz.lookup(cs);
|
||||
return MakeTimeWithOverflow(cl.pre, cs, cz);
|
||||
}
|
||||
|
||||
absl::Time TimeFromTimespec(timespec ts) {
|
||||
return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
|
||||
}
|
||||
|
||||
absl::Time TimeFromTimeval(timeval tv) {
|
||||
return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
|
||||
}
|
||||
|
||||
absl::Time FromUDate(double udate) {
|
||||
return time_internal::FromUnixDuration(absl::Milliseconds(udate));
|
||||
}
|
||||
|
||||
absl::Time FromUniversal(int64_t universal) {
|
||||
return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal);
|
||||
}
|
||||
|
||||
//
|
||||
// Conversion to other time types.
|
||||
//
|
||||
|
||||
int64_t ToUnixNanos(Time t) {
|
||||
if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
|
||||
time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) {
|
||||
return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
|
||||
1000 * 1000 * 1000) +
|
||||
(time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4);
|
||||
}
|
||||
return FloorToUnit(time_internal::ToUnixDuration(t), absl::Nanoseconds(1));
|
||||
}
|
||||
|
||||
int64_t ToUnixMicros(Time t) {
|
||||
if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
|
||||
time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) {
|
||||
return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
|
||||
1000 * 1000) +
|
||||
(time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000);
|
||||
}
|
||||
return FloorToUnit(time_internal::ToUnixDuration(t), absl::Microseconds(1));
|
||||
}
|
||||
|
||||
int64_t ToUnixMillis(Time t) {
|
||||
if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
|
||||
time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) {
|
||||
return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) +
|
||||
(time_internal::GetRepLo(time_internal::ToUnixDuration(t)) /
|
||||
(4000 * 1000));
|
||||
}
|
||||
return FloorToUnit(time_internal::ToUnixDuration(t), absl::Milliseconds(1));
|
||||
}
|
||||
|
||||
int64_t ToUnixSeconds(Time t) {
|
||||
return time_internal::GetRepHi(time_internal::ToUnixDuration(t));
|
||||
}
|
||||
|
||||
time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; }
|
||||
|
||||
timespec ToTimespec(Time t) {
|
||||
timespec ts;
|
||||
absl::Duration d = time_internal::ToUnixDuration(t);
|
||||
if (!time_internal::IsInfiniteDuration(d)) {
|
||||
ts.tv_sec = time_internal::GetRepHi(d);
|
||||
if (ts.tv_sec == time_internal::GetRepHi(d)) { // no time_t narrowing
|
||||
ts.tv_nsec = time_internal::GetRepLo(d) / 4; // floor
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
if (d >= absl::ZeroDuration()) {
|
||||
ts.tv_sec = std::numeric_limits<time_t>::max();
|
||||
ts.tv_nsec = 1000 * 1000 * 1000 - 1;
|
||||
} else {
|
||||
ts.tv_sec = std::numeric_limits<time_t>::min();
|
||||
ts.tv_nsec = 0;
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
|
||||
timeval ToTimeval(Time t) {
|
||||
timeval tv;
|
||||
timespec ts = absl::ToTimespec(t);
|
||||
tv.tv_sec = ts.tv_sec;
|
||||
if (tv.tv_sec != ts.tv_sec) { // narrowing
|
||||
if (ts.tv_sec < 0) {
|
||||
tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
|
||||
tv.tv_usec = 0;
|
||||
} else {
|
||||
tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();
|
||||
tv.tv_usec = 1000 * 1000 - 1;
|
||||
}
|
||||
return tv;
|
||||
}
|
||||
tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t
|
||||
return tv;
|
||||
}
|
||||
|
||||
double ToUDate(Time t) {
|
||||
return absl::FDivDuration(time_internal::ToUnixDuration(t),
|
||||
absl::Milliseconds(1));
|
||||
}
|
||||
|
||||
int64_t ToUniversal(absl::Time t) {
|
||||
return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
|
||||
}
|
||||
|
||||
} // namespace absl
|
1181
absl/time/time.h
Normal file
1181
absl/time/time.h
Normal file
File diff suppressed because it is too large
Load diff
306
absl/time/time_norm_test.cc
Normal file
306
absl/time/time_norm_test.cc
Normal file
|
@ -0,0 +1,306 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file contains tests for FromDateTime() normalization, which is
|
||||
// time-zone independent so we just use UTC throughout.
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/internal/test_util.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(TimeNormCase, SimpleOverflow) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
|
||||
absl::TimeConversion tc =
|
||||
absl::ConvertDateTime(2013, 11, 15, 16, 32, 59 + 1, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
absl::Time::Breakdown bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 33, 0, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15, 16, 59 + 1, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 17, 0, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15, 23 + 1, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 16, 0, 32, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 30 + 1, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 1, 16, 32, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 12 + 1, 15, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 15, 16, 32, 14, 0, false, "UTC");
|
||||
}
|
||||
|
||||
TEST(TimeNormCase, SimpleUnderflow) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
|
||||
absl::TimeConversion tc = ConvertDateTime(2013, 11, 15, 16, 32, 0 - 1, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
absl::Time::Breakdown bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 31, 59, 0, false, "UTC");
|
||||
|
||||
tc = ConvertDateTime(2013, 11, 15, 16, 0 - 1, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 15, 59, 14, 0, false, "UTC");
|
||||
|
||||
tc = ConvertDateTime(2013, 11, 15, 0 - 1, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 14, 23, 32, 14, 0, false, "UTC");
|
||||
|
||||
tc = ConvertDateTime(2013, 11, 1 - 1, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 10, 31, 16, 32, 14, 0, false, "UTC");
|
||||
|
||||
tc = ConvertDateTime(2013, 1 - 1, 15, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 12, 15, 16, 32, 14, 0, false, "UTC");
|
||||
}
|
||||
|
||||
TEST(TimeNormCase, MultipleOverflow) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
absl::TimeConversion tc = ConvertDateTime(2013, 12, 31, 23, 59, 59 + 1, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
absl::Time::Breakdown bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 1, 0, 0, 0, 0, false, "UTC");
|
||||
}
|
||||
|
||||
TEST(TimeNormCase, MultipleUnderflow) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
absl::TimeConversion tc = absl::ConvertDateTime(2014, 1, 1, 0, 0, 0 - 1, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
absl::Time::Breakdown bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 31, 23, 59, 59, 0, false, "UTC");
|
||||
}
|
||||
|
||||
TEST(TimeNormCase, OverflowLimits) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
absl::TimeConversion tc;
|
||||
absl::Time::Breakdown bd;
|
||||
|
||||
const int kintmax = std::numeric_limits<int>::max();
|
||||
tc = absl::ConvertDateTime(0, kintmax, kintmax, kintmax, kintmax, kintmax,
|
||||
utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 185085715, 11, 27, 12, 21, 7, 0, false, "UTC");
|
||||
|
||||
const int kintmin = std::numeric_limits<int>::min();
|
||||
tc = absl::ConvertDateTime(0, kintmin, kintmin, kintmin, kintmin, kintmin,
|
||||
utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, -185085717, 10, 31, 10, 37, 52, 0, false,
|
||||
"UTC");
|
||||
|
||||
const int64_t max_year = std::numeric_limits<int64_t>::max();
|
||||
tc = absl::ConvertDateTime(max_year, 12, 31, 23, 59, 59, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
EXPECT_EQ(absl::InfiniteFuture(), tc.pre);
|
||||
|
||||
const int64_t min_year = std::numeric_limits<int64_t>::min();
|
||||
tc = absl::ConvertDateTime(min_year, 1, 1, 0, 0, 0, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
EXPECT_EQ(absl::InfinitePast(), tc.pre);
|
||||
}
|
||||
|
||||
TEST(TimeNormCase, ComplexOverflow) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
|
||||
absl::TimeConversion tc =
|
||||
ConvertDateTime(2013, 11, 15, 16, 32, 14 + 123456789, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
absl::Time::Breakdown bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 10, 14, 14, 5, 23, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 + 1234567, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2016, 3, 22, 0, 39, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15, 16 + 123456, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2027, 12, 16, 16, 32, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15 + 1234, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 4, 2, 16, 32, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11 + 123, 15, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2024, 2, 15, 16, 32, 14, 0, false, "UTC");
|
||||
}
|
||||
|
||||
TEST(TimeNormCase, ComplexUnderflow) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
|
||||
absl::TimeConversion tc =
|
||||
absl::ConvertDateTime(1999, 3, 0, 0, 0, 0, utc); // year 400
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
absl::Time::Breakdown bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 2, 28, 0, 0, 0, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15, 16, 32, 14 - 123456789, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2009, 12, 17, 18, 59, 5, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 - 1234567, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2011, 7, 12, 8, 25, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15, 16 - 123456, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 10, 16, 16, 32, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11, 15 - 1234, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2010, 6, 30, 16, 32, 14, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11 - 123, 15, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2003, 8, 15, 16, 32, 14, 0, false, "UTC");
|
||||
}
|
||||
|
||||
TEST(TimeNormCase, Mishmash) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
|
||||
absl::TimeConversion tc =
|
||||
absl::ConvertDateTime(2013, 11 - 123, 15 + 1234, 16 - 123456,
|
||||
32 + 1234567, 14 - 123456789, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
absl::Time::Breakdown bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 1991, 5, 9, 3, 6, 5, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2013, 11 + 123, 15 - 1234, 16 + 123456,
|
||||
32 - 1234567, 14 + 123456789, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2036, 5, 24, 5, 58, 23, 0, false, "UTC");
|
||||
|
||||
// Here is a normalization case we got wrong for a while. Because the
|
||||
// day is converted to "1" within a 400-year (146097-day) period, we
|
||||
// didn't need to roll the month and so we didn't mark it as normalized.
|
||||
tc = absl::ConvertDateTime(2013, 11, -146097 + 1, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 1613, 11, 1, 16, 32, 14, 0, false, "UTC");
|
||||
|
||||
// Even though the month overflow compensates for the day underflow,
|
||||
// this should still be marked as normalized.
|
||||
tc = absl::ConvertDateTime(2013, 11 + 400 * 12, -146097 + 1, 16, 32, 14, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 1, 16, 32, 14, 0, false, "UTC");
|
||||
}
|
||||
|
||||
TEST(TimeNormCase, LeapYears) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
|
||||
absl::TimeConversion tc =
|
||||
absl::ConvertDateTime(2013, 2, 28 + 1, 0, 0, 0, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
absl::Time::Breakdown bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 3, 1, 0, 0, 0, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2012, 2, 28 + 1, 0, 0, 0, utc);
|
||||
EXPECT_FALSE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 2, 29, 0, 0, 0, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(2000, 2, 28 + 1, 0, 0, 0, utc);
|
||||
EXPECT_FALSE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 2000, 2, 29, 0, 0, 0, 0, false, "UTC");
|
||||
|
||||
tc = absl::ConvertDateTime(1900, 2, 28 + 1, 0, 0, 0, utc);
|
||||
EXPECT_TRUE(tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
bd = tc.pre.In(utc);
|
||||
ABSL_INTERNAL_EXPECT_TIME(bd, 1900, 3, 1, 0, 0, 0, 0, false, "UTC");
|
||||
}
|
||||
|
||||
// Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31)
|
||||
// and check that they normalize to the expected time. 146097 days span
|
||||
// the 400-year Gregorian cycle used during normalization.
|
||||
TEST(TimeNormCase, AllTheDays) {
|
||||
const absl::TimeZone utc = absl::UTCTimeZone();
|
||||
absl::Time exp_time = absl::UnixEpoch();
|
||||
|
||||
for (int day = 1; day <= 146097; ++day) {
|
||||
absl::TimeConversion tc = absl::ConvertDateTime(1970, 1, day, 0, 0, 0, utc);
|
||||
EXPECT_EQ(day > 31, tc.normalized);
|
||||
EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
|
||||
EXPECT_EQ(exp_time, tc.pre);
|
||||
exp_time += absl::Hours(24);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
1027
absl/time/time_test.cc
Normal file
1027
absl/time/time_test.cc
Normal file
File diff suppressed because it is too large
Load diff
95
absl/time/time_zone_test.cc
Normal file
95
absl/time/time_zone_test.cc
Normal file
|
@ -0,0 +1,95 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "cctz/time_zone.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/internal/test_util.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(TimeZone, ValueSemantics) {
|
||||
absl::TimeZone tz;
|
||||
absl::TimeZone tz2 = tz; // Copy-construct
|
||||
EXPECT_EQ(tz, tz2);
|
||||
tz2 = tz; // Copy-assign
|
||||
EXPECT_EQ(tz, tz2);
|
||||
}
|
||||
|
||||
TEST(TimeZone, Equality) {
|
||||
absl::TimeZone a, b;
|
||||
EXPECT_EQ(a, b);
|
||||
EXPECT_EQ(a.name(), b.name());
|
||||
|
||||
absl::TimeZone implicit_utc;
|
||||
absl::TimeZone explicit_utc = absl::UTCTimeZone();
|
||||
EXPECT_EQ(implicit_utc, explicit_utc);
|
||||
EXPECT_EQ(implicit_utc.name(), explicit_utc.name());
|
||||
|
||||
absl::TimeZone la = absl::time_internal::LoadTimeZone("America/Los_Angeles");
|
||||
absl::TimeZone nyc = absl::time_internal::LoadTimeZone("America/New_York");
|
||||
EXPECT_NE(la, nyc);
|
||||
}
|
||||
|
||||
TEST(TimeZone, CCTZConversion) {
|
||||
const cctz::time_zone cz = cctz::utc_time_zone();
|
||||
const absl::TimeZone tz(cz);
|
||||
EXPECT_EQ(cz, cctz::time_zone(tz));
|
||||
}
|
||||
|
||||
TEST(TimeZone, DefaultTimeZones) {
|
||||
absl::TimeZone tz;
|
||||
EXPECT_EQ("UTC", absl::TimeZone().name());
|
||||
EXPECT_EQ("UTC", absl::UTCTimeZone().name());
|
||||
}
|
||||
|
||||
TEST(TimeZone, FixedTimeZone) {
|
||||
const absl::TimeZone tz = absl::FixedTimeZone(123);
|
||||
const cctz::time_zone cz = cctz::fixed_time_zone(cctz::sys_seconds(123));
|
||||
EXPECT_EQ(tz, absl::TimeZone(cz));
|
||||
}
|
||||
|
||||
TEST(TimeZone, LocalTimeZone) {
|
||||
const absl::TimeZone local_tz = absl::LocalTimeZone();
|
||||
absl::TimeZone tz = absl::time_internal::LoadTimeZone("localtime");
|
||||
EXPECT_EQ(tz, local_tz);
|
||||
}
|
||||
|
||||
TEST(TimeZone, NamedTimeZones) {
|
||||
absl::TimeZone nyc = absl::time_internal::LoadTimeZone("America/New_York");
|
||||
EXPECT_EQ("America/New_York", nyc.name());
|
||||
absl::TimeZone syd = absl::time_internal::LoadTimeZone("Australia/Sydney");
|
||||
EXPECT_EQ("Australia/Sydney", syd.name());
|
||||
absl::TimeZone fixed = absl::FixedTimeZone((((3 * 60) + 25) * 60) + 45);
|
||||
EXPECT_EQ("Fixed/UTC+03:25:45", fixed.name());
|
||||
}
|
||||
|
||||
TEST(TimeZone, Failures) {
|
||||
absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
|
||||
EXPECT_FALSE(LoadTimeZone("Invalid/TimeZone", &tz));
|
||||
EXPECT_EQ(absl::UTCTimeZone(), tz); // guaranteed fallback to UTC
|
||||
|
||||
// Ensures that the load still fails on a subsequent attempt.
|
||||
tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
|
||||
EXPECT_FALSE(LoadTimeZone("Invalid/TimeZone", &tz));
|
||||
EXPECT_EQ(absl::UTCTimeZone(), tz); // guaranteed fallback to UTC
|
||||
|
||||
// Loading an empty std::string timezone should fail.
|
||||
tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
|
||||
EXPECT_FALSE(LoadTimeZone("", &tz));
|
||||
EXPECT_EQ(absl::UTCTimeZone(), tz); // guaranteed fallback to UTC
|
||||
}
|
||||
|
||||
} // namespace
|
Loading…
Add table
Add a link
Reference in a new issue