Export of internal Abseil changes

--
6a60bc6c79a3069f49986c2567dd51d2792f8ec1 by Abseil Team <absl-team@google.com>:

Internal cleanup

PiperOrigin-RevId: 311210039

--
a1049de1dd9071efa3a3dda1c3f25ab578b23e27 by Laramie Leavitt <lar@google.com>:

Internal change

PiperOrigin-RevId: 311188627

--
c2ccddd1cd89ef9d79c35bbe9e1813164db27031 by Matt Kulukundis <kfm@google.com>:

Migrate time parsing/formatting to string_view.

- make a copy before handing to cctz but handle local cases without

PiperOrigin-RevId: 311009254

--
d91d0cd68f3672a727ff76ee43f2da5226673d60 by Gennadiy Rozental <rogeeff@google.com>:

Eliminate public method absl::Flag<T>::IsSpecfiedOnCommandLine. This interface was never intended to be supported. Prefer to react to the current value of flag.

PiperOrigin-RevId: 310991916

--
8ad41e7ec24f43598ed232545314117802e7895c by Gennadiy Rozental <rogeeff@google.com>:

Internal change

PiperOrigin-RevId: 310757743

--
f091f77a13ce9481218cb356f8b4ceb49c1530f9 by Jorg Brown <jorg@google.com>:

Change #include of <iostream> to <iosfwd> from absl/strings/cord.h

PiperOrigin-RevId: 310657413

--
39419418af6be4ac9b9204ebe2c7a92a6c3a0bc9 by Derek Mauro <dmauro@google.com>:

Internal change

PiperOrigin-RevId: 310615554
GitOrigin-RevId: 6a60bc6c79a3069f49986c2567dd51d2792f8ec1
Change-Id: I57dd35424269d67740272c4f88b2de54d8022cb2
This commit is contained in:
Abseil Team 2020-05-12 15:05:26 -07:00 committed by Andy Getz
parent c45d1c09d5
commit cbfd0f0fe5
18 changed files with 279 additions and 126 deletions

View file

@ -777,3 +777,17 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "unique_small_name_test",
size = "small",
srcs = ["internal/unique_small_name_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
linkstatic = 1,
deps = [
":core_headers",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],
)

View file

@ -0,0 +1,77 @@
// Copyright 2020 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
//
// https://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 "gtest/gtest.h"
#include "absl/base/optimization.h"
#include "absl/strings/string_view.h"
// This test by itself does not do anything fancy, but it serves as binary I can
// query in shell test.
namespace {
template <class T>
void DoNotOptimize(const T& var) {
#ifdef __GNUC__
asm volatile("" : "+m"(const_cast<T&>(var)));
#else
std::cout << (void*)&var;
#endif
}
int very_long_int_variable_name ABSL_INTERNAL_UNIQUE_SMALL_NAME() = 0;
char very_long_str_variable_name[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = "abc";
TEST(UniqueSmallName, NonAutomaticVar) {
EXPECT_EQ(very_long_int_variable_name, 0);
EXPECT_EQ(absl::string_view(very_long_str_variable_name), "abc");
}
int VeryLongFreeFunctionName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
TEST(UniqueSmallName, FreeFunction) {
DoNotOptimize(&VeryLongFreeFunctionName);
EXPECT_EQ(VeryLongFreeFunctionName(), 456);
}
int VeryLongFreeFunctionName() { return 456; }
struct VeryLongStructName {
explicit VeryLongStructName(int i);
int VeryLongMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
static int VeryLongStaticMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
private:
int fld;
};
TEST(UniqueSmallName, Struct) {
VeryLongStructName var(10);
DoNotOptimize(var);
DoNotOptimize(&VeryLongStructName::VeryLongMethodName);
DoNotOptimize(&VeryLongStructName::VeryLongStaticMethodName);
EXPECT_EQ(var.VeryLongMethodName(), 10);
EXPECT_EQ(VeryLongStructName::VeryLongStaticMethodName(), 123);
}
VeryLongStructName::VeryLongStructName(int i) : fld(i) {}
int VeryLongStructName::VeryLongMethodName() { return fld; }
int VeryLongStructName::VeryLongStaticMethodName() { return 123; }
} // namespace

View file

@ -212,4 +212,30 @@
} while (0)
#endif
// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
// This macro forces small unique name on a static file level symbols like
// static local variables or static functions. This is intended to be used in
// macro definitions to optimize the cost of generated code. Do NOT use it on
// symbols exported from translation unit since it may casue a link time
// conflict.
//
// Example:
//
// #define MY_MACRO(txt)
// namespace {
// char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt;
// const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
// const char* VeryVeryLongFuncName() { return txt; }
// }
//
#if defined(__GNUC__)
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x)
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__))
#else
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME()
#endif
#endif // ABSL_BASE_OPTIMIZATION_H_

