summaryrefslogtreecommitdiff
path: root/absl/strings
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings')
-rw-r--r--absl/strings/internal/str_format/arg.cc36
-rw-r--r--absl/strings/internal/str_format/arg.h2
-rw-r--r--absl/strings/internal/str_format/arg_test.cc4
-rw-r--r--absl/strings/internal/str_format/checker_test.cc8
-rw-r--r--absl/strings/internal/str_format/extension.cc15
-rw-r--r--absl/strings/internal/str_format/extension.h80
-rw-r--r--absl/strings/str_format.h4
-rw-r--r--absl/strings/str_format_test.cc97
8 files changed, 92 insertions, 154 deletions
diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc
index 02646add..9feb2248 100644
--- a/absl/strings/internal/str_format/arg.cc
+++ b/absl/strings/internal/str_format/arg.cc
@@ -267,38 +267,42 @@ bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
using U = typename MakeUnsigned<T>::type;
IntDigits as_digits;
- switch (conv.conversion_char()) {
- case FormatConversionCharInternal::c:
+ // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
+ // it to complain about a switch/case type mismatch, even though both are
+ // FormatConverionChar. Likely this is because at this point
+ // FormatConversionChar is declared, but not defined.
+ switch (static_cast<uint8_t>(conv.conversion_char())) {
+ case static_cast<uint8_t>(FormatConversionCharInternal::c):
return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
- case FormatConversionCharInternal::o:
+ case static_cast<uint8_t>(FormatConversionCharInternal::o):
as_digits.PrintAsOct(static_cast<U>(v));
break;
- case FormatConversionCharInternal::x:
+ case static_cast<uint8_t>(FormatConversionCharInternal::x):
as_digits.PrintAsHexLower(static_cast<U>(v));
break;
- case FormatConversionCharInternal::X:
+ case static_cast<uint8_t>(FormatConversionCharInternal::X):
as_digits.PrintAsHexUpper(static_cast<U>(v));
break;
- case FormatConversionCharInternal::u:
+ case static_cast<uint8_t>(FormatConversionCharInternal::u):
as_digits.PrintAsDec(static_cast<U>(v));
break;
- case FormatConversionCharInternal::d:
- case FormatConversionCharInternal::i:
+ case static_cast<uint8_t>(FormatConversionCharInternal::d):
+ case static_cast<uint8_t>(FormatConversionCharInternal::i):
as_digits.PrintAsDec(v);
break;
- case FormatConversionCharInternal::a:
- case FormatConversionCharInternal::e:
- case FormatConversionCharInternal::f:
- case FormatConversionCharInternal::g:
- case FormatConversionCharInternal::A:
- case FormatConversionCharInternal::E:
- case FormatConversionCharInternal::F:
- case FormatConversionCharInternal::G:
+ case static_cast<uint8_t>(FormatConversionCharInternal::a):
+ case static_cast<uint8_t>(FormatConversionCharInternal::e):
+ case static_cast<uint8_t>(FormatConversionCharInternal::f):
+ case static_cast<uint8_t>(FormatConversionCharInternal::g):
+ case static_cast<uint8_t>(FormatConversionCharInternal::A):
+ case static_cast<uint8_t>(FormatConversionCharInternal::E):
+ case static_cast<uint8_t>(FormatConversionCharInternal::F):
+ case static_cast<uint8_t>(FormatConversionCharInternal::G):
return ConvertFloatImpl(static_cast<double>(v), conv, sink);
default:
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index 8f79948b..d441e87f 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -27,6 +27,8 @@ class FormatSink;
namespace str_format_internal {
+class FormatConversionSpec;
+
template <typename T, typename = void>
struct HasUserDefinedConvert : std::false_type {};
diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc
index 37e5b754..bf3d7e8e 100644
--- a/absl/strings/internal/str_format/arg_test.cc
+++ b/absl/strings/internal/str_format/arg_test.cc
@@ -96,8 +96,8 @@ TEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) {
std::string s;
FormatSinkImpl sink(&s);
FormatConversionSpecImpl conv;
- FormatConversionSpecImplFriend::SetConversionChar(FormatConversionChar::s,
- &conv);
+ FormatConversionSpecImplFriend::SetConversionChar(
+ FormatConversionCharInternal::s, &conv);
FormatConversionSpecImplFriend::SetFlags(Flags(), &conv);
FormatConversionSpecImplFriend::SetWidth(-1, &conv);
FormatConversionSpecImplFriend::SetPrecision(-1, &conv);
diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc
index 23348174..a76d70b0 100644
--- a/absl/strings/internal/str_format/checker_test.cc
+++ b/absl/strings/internal/str_format/checker_test.cc
@@ -11,13 +11,13 @@ namespace {
std::string ConvToString(FormatConversionCharSet conv) {
std::string out;
-#define CONV_SET_CASE(c) \
- if (Contains(conv, FormatConversionCharSet::c)) { \
- out += #c; \
+#define CONV_SET_CASE(c) \
+ if (Contains(conv, FormatConversionCharSetInternal::c)) { \
+ out += #c; \
}
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
#undef CONV_SET_CASE
- if (Contains(conv, FormatConversionCharSet::kStar)) {
+ if (Contains(conv, FormatConversionCharSetInternal::kStar)) {
out += "*";
}
return out;
diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc
index 2e5bc2ce..94f2b9c2 100644
--- a/absl/strings/internal/str_format/extension.cc
+++ b/absl/strings/internal/str_format/extension.cc
@@ -33,16 +33,17 @@ std::string Flags::ToString() const {
return s;
}
-bool FormatSinkImpl::PutPaddedString(string_view v, int w, int p, bool l) {
+bool FormatSinkImpl::PutPaddedString(string_view value, int width,
+ int precision, bool left) {
size_t space_remaining = 0;
- if (w >= 0) space_remaining = w;
- size_t n = v.size();
- if (p >= 0) n = std::min(n, static_cast<size_t>(p));
- string_view shown(v.data(), n);
+ if (width >= 0) space_remaining = width;
+ size_t n = value.size();
+ if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
+ string_view shown(value.data(), n);
space_remaining = Excess(shown.size(), space_remaining);
- if (!l) Append(space_remaining, ' ');
+ if (!left) Append(space_remaining, ' ');
Append(shown);
- if (l) Append(space_remaining, ' ');
+ if (left) Append(space_remaining, ' ');
return true;
}
diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h
index 36e70646..6c60c6c3 100644
--- a/absl/strings/internal/str_format/extension.h
+++ b/absl/strings/internal/str_format/extension.h
@@ -32,8 +32,9 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-enum class FormatConversionCharSet : uint64_t;
+
enum class FormatConversionChar : uint8_t;
+enum class FormatConversionCharSet : uint64_t;
class FormatRawSinkImpl {
public:
@@ -106,7 +107,7 @@ class FormatSinkImpl {
size_t size() const { return size_; }
// Put 'v' to 'sink' with specified width, precision, and left flag.
- bool PutPaddedString(string_view v, int w, int p, bool l);
+ bool PutPaddedString(string_view v, int width, int precision, bool left);
template <typename T>
T Wrap() {
@@ -420,81 +421,6 @@ inline size_t Excess(size_t used, size_t capacity) {
return used < capacity ? capacity - used : 0;
}
-class FormatConversionSpec {
- public:
- // Width and precison are not specified, no flags are set.
- bool is_basic() const { return impl_.is_basic(); }
- bool has_left_flag() const { return impl_.has_left_flag(); }
- bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
- bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
- bool has_alt_flag() const { return impl_.has_alt_flag(); }
- bool has_zero_flag() const { return impl_.has_zero_flag(); }
-
- FormatConversionChar conversion_char() const {
- return impl_.conversion_char();
- }
-
- // Returns the specified width. If width is unspecfied, it returns a negative
- // value.
- int width() const { return impl_.width(); }
- // Returns the specified precision. If precision is unspecfied, it returns a
- // negative value.
- int precision() const { return impl_.precision(); }
-
- private:
- explicit FormatConversionSpec(
- str_format_internal::FormatConversionSpecImpl impl)
- : impl_(impl) {}
-
- friend str_format_internal::FormatConversionSpecImpl;
-
- absl::str_format_internal::FormatConversionSpecImpl impl_;
-};
-
-// clang-format off
-enum class FormatConversionChar : uint8_t {
- c, s, // text
- d, i, o, u, x, X, // int
- f, F, e, E, g, G, a, A, // float
- n, p // misc
-};
-// clang-format on
-
-enum class FormatConversionCharSet : uint64_t {
- // text
- c = str_format_internal::FormatConversionCharToConvInt('c'),
- s = str_format_internal::FormatConversionCharToConvInt('s'),
- // integer
- d = str_format_internal::FormatConversionCharToConvInt('d'),
- i = str_format_internal::FormatConversionCharToConvInt('i'),
- o = str_format_internal::FormatConversionCharToConvInt('o'),
- u = str_format_internal::FormatConversionCharToConvInt('u'),
- x = str_format_internal::FormatConversionCharToConvInt('x'),
- X = str_format_internal::FormatConversionCharToConvInt('X'),
- // Float
- f = str_format_internal::FormatConversionCharToConvInt('f'),
- F = str_format_internal::FormatConversionCharToConvInt('F'),
- e = str_format_internal::FormatConversionCharToConvInt('e'),
- E = str_format_internal::FormatConversionCharToConvInt('E'),
- g = str_format_internal::FormatConversionCharToConvInt('g'),
- G = str_format_internal::FormatConversionCharToConvInt('G'),
- a = str_format_internal::FormatConversionCharToConvInt('a'),
- A = str_format_internal::FormatConversionCharToConvInt('A'),
- // misc
- n = str_format_internal::FormatConversionCharToConvInt('n'),
- p = str_format_internal::FormatConversionCharToConvInt('p'),
-
- // Used for width/precision '*' specification.
- kStar = str_format_internal::FormatConversionCharToConvInt('*'),
-
- // Some predefined values:
- kIntegral = d | i | u | o | x | X,
- kFloating = a | e | f | g | A | E | F | G,
- kNumeric = kIntegral | kFloating,
- kString = s,
- kPointer = p,
-};
-
} // namespace str_format_internal
ABSL_NAMESPACE_END
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index f48510b4..f833a80a 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -63,10 +63,6 @@
// loosely typed. `FormatUntyped()` is not a template and does not perform
// any compile-time checking of the format string; instead, it returns a
// boolean from a runtime check.
-//
-// In addition, the `str_format` library provides extension points for
-// augmenting formatting to new types. These extensions are fully documented
-// within the `str_format_extension.h` header file.
#ifndef ABSL_STRINGS_STR_FORMAT_H_
#define ABSL_STRINGS_STR_FORMAT_H_
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index 3f14dba3..49a68849 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -1,4 +1,6 @@
+#include "absl/strings/str_format.h"
+
#include <cstdarg>
#include <cstdint>
#include <cstdio>
@@ -6,13 +8,14 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/strings/str_format.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace {
using str_format_internal::FormatArgImpl;
+using str_format_internal::FormatConversionCharSetInternal;
using FormatEntryPointTest = ::testing::Test;
@@ -535,100 +538,106 @@ TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
using absl::str_format_internal::FormatConversionCharSet;
TEST_F(ParsedFormatTest, UncheckedCorrect) {
- auto f = ExtendedParsedFormat<FormatConversionCharSet::d>::New("ABC%dDEF");
+ auto f =
+ ExtendedParsedFormat<FormatConversionCharSetInternal::d>::New("ABC%dDEF");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
std::string format = "%sFFF%dZZZ%f";
- auto f2 =
- ExtendedParsedFormat<FormatConversionCharSet::kString,
- FormatConversionCharSet::d,
- FormatConversionCharSet::kFloating>::New(format);
+ auto f2 = ExtendedParsedFormat<
+ FormatConversionCharSetInternal::kString,
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::kFloating>::New(format);
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
- f2 =
- ExtendedParsedFormat<FormatConversionCharSet::kString,
- FormatConversionCharSet::d,
- FormatConversionCharSet::kFloating>::New("%s %d %f");
+ f2 = ExtendedParsedFormat<
+ FormatConversionCharSetInternal::kString,
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::kFloating>::New("%s %d %f");
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
- auto star = ExtendedParsedFormat<FormatConversionCharSet::kStar,
- FormatConversionCharSet::d>::New("%*d");
+ auto star =
+ ExtendedParsedFormat<FormatConversionCharSetInternal::kStar,
+ FormatConversionCharSetInternal::d>::New("%*d");
ASSERT_TRUE(star);
EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
- auto dollar =
- ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("%2$s %1$d");
+ auto dollar = ExtendedParsedFormat<
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::s>::New("%2$s %1$d");
ASSERT_TRUE(dollar);
EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
// with reuse
- dollar =
- ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
+ dollar = ExtendedParsedFormat<
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::s>::New("%2$s %1$d %1$d");
ASSERT_TRUE(dollar);
EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
SummarizeParsedFormat(*dollar));
}
TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
- EXPECT_FALSE((ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("ABC")));
EXPECT_FALSE(
- (ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("%dABC")));
+ (ExtendedParsedFormat<FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::s>::New("ABC")));
EXPECT_FALSE(
- (ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("ABC%2$s")));
- auto f =
- ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::NewAllowIgnored("ABC");
+ (ExtendedParsedFormat<FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::s>::New("%dABC")));
+ EXPECT_FALSE((ExtendedParsedFormat<
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::s>::New("ABC%2$s")));
+ auto f = ExtendedParsedFormat<
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::s>::NewAllowIgnored("ABC");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
f = ExtendedParsedFormat<
- FormatConversionCharSet::d,
- FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::s>::NewAllowIgnored("%dABC");
ASSERT_TRUE(f);
EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
f = ExtendedParsedFormat<
- FormatConversionCharSet::d,
- FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::s>::NewAllowIgnored("ABC%2$s");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
}
TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
- auto dx = ExtendedParsedFormat<FormatConversionCharSet::d |
- FormatConversionCharSet::x>::New("%1$d %1$x");
+ auto dx = ExtendedParsedFormat<
+ FormatConversionCharSetInternal::d |
+ FormatConversionCharSetInternal::x>::New("%1$d %1$x");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
- dx = ExtendedParsedFormat<FormatConversionCharSet::d |
- FormatConversionCharSet::x>::New("%1$d");
+ dx = ExtendedParsedFormat<FormatConversionCharSetInternal::d |
+ FormatConversionCharSetInternal::x>::New("%1$d");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
}
TEST_F(ParsedFormatTest, UncheckedIncorrect) {
- EXPECT_FALSE(ExtendedParsedFormat<FormatConversionCharSet::d>::New(""));
-
EXPECT_FALSE(
- ExtendedParsedFormat<FormatConversionCharSet::d>::New("ABC%dDEF%d"));
+ ExtendedParsedFormat<FormatConversionCharSetInternal::d>::New(""));
+
+ EXPECT_FALSE(ExtendedParsedFormat<FormatConversionCharSetInternal::d>::New(
+ "ABC%dDEF%d"));
std::string format = "%sFFF%dZZZ%f";
- EXPECT_FALSE((ExtendedParsedFormat<FormatConversionCharSet::s,
- FormatConversionCharSet::d,
- FormatConversionCharSet::g>::New(format)));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<FormatConversionCharSetInternal::s,
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::g>::New(format)));
}
TEST_F(ParsedFormatTest, RegressionMixPositional) {
- EXPECT_FALSE(
- (ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::o>::New("%1$d %o")));
+ EXPECT_FALSE((ExtendedParsedFormat<
+ FormatConversionCharSetInternal::d,
+ FormatConversionCharSetInternal::o>::New("%1$d %o")));
}
using FormatWrapperTest = ::testing::Test;