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.
This commit is contained in:
asynts 2020-10-15 13:46:00 +02:00 committed by Andreas Kling
parent a274a8e5a0
commit 0508fdbbcd
3 changed files with 49 additions and 44 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -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)