summaryrefslogtreecommitdiff
path: root/absl/strings/internal
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings/internal')
-rw-r--r--absl/strings/internal/charconv_parse.cc6
-rw-r--r--absl/strings/internal/str_format/convert_test.cc110
2 files changed, 73 insertions, 43 deletions
diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc
index f3c72324..fa9a8965 100644
--- a/absl/strings/internal/charconv_parse.cc
+++ b/absl/strings/internal/charconv_parse.cc
@@ -253,6 +253,12 @@ std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits,
assert(max_digits * 4 <= std::numeric_limits<T>::digits);
}
const char* const original_begin = begin;
+
+ // Skip leading zeros, but only if *out is zero.
+ // They don't cause an overflow so we don't have to count them for
+ // `max_digits`.
+ while (!*out && end != begin && *begin == '0') ++begin;
+
T accumulator = *out;
const char* significant_digits_end =
(end - begin > max_digits) ? begin + max_digits : end;
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index 814ccf4c..ab8d5391 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -5,7 +5,9 @@
#include <cmath>
#include <string>
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
#include "absl/strings/internal/str_format/bind.h"
namespace absl {
@@ -157,12 +159,20 @@ TEST_F(FormatConvertTest, StringPrecision) {
EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)}));
}
+// Pointer formatting is implementation defined. This checks that the argument
+// can be matched to `ptr`.
+MATCHER_P(MatchesPointerString, ptr, "") {
+ if (ptr == nullptr && arg == "(nil)") {
+ return true;
+ }
+ void* parsed = nullptr;
+ if (sscanf(arg.c_str(), "%p", &parsed) != 1) {
+ ABSL_RAW_LOG(FATAL, "Could not parse %s", arg.c_str());
+ }
+ return ptr == parsed;
+}
+
TEST_F(FormatConvertTest, Pointer) {
-#ifdef _MSC_VER
- // MSVC's printf implementation prints pointers differently. We can't easily
- // compare our implementation to theirs.
- return;
-#endif
static int x = 0;
const int *xp = &x;
char c = 'h';
@@ -173,48 +183,62 @@ TEST_F(FormatConvertTest, Pointer) {
using VoidF = void (*)();
VoidF fp = [] {}, fnil = nullptr;
volatile char vc;
- volatile char* vcp = &vc;
- volatile char* vcnil = nullptr;
- const FormatArgImpl args[] = {
+ volatile char *vcp = &vc;
+ volatile char *vcnil = nullptr;
+ const FormatArgImpl args_array[] = {
FormatArgImpl(xp), FormatArgImpl(cp), FormatArgImpl(inil),
FormatArgImpl(cnil), FormatArgImpl(mcp), FormatArgImpl(fp),
FormatArgImpl(fnil), FormatArgImpl(vcp), FormatArgImpl(vcnil),
};
- struct Expectation {
- std::string out;
- const char *fmt;
- };
- const Expectation kExpect[] = {
- {StrPrint("%p", &x), "%p"},
- {StrPrint("%20p", &x), "%20p"},
- {StrPrint("%.1p", &x), "%.1p"},
- {StrPrint("%.20p", &x), "%.20p"},
- {StrPrint("%30.20p", &x), "%30.20p"},
-
- {StrPrint("%-p", &x), "%-p"},
- {StrPrint("%-20p", &x), "%-20p"},
- {StrPrint("%-.1p", &x), "%-.1p"},
- {StrPrint("%.20p", &x), "%.20p"},
- {StrPrint("%-30.20p", &x), "%-30.20p"},
-
- {StrPrint("%p", cp), "%2$p"}, // const char*
- {"(nil)", "%3$p"}, // null const char *
- {"(nil)", "%4$p"}, // null const int *
- {StrPrint("%p", mcp), "%5$p"}, // nonconst char*
-
- {StrPrint("%p", fp), "%6$p"}, // function pointer
- {StrPrint("%p", vcp), "%8$p"}, // function pointer
-
-#ifndef __APPLE__
- // Apple's printf differs here (0x0 vs. nil)
- {StrPrint("%p", fnil), "%7$p"}, // null function pointer
- {StrPrint("%p", vcnil), "%9$p"}, // null function pointer
-#endif
- };
- for (const Expectation &e : kExpect) {
- UntypedFormatSpecImpl format(e.fmt);
- EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))) << e.fmt;
- }
+ auto args = absl::MakeConstSpan(args_array);
+
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%20p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.1p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%30.20p"), args),
+ MatchesPointerString(&x));
+
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-20p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-.1p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-30.20p"), args),
+ MatchesPointerString(&x));
+
+ // const char*
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%2$p"), args),
+ MatchesPointerString(cp));
+ // null const int*
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%3$p"), args),
+ MatchesPointerString(nullptr));
+ // null const char*
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%4$p"), args),
+ MatchesPointerString(nullptr));
+ // nonconst char*
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%5$p"), args),
+ MatchesPointerString(mcp));
+
+ // function pointers
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%6$p"), args),
+ MatchesPointerString(reinterpret_cast<const void*>(fp)));
+ EXPECT_THAT(
+ FormatPack(UntypedFormatSpecImpl("%8$p"), args),
+ MatchesPointerString(reinterpret_cast<volatile const void *>(vcp)));
+
+ // null function pointers
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%7$p"), args),
+ MatchesPointerString(nullptr));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%9$p"), args),
+ MatchesPointerString(nullptr));
}
struct Cardinal {