ReadFdToString: accommodate non-shrinking reserve
The file.ReadFileToString_capacity test verifies that
base::ReadFileToString shrinks an existing string's capacity to fit the
file. Previously, std::string::reserve was responsible for this, but as
of https://wg21.link/P0966R1, it no longer shrinks. Preserve the
existing behavior explicitly, and avoid reallocating when it isn't
needed.
Bug: b/175635923
Test: libbase_test
Change-Id: I0d77cf84527aa8209828914c7b665fcbbdf0e8b2
diff --git a/file.cpp b/file.cpp
index f71773b..55671b7 100644
--- a/file.cpp
+++ b/file.cpp
@@ -222,8 +222,18 @@
// very large files too, where the std::string growth heuristics might not
// be suitable. https://code.google.com/p/android/issues/detail?id=258500.
struct stat sb;
- if (fstat(fd.get(), &sb) != -1 && sb.st_size > 0) {
- content->reserve(sb.st_size);
+ if (fstat(fd.get(), &sb) != -1 && sb.st_size > 0 && sb.st_size <= SSIZE_MAX) {
+ // Shrink the string capacity to fit the file, but if the capacity is only
+ // slightly larger than needed, avoid reallocating. std::string::reserve no
+ // longer lowers capacity after P0966R1, but it does round the request up a
+ // small amount (e.g. 8 or 16 bytes).
+ size_t fd_size = sb.st_size;
+ if (fd_size > content->capacity()) {
+ content->reserve(fd_size);
+ } else if (fd_size < content->capacity() && content->capacity() - fd_size >= 64) {
+ content->shrink_to_fit();
+ content->reserve(fd_size);
+ }
}
char buf[4096] __attribute__((__uninitialized__));