View file

@ -128,7 +128,6 @@ class CommandLineFlag {
virtual std::string Help() const = 0;
// Returns true iff this object corresponds to retired flag.
virtual bool IsRetired() const;
virtual bool IsSpecifiedOnCommandLine() const = 0;
virtual std::string DefaultValue() const = 0;
virtual std::string CurrentValue() const = 0;
@ -167,6 +166,10 @@ class CommandLineFlag {
// the dst based on the current flag's value.
virtual void Read(void* dst) const = 0;
// To be deleted. Used to return true if flag's current value originated from
// command line.
virtual bool IsSpecifiedOnCommandLine() const = 0;
// Validates supplied value usign validator or parseflag routine
virtual bool ValidateInputValue(absl::string_view value) const = 0;

View file

@ -121,42 +121,48 @@ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
std::string err;
auto* flag_01 = flags::FindCommandLineFlag("int_flag");
EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
&err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
&err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
&err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, &err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
EXPECT_TRUE(flag_01->IsSpecifiedOnCommandLine());
EXPECT_TRUE(flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));

View file

@ -624,6 +624,7 @@ class Flag {
absl::string_view Name() const { return impl_.Name(); }
std::string Filename() const { return impl_.Filename(); }
std::string Help() const { return impl_.Help(); }
// Do not use. To be removed.
bool IsSpecifiedOnCommandLine() const {
return impl_.IsSpecifiedOnCommandLine();
}

View file

@ -28,6 +28,11 @@ std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(
return flag->SaveState();
}
bool PrivateHandleAccessor::IsSpecifiedOnCommandLine(
const CommandLineFlag& flag) {
return flag.IsSpecifiedOnCommandLine();
}
bool PrivateHandleAccessor::ValidateInputValue(const CommandLineFlag& flag,
absl::string_view value) {
return flag.ValidateInputValue(value);

View file

@ -33,6 +33,9 @@ class PrivateHandleAccessor {
// Access to CommandLineFlag::SaveState.
static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag* flag);
// Access to CommandLineFlag::IsSpecifiedOnCommandLine.
static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);
// Access to CommandLineFlag::ValidateInputValue.
static bool ValidateInputValue(const CommandLineFlag& flag,
absl::string_view value);

View file

@ -81,14 +81,6 @@ bool IsValidFlagValue(absl::string_view name, absl::string_view value) {
// --------------------------------------------------------------------
bool SpecifiedOnCommandLine(absl::string_view name) {
CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
if (flag != nullptr && !flag->IsRetired()) {
return flag->IsSpecifiedOnCommandLine();
}
return false;
}
} // namespace flags_internal
ABSL_NAMESPACE_END
} // namespace absl

View file

@ -55,17 +55,6 @@ bool IsValidFlagValue(absl::string_view name, absl::string_view value);
//-----------------------------------------------------------------------------
// Returns true iff a flag named "name" was specified on the command line
// (either directly, or via one of --flagfile or --fromenv or --tryfromenv).
//
// Any non-command-line modification of the flag does not affect the
// result of this function. So for example, if a flag was passed on
// the command line but then reset via SET_FLAGS_DEFAULT, this
// function will still return true.
bool SpecifiedOnCommandLine(absl::string_view name);
//-----------------------------------------------------------------------------
// If a flag with specified "name" exists and has type T, store
// its current value in *dst and return true. Else return false
// without touching *dst. T must obey all of the requirements for

View file

@ -37,9 +37,6 @@ cc_library(
hdrs = ["traits.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl/random:__pkg__",
],
deps = ["//absl/base:config"],
)
@ -48,9 +45,6 @@ cc_library(
hdrs = ["distribution_caller.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl/random:__pkg__",
],
deps = ["//absl/base:config"],
)
@ -76,9 +70,6 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl/random:__pkg__",
],
deps = ["//absl/base:config"],
)
@ -517,9 +508,6 @@ cc_library(
name = "mock_overload_set",
testonly = 1,
hdrs = ["mock_overload_set.h"],
visibility = [
"//absl/random:__pkg__",
],
deps = [
"//absl/random:mocking_bit_gen",
"@com_google_googletest//:gtest",
@ -669,6 +657,7 @@ cc_library(
deps = [
":platform",
":randen_engine",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
],

View file

@ -20,6 +20,7 @@
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <limits>
#include <ostream>
#include <sstream>

View file

@ -65,7 +65,7 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <iosfwd>
#include <iterator>
#include <string>
#include <type_traits>

View file

@ -120,7 +120,9 @@ class Arg {
// representation. However, we can't really know, so we make the caller decide
// what to do.
Arg(char value) // NOLINT(runtime/explicit)
: piece_(scratch_, 1) { scratch_[0] = value; }
: piece_(scratch_, 1) {
scratch_[0] = value;
}
Arg(short value) // NOLINT(*)
: piece_(scratch_,
numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
@ -203,10 +205,11 @@ constexpr const char* SkipNumber(const char* format) {
}
constexpr int PlaceholderBitmask(const char* format) {
return !*format ? 0 : *format != '$'
? PlaceholderBitmask(format + 1)
: (CalculateOneBit(format + 1) |
PlaceholderBitmask(SkipNumber(format + 1)));
return !*format
? 0
: *format != '$' ? PlaceholderBitmask(format + 1)
: (CalculateOneBit(format + 1) |
PlaceholderBitmask(SkipNumber(format + 1)));
}
#endif // ABSL_BAD_CALL_IF

View file

@ -769,6 +769,8 @@ class Condition {
//
class CondVar {
public:
// A `CondVar` allocated on the heap or on the stack can use the this
// constructor.
CondVar();
~CondVar();
@ -900,9 +902,11 @@ class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
};
#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {}
#else
inline Mutex::Mutex() : mu_(0) {
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
}
@ -910,7 +914,8 @@ inline Mutex::Mutex() : mu_(0) {
inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
inline CondVar::CondVar() : cv_(0) {}
#endif
#endif // ABSL_INTERNAL_USE_NONPROD_MUTEX
// static
template <typename T>

View file

@ -67,7 +67,9 @@
#include <string>
#include "absl/base/casts.h"
#include "absl/base/macros.h"
#include "absl/numeric/int128.h"
#include "absl/strings/strip.h"
#include "absl/time/time.h"
namespace absl {
@ -800,23 +802,27 @@ namespace {
// A helper for ParseDuration() that parses a leading number from the given
// string and stores the result in *int_part/*frac_part/*frac_scale. The
// given string pointer is modified to point to the first unconsumed char.
bool ConsumeDurationNumber(const char** dpp, int64_t* int_part,
bool ConsumeDurationNumber(const char** dpp, const char* ep, int64_t* int_part,
int64_t* frac_part, int64_t* frac_scale) {
*int_part = 0;
*frac_part = 0;
*frac_scale = 1; // invariant: *frac_part < *frac_scale
const char* start = *dpp;
for (; std::isdigit(**dpp); *dpp += 1) {
for (; *dpp != ep; *dpp += 1) {
const int d = **dpp - '0'; // contiguous digits
if (d < 0 || 10 <= d) break;
if (*int_part > kint64max / 10) return false;
*int_part *= 10;
if (*int_part > kint64max - d) return false;
*int_part += d;
}
const bool int_part_empty = (*dpp == start);
if (**dpp != '.') return !int_part_empty;
for (*dpp += 1; std::isdigit(**dpp); *dpp += 1) {
if (*dpp == ep || **dpp != '.') return !int_part_empty;
for (*dpp += 1; *dpp != ep; *dpp += 1) {
const int d = **dpp - '0'; // contiguous digits
if (d < 0 || 10 <= d) break;
if (*frac_scale <= kint64max / 10) {
*frac_part *= 10;
*frac_part += d;
@ -830,32 +836,56 @@ bool ConsumeDurationNumber(const char** dpp, int64_t* int_part,
// ns, us, ms, s, m, h) from the given string and stores the resulting unit
// in "*unit". The given 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;
bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) {
size_t size = end - *start;
switch (size) {
case 0:
return false;
default:
switch (**start) {
case 'n':
if (*(*start + 1) == 's') {
*start += 2;
*unit = Nanoseconds(1);
return true;
}
break;
case 'u':
if (*(*start + 1) == 's') {
*start += 2;
*unit = Microseconds(1);
return true;
}
break;
case 'm':
if (*(*start + 1) == 's') {
*start += 2;
*unit = Milliseconds(1);
return true;
}
break;
default:
break;
}
ABSL_FALLTHROUGH_INTENDED;
case 1:
switch (**start) {
case 's':
*unit = Seconds(1);
*start += 1;
return true;
case 'm':
*unit = Minutes(1);
*start += 1;
return true;
case 'h':
*unit = Hours(1);
*start += 1;
return true;
default:
return false;
}
}
*start = s;
return ok;
}
} // namespace
@ -865,39 +895,38 @@ bool ConsumeDurationUnit(const char** start, Duration* unit) {
// 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();
bool ParseDuration(absl::string_view dur_sv, Duration* d) {
int sign = 1;
if (*start == '-' || *start == '+') {
sign = *start == '-' ? -1 : 1;
++start;
}
// Can't parse a duration from an empty string.
if (*start == '\0') {
return false;
if (absl::ConsumePrefix(&dur_sv, "-")) {
sign = -1;
} else {
absl::ConsumePrefix(&dur_sv, "+");
}
if (dur_sv.empty()) return false;
// Special case for a string of "0".
if (*start == '0' && *(start + 1) == '\0') {
if (dur_sv == "0") {
*d = ZeroDuration();
return true;
}
if (strcmp(start, "inf") == 0) {
if (dur_sv == "inf") {
*d = sign * InfiniteDuration();
return true;
}
const char* start = dur_sv.data();
const char* end = start + dur_sv.size();
Duration dur;
while (*start != '\0') {
while (start != end) {
int64_t int_part;
int64_t frac_part;
int64_t frac_scale;
Duration unit;
if (!ConsumeDurationNumber(&start, &int_part, &frac_part, &frac_scale) ||
!ConsumeDurationUnit(&start, &unit)) {
if (!ConsumeDurationNumber(&start, end, &int_part, &frac_part,
&frac_scale) ||
!ConsumeDurationUnit(&start, end, &unit)) {
return false;
}
if (int_part != 0) dur += sign * int_part * unit;
@ -908,7 +937,7 @@ bool ParseDuration(const std::string& dur_string, Duration* d) {
}
bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) {
return ParseDuration(std::string(text), dst);
return ParseDuration(text, dst);
}
std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); }

View file

@ -13,9 +13,12 @@
// limitations under the License.
#include <string.h>
#include <cctype>
#include <cstdint>
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
#include "absl/time/time.h"
@ -71,12 +74,12 @@ absl::Time Join(const cctz_parts& parts) {
} // namespace
std::string FormatTime(const std::string& format, absl::Time t,
std::string FormatTime(absl::string_view format, absl::Time t,
absl::TimeZone tz) {
if (t == absl::InfiniteFuture()) return kInfiniteFutureStr;
if (t == absl::InfinitePast()) return kInfinitePastStr;
if (t == absl::InfiniteFuture()) return std::string(kInfiniteFutureStr);
if (t == absl::InfinitePast()) return std::string(kInfinitePastStr);
const auto parts = Split(t);
return cctz::detail::format(format, parts.sec, parts.fem,
return cctz::detail::format(std::string(format), parts.sec, parts.fem,
cctz::time_zone(tz));
}
@ -88,42 +91,50 @@ std::string FormatTime(absl::Time t) {
return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone());
}
bool ParseTime(const std::string& format, const std::string& input,
bool ParseTime(absl::string_view format, absl::string_view input,
absl::Time* time, std::string* err) {
return absl::ParseTime(format, input, absl::UTCTimeZone(), time, err);
}
// If the input 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,
bool ParseTime(absl::string_view format, absl::string_view 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;
auto strip_leading_space = [](absl::string_view* sv) {
while (!sv->empty()) {
if (!std::isspace(sv->front())) return;
sv->remove_prefix(1);
}
}
};
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;
// Portable toolchains means we don't get nice constexpr here.
struct Literal {
const char* name;
size_t size;
absl::Time value;
};
static Literal literals[] = {
{kInfiniteFutureStr, strlen(kInfiniteFutureStr), InfiniteFuture()},
{kInfinitePastStr, strlen(kInfinitePastStr), InfinitePast()},
};
strip_leading_space(&input);
for (const auto& lit : literals) {
if (absl::StartsWith(input, absl::string_view(lit.name, lit.size))) {
absl::string_view tail = input;
tail.remove_prefix(lit.size);
strip_leading_space(&tail);
if (tail.empty()) {
*time = lit.value;
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);
const bool b =
cctz::detail::parse(std::string(format), std::string(input),
cctz::time_zone(tz), &parts.sec, &parts.fem, &error);
if (b) {
*time = Join(parts);
} else if (err != nullptr) {
@ -134,8 +145,7 @@ bool ParseTime(const std::string& format, const std::string& input,
// Functions required to support absl::Time flags.
bool AbslParseFlag(absl::string_view text, absl::Time* t, std::string* error) {
return absl::ParseTime(RFC3339_full, std::string(text), absl::UTCTimeZone(),
t, error);
return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);
}
std::string AbslUnparseFlag(absl::Time t) {

View file

@ -545,7 +545,7 @@ inline std::ostream& operator<<(std::ostream& os, Duration d) {
// suffix. The valid suffixes are "ns", "us" "ms", "s", "m", and "h".
// Simple examples include "300ms", "-1.5h", and "2h45m". Parses "0" as
// `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`.
bool ParseDuration(const std::string& dur_string, Duration* d);
bool ParseDuration(absl::string_view dur_string, Duration* d);
// Support for flag values of type Duration. Duration flags must be specified
// in a format that is valid input for absl::ParseDuration().
@ -1021,13 +1021,13 @@ class TimeZone {
// Loads the named zone. May perform I/O on the initial load of the named
// zone. If the name is invalid, or some other kind of error occurs, returns
// `false` and `*tz` is set to the UTC time zone.
inline bool LoadTimeZone(const std::string& name, TimeZone* tz) {
inline bool LoadTimeZone(absl::string_view name, TimeZone* tz) {
if (name == "localtime") {
*tz = TimeZone(time_internal::cctz::local_time_zone());
return true;
}
time_internal::cctz::time_zone cz;
const bool b = time_internal::cctz::load_time_zone(name, &cz);
const bool b = time_internal::cctz::load_time_zone(std::string(name), &cz);
*tz = TimeZone(cz);
return b;
}
@ -1252,7 +1252,7 @@ ABSL_DLL extern const char
// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
// In both cases the given format string and `absl::TimeZone` are ignored.
//
std::string FormatTime(const std::string& format, Time t, TimeZone tz);
std::string FormatTime(absl::string_view format, Time t, TimeZone tz);
// Convenience functions that format the given time using the RFC3339_full
// format. The first overload uses the provided TimeZone, while the second
@ -1313,7 +1313,7 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
// If the input string is "infinite-past", the returned `absl::Time` will be
// `absl::InfinitePast()` and `true` will be returned.
//
bool ParseTime(const std::string& format, const std::string& input, Time* time,
bool ParseTime(absl::string_view format, absl::string_view input, Time* time,
std::string* err);
// Like ParseTime() above, but if the format string does not contain a UTC
@ -1323,7 +1323,7 @@ bool ParseTime(const std::string& format, const std::string& input, Time* time,
// of ambiguity or non-existence, in which case the "pre" time (as defined
// by TimeZone::TimeInfo) is returned. For these reasons we recommend that
// all date/time strings include a UTC offset so they're context independent.
bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
bool ParseTime(absl::string_view format, absl::string_view input, TimeZone tz,
Time* time, std::string* err);
// ============================================================================