Merge "Keep the ReadFileToString/ReadFdToString overhead down."
This commit is contained in:
commit
2af784bf20
2 changed files with 51 additions and 0 deletions
|
|
@ -49,6 +49,14 @@ using namespace android::base::utf8;
|
||||||
bool ReadFdToString(int fd, std::string* content) {
|
bool ReadFdToString(int fd, std::string* content) {
|
||||||
content->clear();
|
content->clear();
|
||||||
|
|
||||||
|
// Although original we had small files in mind, this code gets used for
|
||||||
|
// 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, &sb) != -1 && sb.st_size > 0) {
|
||||||
|
content->reserve(sb.st_size);
|
||||||
|
}
|
||||||
|
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
|
while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
|
||||||
|
|
|
||||||
|
|
@ -214,3 +214,46 @@ TEST(file, Dirname) {
|
||||||
EXPECT_EQ(".", android::base::Dirname("sh"));
|
EXPECT_EQ(".", android::base::Dirname("sh"));
|
||||||
EXPECT_EQ("/system/bin", android::base::Dirname("/system/bin/sh/"));
|
EXPECT_EQ("/system/bin", android::base::Dirname("/system/bin/sh/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(file, ReadFileToString_capacity) {
|
||||||
|
TemporaryFile tf;
|
||||||
|
ASSERT_TRUE(tf.fd != -1);
|
||||||
|
|
||||||
|
// For a huge file, the overhead should still be small.
|
||||||
|
std::string s;
|
||||||
|
size_t size = 16 * 1024 * 1024;
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
|
||||||
|
ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
|
||||||
|
EXPECT_EQ(size, s.size());
|
||||||
|
EXPECT_LT(s.capacity(), size + 16);
|
||||||
|
|
||||||
|
// Even for weird badly-aligned sizes.
|
||||||
|
size += 12345;
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
|
||||||
|
ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
|
||||||
|
EXPECT_EQ(size, s.size());
|
||||||
|
EXPECT_LT(s.capacity(), size + 16);
|
||||||
|
|
||||||
|
// We'll shrink an enormous string if you read a small file into it.
|
||||||
|
size = 64;
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
|
||||||
|
ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
|
||||||
|
EXPECT_EQ(size, s.size());
|
||||||
|
EXPECT_LT(s.capacity(), size + 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(file, ReadFileToString_capacity_0) {
|
||||||
|
TemporaryFile tf;
|
||||||
|
ASSERT_TRUE(tf.fd != -1);
|
||||||
|
|
||||||
|
// Because /proc reports its files as zero-length, we don't actually trust
|
||||||
|
// any file that claims to be zero-length. Rather than add increasingly
|
||||||
|
// complex heuristics for shrinking the passed-in string in that case, we
|
||||||
|
// currently leave it alone.
|
||||||
|
std::string s;
|
||||||
|
size_t initial_capacity = s.capacity();
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile("", tf.path));
|
||||||
|
ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
|
||||||
|
EXPECT_EQ(0U, s.size());
|
||||||
|
EXPECT_EQ(initial_capacity, s.capacity());
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue