fd/fmt: Fix for compiled strings
This ensures that we can use the faster variants of complex formatting
strings via pre-compilation.
Change-Id: I6e6433edf1c96d717638555e0734657ae32e3dba
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include-fd/stdplus/fd/fmt.hpp b/include-fd/stdplus/fd/fmt.hpp
index 673a93a..b0e4c11 100644
--- a/include-fd/stdplus/fd/fmt.hpp
+++ b/include-fd/stdplus/fd/fmt.hpp
@@ -5,6 +5,16 @@
#include <stdplus/fd/intf.hpp>
#include <stdplus/fd/managed.hpp>
#include <string_view>
+#include <type_traits>
+
+namespace fmt
+{
+namespace detail
+{
+template <typename T>
+struct is_compiled_string;
+}
+} // namespace fmt
namespace stdplus
{
@@ -22,13 +32,22 @@
FormatBuffer& operator=(FormatBuffer&&) = default;
template <typename... Args>
- void append(fmt::format_string<Args...> fmt, Args&&... args)
+ inline void append(fmt::format_string<Args...> fmt, Args&&... args)
{
fmt::format_to(std::back_inserter(buf), fmt,
std::forward<Args>(args)...);
writeIfNeeded();
}
+ template <typename T, typename... Args,
+ std::enable_if_t<fmt::detail::is_compiled_string<T>::value,
+ bool> = true>
+ inline void append(const T& t, Args&&... args)
+ {
+ fmt::format_to(std::back_inserter(buf), t, std::forward<Args>(args)...);
+ writeIfNeeded();
+ }
+
void flush();
private:
@@ -50,10 +69,17 @@
FormatToFile& operator=(FormatToFile&&) = delete;
template <typename... Args>
- void append(fmt::format_string<Args...> fmt, Args&&... args)
+ inline void append(fmt::format_string<Args...> fmt, Args&&... args)
{
buf.append(fmt, std::forward<Args>(args)...);
}
+ template <typename T, typename... Args,
+ std::enable_if_t<fmt::detail::is_compiled_string<T>::value,
+ bool> = true>
+ inline void append(const T& t, Args&&... args)
+ {
+ buf.append(t, std::forward<Args>(args)...);
+ }
void commit(const std::filesystem::path& out, int mode = 0644);
diff --git a/test/fd/fmt.cpp b/test/fd/fmt.cpp
index fe1fed4..55f6c5d 100644
--- a/test/fd/fmt.cpp
+++ b/test/fd/fmt.cpp
@@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#include <filesystem>
+#include <fmt/compile.h>
#include <memory>
#include <stdplus/fd/fmt.hpp>
#include <stdplus/fd/managed.hpp>
@@ -8,30 +9,37 @@
#include <stdplus/util/cexec.hpp>
#include <sys/mman.h>
+#include <string>
+#include <string_view>
+
namespace stdplus
{
namespace fd
{
+using fmt::operator""_cf;
+using std::literals::string_view_literals::operator""sv;
+
TEST(FormatBuffer, Basic)
{
auto fd = ManagedFd(CHECK_ERRNO(memfd_create("test", 0), "memfd_create"));
{
FormatBuffer buf(fd, 4096);
buf.append("hi\n");
+ buf.append("hi\n"sv);
EXPECT_EQ(0, fd.lseek(0, Whence::Cur));
buf.flush();
- EXPECT_EQ(3, fd.lseek(0, Whence::Cur));
- buf.append("{}", std::string(2050, 'a'));
- EXPECT_EQ(3, fd.lseek(0, Whence::Cur));
- buf.append("{}", std::string(2050, 'a'));
- EXPECT_EQ(4103, fd.lseek(0, Whence::Cur));
+ EXPECT_EQ(6, fd.lseek(0, Whence::Cur));
+ buf.append(FMT_COMPILE("{}"), std::string(2050, 'a'));
+ EXPECT_EQ(6, fd.lseek(0, Whence::Cur));
+ buf.append("{}"_cf, std::string(2050, 'a'));
+ EXPECT_EQ(4106, fd.lseek(0, Whence::Cur));
- buf.append("hi\n");
- EXPECT_EQ(4103, fd.lseek(0, Whence::Cur));
+ buf.append(FMT_STRING("hi\n"));
+ EXPECT_EQ(4106, fd.lseek(0, Whence::Cur));
}
- EXPECT_EQ(4106, fd.lseek(0, Whence::Cur));
+ EXPECT_EQ(4109, fd.lseek(0, Whence::Cur));
}
class FormatToFileTest : public gtest::TestWithTmp
@@ -64,11 +72,14 @@
TEST_F(FormatToFileTest, Basic)
{
file->append("hi\n");
+ file->append("hi\n"sv);
+ file->append(FMT_STRING("hi\n"));
+ file->append(FMT_COMPILE("hi\n"));
EXPECT_EQ(0, std::filesystem::file_size(tmpname));
auto filename = fmt::format("{}/out", CaseTmpDir());
file->commit(filename);
EXPECT_FALSE(std::filesystem::exists(tmpname));
- EXPECT_EQ(3, std::filesystem::file_size(filename));
+ EXPECT_EQ(12, std::filesystem::file_size(filename));
}
} // namespace fd