Utilities/wc: Seek the input file(s) if only -c is passed

If the user only wants to get the byte count of a set of files, then for
each file we can simply seek it to get the byte count instead of
iterating over all the bytes.
This commit is contained in:
Thomas Voss 2023-11-16 14:05:13 +01:00 committed by Tim Schumacher
parent bd474dab14
commit 96efa81dc6

View file

@ -45,7 +45,7 @@ static void wc_out(Count const& count)
outln("{:>14}", count.name);
}
static ErrorOr<Count> get_count(StringView file_specifier)
static ErrorOr<Count> get_count(StringView file_specifier, bool only_bytes)
{
Count count;
@ -58,9 +58,20 @@ static ErrorOr<Count> get_count(StringView file_specifier)
}
auto file = TRY(Core::InputBufferedFile::create(maybe_file.release_value()));
count.name = file_specifier;
if (only_bytes) {
auto seek_or_error = file->size();
if (!seek_or_error.is_error()) {
count.bytes = seek_or_error.release_value();
return count;
}
// Handle the file as non-seekable if the error indicates it as such.
if (seek_or_error.error().code() != ESPIPE)
return seek_or_error.release_error();
}
bool start_a_new_word = true;
unsigned current_line_length = 0;
@ -118,14 +129,16 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
if (!g_output_line && !g_output_byte && !g_output_word && !g_output_max_line_length)
g_output_line = g_output_byte = g_output_word = true;
bool only_bytes = !g_output_line && !g_output_word && !g_output_max_line_length;
Vector<Count> counts;
for (auto const& file_specifier : file_specifiers)
counts.append(TRY(get_count(file_specifier)));
counts.append(TRY(get_count(file_specifier, only_bytes)));
TRY(Core::System::pledge("stdio"));
if (file_specifiers.is_empty())
counts.append(TRY(get_count(""sv)));
counts.append(TRY(get_count(""sv, only_bytes)));
else if (file_specifiers.size() > 1)
counts.append(get_total_count(counts));