summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorasynts <asynts@gmail.com>2020-10-15 13:46:00 +0200
committerAndreas Kling <kling@serenityos.org>2020-10-17 23:20:31 +0200
commit0508fdbbcd82deeec23cdbe5ccf139b84da21d10 (patch)
tree35c91eabccdfc25e967480b34298a793f6b86aeb
parenta274a8e5a079c105ee070efd0f90cdc6d9e95847 (diff)
downloadserenity-0508fdbbcd82deeec23cdbe5ccf139b84da21d10.zip
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.
-rw-r--r--AK/Format.cpp31
-rw-r--r--AK/Format.h41
-rw-r--r--AK/Tests/TestFormat.cpp21
3 files changed, 49 insertions, 44 deletions
diff --git a/AK/Format.cpp b/AK/Format.cpp
index 689a66899f..84ced59711 100644
--- a/AK/Format.cpp
+++ b/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);
}
diff --git a/AK/Format.h b/AK/Format.h
index 4bd3a4f4d9..c3334ca110 100644
--- a/AK/Format.h
+++ b/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
diff --git a/AK/Tests/TestFormat.cpp b/AK/Tests/TestFormat.cpp
index 7d426fb4e1..4f3f9924f3 100644
--- a/AK/Tests/TestFormat.cpp
+++ b/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)