about summary refs log tree commit diff
path: root/absl/strings
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings')
-rw-r--r--absl/strings/internal/str_format/bind.cc3
-rw-r--r--absl/strings/internal/str_format/bind_test.cc24
-rw-r--r--absl/strings/internal/str_format/extension.cc24
-rw-r--r--absl/strings/internal/str_format/extension.h51
-rw-r--r--absl/strings/internal/str_format/parser.cc37
-rw-r--r--absl/strings/internal/str_format/parser.h13
-rw-r--r--absl/strings/internal/str_format/parser_test.cc32
7 files changed, 81 insertions, 103 deletions
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) {}