[libc-commits] [libc] ba7e1cd - [libc] add fprintf and file_writer
Michael Jones via libc-commits
libc-commits at lists.llvm.org
Tue May 31 13:59:22 PDT 2022
Author: Michael Jones
Date: 2022-05-31T13:59:19-07:00
New Revision: ba7e1cddda621adb90175e060a3e2ad8bdef35f8
URL: https://github.com/llvm/llvm-project/commit/ba7e1cddda621adb90175e060a3e2ad8bdef35f8
DIFF: https://github.com/llvm/llvm-project/commit/ba7e1cddda621adb90175e060a3e2ad8bdef35f8.diff
LOG: [libc] add fprintf and file_writer
This patch adds the file_writer header, which just provides a wrapper
for File->write, as well as fprintf to use it. There are no unit tests
for file_writer since it's too simple to need them, but fprintf does
have a simple test of writing to a file.
Reviewed By: sivachandra
Differential Revision: https://reviews.llvm.org/D125939
Added:
libc/src/stdio/fprintf.cpp
libc/src/stdio/fprintf.h
libc/src/stdio/printf_core/file_writer.h
libc/test/src/stdio/fprintf_test.cpp
Modified:
libc/config/linux/x86_64/entrypoints.txt
libc/src/stdio/CMakeLists.txt
libc/src/stdio/printf_core/CMakeLists.txt
libc/test/src/stdio/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 300d94761f701..28607d615edcb 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -276,6 +276,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdio.fwrite_unlocked
libc.src.stdio.sprintf
libc.src.stdio.snprintf
+ libc.src.stdio.fprintf
libc.src.stdio.stderr
libc.src.stdio.stdout
diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index f4684c6b371f4..16fb58fb15b88 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -250,3 +250,16 @@ add_entrypoint_object(
libc.src.stdio.printf_core.string_writer
libc.src.stdio.printf_core.writer
)
+
+add_entrypoint_object(
+ fprintf
+ SRCS
+ fprintf.cpp
+ HDRS
+ fprintf.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.stdio.printf_core.printf_main
+ libc.src.stdio.printf_core.file_writer
+ libc.src.stdio.printf_core.writer
+)
diff --git a/libc/src/stdio/fprintf.cpp b/libc/src/stdio/fprintf.cpp
new file mode 100644
index 0000000000000..21451f5d5f5b0
--- /dev/null
+++ b/libc/src/stdio/fprintf.cpp
@@ -0,0 +1,40 @@
+//===-- Implementation of fprintf -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fprintf.h"
+
+#include "src/__support/arg_list.h"
+#include "src/stdio/ferror.h"
+#include "src/stdio/printf_core/file_writer.h"
+#include "src/stdio/printf_core/printf_main.h"
+#include "src/stdio/printf_core/writer.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, fprintf,
+ (::FILE *__restrict stream, const char *__restrict format,
+ ...)) {
+ va_list vlist;
+ va_start(vlist, format);
+ internal::ArgList args(vlist); // This holder class allows for easier copying
+ // and pointer semantics, as well as handling
+ // destruction automatically.
+ va_end(vlist);
+ printf_core::Writer writer(reinterpret_cast<void *>(stream),
+ printf_core::write_to_file);
+
+ int ret_val = printf_core::printf_main(&writer, format, args);
+ if (__llvm_libc::ferror(stream))
+ return -1;
+ return ret_val;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/fprintf.h b/libc/src/stdio/fprintf.h
new file mode 100644
index 0000000000000..caac3e88ee4fe
--- /dev/null
+++ b/libc/src/stdio/fprintf.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of fprintf ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_FPRINTF_H
+#define LLVM_LIBC_SRC_STDIO_FPRINTF_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+int fprintf(::FILE *__restrict stream, const char *__restrict format, ...);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FPRINTF_H
diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index 7c9853ee33708..7a1e46907753e 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -28,6 +28,14 @@ add_header_library(
libc.src.string.memory_utils.memcpy_implementation
)
+add_header_library(
+ file_writer
+ HDRS
+ file_writer.h
+ DEPENDS
+ libc.src.__support.File.file
+)
+
add_object_library(
writer
SRCS
diff --git a/libc/src/stdio/printf_core/file_writer.h b/libc/src/stdio/printf_core/file_writer.h
new file mode 100644
index 0000000000000..10fea82d83098
--- /dev/null
+++ b/libc/src/stdio/printf_core/file_writer.h
@@ -0,0 +1,29 @@
+//===-- FILE Writer class for printf ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FILE_WRITER_H
+#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FILE_WRITER_H
+
+#include "src/__support/File/file.h"
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace printf_core {
+
+// write_to_file treats raw_pointer as a File and calls its write
+// function.
+void write_to_file(void *raw_pointer, const char *__restrict to_write,
+ size_t len) {
+ __llvm_libc::File *file = reinterpret_cast<__llvm_libc::File *>(raw_pointer);
+ file->write(to_write, len);
+}
+
+} // namespace printf_core
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FILE_WRITER_H
diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt
index 331b90f32162b..e0e7357620a7c 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -83,6 +83,20 @@ add_libc_unittest(
libc.src.stdio.snprintf
)
+add_libc_unittest(
+ fprintf_test
+ SUITE
+ libc_stdio_unittests
+ SRCS
+ fprintf_test.cpp
+ DEPENDS
+ libc.src.stdio.fprintf
+ libc.src.stdio.fclose
+ libc.src.stdio.ferror
+ libc.src.stdio.fopen
+ libc.src.stdio.fread
+)
+
add_subdirectory(printf_core)
add_subdirectory(testdata)
diff --git a/libc/test/src/stdio/fprintf_test.cpp b/libc/test/src/stdio/fprintf_test.cpp
new file mode 100644
index 0000000000000..c7bf2cc1525d2
--- /dev/null
+++ b/libc/test/src/stdio/fprintf_test.cpp
@@ -0,0 +1,68 @@
+//===-- Unittests for fprintf ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fclose.h"
+#include "src/stdio/ferror.h"
+#include "src/stdio/fopen.h"
+#include "src/stdio/fread.h"
+
+#include "src/stdio/fprintf.h"
+
+#include "utils/UnitTest/Test.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+TEST(LlvmLibcFPrintfTest, WriteToFile) {
+ constexpr char FILENAME[] = "testdata/fprintf_output.test";
+ ::FILE *file = __llvm_libc::fopen(FILENAME, "w");
+ ASSERT_FALSE(file == nullptr);
+
+ int written;
+
+ constexpr char simple[] = "A simple string with no conversions.\n";
+ written = __llvm_libc::fprintf(file, simple);
+ EXPECT_EQ(written, 37);
+
+ constexpr char numbers[] = "1234567890\n";
+ written = __llvm_libc::fprintf(file, "%s", numbers);
+ EXPECT_EQ(written, 11);
+
+ constexpr char format_more[] = "%s and more\n";
+ constexpr char short_numbers[] = "1234";
+ written = __llvm_libc::fprintf(file, format_more, short_numbers);
+ EXPECT_EQ(written, 14);
+
+ ASSERT_EQ(0, __llvm_libc::fclose(file));
+
+ file = __llvm_libc::fopen(FILENAME, "r");
+ ASSERT_FALSE(file == nullptr);
+
+ char data[50];
+ ASSERT_EQ(__llvm_libc::fread(data, 1, sizeof(simple) - 1, file),
+ sizeof(simple) - 1);
+ data[sizeof(simple) - 1] = '\0';
+ ASSERT_STREQ(data, simple);
+ ASSERT_EQ(__llvm_libc::fread(data, 1, sizeof(numbers) - 1, file),
+ sizeof(numbers) - 1);
+ data[sizeof(numbers) - 1] = '\0';
+ ASSERT_STREQ(data, numbers);
+ ASSERT_EQ(__llvm_libc::fread(
+ data, 1, sizeof(format_more) + sizeof(short_numbers) - 4, file),
+ sizeof(format_more) + sizeof(short_numbers) - 4);
+ data[sizeof(format_more) + sizeof(short_numbers) - 4] = '\0';
+ ASSERT_STREQ(data, "1234 and more\n");
+
+ ASSERT_EQ(__llvm_libc::ferror(file), 0);
+
+ written =
+ __llvm_libc::fprintf(file, "Writing to a read only file should fail.");
+ EXPECT_EQ(written, -1);
+
+ ASSERT_EQ(__llvm_libc::fclose(file), 0);
+}
More information about the libc-commits
mailing list