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"));
|
TRY(Core::System::pledge("stdio rpath"));
|
||||||
|
|
||||||
bool follow = false;
|
bool follow = false;
|
||||||
|
size_t wanted_byte_count = 0;
|
||||||
|
bool byte_mode = false;
|
||||||
size_t wanted_line_count = DEFAULT_LINE_COUNT;
|
size_t wanted_line_count = DEFAULT_LINE_COUNT;
|
||||||
bool start_from_end = true;
|
bool start_from_end = true;
|
||||||
StringView file;
|
StringView file;
|
||||||
|
@ -114,6 +116,30 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
return true;
|
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.add_positional_argument(file, "File path", "file", Core::ArgsParser::Required::No);
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
|
@ -135,6 +161,26 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
size_t line_index = 0;
|
size_t line_index = 0;
|
||||||
StringBuilder line;
|
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) {
|
if (!line_count && wanted_line_count) {
|
||||||
out("{}", StringView { bytes });
|
out("{}", StringView { bytes });
|
||||||
continue;
|
continue;
|
||||||
|
@ -180,7 +226,23 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
return 0;
|
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));
|
TRY(tail_from_pos(*f, pos));
|
||||||
|
|
||||||
if (follow) {
|
if (follow) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue