فهرست منبع

AK+Format: Add outln(FILE*, ...) overload.

This commit also removes a few functions like raw_out and vwarn. If we
want to write raw output, we can do this as follows:

    out("{}", "Hello, World!");

The vout stuff isn't really public API anyways, so no need for another
vwarn.
asynts 4 سال پیش
والد
کامیت
0508fdbbcd
3فایلهای تغییر یافته به همراه49 افزوده شده و 44 حذف شده
  1. 6 25
      AK/Format.cpp
  2. 22 19
      AK/Format.h
  3. 21 0
      AK/Tests/TestFormat.cpp

+ 6 - 25
AK/Format.cpp

@@ -572,37 +572,18 @@ void Formatter<bool>::format(TypeErasedFormatParams& params, FormatBuilder& buil
 }
 
 #ifndef KERNEL
-void raw_out(StringView string)
-{
-    const auto retval = ::fwrite(string.characters_without_null_termination(), 1, string.length(), stdout);
-    ASSERT(retval == string.length());
-}
-void vout(StringView fmtstr, TypeErasedFormatParams params, bool newline)
+void vout(FILE* file, StringView fmtstr, TypeErasedFormatParams params, bool newline)
 {
     StringBuilder builder;
     vformat(builder, fmtstr, params);
 
-    if (newline && !builder.is_empty())
+    if (newline)
         builder.append('\n');
 
-    raw_out(builder.to_string());
-}
-
-void raw_warn(StringView string)
-{
-    const auto retval = ::write(STDERR_FILENO, string.characters_without_null_termination(), string.length());
+    const auto string = builder.string_view();
+    const auto retval = ::fwrite(string.characters_without_null_termination(), 1, string.length(), file);
     ASSERT(static_cast<size_t>(retval) == string.length());
 }
-void vwarn(StringView fmtstr, TypeErasedFormatParams params, bool newline)
-{
-    StringBuilder builder;
-    vformat(builder, fmtstr, params);
-
-    if (newline && !builder.is_empty())
-        builder.append('\n');
-
-    raw_warn(builder.to_string());
-}
 #endif
 
 void vdbgln(StringView fmtstr, TypeErasedFormatParams params)
@@ -636,9 +617,9 @@ void vdbgln(StringView fmtstr, TypeErasedFormatParams params)
     vformat(builder, fmtstr, params);
     builder.append('\n');
 
-    const auto string = builder.build();
+    const auto string = builder.string_view();
 
-    const auto retval = dbgputstr(string.characters(), string.length());
+    const auto retval = dbgputstr(string.characters_without_null_termination(), string.length());
     ASSERT(retval == 0);
 }
 

+ 22 - 19
AK/Format.h

@@ -30,9 +30,9 @@
 #include <AK/GenericLexer.h>
 #include <AK/StringView.h>
 
