From d95d1567165d449e4c213ea31a15cbb112a9865f Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 7 Feb 2020 13:06:07 -0800 Subject: 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/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 +++++-- absl/strings/internal/str_format/parser_test.cc | 32 +++++++++++++--- 7 files changed, 81 insertions(+), 103 deletions(-) (limited to 'absl/strings') 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(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 #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 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) {} -- cgit 1.4.1