Export of internal Abseil changes

--
47f13ea42ae272c995b1cd5073a45e046fa325eb by Matthew Brown <matthewbr@google.com>:

absl::StrFormat: Centralize FormatConversionCharSet vs FormatConversionSpec checking
 - Move it into a central location, rather than requiring individual overloads to
   validate.

PiperOrigin-RevId: 310583805

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

Internal change

PiperOrigin-RevId: 310427635

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

Make Get/Set private methods of absl::Flag<T>.

PiperOrigin-RevId: 310413908
GitOrigin-RevId: 47f13ea42ae272c995b1cd5073a45e046fa325eb
Change-Id: I6530c754731c1a9463877561fa61786460ed60af
This commit is contained in:
Abseil Team 2020-05-08 10:36:00 -07:00 committed by vslashg
parent a35ef8a62c
commit c45d1c09d5
8 changed files with 148 additions and 36 deletions

View file

@ -40,6 +40,30 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
// Forward declaration of absl::Flag<T> public API.
namespace flags_internal {
template <typename T>
class Flag;
} // namespace flags_internal
#if defined(_MSC_VER) && !defined(__clang__)
template <typename T>
class Flag;
#else
template <typename T>
using Flag = flags_internal::Flag<T>;
#endif
template <typename T>
ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
template <typename T>
void SetFlag(absl::Flag<T>* flag, const T& v);
template <typename T, typename V>
void SetFlag(absl::Flag<T>* flag, const V& v);
namespace flags_internal {
///////////////////////////////////////////////////////////////////////////////
@ -596,6 +620,32 @@ class Flag {
flags_internal::StorageKind<T>(), default_arg),
value_() {}
// CommandLineFlag interface
absl::string_view Name() const { return impl_.Name(); }
std::string Filename() const { return impl_.Filename(); }
std::string Help() const { return impl_.Help(); }
bool IsSpecifiedOnCommandLine() const {
return impl_.IsSpecifiedOnCommandLine();
}
std::string DefaultValue() const { return impl_.DefaultValue(); }
std::string CurrentValue() const { return impl_.CurrentValue(); }
private:
template <typename U, bool do_register>
friend class FlagRegistrar;
#if !defined(_MSC_VER) || defined(__clang__)
template <typename U>
friend U absl::GetFlag(const flags_internal::Flag<U>& flag);
template <typename U>
friend void absl::SetFlag(flags_internal::Flag<U>* flag, const U& v);
template <typename U, typename V>
friend void absl::SetFlag(flags_internal::Flag<U>* flag, const V& v);
#else
template <typename U>
friend class absl::Flag;
#endif
T Get() const {
// See implementation notes in CommandLineFlag::Get().
union U {
@ -617,20 +667,6 @@ class Flag {
impl_.Write(&v);
}
// CommandLineFlag interface
absl::string_view Name() const { return impl_.Name(); }
std::string Filename() const { return impl_.Filename(); }
std::string Help() const { return impl_.Help(); }
bool IsSpecifiedOnCommandLine() const {
return impl_.IsSpecifiedOnCommandLine();
}
std::string DefaultValue() const { return impl_.DefaultValue(); }
std::string CurrentValue() const { return impl_.CurrentValue(); }
private:
template <typename U, bool do_register>
friend class FlagRegistrar;
// Flag's data
// The implementation depends on value_ field to be placed exactly after the
// impl_ field, so that impl_ can figure out the offset to the value and

View file

@ -44,6 +44,13 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
UsageFlagsAction usage_flag_act,
OnUndefinedFlag on_undef_flag);
// --------------------------------------------------------------------
// Inspect original command line
// Returns true if flag with specified name was either present on the original
// command line or specified in flag file present on the original command line.
bool WasPresentOnCommandLine(absl::string_view flag_name);
} // namespace flags_internal
ABSL_NAMESPACE_END
} // namespace absl

View file

@ -67,6 +67,22 @@ ABSL_CONST_INIT bool fromenv_needs_processing
ABSL_CONST_INIT bool tryfromenv_needs_processing
ABSL_GUARDED_BY(processing_checks_guard) = false;
ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit);
ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
struct SpecifiedFlagsCompare {
bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {
return a->Name() < b->Name();
}
bool operator()(const CommandLineFlag* a, absl::string_view b) const {
return a->Name() < b;
}
bool operator()(absl::string_view a, const CommandLineFlag* b) const {
return a < b->Name();
}
};
} // namespace
} // namespace flags_internal
ABSL_NAMESPACE_END
@ -577,6 +593,17 @@ bool CanIgnoreUndefinedFlag(absl::string_view flag_name) {
// --------------------------------------------------------------------
bool WasPresentOnCommandLine(absl::string_view flag_name) {
absl::MutexLock l(&specified_flags_guard);
ABSL_INTERNAL_CHECK(specified_flags != nullptr,
"ParseCommandLine is not invoked yet");
return std::binary_search(specified_flags->begin(), specified_flags->end(),
flag_name, SpecifiedFlagsCompare{});
}
// --------------------------------------------------------------------
std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
ArgvListAction arg_list_act,
UsageFlagsAction usage_flag_act,
@ -607,6 +634,13 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
}
output_args.push_back(argv[0]);
absl::MutexLock l(&specified_flags_guard);
if (specified_flags == nullptr) {
specified_flags = new std::vector<const CommandLineFlag*>;
} else {
specified_flags->clear();
}
// Iterate through the list of the input arguments. First level are arguments
// originated from argc/argv. Following levels are arguments originated from
// recursive parsing of flagfile(s).
@ -702,6 +736,8 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
flag, value, SET_FLAGS_VALUE, kCommandLine, &error)) {
flags_internal::ReportUsageError(error, true);
success = false;
} else {
specified_flags->push_back(flag);
}
}
@ -753,6 +789,10 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
}
}
// Trim and sort the vector.
specified_flags->shrink_to_fit();
std::sort(specified_flags->begin(), specified_flags->end(),
SpecifiedFlagsCompare{});
return output_args;
}

View file

@ -869,4 +869,26 @@ TEST_F(ParseDeathTest, TestHelpFlagHandling) {
EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
}
// --------------------------------------------------------------------
TEST_F(ParseTest, WasPresentOnCommandLine) {
const char* in_args1[] = {
"testbin", "arg1", "--bool_flag",
"--int_flag=211", "arg2", "--double_flag=1.1",
"--string_flag", "asd", "--",
"--some_flag", "arg4",
};
InvokeParse(in_args1);
EXPECT_TRUE(flags::WasPresentOnCommandLine("bool_flag"));
EXPECT_TRUE(flags::WasPresentOnCommandLine("int_flag"));
EXPECT_TRUE(flags::WasPresentOnCommandLine("double_flag"));
EXPECT_TRUE(flags::WasPresentOnCommandLine("string_flag"));
EXPECT_FALSE(flags::WasPresentOnCommandLine("some_flag"));
EXPECT_FALSE(flags::WasPresentOnCommandLine("another_flag"));
}
// --------------------------------------------------------------------
} // namespace