-// FIXME: I would really love to merge the format_value and make_type_erased_parameters functions,
-//        but the compiler creates weird error messages when I do that. Here is a small snippet that
-//        reproduces the issue: https://godbolt.org/z/o55crs
+#ifndef KERNEL
+#    include <stdio.h>
+#endif
 
 namespace AK {
 
@@ -307,29 +307,34 @@ void vformat(StringBuilder& builder, StringView fmtstr, TypeErasedFormatParams);
 void vformat(const LogStream& stream, StringView fmtstr, TypeErasedFormatParams);
 
 #ifndef KERNEL
-void vout(StringView fmtstr, TypeErasedFormatParams, bool newline = false);
-void raw_out(StringView string);
+void vout(FILE*, StringView fmtstr, TypeErasedFormatParams, bool newline = false);
 
-// FIXME: Rename this function to 'out' when that name becomes avaliable.
+// FIXME: Rename 'new_out' to 'out' when the name becomes avaliable.
 template<typename... Parameters>
-void new_out(StringView fmtstr, const Parameters&... parameters) { vout(fmtstr, VariadicFormatParams { parameters... }); }
+void new_out(FILE* file, StringView fmtstr, const Parameters&... parameters) { vout(file, fmtstr, VariadicFormatParams { parameters... }); }
 template<typename... Parameters>
-void outln(StringView fmtstr, const Parameters&... parameters) { vout(fmtstr, VariadicFormatParams { parameters... }, true); }
+void outln(FILE* file, StringView fmtstr, const Parameters&... parameters) { vout(file, fmtstr, VariadicFormatParams { parameters... }, true); }
 template<typename... Parameters>
-void outln(const char* fmtstr, const Parameters&... parameters) { outln(StringView { fmtstr }, parameters...); }
-inline void outln() { raw_out("\n"); }
+void outln(FILE* file, const char* fmtstr, const Parameters&... parameters) { vout(file, fmtstr, VariadicFormatParams { parameters... }, true); }
+inline void outln(FILE* file) { fputc('\n', file); }
 
-void vwarn(StringView fmtstr, TypeErasedFormatParams, bool newline = false);
-void raw_warn(StringView string);
+// FIXME: Rename 'new_out' to 'out' when the name becomes avaliable.
+template<typename... Parameters>
+void new_out(StringView fmtstr, const Parameters&... parameters) { new_out(stdout, fmtstr, parameters...); }
+template<typename... Parameters>
+void outln(StringView fmtstr, const Parameters&... parameters) { outln(stdout, fmtstr, parameters...); }
+template<typename... Parameters>
+void outln(const char* fmtstr, const Parameters&... parameters) { outln(stdout, fmtstr, parameters...); }
+inline void outln() { outln(stdout); }
 
-// FIXME: Rename this function to 'warn' when that name becomes avaliable.
+// FIXME: Rename 'new_warn' to 'warn' when the name becomes avaliable.
 template<typename... Parameters>
-void new_warn(StringView fmtstr, const Parameters&... parameters) { vwarn(fmtstr, VariadicFormatParams { parameters... }); }
+void new_warn(StringView fmtstr, const Parameters&... parameters) { new_out(stderr, fmtstr, parameters...); }
 template<typename... Parameters>
-void warnln(StringView fmtstr, const Parameters&... parameters) { vwarn(fmtstr, VariadicFormatParams { parameters... }, true); }
+void warnln(StringView fmtstr, const Parameters&... parameters) { outln(stderr, fmtstr, parameters...); }
 template<typename... Parameters>
-void warnln(const char* fmtstr, const Parameters&... parameters) { warnln(StringView { fmtstr }, parameters...); }
-inline void warnln() { raw_out("\n"); }
+void warnln(const char* fmtstr, const Parameters&... parameters) { outln(stderr, fmtstr, parameters...); }
+inline void warnln() { outln(stderr); }
 #endif
 
 void vdbgln(StringView fmtstr, TypeErasedFormatParams);
@@ -382,10 +387,8 @@ struct Formatter<FormatIfSupported<T>> : __FormatIfSupported<T, HasFormatter<T>:
 #ifndef KERNEL
 using AK::new_out;
 using AK::outln;
-using AK::raw_out;
 
 using AK::new_warn;
-using AK::raw_warn;
 using AK::warnln;
 #endif
 

+ 21 - 0
AK/Tests/TestFormat.cpp

@@ -214,4 +214,25 @@ TEST_CASE(format_if_supported)
     EXPECT_EQ(String::formatted("{}", FormatIfSupported { B {} }), "B");
 }
 
+TEST_CASE(file_descriptor)
+{
+    char filename[] = "/tmp/test-file-descriptor-XXXXXX";
+
+    int fd = mkstemp(filename);
+    FILE* file = fdopen(fd, "w+");
+
+    outln(file, "{}", "Hello, World!");
+    new_out(file, "foo");
+    outln(file, "bar");
+
+    rewind(file);
+
+    Array<u8, 256> buffer;
+    const auto nread = fread(buffer.data(), 1, buffer.size(), file);
+
+    EXPECT_EQ(StringView { "Hello, World!\nfoobar\n" }, StringView { buffer.span().trim(nread) });
+
+    fclose(file);
+}
+
 TEST_MAIN(Format)