summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-05-26 10:57:33 -0700
committerGravatar Derek Mauro <dmauro@google.com>2020-05-26 14:45:38 -0400
commit33caf1097ecce4fe892567462fa8821d477854b4 (patch)
tree27eecef4f8c5638857b134ea117c3bd20a980b96
parentcf1a02e2dc5a1bc9d095f4c996306de448ca200f (diff)
Export of internal Abseil changes
-- 7d0468a6610ed85586d5c87fd65de8dac5118923 by Derek Mauro <dmauro@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 313226473 -- 1131ef6d116f5ce7d46537a82f300ea06dcaaa53 by Gennadiy Rozental <rogeeff@google.com>: Migrate internal interface to use mutable references. PiperOrigin-RevId: 312931131 -- 96225212a9f5fbd0b38c71fe65539164992c7c3b by Laramie Leavitt <lar@google.com>: Remove random/internal/distributions.h This file was something of an historical artifact. All of the related code has either been removed or migraged, and so the only remaining type belongs with uniform_helper.h, as it is used to infer the return type of the absl::Uniform method in a few cases. PiperOrigin-RevId: 312878173 -- 6dcbd5be58ad425e08740ff64088373ee7fe4a72 by Mark Barolak <mbar@google.com>: Release the StrFormat test case for Cords to open source. PiperOrigin-RevId: 312707974 -- 34484d18dfb63a0a7ad6e2aaeb570e33592968be by Abseil Team <absl-team@google.com>: Let Cord::Cord(string&&), Cord::operator=(string&&), Cord::Append(string&&), and Cord::Prepend(string&&) steal string data and embed it into the Cord as a single external chunk, instead of copying it into flat chunks (at most 4083-byte each). Stealing string data is faster, but it creates a long chunk, which leads to a higher more memory usage if its subcords are created and outlive the whole Cord. These functions revert to copying the data if any of the following conditions holds: - string size is at most kMaxBytesToCopy (511), to avoid the overhead of an external chunk for short strings; - less than half of string capacity is used, to avoid pinning to much unused memory. PiperOrigin-RevId: 312683785 GitOrigin-RevId: 7d0468a6610ed85586d5c87fd65de8dac5118923 Change-Id: If79b5a1dfe6d53a8ddddbc7da84338f11fc4cfa3
-rw-r--r--CMake/AbseilDll.cmake1
-rw-r--r--absl/flags/commandlineflag.cc2
-rw-r--r--absl/flags/commandlineflag.h2
-rw-r--r--absl/flags/commandlineflag_test.cc50
-rw-r--r--absl/flags/flag.h32
-rw-r--r--absl/flags/flag_test.cc10
-rw-r--r--absl/flags/internal/flag.cc38
-rw-r--r--absl/flags/internal/flag.h24
-rw-r--r--absl/flags/internal/private_handle_accessor.cc10
-rw-r--r--absl/flags/internal/private_handle_accessor.h6
-rw-r--r--absl/flags/internal/registry.cc95
-rw-r--r--absl/flags/internal/registry.h6
-rw-r--r--absl/flags/internal/type_erased.cc2
-rw-r--r--absl/flags/internal/usage.cc25
-rw-r--r--absl/flags/marshalling.cc21
-rw-r--r--absl/flags/parse.cc38
-rw-r--r--absl/flags/parse_test.cc26
-rw-r--r--absl/random/BUILD.bazel3
-rw-r--r--absl/random/CMakeLists.txt29
-rw-r--r--absl/random/distributions.h2
-rw-r--r--absl/random/internal/BUILD.bazel18
-rw-r--r--absl/random/internal/distributions.h52
-rw-r--r--absl/random/internal/uniform_helper.h30
-rw-r--r--absl/strings/cord.cc65
-rw-r--r--absl/strings/cord.h27
-rw-r--r--absl/strings/str_format_test.cc2
-rw-r--r--absl/time/internal/cctz/include/cctz/time_zone.h3
-rw-r--r--absl/time/internal/cctz/src/cctz_benchmark.cc16
-rw-r--r--absl/time/internal/cctz/src/time_zone_format.cc23
-rw-r--r--absl/time/internal/cctz/src/time_zone_format_test.cc18
-rw-r--r--absl/time/internal/cctz/src/time_zone_lookup_test.cc2
31 files changed, 345 insertions, 333 deletions
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index a5c9bc0d..ccd409f3 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -135,7 +135,6 @@ set(ABSL_INTERNAL_DLL_FILES
"random/exponential_distribution.h"
"random/gaussian_distribution.cc"
"random/gaussian_distribution.h"
- "random/internal/distributions.h"
"random/internal/distribution_caller.h"
"random/internal/fast_uniform_bits.h"
"random/internal/fastmath.h"
diff --git a/absl/flags/commandlineflag.cc b/absl/flags/commandlineflag.cc
index 83d14c1b..cea57234 100644
--- a/absl/flags/commandlineflag.cc
+++ b/absl/flags/commandlineflag.cc
@@ -21,7 +21,7 @@ ABSL_NAMESPACE_BEGIN
bool CommandLineFlag::IsRetired() const { return false; }
bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
return ParseFrom(value, flags_internal::SET_FLAGS_VALUE,
- flags_internal::kProgrammaticChange, error);
+ flags_internal::kProgrammaticChange, *error);
}
namespace flags_internal {
diff --git a/absl/flags/commandlineflag.h b/absl/flags/commandlineflag.h
index f09f1f70..43055d04 100644
--- a/absl/flags/commandlineflag.h
+++ b/absl/flags/commandlineflag.h
@@ -159,7 +159,7 @@ class CommandLineFlag {
virtual bool ParseFrom(absl::string_view value,
flags_internal::FlagSettingMode set_mode,
flags_internal::ValueSource source,
- std::string* error) = 0;
+ std::string& error) = 0;
// Returns id of the flag's value type.
virtual flags_internal::FlagFastTypeId TypeId() const = 0;
diff --git a/absl/flags/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc
index 352edccf..4b9718e9 100644
--- a/absl/flags/commandlineflag_test.cc
+++ b/absl/flags/commandlineflag_test.cc
@@ -129,57 +129,57 @@ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
+ *flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
- &err));
+ *flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
- &err));
+ *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(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
+ *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(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
- &err));
+ *flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, &err));
+ *flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
EXPECT_TRUE(flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
+ *flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
auto* flag_02 = flags::FindCommandLineFlag("string_flag");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
- &err));
+ *flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
+ *flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
}
@@ -191,15 +191,15 @@ TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
auto* flag_01 = flags::FindCommandLineFlag("int_flag");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
- &err));
+ *flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
+ err));
EXPECT_EQ(flag_01->DefaultValue(), "111");
auto* flag_02 = flags::FindCommandLineFlag("string_flag");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
- &err));
+ *flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
+ err));
EXPECT_EQ(flag_02->DefaultValue(), "abc");
}
@@ -211,25 +211,25 @@ TEST_F(CommandLineFlagTest, TestParseFromIfDefault) {
auto* flag_01 = flags::FindCommandLineFlag("int_flag");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
- &err))
+ *flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+ err))
<< err;
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
- &err));
+ *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+ err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
// EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
// Reset back to default value
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
- &err));
+ *flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
- flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
- &err));
+ *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+ err));
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
// EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
}
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index f84853ea..dd36e6c7 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -110,12 +110,12 @@ class Flag {
impl_(nullptr) {}
#endif
- flags_internal::Flag<T>* GetImpl() const {
+ flags_internal::Flag<T>& GetImpl() const {
if (!inited_.load(std::memory_order_acquire)) {
absl::MutexLock l(flags_internal::GetGlobalConstructionGuard());
if (inited_.load(std::memory_order_acquire)) {
- return impl_;
+ return *impl_;
}
impl_ = new flags_internal::Flag<T>(
@@ -127,28 +127,28 @@ class Flag {
inited_.store(true, std::memory_order_release);
}
- return impl_;
+ return *impl_;
}
// Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API.
// See https://abseil.io/docs/cpp/guides/flags
- bool IsRetired() const { return GetImpl()->IsRetired(); }
- absl::string_view Name() const { return GetImpl()->Name(); }
- std::string Help() const { return GetImpl()->Help(); }
- bool IsModified() const { return GetImpl()->IsModified(); }
+ bool IsRetired() const { return GetImpl().IsRetired(); }
+ absl::string_view Name() const { return GetImpl().Name(); }
+ std::string Help() const { return GetImpl().Help(); }
+ bool IsModified() const { return GetImpl().IsModified(); }
bool IsSpecifiedOnCommandLine() const {
- return GetImpl()->IsSpecifiedOnCommandLine();
+ return GetImpl().IsSpecifiedOnCommandLine();
}
- std::string Filename() const { return GetImpl()->Filename(); }
- std::string DefaultValue() const { return GetImpl()->DefaultValue(); }
- std::string CurrentValue() const { return GetImpl()->CurrentValue(); }
+ std::string Filename() const { return GetImpl().Filename(); }
+ std::string DefaultValue() const { return GetImpl().DefaultValue(); }
+ std::string CurrentValue() const { return GetImpl().CurrentValue(); }
template <typename U>
inline bool IsOfType() const {
- return GetImpl()->template IsOfType<U>();
+ return GetImpl().template IsOfType<U>();
}
- T Get() const { return GetImpl()->Get(); }
- void Set(const T& v) { GetImpl()->Set(v); }
- void InvokeCallback() { GetImpl()->InvokeCallback(); }
+ T Get() const { return GetImpl().Get(); }
+ void Set(const T& v) { GetImpl().Set(v); }
+ void InvokeCallback() { GetImpl().InvokeCallback(); }
// The data members are logically private, but they need to be public for
// this to be an aggregate type.
@@ -265,7 +265,7 @@ ABSL_NAMESPACE_END
// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
#if !defined(_MSC_VER) || defined(__clang__)
-#define ABSL_FLAG_IMPL_FLAG_PTR(flag) &flag
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
#define ABSL_FLAG_IMPL_HELP_ARG(name) \
absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
FLAGS_help_storage_##name)
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
index 8d53ecd6..58a07999 100644
--- a/absl/flags/flag_test.cc
+++ b/absl/flags/flag_test.cc
@@ -150,21 +150,21 @@ DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
template <typename T>
-bool TestConstructionFor(const flags::Flag<T>& f1, flags::Flag<T>* f2) {
+bool TestConstructionFor(const flags::Flag<T>& f1, flags::Flag<T>& f2) {
EXPECT_EQ(f1.Name(), "f1");
EXPECT_EQ(f1.Help(), "literal help");
EXPECT_EQ(f1.Filename(), "file");
flags::FlagRegistrar<T, false>(f2).OnUpdate(TestCallback);
- EXPECT_EQ(f2->Name(), "f2");
- EXPECT_EQ(f2->Help(), "dynamic help");
- EXPECT_EQ(f2->Filename(), "file");
+ EXPECT_EQ(f2.Name(), "f2");
+ EXPECT_EQ(f2.Help(), "dynamic help");
+ EXPECT_EQ(f2.Filename(), "file");
return true;
}
-#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, &f2##T);
+#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
TEST_F(FlagTest, TestConstruction) {
TEST_CONSTRUCTED_FLAG(bool);
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc
index 35ae55fb..ee974244 100644
--- a/absl/flags/internal/flag.cc
+++ b/absl/flags/internal/flag.cc
@@ -62,14 +62,14 @@ bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
// need to acquire these locks themselves.
class MutexRelock {
public:
- explicit MutexRelock(absl::Mutex* mu) : mu_(mu) { mu_->Unlock(); }
- ~MutexRelock() { mu_->Lock(); }
+ explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); }
+ ~MutexRelock() { mu_.Lock(); }
MutexRelock(const MutexRelock&) = delete;
MutexRelock& operator=(const MutexRelock&) = delete;
private:
- absl::Mutex* mu_;
+ absl::Mutex& mu_;
};
} // namespace
@@ -82,7 +82,7 @@ class FlagImpl;
class FlagState : public flags_internal::FlagStateInterface {
public:
template <typename V>
- FlagState(FlagImpl* flag_impl, const V& v, bool modified,
+ FlagState(FlagImpl& flag_impl, const V& v, bool modified,
bool on_command_line, int64_t counter)
: flag_impl_(flag_impl),
value_(v),
@@ -91,9 +91,9 @@ class FlagState : public flags_internal::FlagStateInterface {
counter_(counter) {}
~FlagState() override {
- if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer)
+ if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer)
return;
- flags_internal::Delete(flag_impl_->op_, value_.heap_allocated);
+ flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
}
private:
@@ -101,15 +101,15 @@ class FlagState : public flags_internal::FlagStateInterface {
// Restores the flag to the saved state.
void Restore() const override {
- if (!flag_impl_->RestoreState(*this)) return;
+ if (!flag_impl_.RestoreState(*this)) return;
- ABSL_INTERNAL_LOG(
- INFO, absl::StrCat("Restore saved value of ", flag_impl_->Name(),
- " to: ", flag_impl_->CurrentValue()));
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat("Restore saved value of ", flag_impl_.Name(),
+ " to: ", flag_impl_.CurrentValue()));
}
// Flag and saved flag data.
- FlagImpl* flag_impl_;
+ FlagImpl& flag_impl_;
union SavedValue {
explicit SavedValue(void* v) : heap_allocated(v) {}
explicit SavedValue(int64_t v) : one_word(v) {}
@@ -326,7 +326,7 @@ void FlagImpl::InvokeCallback() const {
// and it also can be different by the time the callback invocation is
// completed. Requires that *primary_lock be held in exclusive mode; it may be
// released and reacquired by the implementation.
- MutexRelock relock(DataGuard());
+ MutexRelock relock(*DataGuard());
absl::MutexLock lock(&callback_->guard);
cb();
}
@@ -339,17 +339,17 @@ std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
switch (ValueStorageKind()) {
case FlagValueStorageKind::kAlignedBuffer: {
return absl::make_unique<FlagState>(
- this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
+ *this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
on_command_line, counter_);
}
case FlagValueStorageKind::kOneWordAtomic: {
return absl::make_unique<FlagState>(
- this, OneWordValue().load(std::memory_order_acquire), modified,
+ *this, OneWordValue().load(std::memory_order_acquire), modified,
on_command_line, counter_);
}
case FlagValueStorageKind::kTwoWordsAtomic: {
return absl::make_unique<FlagState>(
- this, TwoWordsValue().load(std::memory_order_acquire), modified,
+ *this, TwoWordsValue().load(std::memory_order_acquire), modified,
on_command_line, counter_);
}
}
@@ -410,14 +410,14 @@ std::atomic<AlignedTwoWords>& FlagImpl::TwoWordsValue() const {
// parsed value. In case if any error is encountered in either step, the error
// message is stored in 'err'
std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
- absl::string_view value, std::string* err) const {
+ absl::string_view value, std::string& err) const {
std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();
std::string parse_err;
if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) {
absl::string_view err_sep = parse_err.empty() ? "" : "; ";
- *err = absl::StrCat("Illegal value '", value, "' specified for flag '",
- Name(), "'", err_sep, parse_err);
+ err = absl::StrCat("Illegal value '", value, "' specified for flag '",
+ Name(), "'", err_sep, parse_err);
return nullptr;
}
@@ -473,7 +473,7 @@ void FlagImpl::Write(const void* src) {
// * Update the current flag value if it was never set before
// The mode is selected based on 'set_mode' parameter.
bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode,
- ValueSource source, std::string* err) {
+ ValueSource source, std::string& err) {
absl::MutexLock l(DataGuard());
switch (set_mode) {
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 97ddb5f9..e1885809 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -374,31 +374,31 @@ struct FlagValue;
template <typename T>
struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
- bool Get(T*) const { return false; }
+ bool Get(T&) const { return false; }
alignas(T) char value[sizeof(T)];
};
template <typename T>
struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
- bool Get(T* dst) const {
+ bool Get(T& dst) const {
int64_t one_word_val = value.load(std::memory_order_acquire);
if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) {
return false;
}
- std::memcpy(dst, static_cast<const void*>(&one_word_val), sizeof(T));
+ std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
return true;
}
};
template <typename T>
struct FlagValue<T, FlagValueStorageKind::kTwoWordsAtomic> : FlagTwoWordsValue {
- bool Get(T* dst) const {
+ bool Get(T& dst) const {
AlignedTwoWords two_words_val = value.load(std::memory_order_acquire);
if (ABSL_PREDICT_FALSE(!two_words_val.IsInitialized())) {
return false;
}
- std::memcpy(dst, static_cast<const void*>(&two_words_val), sizeof(T));
+ std::memcpy(&dst, static_cast<const void*>(&two_words_val), sizeof(T));
return true;
}
};
@@ -502,7 +502,7 @@ class FlagImpl final : public CommandLineFlag {
// Attempts to parse supplied `value` string. If parsing is successful,
// returns new value. Otherwise returns nullptr.
std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
- std::string* err) const
+ std::string& err) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
// Stores the flag value based on the pointer to the source.
void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
@@ -544,7 +544,7 @@ class FlagImpl final : public CommandLineFlag {
ABSL_LOCKS_EXCLUDED(*DataGuard());
bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
- ValueSource source, std::string* error) override
+ ValueSource source, std::string& error) override
ABSL_LOCKS_EXCLUDED(*DataGuard());
// Immutable flag's state.
@@ -651,7 +651,7 @@ class Flag {
impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
#endif
- if (!value_.Get(&u.value)) impl_.Read(&u.value);
+ if (!value_.Get(u.value)) impl_.Read(&u.value);
return std::move(u.value);
}
void Set(const T& v) {
@@ -730,12 +730,12 @@ struct FlagRegistrarEmpty {};
template <typename T, bool do_register>
class FlagRegistrar {
public:
- explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) {
- if (do_register) flags_internal::RegisterCommandLineFlag(&flag_->impl_);
+ explicit FlagRegistrar(Flag<T>& flag) : flag_(flag) {
+ if (do_register) flags_internal::RegisterCommandLineFlag(flag_.impl_);
}
FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
- flag_->impl_.SetCallback(cb);
+ flag_.impl_.SetCallback(cb);
return *this;
}
@@ -745,7 +745,7 @@ class FlagRegistrar {
operator FlagRegistrarEmpty() const { return {}; } // NOLINT
private:
- Flag<T>* flag_; // Flag being registered (not owned).
+ Flag<T>& flag_; // Flag being registered (not owned).
};
} // namespace flags_internal
diff --git a/absl/flags/internal/private_handle_accessor.cc b/absl/flags/internal/private_handle_accessor.cc
index 64fe3166..24b49136 100644
--- a/absl/flags/internal/private_handle_accessor.cc
+++ b/absl/flags/internal/private_handle_accessor.cc
@@ -24,8 +24,8 @@ FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) {
}
std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(
- CommandLineFlag* flag) {
- return flag->SaveState();
+ CommandLineFlag& flag) {
+ return flag.SaveState();
}
bool PrivateHandleAccessor::IsSpecifiedOnCommandLine(
@@ -43,12 +43,12 @@ void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
flag.CheckDefaultValueParsingRoundtrip();
}
-bool PrivateHandleAccessor::ParseFrom(CommandLineFlag* flag,
+bool PrivateHandleAccessor::ParseFrom(CommandLineFlag& flag,
absl::string_view value,
flags_internal::FlagSettingMode set_mode,
flags_internal::ValueSource source,
- std::string* error) {
- return flag->ParseFrom(value, set_mode, source, error);
+ std::string& error) {
+ return flag.ParseFrom(value, set_mode, source, error);
}
} // namespace flags_internal
diff --git a/absl/flags/internal/private_handle_accessor.h b/absl/flags/internal/private_handle_accessor.h
index 07838600..9a327a07 100644
--- a/absl/flags/internal/private_handle_accessor.h
+++ b/absl/flags/internal/private_handle_accessor.h
@@ -31,7 +31,7 @@ class PrivateHandleAccessor {
static FlagFastTypeId TypeId(const CommandLineFlag& flag);
// Access to CommandLineFlag::SaveState.
- static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag* flag);
+ static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag& flag);
// Access to CommandLineFlag::IsSpecifiedOnCommandLine.
static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);
@@ -43,9 +43,9 @@ class PrivateHandleAccessor {
// Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.
static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag);
- static bool ParseFrom(CommandLineFlag* flag, absl::string_view value,
+ static bool ParseFrom(CommandLineFlag& flag, absl::string_view value,
flags_internal::FlagSettingMode set_mode,
- flags_internal::ValueSource source, std::string* error);
+ flags_internal::ValueSource source, std::string& error);
};
} // namespace flags_internal
diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc
index 70d76557..4bcebfa9 100644
--- a/absl/flags/internal/registry.cc
+++ b/absl/flags/internal/registry.cc
@@ -60,8 +60,8 @@ class FlagRegistry {
FlagRegistry() = default;
~FlagRegistry() = default;
- // Store a flag in this registry. Takes ownership of *flag.
- void RegisterFlag(CommandLineFlag* flag);
+ // Store a flag in this registry. Takes ownership of *flag.
+ void RegisterFlag(CommandLineFlag& flag);
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
@@ -74,12 +74,12 @@ class FlagRegistry {
// found or not retired. Does not emit a warning.
CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
- static FlagRegistry* GlobalRegistry(); // returns a singleton registry
+ static FlagRegistry& GlobalRegistry(); // returns a singleton registry
private:
friend class FlagSaverImpl; // reads all the flags in order to copy them
friend void ForEachFlagUnlocked(
- std::function<void(CommandLineFlag*)> visitor);
+ std::function<void(CommandLineFlag&)> visitor);
// The map from name to flag, for FindFlagLocked().
using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
@@ -94,65 +94,62 @@ class FlagRegistry {
FlagRegistry& operator=(const FlagRegistry&);
};
-FlagRegistry* FlagRegistry::GlobalRegistry() {
+FlagRegistry& FlagRegistry::GlobalRegistry() {
static FlagRegistry* global_registry = new FlagRegistry;
- return global_registry;
+ return *global_registry;
}
namespace {
class FlagRegistryLock {
public:
- explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
- ~FlagRegistryLock() { fr_->Unlock(); }
+ explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.Lock(); }
+ ~FlagRegistryLock() { fr_.Unlock(); }
private:
- FlagRegistry* const fr_;
+ FlagRegistry& fr_;
};
-void DestroyRetiredFlag(CommandLineFlag* flag);
+void DestroyRetiredFlag(CommandLineFlag& flag);
} // namespace
-void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
- FlagRegistryLock registry_lock(this);
+void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
+ FlagRegistryLock registry_lock(*this);
std::pair<FlagIterator, bool> ins =
- flags_.insert(FlagMap::value_type(flag->Name(), flag));
+ flags_.insert(FlagMap::value_type(flag.Name(), &flag));
if (ins.second == false) { // means the name was already in the map
- CommandLineFlag* old_flag = ins.first->second;
- if (flag->IsRetired() != old_flag->IsRetired()) {
+ CommandLineFlag& old_flag = *ins.first->second;
+ if (flag.IsRetired() != old_flag.IsRetired()) {
// All registrations must agree on the 'retired' flag.
flags_internal::ReportUsageError(
absl::StrCat(
- "Retired flag '", flag->Name(),
- "' was defined normally in file '",
- (flag->IsRetired() ? old_flag->Filename() : flag->Filename()),
- "'."),
+ "Retired flag '", flag.Name(), "' was defined normally in file '",
+ (flag.IsRetired() ? old_flag.Filename() : flag.Filename()), "'."),
true);
- } else if (flags_internal::PrivateHandleAccessor::TypeId(*flag) !=
- flags_internal::PrivateHandleAccessor::TypeId(*old_flag)) {
+ } else if (flags_internal::PrivateHandleAccessor::TypeId(flag) !=
+ flags_internal::PrivateHandleAccessor::TypeId(old_flag)) {
flags_internal::ReportUsageError(
- absl::StrCat("Flag '", flag->Name(),
+ absl::StrCat("Flag '", flag.Name(),
"' was defined more than once but with "
"differing types. Defined in files '",
- old_flag->Filename(), "' and '", flag->Filename(), "'."),
+ old_flag.Filename(), "' and '", flag.Filename(), "'."),
true);
- } else if (old_flag->IsRetired()) {
+ } else if (old_flag.IsRetired()) {
// Retired flag can just be deleted.
DestroyRetiredFlag(flag);
return;
- } else if (old_flag->Filename() != flag->Filename()) {
+ } else if (old_flag.Filename() != flag.Filename()) {
flags_internal::ReportUsageError(
- absl::StrCat("Flag '", flag->Name(),
+ absl::StrCat("Flag '", flag.Name(),
"' was defined more than once (in files '",
- old_flag->Filename(), "' and '", flag->Filename(),
- "')."),
+ old_flag.Filename(), "' and '", flag.Filename(), "')."),
true);
} else {
flags_internal::ReportUsageError(
absl::StrCat(
- "Something wrong with flag '", flag->Name(), "' in file '",
- flag->Filename(), "'. One possibility: file '", flag->Filename(),
+ "Something wrong with flag '", flag.Name(), "' in file '",
+ flag.Filename(), "'. One possibility: file '", flag.Filename(),
"' is being linked both statically and dynamically into this "
"executable. e.g. some files listed as srcs to a test and also "
"listed as srcs of some shared lib deps of the same test."),
@@ -206,7 +203,7 @@ class FlagSaverImpl {
// It's an error to call this more than once.
void SaveFromRegistry() {
assert(backup_registry_.empty()); // call only once!
- flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
if (auto flag_state =
flags_internal::PrivateHandleAccessor::SaveState(flag)) {
backup_registry_.emplace_back(std::move(flag_state));
@@ -244,39 +241,39 @@ FlagSaver::~FlagSaver() {
CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
if (name.empty()) return nullptr;
- FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+ FlagRegistry& registry = FlagRegistry::GlobalRegistry();
FlagRegistryLock frl(registry);
- return registry->FindFlagLocked(name);
+ return registry.FindFlagLocked(name);
}
CommandLineFlag* FindRetiredFlag(absl::string_view name) {
- FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+ FlagRegistry& registry = FlagRegistry::GlobalRegistry();
FlagRegistryLock frl(registry);
- return registry->FindRetiredFlagLocked(name);
+ return registry.FindRetiredFlagLocked(name);
}
// --------------------------------------------------------------------
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor) {
- FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
- for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
- i != registry->flags_.end(); ++i) {
- visitor(i->second);
+void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor) {
+ FlagRegistry& registry = FlagRegistry::GlobalRegistry();
+ for (FlagRegistry::FlagConstIterator i = registry.flags_.begin();
+ i != registry.flags_.end(); ++i) {
+ visitor(*i->second);
}
}
-void ForEachFlag(std::function<void(CommandLineFlag*)> visitor) {
- FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
+ FlagRegistry& registry = FlagRegistry::GlobalRegistry();
FlagRegistryLock frl(registry);
ForEachFlagUnlocked(visitor);
}
// --------------------------------------------------------------------
-bool RegisterCommandLineFlag(CommandLineFlag* flag) {
- FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
+bool RegisterCommandLineFlag(CommandLineFlag& flag) {
+ FlagRegistry::GlobalRegistry().RegisterFlag(flag);
return true;
}
@@ -307,7 +304,7 @@ class RetiredFlagObj final : public CommandLineFlag {
}
bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode,
- flags_internal::ValueSource, std::string*) override {
+ flags_internal::ValueSource, std::string&) override {
return false;
}
@@ -320,16 +317,16 @@ class RetiredFlagObj final : public CommandLineFlag {
const FlagFastTypeId type_id_;
};
-void DestroyRetiredFlag(CommandLineFlag* flag) {
- assert(flag->IsRetired());
- delete static_cast<RetiredFlagObj*>(flag);
+void DestroyRetiredFlag(CommandLineFlag& flag) {
+ assert(flag.IsRetired());
+ delete static_cast<RetiredFlagObj*>(&flag);
}
} // namespace
bool Retire(const char* name, FlagFastTypeId type_id) {
auto* flag = new flags_internal::RetiredFlagObj(name, type_id);
- FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
+ FlagRegistry::GlobalRegistry().RegisterFlag(*flag);
return true;
}
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index f722fd44..a118865a 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -39,14 +39,14 @@ CommandLineFlag* FindRetiredFlag(absl::string_view name);
// Executes specified visitor for each non-retired flag in the registry.
// Requires the caller hold the registry lock.
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor);
+void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor);
// Executes specified visitor for each non-retired flag in the registry. While
// callback are executed, the registry is locked and can't be changed.
-void ForEachFlag(std::function<void(CommandLineFlag*)> visitor);
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
//-----------------------------------------------------------------------------
-bool RegisterCommandLineFlag(CommandLineFlag*);
+bool RegisterCommandLineFlag(CommandLineFlag&);
//-----------------------------------------------------------------------------
// Retired registrations:
diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc
index 35b0d125..b2523b24 100644
--- a/absl/flags/internal/type_erased.cc
+++ b/absl/flags/internal/type_erased.cc
@@ -58,7 +58,7 @@ bool SetCommandLineOptionWithMode(absl::string_view name,
std::string error;
if (!flags_internal::PrivateHandleAccessor::ParseFrom(
- flag, value, set_mode, kProgrammaticChange, &error)) {
+ *flag, value, set_mode, kProgrammaticChange, error)) {
// Errors here are all of the form: the provided name was a recognized
// flag, but the value was invalid (bad type, or validation failed).
flags_internal::ReportUsageError(error, false);
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 11664e10..2a2231a7 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -107,8 +107,8 @@ class FlagHelpPrettyPrinter {
public:
// Pretty printer holds on to the std::ostream& reference to direct an output
// to that stream.
- FlagHelpPrettyPrinter(int max_line_len, std::ostream* out)
- : out_(*out),
+ FlagHelpPrettyPrinter(int max_line_len, std::ostream& out)
+ : out_(out),
max_line_len_(max_line_len),
line_len_(0),
first_line_(true) {}
@@ -182,7 +182,7 @@ class FlagHelpPrettyPrinter {
bool first_line_;
};
-void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream* out) {
+void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
FlagHelpPrettyPrinter printer(80, out); // Max line length is 80.
// Flag name.
@@ -244,29 +244,28 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
// This map is used to output matching flags grouped by package and file
// name.
std::map<std::string,
- std::map<std::string, std::vector<const CommandLineFlag*>>>
+ std::map<std::string, std::vector<const absl::CommandLineFlag*>>>
matching_flags;
- flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
- std::string flag_filename = flag->Filename();
+ flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {
+ std::string flag_filename = flag.Filename();
// Ignore retired flags.
- if (flag->IsRetired()) return;
+ if (flag.IsRetired()) return;
// If the flag has been stripped, pretend that it doesn't exist.
- if (flag->Help() == flags_internal::kStrippedFlagHelp) return;
+ if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
// Make sure flag satisfies the filter
if (!filter_cb || !filter_cb(flag_filename)) return;
matching_flags[std::string(flags_internal::Package(flag_filename))]
[flag_filename]
- .push_back(flag);
+ .push_back(&flag);
});
- absl::string_view
- package_separator; // controls blank lines between packages.
- absl::string_view file_separator; // controls blank lines between files.
+ absl::string_view package_separator; // controls blank lines between packages
+ absl::string_view file_separator; // controls blank lines between files
for (const auto& package : matching_flags) {
if (format == HelpFormat::kHumanReadable) {
out << package_separator;
@@ -304,7 +303,7 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
HelpFormat format) {
if (format == HelpFormat::kHumanReadable)
- flags_internal::FlagHelpHumanReadable(flag, &out);
+ flags_internal::FlagHelpHumanReadable(flag, out);
}
// --------------------------------------------------------------------
diff --git a/absl/flags/marshalling.cc b/absl/flags/marshalling.cc
index 09baae88..81f9cebd 100644
--- a/absl/flags/marshalling.cc
+++ b/absl/flags/marshalling.cc
@@ -74,15 +74,16 @@ static int NumericBase(absl::string_view text) {
}
template <typename IntType>
-inline bool ParseFlagImpl(absl::string_view text, IntType* dst) {
+inline bool ParseFlagImpl(absl::string_view text, IntType& dst) {
text = absl::StripAsciiWhitespace(text);
- return absl::numbers_internal::safe_strtoi_base(text, dst, NumericBase(text));
+ return absl::numbers_internal::safe_strtoi_base(text, &dst,
+ NumericBase(text));
}
bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
int val;
- if (!ParseFlagImpl(text, &val)) return false;
+ if (!ParseFlagImpl(text, val)) return false;
if (static_cast<short>(val) != val) // worked, but number out of range
return false;
*dst = static_cast<short>(val);
@@ -91,7 +92,7 @@ bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
unsigned int val;
- if (!ParseFlagImpl(text, &val)) return false;
+ if (!ParseFlagImpl(text, val)) return false;
if (static_cast<unsigned short>(val) !=
val) // worked, but number out of range
return false;
@@ -100,28 +101,28 @@ bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
}
bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
- return ParseFlagImpl(text, dst);
+ return ParseFlagImpl(text, *dst);
}
bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
- return ParseFlagImpl(text, dst);
+ return ParseFlagImpl(text, *dst);
}
bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
- return ParseFlagImpl(text, dst);
+ return ParseFlagImpl(text, *dst);
}
bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
- return ParseFlagImpl(text, dst);
+ return ParseFlagImpl(text, *dst);
}
bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
- return ParseFlagImpl(text, dst);
+ return ParseFlagImpl(text, *dst);
}
bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
std::string*) {
- return ParseFlagImpl(text, dst);
+ return ParseFlagImpl(text, *dst);
}
// --------------------------------------------------------------------
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index 3f0a7a75..15300786 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -222,7 +222,7 @@ bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
// Reads the environment variable with name `name` and stores results in
// `value`. If variable is not present in environment returns false, otherwise
// returns true.
-bool GetEnvVar(const char* var_name, std::string* var_value) {
+bool GetEnvVar(const char* var_name, std::string& var_value) {
#ifdef _WIN32
char buf[1024];
auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
@@ -234,14 +234,14 @@ bool GetEnvVar(const char* var_name, std::string* var_value) {
return false;
}
- *var_value = std::string(buf, get_res);
+ var_value = std::string(buf, get_res);
#else
const char* val = ::getenv(var_name);
if (val == nullptr) {
return false;
}
- *var_value = val;
+ var_value = val;
#endif
return true;
@@ -306,17 +306,17 @@ std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
// back.
void CheckDefaultValuesParsingRoundtrip() {
#ifndef NDEBUG
- flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
- if (flag->IsRetired()) return;
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+ if (flag.IsRetired()) return;
#define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
- if (flag->IsOfType<T>()) return;
+ if (flag.IsOfType<T>()) return;
ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE)
#undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE
flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
- *flag);
+ flag);
});
#endif
}
@@ -329,13 +329,13 @@ void CheckDefaultValuesParsingRoundtrip() {
// the first flagfile in the input list are processed before the second flagfile
// etc.
bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
- std::vector<ArgsList>* input_args) {
+ std::vector<ArgsList>& input_args) {
bool success = true;
for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
ArgsList al;
if (al.ReadFromFlagfile(*it)) {
- input_args->push_back(al);
+ input_args.push_back(al);
} else {
success = false;
}
@@ -350,7 +350,7 @@ bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
// `flag_name` is a string from the input flag_names list. If successful we
// append a single ArgList at the end of the input_args.
bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
- std::vector<ArgsList>* input_args,
+ std::vector<ArgsList>& input_args,
bool fail_on_absent_in_env) {
bool success = true;
std::vector<std::string> args;
@@ -371,7 +371,7 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
const std::string envname = absl::StrCat("FLAGS_", flag_name);
std::string envval;
- if (!GetEnvVar(envname.c_str(), &envval)) {
+ if (!GetEnvVar(envname.c_str(), envval)) {
if (fail_on_absent_in_env) {
flags_internal::ReportUsageError(
absl::StrCat(envname, " not found in environment"), true);
@@ -386,7 +386,7 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
}
if (success) {
- input_args->emplace_back(args);
+ input_args.emplace_back(args);
}
return success;
@@ -396,8 +396,8 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
// Returns success status, which is true if were able to handle all generator
// flags (flagfile, fromenv, tryfromemv) successfully.
-bool HandleGeneratorFlags(std::vector<ArgsList>* input_args,
- std::vector<std::string>* flagfile_value) {
+bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
+ std::vector<std::string>& flagfile_value) {
bool success = true;
absl::MutexLock l(&flags_internal::processing_checks_guard);
@@ -422,9 +422,9 @@ bool HandleGeneratorFlags(std::vector<ArgsList>* input_args,
if (flags_internal::flagfile_needs_processing) {
auto flagfiles = absl::GetFlag(FLAGS_flagfile);
- if (input_args->size() == 1) {
- flagfile_value->insert(flagfile_value->end(), flagfiles.begin(),
- flagfiles.end());
+ if (input_args.size() == 1) {
+ flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
+ flagfiles.end());
}
success &= ReadFlagfiles(flagfiles, input_args);
@@ -647,7 +647,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
bool success = true;
while (!input_args.empty()) {
// 10. First we process the built-in generator flags.
- success &= HandleGeneratorFlags(&input_args, &flagfile_value);
+ success &= HandleGeneratorFlags(input_args, flagfile_value);
// 30. Select top-most (most recent) arguments list. If it is empty drop it
// and re-try.
@@ -733,7 +733,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
std::string error;
if (!flags_internal::PrivateHandleAccessor::ParseFrom(
- flag, value, SET_FLAGS_VALUE, kCommandLine, &error)) {
+ *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) {
flags_internal::ReportUsageError(error, true);
success = false;
} else {
diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc
index e6a53ae6..aea068ee 100644
--- a/absl/flags/parse_test.cc
+++ b/absl/flags/parse_test.cc
@@ -171,8 +171,8 @@ constexpr const char* const ff2_data[] = {
// temporary directory location. This way we can test inclusion of one flagfile
// from another flagfile.
const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
- std::string* flagfile_flag) {
- *flagfile_flag = "--flagfile=";
+ std::string& flagfile_flag) {
+ flagfile_flag = "--flagfile=";
absl::string_view separator;
for (const auto& flagfile_data : ffd) {
std::string flagfile_name =
@@ -183,11 +183,11 @@ const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
}
- absl::StrAppend(flagfile_flag, separator, flagfile_name);
+ absl::StrAppend(&flagfile_flag, separator, flagfile_name);
separator = ",";
}
- return flagfile_flag->c_str();
+ return flagfile_flag.c_str();
}
} // namespace
@@ -588,14 +588,14 @@ TEST_F(ParseTest, TestSimpleValidFlagfile) {
const char* in_args1[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- &flagfile_flag),
+ flagfile_flag),
};
TestParse(in_args1, -1, 0.1, "q2w2 ", true);
const char* in_args2[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}},
- &flagfile_flag),
+ flagfile_flag),
};
TestParse(in_args2, 100, 0.1, "q2w2 ", false);
}
@@ -609,7 +609,7 @@ TEST_F(ParseTest, TestValidMultiFlagfile) {
"testbin",
GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- &flagfile_flag),
+ flagfile_flag),
};
TestParse(in_args1, -1, 0.1, "q2w2 ", true);
}
@@ -622,7 +622,7 @@ TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
const char* in_args1[] = {
"testbin", "--int_flag=3",
GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- &flagfile_flag),
+ flagfile_flag),
"-double_flag=0.2"};
TestParse(in_args1, -1, 0.2, "q2w2 ", true);
}
@@ -640,7 +640,7 @@ TEST_F(ParseTest, TestFlagfileInFlagfile) {
const char* in_args1[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
- &flagfile_flag),
+ flagfile_flag),
};
TestParse(in_args1, 100, 0.1, "q2w2 ", false);
}
@@ -657,7 +657,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
const char* in_args1[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff4",
- absl::MakeConstSpan(ff4_data)}}, &flagfile_flag),
+ absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
};
EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
"Unknown command line flag 'unknown_flag'");
@@ -669,7 +669,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
const char* in_args2[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff5",
- absl::MakeConstSpan(ff5_data)}}, &flagfile_flag),
+ absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
};
EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
"Unknown command line flag 'int_flag 10'");
@@ -681,7 +681,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
const char* in_args3[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
- &flagfile_flag),
+ flagfile_flag),
};
EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
"Flagfile can't contain position arguments or --");
@@ -702,7 +702,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
const char* in_args5[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
- &flagfile_flag),
+ flagfile_flag),
};
EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
"Unexpected line in the flagfile .*: \\*bin\\*");
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index 9ba75b52..4b804c86 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -69,7 +69,7 @@ cc_library(
"//absl/base:config",
"//absl/base:core_headers",
"//absl/meta:type_traits",
- "//absl/random/internal:distributions",
+ "//absl/random/internal:distribution_caller",
"//absl/random/internal:fast_uniform_bits",
"//absl/random/internal:fastmath",
"//absl/random/internal:generate_real",
@@ -78,7 +78,6 @@ cc_library(
"//absl/random/internal:uniform_helper",
"//absl/random/internal:wide_multiply",
"//absl/strings",
- "//absl/types:span",
],
)
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index ec616dd9..85a2ea37 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -183,7 +183,7 @@ absl_cc_library(
absl::config
absl::core_headers
absl::random_internal_generate_real
- absl::random_internal_distributions
+ absl::random_internal_distribution_caller
absl::random_internal_fast_uniform_bits
absl::random_internal_fastmath
absl::random_internal_iostream_state_saver
@@ -191,7 +191,6 @@ absl_cc_library(
absl::random_internal_uniform_helper
absl::random_internal_wide_multiply
absl::strings
- absl::span
absl::type_traits
)
@@ -539,27 +538,6 @@ absl_cc_library(
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
- random_internal_distributions
- HDRS
- "internal/distributions.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- LINKOPTS
- ${ABSL_DEFAULT_LINKOPTS}
- DEPS
- absl::random_internal_distribution_caller
- absl::random_internal_fast_uniform_bits
- absl::random_internal_fastmath
- absl::random_internal_traits
- absl::random_internal_uniform_helper
- absl::span
- absl::strings
- absl::type_traits
-)
-
-# Internal-only target, do not depend on directly.
-absl_cc_library(
- NAME
random_internal_fast_uniform_bits
HDRS
"internal/fast_uniform_bits.h"
@@ -745,7 +723,6 @@ absl_cc_library(
absl::random_internal_salted_seed_seq
absl::random_internal_seed_material
absl::span
- absl::strings
absl::type_traits
)
@@ -1174,9 +1151,7 @@ absl_cc_library(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
- absl::core_headers
- absl::random_internal_fast_uniform_bits
- absl::random_internal_iostream_state_saver
+ absl::config
absl::random_internal_traits
absl::type_traits
)
diff --git a/absl/random/distributions.h b/absl/random/distributions.h
index 8680f6a6..6775c5d6 100644
--- a/absl/random/distributions.h
+++ b/absl/random/distributions.h
@@ -57,7 +57,7 @@
#include "absl/random/beta_distribution.h"
#include "absl/random/exponential_distribution.h"
#include "absl/random/gaussian_distribution.h"
-#include "absl/random/internal/distributions.h" // IWYU pragma: export
+#include "absl/random/internal/distribution_caller.h" // IWYU pragma: export
#include "absl/random/internal/uniform_helper.h" // IWYU pragma: export
#include "absl/random/log_uniform_int_distribution.h"
#include "absl/random/poisson_distribution.h"
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index 85d1fb81..813d926e 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -49,21 +49,6 @@ cc_library(
)
cc_library(
- name = "distributions",
- hdrs = ["distributions.h"],
- copts = ABSL_DEFAULT_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = [
- ":distribution_caller",
- ":traits",
- ":uniform_helper",
- "//absl/base",
- "//absl/meta:type_traits",
- "//absl/strings",
- ],
-)
-
-cc_library(
name = "fast_uniform_bits",
hdrs = [
"fast_uniform_bits.h",
@@ -221,7 +206,6 @@ cc_library(
":seed_material",
"//absl/base:core_headers",
"//absl/meta:type_traits",
- "//absl/strings",
"//absl/types:optional",
"//absl/types:span",
],
@@ -672,6 +656,8 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":traits",
+ "//absl/base:config",
"//absl/meta:type_traits",
],
)
diff --git a/absl/random/internal/distributions.h b/absl/random/internal/distributions.h
deleted file mode 100644
index d7e3c016..00000000
--- a/absl/random/internal/distributions.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2019 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.
-
-#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
-#define ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
-
-#include <type_traits>
-
-#include "absl/meta/type_traits.h"
-#include "absl/random/internal/distribution_caller.h"
-#include "absl/random/internal/traits.h"
-#include "absl/random/internal/uniform_helper.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace random_internal {
-
-// In the absence of an explicitly provided return-type, the template
-// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
-// the data-types of the endpoint-arguments {A lo, B hi}.
-//
-// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
-// return-type, if one type can be implicitly converted into the other, in a
-// lossless way. The template "is_widening_convertible" implements the
-// compile-time logic for deciding if such a conversion is possible.
-//
-// If no such conversion between {A, B} exists, then the overload for
-// absl::Uniform() will be discarded, and the call will be ill-formed.
-// Return-type for absl::Uniform() when the return-type is inferred.
-template <typename A, typename B>
-using uniform_inferred_return_t =
- absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
- is_widening_convertible<B, A>>::value,
- typename std::conditional<
- is_widening_convertible<A, B>::value, B, A>::type>;
-
-} // namespace random_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h
index 663107cb..5b2afecb 100644
--- a/absl/random/internal/uniform_helper.h
+++ b/absl/random/internal/uniform_helper.h
@@ -19,10 +19,13 @@
#include <limits>
#include <type_traits>
+#include "absl/base/config.h"
#include "absl/meta/type_traits.h"
+#include "absl/random/internal/traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
+
template <typename IntType>
class uniform_int_distribution;
@@ -58,6 +61,26 @@ struct IntervalOpenOpenTag
: public random_internal::TagTypeCompare<IntervalOpenOpenTag> {};
namespace random_internal {
+
+// In the absence of an explicitly provided return-type, the template
+// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
+// the data-types of the endpoint-arguments {A lo, B hi}.
+//
+// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
+// return-type, if one type can be implicitly converted into the other, in a
+// lossless way. The template "is_widening_convertible" implements the
+// compile-time logic for deciding if such a conversion is possible.
+//
+// If no such conversion between {A, B} exists, then the overload for
+// absl::Uniform() will be discarded, and the call will be ill-formed.
+// Return-type for absl::Uniform() when the return-type is inferred.
+template <typename A, typename B>
+using uniform_inferred_return_t =
+ absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
+ is_widening_convertible<B, A>>::value,
+ typename std::conditional<
+ is_widening_convertible<A, B>::value, B, A>::type>;
+
// The functions
// uniform_lower_bound(tag, a, b)
// and
@@ -149,12 +172,19 @@ uniform_upper_bound(Tag, FloatType, FloatType b) {
return std::nextafter(b, (std::numeric_limits<FloatType>::max)());
}
+// UniformDistribution selects either absl::uniform_int_distribution
+// or absl::uniform_real_distribution depending on the NumType parameter.
template <typename NumType>
using UniformDistribution =
typename std::conditional<std::is_integral<NumType>::value,
absl::uniform_int_distribution<NumType>,
absl::uniform_real_distribution<NumType>>::type;
+// UniformDistributionWrapper is used as the underlying distribution type
+// by the absl::Uniform template function. It selects the proper Abseil
+// uniform distribution and provides constructor overloads that match the
+// expected parameter order as well as adjusting distribtuion bounds based
+// on the tag.
template <typename NumType>
struct UniformDistributionWrapper : public UniformDistribution<NumType> {
template <typename TagType>
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index 1ddd6aec..68f53987 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -705,6 +705,37 @@ Cord::Cord(absl::string_view src) {
}
}
+template <typename T, Cord::EnableIfString<T>>
+Cord::Cord(T&& src) {
+ if (
+ // String is short: copy data to avoid external block overhead.
+ src.size() <= kMaxBytesToCopy ||
+ // String is wasteful: copy data to avoid pinning too much unused memory.
+ src.size() < src.capacity() / 2
+ ) {
+ if (src.size() <= InlineRep::kMaxInline) {
+ contents_.set_data(src.data(), src.size(), false);
+ } else {
+ contents_.set_tree(NewTree(src.data(), src.size(), 0));
+ }
+ } else {
+ struct StringReleaser {
+ void operator()(absl::string_view /* data */) {}
+ std::string data;
+ };
+ const absl::string_view original_data = src;
+ CordRepExternal* rep =
+ static_cast<CordRepExternal*>(absl::cord_internal::NewExternalRep(
+ original_data, StringReleaser{std::move(src)}));
+ // Moving src may have invalidated its data pointer, so adjust it.
+ rep->base =
+ static_cast<StringReleaser*>(GetExternalReleaser(rep))->data.data();
+ contents_.set_tree(rep);
+ }
+}
+
+template Cord::Cord(std::string&& src);
+
// The destruction code is separate so that the compiler can determine
// that it does not need to call the destructor on a moved-from Cord.
void Cord::DestroyCordSlow() {
@@ -742,6 +773,18 @@ Cord& Cord::operator=(absl::string_view src) {
return *this;
}
+template <typename T, Cord::EnableIfString<T>>
+Cord& Cord::operator=(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ *this = absl::string_view(src);
+ } else {
+ *this = Cord(std::move(src));
+ }
+ return *this;
+}
+
+template Cord& Cord::operator=(std::string&& src);
+
// TODO(sanjay): Move to Cord::InlineRep section of file. For now,
// we keep it here to make diffs easier.
void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
@@ -853,6 +896,17 @@ void Cord::Append(const Cord& src) { AppendImpl(src); }
void Cord::Append(Cord&& src) { AppendImpl(std::move(src)); }
+template <typename T, Cord::EnableIfString<T>>
+void Cord::Append(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Append(absl::string_view(src));
+ } else {
+ Append(Cord(std::move(src)));
+ }
+}
+
+template void Cord::Append(std::string&& src);
+
void Cord::Prepend(const Cord& src) {
CordRep* src_tree = src.contents_.tree();
if (src_tree != nullptr) {
@@ -882,6 +936,17 @@ void Cord::Prepend(absl::string_view src) {
}
}
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Prepend(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Prepend(absl::string_view(src));
+ } else {
+ Prepend(Cord(std::move(src)));
+ }
+}
+
+template void Cord::Prepend(std::string&& src);
+
static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
if (n >= node->length) return nullptr;
if (n == 0) return Ref(node);
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
index 3be8d7d8..dc987454 100644
--- a/absl/strings/cord.h
+++ b/absl/strings/cord.h
@@ -147,11 +147,8 @@ class Cord {
// Creates a Cord from a `std::string&&` rvalue. These constructors are
// templated to avoid ambiguities for types that are convertible to both
// `absl::string_view` and `std::string`, such as `const char*`.
- //
- // Note that these functions reserve the right to use the `string&&`'s
- // memory and that they will do so in the future.
template <typename T, EnableIfString<T> = 0>
- explicit Cord(T&& src) : Cord(absl::string_view(src)) {}
+ explicit Cord(T&& src);
template <typename T, EnableIfString<T> = 0>
Cord& operator=(T&& src);
@@ -1048,11 +1045,8 @@ inline Cord& Cord::operator=(Cord&& x) noexcept {
return *this;
}
-template <typename T, Cord::EnableIfString<T>>
-inline Cord& Cord::operator=(T&& src) {
- *this = absl::string_view(src);
- return *this;
-}
+extern template Cord::Cord(std::string&& src);
+extern template Cord& Cord::operator=(std::string&& src);
inline size_t Cord::size() const {
// Length is 1st field in str.rep_
@@ -1098,19 +1092,8 @@ inline void Cord::Append(absl::string_view src) {
contents_.AppendArray(src.data(), src.size());
}
-template <typename T, Cord::EnableIfString<T>>
-inline void Cord::Append(T&& src) {
- // Note that this function reserves the right to reuse the `string&&`'s
- // memory and that it will do so in the future.
- Append(absl::string_view(src));
-}
-
-template <typename T, Cord::EnableIfString<T>>
-inline void Cord::Prepend(T&& src) {
- // Note that this function reserves the right to reuse the `string&&`'s
- // memory and that it will do so in the future.
- Prepend(absl::string_view(src));
-}
+extern template void Cord::Append(std::string&& src);
+extern template void Cord::Prepend(std::string&& src);
inline int Cord::Compare(const Cord& rhs) const {
if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index 49a68849..22cfef66 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -8,6 +8,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/strings/cord.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
@@ -353,6 +354,7 @@ TEST(StrFormat, BehavesAsDocumented) {
EXPECT_EQ(StrFormat("%s", "C"), "C");
EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
+ EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord");
// Integral Conversion
// These format integral types: char, int, long, uint64_t, etc.
EXPECT_EQ(StrFormat("%d", char{10}), "10");
diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h
index d4ea90ef..b33e0c0a 100644
--- a/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -292,6 +292,7 @@ bool parse(const std::string&, const std::string&, const time_zone&,
// - %E#f - Fractional seconds with # digits of precision
// - %E*f - Fractional seconds with full precision (a literal '*')
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+// - %ET - The RFC3339 "date-time" separator "T"
//
// Note that %E0S behaves like %S, and %E0f produces no characters. In
// contrast %E*f always produces at least one digit, which may be '0'.
@@ -321,7 +322,7 @@ inline std::string format(const std::string& fmt, const time_point<D>& tp,
// returns the corresponding time_point. Uses strftime()-like formatting
// options, with the same extensions as cctz::format(), but with the
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
-// and %E*z also accept the same inputs.
+// and %E*z also accept the same inputs. %ET accepts either 'T' or 't'.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
index a402760d..4e39188f 100644
--- a/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -97,8 +97,8 @@ void BM_PrevWeekday(benchmark::State& state) {
}
BENCHMARK(BM_PrevWeekday);
-const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
+const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
@@ -991,12 +991,12 @@ void BM_Time_FromCivilDay0_Libc(benchmark::State& state) {
BENCHMARK(BM_Time_FromCivilDay0_Libc);
const char* const kFormats[] = {
- RFC1123_full, // 0
- RFC1123_no_wday, // 1
- RFC3339_full, // 2
- RFC3339_sec, // 3
- "%Y-%m-%dT%H:%M:%S", // 4
- "%Y-%m-%d", // 5
+ RFC1123_full, // 0
+ RFC1123_no_wday, // 1
+ RFC3339_full, // 2
+ RFC3339_sec, // 3
+ "%Y-%m-%d%ET%H:%M:%S", // 4
+ "%Y-%m-%d", // 5
};
const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc
index 179975e0..a4428632 100644
--- a/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/absl/time/internal/cctz/src/time_zone_format.cc
@@ -290,6 +290,7 @@ const std::int_fast64_t kExp10[kDigits10_64 + 1] = {
// - %E#S - Seconds with # digits of fractional precision
// - %E*S - Seconds with full fractional precision (a literal '*')
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+// - %ET - The RFC3339 "date-time" separator "T"
//
// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
// handled internally for performance reasons. strftime(3) is slow due to
@@ -448,7 +449,14 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
if (*cur != 'E' || ++cur == end) continue;
// Format our extensions.
- if (*cur == 'z') {
+ if (*cur == 'T') {
+ // Formats %ET.
+ if (cur - 2 != pending) {
+ FormatTM(&result, std::string(pending, cur - 2), tm);
+ }
+ result.append("T");
+ pending = ++cur;
+ } else if (*cur == 'z') {
// Formats %Ez.
if (cur - 2 != pending) {
FormatTM(&result, std::string(pending, cur - 2), tm);
@@ -551,7 +559,7 @@ const char* ParseOffset(const char* dp, const char* mode, int* offset) {
} else {
dp = nullptr;
}
- } else if (first == 'Z') { // Zulu
+ } else if (first == 'Z' || first == 'z') { // Zulu
*offset = 0;
} else {
dp = nullptr;
@@ -607,7 +615,7 @@ const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) {
// Uses strptime(3) to parse the given input. Supports the same extended
// format specifiers as format(), although %E#S and %E*S are treated
// identically (and similarly for %E#f and %E*f). %Ez and %E*z also accept
-// the same inputs.
+// the same inputs. %ET accepts either 'T' or 't'.
//
// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
// handled internally so that we can normally avoid strptime() altogether
@@ -742,6 +750,15 @@ bool parse(const std::string& format, const std::string& input,
data = (*data == '%' ? data + 1 : nullptr);
continue;
case 'E':
+ if (fmt[0] == 'T') {
+ if (*data == 'T' || *data == 't') {
+ ++data;
+ ++fmt;
+ } else {
+ data = nullptr;
+ }
+ continue;
+ }
if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {
data = ParseOffset(data, ":", &offset);
if (data != nullptr) saw_offset = true;
diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc
index 87382e15..13a4227e 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -48,8 +48,8 @@ namespace {
EXPECT_STREQ(zone, al.abbr); \
} while (0)
-const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
+const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
@@ -1379,10 +1379,20 @@ TEST(Parse, RFC3339Format) {
EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp));
ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC");
- // Check that %Ez also accepts "Z" as a synonym for "+00:00".
+ // Check that %ET also accepts "t".
time_point<chrono::nanoseconds> tp2;
- EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp2));
+ EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2));
EXPECT_EQ(tp, tp2);
+
+ // Check that %Ez also accepts "Z" as a synonym for "+00:00".
+ time_point<chrono::nanoseconds> tp3;
+ EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp3));
+ EXPECT_EQ(tp, tp3);
+
+ // Check that %Ez also accepts "z" as a synonym for "+00:00".
+ time_point<chrono::nanoseconds> tp4;
+ EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00z", tz, &tp4));
+ EXPECT_EQ(tp, tp4);
}
TEST(Parse, MaxRange) {
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index 0b0c1a3b..8f7ab154 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -933,7 +933,7 @@ TEST(MakeTime, Normalization) {
// NOTE: Run this with -ftrapv to detect overflow problems.
TEST(MakeTime, SysSecondsLimits) {
- const char RFC3339[] = "%Y-%m-%dT%H:%M:%S%Ez";
+ const char RFC3339[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
const time_zone utc = utc_time_zone();
const time_zone east = fixed_time_zone(chrono::hours(14));
const time_zone west = fixed_time_zone(-chrono::hours(14));