tail: Implement byte mode into tail
This works exactly the same as with lines but with bytes instead.
This commit is contained in:
parent
91e944d793
commit
e511c553a8
Notes:
sideshowbarker
2024-07-17 08:38:37 +09:00
Author: https://github.com/fdellwing Commit: https://github.com/SerenityOS/serenity/commit/e511c553a8 Pull-request: https://github.com/SerenityOS/serenity/pull/23584 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/kemzeb
1 changed files with 63 additions and 1 deletions
|
@ -83,6 +83,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
TRY(Core::System::pledge("stdio rpath"));
|
||||
|
||||
bool follow = false;
|
||||
size_t wanted_byte_count = 0;
|
||||
bool byte_mode = false;
|
||||
size_t wanted_line_count = DEFAULT_LINE_COUNT;
|
||||
bool start_from_end = true;
|
||||
StringView file;
|
||||
|
@ -114,6 +116,30 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
return true;
|
||||
},
|
||||
});
|
||||
args_parser.add_option(Core::ArgsParser::Option {
|
||||
.argument_mode = Core::ArgsParser::OptionArgumentMode::Required,
|
||||
.help_string = "output the last NUM bytes; or use -c +NUM to"
|
||||
" output starting with byte NUM",
|
||||
.long_name = "bytes",
|
||||
.short_name = 'c',
|
||||
.value_name = "[+]NUM",
|
||||
.accept_value = [&](StringView bytes) -> ErrorOr<bool> {
|
||||
Optional<size_t> value;
|
||||
if (bytes.starts_with('+')) {
|
||||
value = bytes.substring_view(1, bytes.length() - 1).to_number<size_t>();
|
||||
start_from_end = false;
|
||||
} else {
|
||||
value = bytes.to_number<size_t>();
|
||||
}
|
||||
if (!value.has_value()) {
|
||||
warnln("Invalid number: {}", bytes);
|
||||
return false;
|
||||
}
|
||||
wanted_byte_count = value.value();
|
||||
byte_mode = true;
|
||||
return true;
|
||||
},
|
||||
});
|
||||
args_parser.add_positional_argument(file, "File path", "file", Core::ArgsParser::Required::No);
|
||||
args_parser.parse(arguments);
|
||||
|
||||
|
@ -135,6 +161,26 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
size_t line_index = 0;
|
||||
StringBuilder line;
|
||||
|
||||
if (byte_mode) {
|
||||
if (start_from_end) {
|
||||
if (wanted_byte_count > bytes.size()) {
|
||||
out("{}", StringView { bytes });
|
||||
continue;
|
||||
}
|
||||
out("{}", StringView { bytes }.substring_view(bytes.size() - wanted_byte_count, wanted_byte_count));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wanted_byte_count > bytes.size())
|
||||
continue;
|
||||
|
||||
if (wanted_byte_count > 0)
|
||||
out("{}", StringView { bytes }.substring_view(wanted_byte_count - 1, bytes.size() - wanted_byte_count + 1));
|
||||
else
|
||||
out("{}", StringView { bytes });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!line_count && wanted_line_count) {
|
||||
out("{}", StringView { bytes });
|
||||
continue;
|
||||
|
@ -180,7 +226,23 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
return 0;
|
||||
}
|
||||
|
||||
auto pos = TRY(find_seek_pos(*f, wanted_line_count, start_from_end));
|
||||
off_t pos = 0;
|
||||
if (byte_mode) {
|
||||
auto file_size = TRY(f->size());
|
||||
if (wanted_byte_count > file_size)
|
||||
wanted_byte_count = file_size;
|
||||
if (start_from_end) {
|
||||
TRY(f->seek(wanted_byte_count * -1, SeekMode::FromEndPosition));
|
||||
} else {
|
||||
if (wanted_byte_count > 0 && wanted_byte_count < file_size)
|
||||
TRY(f->seek(wanted_byte_count - 1, SeekMode::SetPosition));
|
||||
else
|
||||
TRY(f->seek(0, SeekMode::FromEndPosition));
|
||||
}
|
||||
pos = TRY(f->tell());
|
||||
} else {
|
||||
pos = TRY(find_seek_pos(*f, wanted_line_count, start_from_end));
|
||||
}
|
||||
TRY(tail_from_pos(*f, pos));
|
||||
|
||||
if (follow) {
|
||||
|
|
Loading…
Add table
Reference in a new issue