diff options
-rw-r--r-- | absl/flags/internal/flag.cc | 12 | ||||
-rw-r--r-- | absl/flags/internal/flag.h | 48 | ||||
-rw-r--r-- | absl/strings/internal/str_format/bind.cc | 3 | ||||
-rw-r--r-- | absl/strings/internal/str_format/bind_test.cc | 24 | ||||
-rw-r--r-- | absl/strings/internal/str_format/extension.cc | 24 | ||||
-rw-r--r-- | absl/strings/internal/str_format/extension.h | 51 | ||||
-rw-r--r-- | absl/strings/internal/str_format/parser.cc | 37 | ||||
-rw-r--r-- | absl/strings/internal/str_format/parser.h | 13 | ||||
-rw-r--r-- | absl/strings/internal/str_format/parser_test.cc | 32 |
9 files changed, 116 insertions, 128 deletions
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index 3df8d82cfede..6ce7def2d3d2 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<void, DynValueDeleter> 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<uint8_t>(FlagDefaultKind::kDynamicValue); } if (!modified_) { diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index cc07dce1829b..b5471fa8a734 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<uint8_t>(help.kind)), + def_kind_(static_cast<uint8_t>(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<FlagHelpKind>(help_source_kind_); + } + FlagDefaultKind DefaultKind() const + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) { + return static_cast<FlagDefaultKind>(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<bool> inited_{false}; + const uint8_t help_source_kind_ : 1; // Mutable flag's state (guarded by `data_guard_`). + // If def_kind_ == kDynamicValue, default_src_ holds a dynamically allocated + // value. + uint8_t def_kind_ : 1 ABSL_GUARDED_BY(*DataGuard()); // Protects against multiple concurrent constructions of `data_guard_`. - bool is_data_guard_inited_ = false; + bool is_data_guard_inited_ : 1; // Has this flag's value been modified? - bool modified_ ABSL_GUARDED_BY(*DataGuard()) = false; + bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard()); // Has this flag been specified on command line. - bool on_command_line_ ABSL_GUARDED_BY(*DataGuard()) = false; + bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard()); + // Indicates that the flag state is initialized. + std::atomic<bool> inited_; // Mutation counter - int64_t counter_ ABSL_GUARDED_BY(*DataGuard()) = 0; - + int64_t counter_ ABSL_GUARDED_BY(*DataGuard()); // 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()); + 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 1ee281af9c16..2d19b613e43d 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 f6817419feb4..64790a85fd23 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 559011bf4a97..21688e873f2c 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 0a7640354fd4..4868eac3e8b4 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 eff68f35c032..c4b527bc48aa 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<true>(p, end, conv, next_arg); diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h index 116dda06d4e2..6cbe257697e4 100644 --- a/absl/strings/internal/str_format/parser.h +++ b/absl/strings/internal/str_format/parser.h @@ -6,10 +6,12 @@ #include <stdlib.h> #include <cassert> +#include <cstdint> #include <initializer_list> #include <iosfwd> #include <iterator> #include <memory> +#include <string> #include <vector> #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<std::int8_t>(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<LengthMod::Id>(~tag_)); + return static_cast<LengthMod>(~tag_); } private: diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc index 33ed8f094436..4a8efd0805aa 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) {} |