From d95d1567165d449e4c213ea31a15cbb112a9865f Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 7 Feb 2020 13:06:07 -0800 Subject: [PATCH] Export of internal Abseil changes -- 832be2d52d7695cf72fd70248909791fb8ad1003 by Gennadiy Rozental : Migrate some FlagImpl fields to bit fields. To save padding space we are migrating some fields representing bool and enums into bit fields. Eventually we'll use remaining padding space for call_once control flag. No other semantic changes made in this CL. PiperOrigin-RevId: 293878165 -- 09162bba5fd8eddacfd732d46fcfeb33074a259f by Samuel Benzaquen : Correctly initialize the `length_mod` member. Now that it is a raw enum, the default initialization is not enough. PiperOrigin-RevId: 293827817 -- 842b7b805d75c5ab670c52ccd7368cdeba11853d by Matthew Brown : Move str_format_internal::LengthMod from extension.h to parser.h; change to enum PiperOrigin-RevId: 293697274 GitOrigin-RevId: 832be2d52d7695cf72fd70248909791fb8ad1003 Change-Id: I90899519e9480543e22638616fdf31a41e7f75c0 --- absl/flags/internal/flag.cc | 12 ++-- absl/flags/internal/flag.h | 56 +++++++++++-------- absl/strings/internal/str_format/bind.cc | 3 +- absl/strings/internal/str_format/bind_test.cc | 24 ++++---- absl/strings/internal/str_format/extension.cc | 24 -------- absl/strings/internal/str_format/extension.h | 51 ----------------- absl/strings/internal/str_format/parser.cc | 37 ++++++++++-- absl/strings/internal/str_format/parser.h | 13 ++++- .../internal/str_format/parser_test.cc | 32 +++++++++-- 9 files changed, 120 insertions(+), 132 deletions(-) diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index 3df8d82cf..6ce7def2d 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc @@ -120,7 +120,7 @@ void FlagImpl::Destroy() { if (value_.dynamic) Delete(op_, value_.dynamic); // Release the dynamically allocated default value if any. - if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) { + if (DefaultKind() == FlagDefaultKind::kDynamicValue) { Delete(op_, default_src_.dynamic_value); } @@ -135,7 +135,7 @@ void FlagImpl::Destroy() { std::unique_ptr FlagImpl::MakeInitValue() const { void* res = nullptr; - if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) { + if (DefaultKind() == FlagDefaultKind::kDynamicValue) { res = Clone(op_, default_src_.dynamic_value); } else { res = (*default_src_.gen_func)(); @@ -150,8 +150,8 @@ std::string FlagImpl::Filename() const { } std::string FlagImpl::Help() const { - return help_source_kind_ == FlagHelpKind::kLiteral ? help_.literal - : help_.gen_func(); + return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal + : help_.gen_func(); } bool FlagImpl::IsModified() const { @@ -364,7 +364,7 @@ bool FlagImpl::SetFromString(absl::string_view value, FlagSettingMode set_mode, break; } case SET_FLAGS_DEFAULT: { - if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) { + if (DefaultKind() == FlagDefaultKind::kDynamicValue) { if (!TryParse(&default_src_.dynamic_value, value, err)) { return false; } @@ -375,7 +375,7 @@ bool FlagImpl::SetFromString(absl::string_view value, FlagSettingMode set_mode, } default_src_.dynamic_value = new_default_val; - def_kind_ = FlagDefaultSrcKind::kDynamicValue; + def_kind_ = static_cast(FlagDefaultKind::kDynamicValue); } if (!modified_) { diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index cc07dce18..b5471fa8a 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -87,7 +87,7 @@ union FlagHelpMsg { HelpGenFunc gen_func; }; -enum class FlagHelpKind : int8_t { kLiteral, kGenFunc }; +enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 }; struct FlagHelpArg { FlagHelpMsg source; @@ -147,7 +147,7 @@ union FlagDefaultSrc { FlagDfltGenFunc gen_func; }; -enum class FlagDefaultSrcKind : int8_t { kDynamicValue, kGenFunc }; +enum class FlagDefaultKind : uint8_t { kDynamicValue = 0, kGenFunc = 1 }; /////////////////////////////////////////////////////////////////////////////// // Flag current value auxiliary structs. @@ -279,8 +279,14 @@ class FlagImpl { op_(op), marshalling_op_(marshalling_op), help_(help.source), - help_source_kind_(help.kind), - def_kind_(FlagDefaultSrcKind::kGenFunc), + help_source_kind_(static_cast(help.kind)), + def_kind_(static_cast(FlagDefaultKind::kGenFunc)), + is_data_guard_inited_(false), + modified_(false), + on_command_line_(false), + inited_(false), + counter_(0), + callback_(nullptr), default_src_(default_value_gen), data_guard_{} {} @@ -370,6 +376,14 @@ class FlagImpl { // Lazy initialization of the Flag's data. void Init(); + FlagHelpKind HelpSourceKind() const { + return static_cast(help_source_kind_); + } + FlagDefaultKind DefaultKind() const + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) { + return static_cast(def_kind_); + } + // Immutable flag's state. // Flags name passed to ABSL_FLAG as second arg. @@ -383,35 +397,31 @@ class FlagImpl { // Help message literal or function to generate it. const FlagHelpMsg help_; // Indicates if help message was supplied as literal or generator func. - const FlagHelpKind help_source_kind_; - - // Indicates that the Flag state is initialized. - std::atomic inited_{false}; + const uint8_t help_source_kind_ : 1; // Mutable flag's state (guarded by `data_guard_`). - // Protects against multiple concurrent constructions of `data_guard_`. - bool is_data_guard_inited_ = false; - // Has this flag's value been modified? - bool modified_ ABSL_GUARDED_BY(*DataGuard()) = false; - // Has this flag been specified on command line. - bool on_command_line_ ABSL_GUARDED_BY(*DataGuard()) = false; - - // Mutation counter - int64_t counter_ ABSL_GUARDED_BY(*DataGuard()) = 0; - - // Optional flag's callback and absl::Mutex to guard the invocations. - FlagCallback* callback_ ABSL_GUARDED_BY(*DataGuard()) = nullptr; - // If def_kind_ == kDynamicValue, default_src_ holds a dynamically allocated // value. - FlagDefaultSrcKind def_kind_ ABSL_GUARDED_BY(*DataGuard()); + uint8_t def_kind_ : 1 ABSL_GUARDED_BY(*DataGuard()); + // Protects against multiple concurrent constructions of `data_guard_`. + bool is_data_guard_inited_ : 1; + // Has this flag's value been modified? + bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard()); + // Has this flag been specified on command line. + bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard()); + + // Indicates that the flag state is initialized. + std::atomic inited_; + // Mutation counter + int64_t counter_ ABSL_GUARDED_BY(*DataGuard()); + // Optional flag's callback and absl::Mutex to guard the invocations. + FlagCallback* callback_ ABSL_GUARDED_BY(*DataGuard()); // Either a pointer to the function generating the default value based on the // value specified in ABSL_FLAG or pointer to the dynamically set default // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish // these two cases. FlagDefaultSrc default_src_ ABSL_GUARDED_BY(*DataGuard()); - // Current Flag Value FlagValue value_; diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc index 1ee281af9..2d19b613e 100644 --- a/absl/strings/internal/str_format/bind.cc +++ b/absl/strings/internal/str_format/bind.cc @@ -77,7 +77,6 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound, bound->set_precision(-1); } - bound->set_length_mod(unbound->length_mod); bound->set_conv(unbound->conv); bound->set_arg(arg); return true; @@ -143,7 +142,7 @@ class SummarizingConverter { ss << "{" << Streamable(spec, {*bound.arg()}) << ":" << bound.flags(); if (bound.width() >= 0) ss << bound.width(); if (bound.precision() >= 0) ss << "." << bound.precision(); - ss << bound.length_mod() << bound.conv() << "}"; + ss << bound.conv() << "}"; Append(ss.str()); return true; } diff --git a/absl/strings/internal/str_format/bind_test.cc b/absl/strings/internal/str_format/bind_test.cc index f6817419f..64790a85f 100644 --- a/absl/strings/internal/str_format/bind_test.cc +++ b/absl/strings/internal/str_format/bind_test.cc @@ -113,18 +113,18 @@ TEST_F(FormatBindTest, FormatPack) { FormatArgImpl(ia[2]), FormatArgImpl(ia[3]), FormatArgImpl(ia[4])}; const Expectation kExpect[] = { - {__LINE__, "a%4db%dc", "a{10:4d}b{20:d}c"}, - {__LINE__, "a%.4db%dc", "a{10:.4d}b{20:d}c"}, - {__LINE__, "a%4.5db%dc", "a{10:4.5d}b{20:d}c"}, - {__LINE__, "a%db%4.5dc", "a{10:d}b{20:4.5d}c"}, - {__LINE__, "a%db%*.*dc", "a{10:d}b{40:20.30d}c"}, - {__LINE__, "a%.*fb", "a{20:.10f}b"}, - {__LINE__, "a%1$db%2$*3$.*4$dc", "a{10:d}b{20:30.40d}c"}, - {__LINE__, "a%4$db%3$*2$.*1$dc", "a{40:d}b{30:20.10d}c"}, - {__LINE__, "a%04ldb", "a{10:04ld}b"}, - {__LINE__, "a%-#04lldb", "a{10:-#04lld}b"}, - {__LINE__, "a%1$*5$db", "a{10:-10d}b"}, - {__LINE__, "a%1$.*5$db", "a{10:d}b"}, + {__LINE__, "a%4db%dc", "a{10:4d}b{20:d}c"}, + {__LINE__, "a%.4db%dc", "a{10:.4d}b{20:d}c"}, + {__LINE__, "a%4.5db%dc", "a{10:4.5d}b{20:d}c"}, + {__LINE__, "a%db%4.5dc", "a{10:d}b{20:4.5d}c"}, + {__LINE__, "a%db%*.*dc", "a{10:d}b{40:20.30d}c"}, + {__LINE__, "a%.*fb", "a{20:.10f}b"}, + {__LINE__, "a%1$db%2$*3$.*4$dc", "a{10:d}b{20:30.40d}c"}, + {__LINE__, "a%4$db%3$*2$.*1$dc", "a{40:d}b{30:20.10d}c"}, + {__LINE__, "a%04ldb", "a{10:04d}b"}, + {__LINE__, "a%-#04lldb", "a{10:-#04d}b"}, + {__LINE__, "a%1$*5$db", "a{10:-10d}b"}, + {__LINE__, "a%1$.*5$db", "a{10:d}b"}, }; for (const Expectation &e : kExpect) { absl::string_view fmt = e.fmt; diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc index 559011bf4..21688e873 100644 --- a/absl/strings/internal/str_format/extension.cc +++ b/absl/strings/internal/str_format/extension.cc @@ -22,28 +22,6 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace str_format_internal { -namespace { -// clang-format off -#define ABSL_LENGTH_MODS_EXPAND_ \ - X_VAL(h) X_SEP \ - X_VAL(hh) X_SEP \ - X_VAL(l) X_SEP \ - X_VAL(ll) X_SEP \ - X_VAL(L) X_SEP \ - X_VAL(j) X_SEP \ - X_VAL(z) X_SEP \ - X_VAL(t) X_SEP \ - X_VAL(q) -// clang-format on -} // namespace - -const LengthMod::Spec LengthMod::kSpecs[] = { -#define X_VAL(id) { LengthMod::id, #id, strlen(#id) } -#define X_SEP , - ABSL_LENGTH_MODS_EXPAND_, {LengthMod::none, "", 0} -#undef X_VAL -#undef X_SEP -}; const ConversionChar::Spec ConversionChar::kSpecs[] = { #define X_VAL(id) { ConversionChar::id, #id[0] } @@ -64,8 +42,6 @@ std::string Flags::ToString() const { return s; } -const size_t LengthMod::kNumValues; - const size_t ConversionChar::kNumValues; bool FormatSinkImpl::PutPaddedString(string_view v, int w, int p, bool l) { diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h index 0a7640354..4868eac3e 100644 --- a/absl/strings/internal/str_format/extension.h +++ b/absl/strings/internal/str_format/extension.h @@ -136,54 +136,6 @@ struct Flags { } }; -struct ABSL_DLL LengthMod { - public: - enum Id : uint8_t { - h, hh, l, ll, L, j, z, t, q, none - }; - static const size_t kNumValues = none + 1; - - LengthMod() : id_(none) {} - - // Index into the opaque array of LengthMod enums. - // Requires: i < kNumValues - static LengthMod FromIndex(size_t i) { - return LengthMod(kSpecs[i].value); - } - - static LengthMod FromId(Id id) { return LengthMod(id); } - - // The length modifier std::string associated with a specified LengthMod. - string_view name() const { - const Spec& spec = kSpecs[id_]; - return {spec.name, spec.name_length}; - } - - Id id() const { return id_; } - - friend bool operator==(const LengthMod& a, const LengthMod& b) { - return a.id() == b.id(); - } - friend bool operator!=(const LengthMod& a, const LengthMod& b) { - return !(a == b); - } - friend std::ostream& operator<<(std::ostream& os, const LengthMod& v) { - return os << v.name(); - } - - private: - struct Spec { - Id value; - const char *name; - size_t name_length; - }; - static const Spec kSpecs[]; - - explicit LengthMod(Id id) : id_(id) {} - - Id id_; -}; - // clang-format off #define ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \ /* text */ \ @@ -306,7 +258,6 @@ struct ABSL_DLL ConversionChar { class ConversionSpec { public: Flags flags() const { return flags_; } - LengthMod length_mod() const { return length_mod_; } ConversionChar conv() const { // Keep this field first in the struct . It generates better code when // accessing it when ConversionSpec is passed by value in registers. @@ -322,7 +273,6 @@ class ConversionSpec { int precision() const { return precision_; } void set_flags(Flags f) { flags_ = f; } - void set_length_mod(LengthMod lm) { length_mod_ = lm; } void set_conv(ConversionChar c) { conv_ = c; } void set_width(int w) { width_ = w; } void set_precision(int p) { precision_ = p; } @@ -331,7 +281,6 @@ class ConversionSpec { private: ConversionChar conv_; Flags flags_; - LengthMod length_mod_; int width_; int precision_; }; diff --git a/absl/strings/internal/str_format/parser.cc b/absl/strings/internal/str_format/parser.cc index eff68f35c..c4b527bc4 100644 --- a/absl/strings/internal/str_format/parser.cc +++ b/absl/strings/internal/str_format/parser.cc @@ -18,7 +18,8 @@ ABSL_NAMESPACE_BEGIN namespace str_format_internal { using CC = ConversionChar::Id; -using LM = LengthMod::Id; +using LM = LengthMod; + ABSL_CONST_INIT const ConvTag kTags[256] = { {}, {}, {}, {}, {}, {}, {}, {}, // 00-07 {}, {}, {}, {}, {}, {}, {}, {}, // 08-0f @@ -205,11 +206,11 @@ flags_done: using str_format_internal::LengthMod; LengthMod length_mod = tag.as_length(); ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - if (c == 'h' && length_mod.id() == LengthMod::h) { - conv->length_mod = LengthMod::FromId(LengthMod::hh); + if (c == 'h' && length_mod == LengthMod::h) { + conv->length_mod = LengthMod::hh; ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); - } else if (c == 'l' && length_mod.id() == LengthMod::l) { - conv->length_mod = LengthMod::FromId(LengthMod::ll); + } else if (c == 'l' && length_mod == LengthMod::l) { + conv->length_mod = LengthMod::ll; ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); } else { conv->length_mod = length_mod; @@ -228,6 +229,32 @@ flags_done: } // namespace +std::string LengthModToString(LengthMod v) { + switch (v) { + case LengthMod::h: + return "h"; + case LengthMod::hh: + return "hh"; + case LengthMod::l: + return "l"; + case LengthMod::ll: + return "ll"; + case LengthMod::L: + return "L"; + case LengthMod::j: + return "j"; + case LengthMod::z: + return "z"; + case LengthMod::t: + return "t"; + case LengthMod::q: + return "q"; + case LengthMod::none: + return ""; + } + return ""; +} + const char *ConsumeUnboundConversion(const char *p, const char *end, UnboundConversion *conv, int *next_arg) { if (*next_arg < 0) return ConsumeConversion(p, end, conv, next_arg); diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h index 116dda06d..6cbe25769 100644 --- a/absl/strings/internal/str_format/parser.h +++ b/absl/strings/internal/str_format/parser.h @@ -6,10 +6,12 @@ #include #include +#include #include #include #include #include +#include #include #include "absl/strings/internal/str_format/checker.h" @@ -19,6 +21,10 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace str_format_internal { +enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none }; + +std::string LengthModToString(LengthMod v); + // The analyzed properties of a single specified conversion. struct UnboundConversion { UnboundConversion() @@ -60,7 +66,7 @@ struct UnboundConversion { InputValue precision; Flags flags; - LengthMod length_mod; + LengthMod length_mod = LengthMod::none; ConversionChar conv; }; @@ -79,7 +85,8 @@ class ConvTag { constexpr ConvTag(ConversionChar::Id id) : tag_(id) {} // NOLINT // We invert the length modifiers to make them negative so that we can easily // test for them. - constexpr ConvTag(LengthMod::Id id) : tag_(~id) {} // NOLINT + constexpr ConvTag(LengthMod length_mod) // NOLINT + : tag_(~static_cast(length_mod)) {} // Everything else is -128, which is negative to make is_conv() simpler. constexpr ConvTag() : tag_(-128) {} @@ -91,7 +98,7 @@ class ConvTag { } LengthMod as_length() const { assert(is_length()); - return LengthMod::FromId(static_cast(~tag_)); + return static_cast(~tag_); } private: diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc index 33ed8f094..4a8efd080 100644 --- a/absl/strings/internal/str_format/parser_test.cc +++ b/absl/strings/internal/str_format/parser_test.cc @@ -17,7 +17,7 @@ using testing::Pair; TEST(LengthModTest, Names) { struct Expectation { int line; - LengthMod::Id id; + LengthMod mod; const char *name; }; const Expectation kExpect[] = { @@ -32,12 +32,10 @@ TEST(LengthModTest, Names) { {__LINE__, LengthMod::t, "t" }, {__LINE__, LengthMod::q, "q" }, }; - EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), LengthMod::kNumValues); + EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), 10); for (auto e : kExpect) { SCOPED_TRACE(e.line); - LengthMod mod = LengthMod::FromId(e.id); - EXPECT_EQ(e.id, mod.id()); - EXPECT_EQ(e.name, mod.name()); + EXPECT_EQ(e.name, LengthModToString(e.mod)); } } @@ -127,7 +125,6 @@ TEST_F(ConsumeUnboundConversionTest, BasicConversion) { EXPECT_FALSE(o.precision.is_from_arg()); EXPECT_LT(o.precision.value(), 0); EXPECT_EQ(1, o.arg_position); - EXPECT_EQ(LengthMod::none, o.length_mod.id()); } TEST_F(ConsumeUnboundConversionTest, ArgPosition) { @@ -290,6 +287,29 @@ TEST_F(ConsumeUnboundConversionTest, BasicFlag) { } } +TEST_F(ConsumeUnboundConversionTest, LengthMod) { + EXPECT_TRUE(Run("d")); + EXPECT_EQ(LengthMod::none, o.length_mod); + EXPECT_TRUE(Run("hd")); + EXPECT_EQ(LengthMod::h, o.length_mod); + EXPECT_TRUE(Run("hhd")); + EXPECT_EQ(LengthMod::hh, o.length_mod); + EXPECT_TRUE(Run("ld")); + EXPECT_EQ(LengthMod::l, o.length_mod); + EXPECT_TRUE(Run("lld")); + EXPECT_EQ(LengthMod::ll, o.length_mod); + EXPECT_TRUE(Run("Lf")); + EXPECT_EQ(LengthMod::L, o.length_mod); + EXPECT_TRUE(Run("qf")); + EXPECT_EQ(LengthMod::q, o.length_mod); + EXPECT_TRUE(Run("jd")); + EXPECT_EQ(LengthMod::j, o.length_mod); + EXPECT_TRUE(Run("zd")); + EXPECT_EQ(LengthMod::z, o.length_mod); + EXPECT_TRUE(Run("td")); + EXPECT_EQ(LengthMod::t, o.length_mod); +} + struct SummarizeConsumer { std::string* out; explicit SummarizeConsumer(std::string* out) : out(out) {}