summaryrefslogtreecommitdiff
path: root/absl/strings
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings')
-rw-r--r--absl/strings/numbers.h13
-rw-r--r--absl/strings/str_cat.cc26
-rw-r--r--absl/strings/str_format.h6
-rw-r--r--absl/strings/string_view.cc4
-rw-r--r--absl/strings/string_view.h6
-rw-r--r--absl/strings/string_view_test.cc12
6 files changed, 39 insertions, 28 deletions
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index 745de67a..9b8ec89a 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -37,7 +37,14 @@
#include <type_traits>
#include "absl/base/internal/bits.h"
+#ifdef __SSE4_2__
+// TODO(jorg): Remove this when we figure out the right way
+// to swap bytes on SSE 4.2 that works with the compilers
+// we claim to support. Also, add tests for the compiler
+// that doesn't support the Intel _bswap64 intrinsic but
+// does support all the SSE 4.2 intrinsics
#include "absl/base/internal/endian.h"
+#endif
#include "absl/base/macros.h"
#include "absl/base/port.h"
#include "absl/numeric/int128.h"
@@ -189,12 +196,12 @@ ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out,
// Returns the number of non-pad digits of the output (it can never be zero
// since 0 has one digit).
inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
- uint64_t be = absl::big_endian::FromHost64(val);
#ifdef __SSE4_2__
+ uint64_t be = absl::big_endian::FromHost64(val);
const auto kNibbleMask = _mm_set1_epi8(0xf);
const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
- auto v = _mm_loadu_si64(reinterpret_cast<__m128i*>(&be)); // load lo dword
+ auto v = _mm_loadl_epi64(reinterpret_cast<__m128i*>(&be)); // load lo dword
auto v4 = _mm_srli_epi64(v, 4); // shift 4 right
auto il = _mm_unpacklo_epi8(v4, v); // interleave bytes
auto m = _mm_and_si128(il, kNibbleMask); // mask out nibbles
@@ -202,7 +209,7 @@ inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
_mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars);
#else
for (int i = 0; i < 8; ++i) {
- auto byte = (be >> (8 * i)) & 0xFF;
+ auto byte = (val >> (56 - 8 * i)) & 0xFF;
auto* hex = &absl::numbers_internal::kHexTable[byte * 2];
std::memcpy(out + 2 * i, hex, 2);
}
diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc
index d5877899..4bd56f5f 100644
--- a/absl/strings/str_cat.cc
+++ b/absl/strings/str_cat.cc
@@ -27,23 +27,21 @@
namespace absl {
AlphaNum::AlphaNum(Hex hex) {
+ static_assert(numbers_internal::kFastToBufferSize >= 32,
+ "This function only works when output buffer >= 32 bytes long");
char* const end = &digits_[numbers_internal::kFastToBufferSize];
- char* writer = end;
- uint64_t value = hex.value;
- do {
- *--writer = absl::numbers_internal::kHexChar[value & 0xF];
- value >>= 4;
- } while (value != 0);
-
- char* beg;
- if (end - writer < hex.width) {
- beg = end - hex.width;
- std::fill_n(beg, writer - beg, hex.fill);
+ auto real_width =
+ absl::numbers_internal::FastHexToBufferZeroPad16(hex.value, end - 16);
+ if (real_width >= hex.width) {
+ piece_ = absl::string_view(end - real_width, real_width);
} else {
- beg = writer;
+ // Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and
+ // max pad width can be up to 20.
+ std::memset(end - 32, hex.fill, 16);
+ // Patch up everything else up to the real_width.
+ std::memset(end - real_width - 16, hex.fill, 16);
+ piece_ = absl::string_view(end - hex.width, hex.width);
}
-
- piece_ = absl::string_view(beg, end - beg);
}
AlphaNum::AlphaNum(Dec dec) {
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index 607e2bca..c11c93a2 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -400,6 +400,12 @@ int FPrintF(std::FILE* output, const FormatSpec<Args...>& format,
// This function is functionally equivalent to `std::snprintf()` (and
// type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.
//
+// In particular, a successful call to `absl::SNPrintF()` writes at most `size`
+// bytes of the formatted output to `output`, including a null terminator, and
+// returns the number of bytes that would have been written if truncation did
+// not occur. In the event of an error, a negative value is returned and `errno`
+// is set.
+//
// Example:
//
// std::string_view s = "Ulaanbaatar";
diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc
index dc034a83..d5e1a3de 100644
--- a/absl/strings/string_view.cc
+++ b/absl/strings/string_view.cc
@@ -14,7 +14,7 @@
#include "absl/strings/string_view.h"
-#ifndef ABSL_HAVE_STD_STRING_VIEW
+#ifndef ABSL_USES_STD_STRING_VIEW
#include <algorithm>
#include <climits>
@@ -230,4 +230,4 @@ constexpr string_view::size_type string_view::kMaxSize;
} // namespace absl
-#endif // ABSL_HAVE_STD_STRING_VIEW
+#endif // ABSL_USES_STD_STRING_VIEW
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 3438ccc1..07075e80 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -30,7 +30,7 @@
#include <algorithm>
#include "absl/base/config.h"
-#ifdef ABSL_HAVE_STD_STRING_VIEW
+#ifdef ABSL_USES_STD_STRING_VIEW
#include <string_view> // IWYU pragma: export
@@ -38,7 +38,7 @@ namespace absl {
using std::string_view;
} // namespace absl
-#else // ABSL_HAVE_STD_STRING_VIEW
+#else // ABSL_USES_STD_STRING_VIEW
#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
(defined(__GNUC__) && !defined(__clang__))
@@ -580,7 +580,7 @@ std::ostream& operator<<(std::ostream& o, string_view piece);
#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
-#endif // ABSL_HAVE_STD_STRING_VIEW
+#endif // ABSL_USES_STD_STRING_VIEW
namespace absl {
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc
index 86f2fbcd..96dacdf0 100644
--- a/absl/strings/string_view_test.cc
+++ b/absl/strings/string_view_test.cc
@@ -830,7 +830,7 @@ TEST(StringViewTest, FrontBackSingleChar) {
// to the standard, but `absl::string_view` implements a different
// behavior for historical reasons. We work around tests that construct
// `string_view` from `nullptr` when using libc++.
-#if !defined(ABSL_HAVE_STD_STRING_VIEW) || \
+#if !defined(ABSL_USES_STD_STRING_VIEW) || \
(!(defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 9) && \
!defined(_LIBCPP_VERSION) && !defined(_MSC_VER))
#define ABSL_HAVE_STRING_VIEW_FROM_NULLPTR 1
@@ -938,7 +938,7 @@ TEST(StringViewTest, ConstexprCompiles) {
#endif
constexpr absl::string_view cstr_len("cstr", 4);
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
+#if defined(ABSL_USES_STD_STRING_VIEW)
// In libstdc++ (as of 7.2), `std::string_view::string_view(const char*)`
// calls `std::char_traits<char>::length(const char*)` to get the std::string
// length, but it is not marked constexpr yet. See GCC bug:
@@ -952,7 +952,7 @@ TEST(StringViewTest, ConstexprCompiles) {
#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
#endif // !__GLIBCXX__
-#else // ABSL_HAVE_STD_STRING_VIEW
+#else // ABSL_USES_STD_STRING_VIEW
// This duplicates the check for __builtin_strlen in the header.
#if ABSL_HAVE_BUILTIN(__builtin_strlen) || \
@@ -967,7 +967,7 @@ TEST(StringViewTest, ConstexprCompiles) {
#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
#endif
-#endif // ABSL_HAVE_STD_STRING_VIEW
+#endif // ABSL_USES_STD_STRING_VIEW
#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR
constexpr absl::string_view cstr_strlen("foo");
@@ -1136,7 +1136,7 @@ TEST(HugeStringView, TwoPointTwoGB) {
}
#endif // THREAD_SANITIZER
-#if !defined(NDEBUG) && !defined(ABSL_HAVE_STD_STRING_VIEW)
+#if !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
TEST(NonNegativeLenTest, NonNegativeLen) {
ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("xyz", -1),
"len <= kMaxSize");
@@ -1152,7 +1152,7 @@ TEST(LenExceedsMaxSizeTest, LenExceedsMaxSize) {
ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("", max_size + 1),
"len <= kMaxSize");
}
-#endif // !defined(NDEBUG) && !defined(ABSL_HAVE_STD_STRING_VIEW)
+#endif // !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
class StringViewStreamTest : public ::testing::Test {
public: