From c45d1c09d517e145d722e00deea9be6c8be8dd57 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 8 May 2020 10:36:00 -0700 Subject: Export of internal Abseil changes -- 47f13ea42ae272c995b1cd5073a45e046fa325eb by Matthew Brown : 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 : Internal change PiperOrigin-RevId: 310427635 -- 49848f7fab9b0f528d33f60cbccf688e2ea68afa by Gennadiy Rozental : Make Get/Set private methods of absl::Flag. PiperOrigin-RevId: 310413908 GitOrigin-RevId: 47f13ea42ae272c995b1cd5073a45e046fa325eb Change-Id: I6530c754731c1a9463877561fa61786460ed60af --- absl/flags/internal/flag.h | 64 ++++++++++++++++++++++------ absl/flags/internal/parse.h | 7 +++ absl/flags/parse.cc | 40 +++++++++++++++++ absl/flags/parse_test.cc | 22 ++++++++++ absl/strings/internal/str_format/arg.cc | 4 +- absl/strings/internal/str_format/arg.h | 21 ++++++--- absl/strings/internal/str_format/checker.h | 9 ---- absl/strings/internal/str_format/extension.h | 17 ++++++-- 8 files changed, 148 insertions(+), 36 deletions(-) (limited to 'absl') diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index f53f484f..b060199e 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -40,6 +40,30 @@ namespace absl { ABSL_NAMESPACE_BEGIN + +// Forward declaration of absl::Flag public API. +namespace flags_internal { +template +class Flag; +} // namespace flags_internal + +#if defined(_MSC_VER) && !defined(__clang__) +template +class Flag; +#else +template +using Flag = flags_internal::Flag; +#endif + +template +ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag& flag); + +template +void SetFlag(absl::Flag* flag, const T& v); + +template +void SetFlag(absl::Flag* flag, const V& v); + namespace flags_internal { /////////////////////////////////////////////////////////////////////////////// @@ -596,6 +620,32 @@ class Flag { flags_internal::StorageKind(), 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 + friend class FlagRegistrar; + +#if !defined(_MSC_VER) || defined(__clang__) + template + friend U absl::GetFlag(const flags_internal::Flag& flag); + template + friend void absl::SetFlag(flags_internal::Flag* flag, const U& v); + template + friend void absl::SetFlag(flags_internal::Flag* flag, const V& v); +#else + template + 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 - 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 diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h index 03e8a07b..d259be73 100644 --- a/absl/flags/internal/parse.h +++ b/absl/flags/internal/parse.h @@ -44,6 +44,13 @@ std::vector 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 diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc index 66a28a93..2e8f03b4 100644 --- a/absl/flags/parse.cc +++ b/absl/flags/parse.cc @@ -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* 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 ParseCommandLineImpl(int argc, char* argv[], ArgvListAction arg_list_act, UsageFlagsAction usage_flag_act, @@ -607,6 +634,13 @@ std::vector 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; + } 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 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 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; } diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc index 065f757a..e6a53ae6 100644 --- a/absl/flags/parse_test.cc +++ b/absl/flags/parse_test.cc @@ -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 diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc index 964f25f7..02646add 100644 --- a/absl/strings/internal/str_format/arg.cc +++ b/absl/strings/internal/str_format/arg.cc @@ -302,7 +302,7 @@ bool ConvertIntArg(T v, const FormatConversionSpecImpl conv, return ConvertFloatImpl(static_cast(v), conv, sink); default: - return false; + ABSL_INTERNAL_ASSUME(false); } if (conv.is_basic()) { @@ -321,7 +321,6 @@ bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv, inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { - if (conv.conversion_char() != FormatConversionCharInternal::s) return false; if (conv.is_basic()) { sink->Append(v); return true; @@ -366,7 +365,6 @@ FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv, // ==================== Raw pointers ==================== ArgConvertResult FormatConvertImpl( VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { - if (conv.conversion_char() != FormatConversionCharInternal::p) return {false}; if (!v.value) { sink->Append("(nil)"); return {true}; diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index 9a1e5ef2..8f79948b 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -86,10 +86,6 @@ template +constexpr FormatConversionCharSet ArgumentToConv() { + return absl::str_format_internal::ExtractCharSet( + decltype(str_format_internal::FormatConvertImpl( + std::declval(), + std::declval(), + std::declval())){}); +} + // A type-erased handle to a format argument. class FormatArgImpl { private: @@ -411,9 +416,13 @@ class FormatArgImpl { return ToInt(arg, static_cast(out), std::is_integral(), std::is_enum()); } - + if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv(), + spec.conversion_char()))) { + return false; + } return str_format_internal::FormatConvertImpl( - Manager::Value(arg), spec, static_cast(out)) + Manager::Value(arg), spec, + static_cast(out)) .value; } diff --git a/absl/strings/internal/str_format/checker.h b/absl/strings/internal/str_format/checker.h index 73ef05ff..424c51f7 100644 --- a/absl/strings/internal/str_format/checker.h +++ b/absl/strings/internal/str_format/checker.h @@ -24,15 +24,6 @@ constexpr bool AllOf(bool b, T... t) { return b && AllOf(t...); } -template -constexpr FormatConversionCharSet ArgumentToConv() { - return absl::str_format_internal::ExtractCharSet( - decltype(str_format_internal::FormatConvertImpl( - std::declval(), - std::declval(), - std::declval())){}); -} - #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER constexpr bool ContainsChar(const char* chars, char c) { diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h index ce78a02a..36e70646 100644 --- a/absl/strings/internal/str_format/extension.h +++ b/absl/strings/internal/str_format/extension.h @@ -327,12 +327,16 @@ constexpr FormatConversionCharSet FormatConversionCharSetUnion( static_cast(FormatConversionCharSetUnion(rest...))); } +constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) { + return uint64_t{1} << (1 + static_cast(c)); +} + constexpr uint64_t FormatConversionCharToConvInt(char conv) { return -#define ABSL_INTERNAL_CHAR_SET_CASE(c) \ - conv == #c[0] ? (uint64_t{1} << (1 + static_cast( \ - FormatConversionCharInternal::c))) \ - : +#define ABSL_INTERNAL_CHAR_SET_CASE(c) \ + conv == #c[0] \ + ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \ + : ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, ) #undef ABSL_INTERNAL_CHAR_SET_CASE conv == '*' @@ -406,6 +410,11 @@ constexpr bool Contains(FormatConversionCharSet set, static_cast(c); } +// Checks whether all the characters in `c` are contained in `set` +constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) { + return (static_cast(set) & FormatConversionCharToConvInt(c)) != 0; +} + // Return capacity - used, clipped to a minimum of 0. inline size_t Excess(size_t used, size_t capacity) { return used < capacity ? capacity - used : 0; -- cgit v1.2.3