From 23c514cda34dc37d22cc2f4b08f92eb620dde61a Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Wed, 1 Mar 2023 00:31:46 +0330 Subject: [PATCH] LibCore+Userland: Remove ArgsParser::add*(Vector&) This finally makes ArgsParser's value API free of silly char*'s! --- Userland/Libraries/LibCore/ArgsParser.cpp | 16 -------------- Userland/Libraries/LibCore/ArgsParser.h | 1 - Userland/Utilities/seq.cpp | 17 ++++++++------- Userland/Utilities/syscall.cpp | 26 +++++++++++------------ Userland/Utilities/watch.cpp | 18 +++++++++------- 5 files changed, 31 insertions(+), 47 deletions(-) diff --git a/Userland/Libraries/LibCore/ArgsParser.cpp b/Userland/Libraries/LibCore/ArgsParser.cpp index 084ef70c1c..62c1190b82 100644 --- a/Userland/Libraries/LibCore/ArgsParser.cpp +++ b/Userland/Libraries/LibCore/ArgsParser.cpp @@ -649,22 +649,6 @@ void ArgsParser::add_positional_argument(double& value, char const* help_string, add_positional_argument(move(arg)); } -void ArgsParser::add_positional_argument(Vector& values, char const* help_string, char const* name, Required required) -{ - Arg arg { - help_string, - name, - required == Required::Yes ? 1 : 0, - INT_MAX, - [&values](StringView s) { - VERIFY(s.length() == strlen(s.characters_without_null_termination())); - values.append(s.characters_without_null_termination()); - return true; - } - }; - add_positional_argument(move(arg)); -} - void ArgsParser::add_positional_argument(Vector& values, char const* help_string, char const* name, Required required) { Arg arg { diff --git a/Userland/Libraries/LibCore/ArgsParser.h b/Userland/Libraries/LibCore/ArgsParser.h index 7535a42593..ba31e88847 100644 --- a/Userland/Libraries/LibCore/ArgsParser.h +++ b/Userland/Libraries/LibCore/ArgsParser.h @@ -105,7 +105,6 @@ public: void add_positional_argument(int& value, char const* help_string, char const* name, Required required = Required::Yes); void add_positional_argument(unsigned& value, char const* help_string, char const* name, Required required = Required::Yes); void add_positional_argument(double& value, char const* help_string, char const* name, Required required = Required::Yes); - void add_positional_argument(Vector& value, char const* help_string, char const* name, Required required = Required::Yes); void add_positional_argument(Vector& value, char const* help_string, char const* name, Required required = Required::Yes); void add_positional_argument(Vector& value, char const* help_string, char const* name, Required required = Required::Yes); diff --git a/Userland/Utilities/seq.cpp b/Userland/Utilities/seq.cpp index 21d26eaabb..ba9f77746c 100644 --- a/Userland/Utilities/seq.cpp +++ b/Userland/Utilities/seq.cpp @@ -27,20 +27,21 @@ static void print_usage(FILE* stream) fputs(g_usage, stream); } -static double get_double(char const* name, char const* d_string, size_t* number_of_decimals) +static double get_double(char const* name, StringView d_string, size_t* number_of_decimals) { - char* end; - double d = strtod(d_string, &end); - if (d == 0 && end == d_string) { + auto d = d_string.to_double(); + if (!d.has_value()) { warnln("{}: invalid argument \"{}\"", name, d_string); print_usage(stderr); exit(1); } - if (char const* dot = strchr(d_string, '.')) - *number_of_decimals = strlen(dot + 1); + + if (auto dot = d_string.find('.'); dot.has_value()) + *number_of_decimals = d_string.length() - *dot - 1; else *number_of_decimals = 0; - return d; + + return *d; } ErrorOr serenity_main(Main::Arguments arguments) @@ -50,7 +51,7 @@ ErrorOr serenity_main(Main::Arguments arguments) StringView separator = "\n"sv; StringView terminator = ""sv; - Vector parameters; + Vector parameters; Core::ArgsParser args_parser; args_parser.add_option(separator, "Characters to print after each number (default: \\n)", "separator", 's', "separator"); diff --git a/Userland/Utilities/syscall.cpp b/Userland/Utilities/syscall.cpp index b19fd9d702..0e9e980780 100644 --- a/Userland/Utilities/syscall.cpp +++ b/Userland/Utilities/syscall.cpp @@ -24,7 +24,7 @@ FlatPtr arg[SC_NARG]; char outbuf[BUFSIZ]; -using Arguments = Vector; +using Arguments = Vector; using ArgIter = Arguments::Iterator; static FlatPtr parse_from(ArgIter&); @@ -41,7 +41,7 @@ ErrorOr serenity_main(Main::Arguments arguments) { bool output_buffer = false; bool list_syscalls = false; - Vector syscall_arguments; + Arguments syscall_arguments; Core::ArgsParser args_parser; args_parser.set_general_help( @@ -140,7 +140,7 @@ static FlatPtr parse_parameter_buffer(ArgIter& iter) { Vector params_vec; while (!iter.is_end()) { - if (strcmp(*iter, "]") == 0) { + if (*iter == "]"sv) { ++iter; return as_buf(params_vec); } @@ -155,36 +155,34 @@ static FlatPtr parse_parameter_buffer(ArgIter& iter) static FlatPtr parse_from(ArgIter& iter) { - char const* this_arg = *iter; + auto const& this_arg_string = *iter; + auto* this_arg = this_arg_string.characters(); ++iter; // Is it a forced literal? if (this_arg[0] == ',') { this_arg += 1; - dbgln_if(SYSCALL_1_DEBUG, "Using (forced) string >>{}<< at {:p}", this_arg, (FlatPtr)this_arg); + dbgln_if(SYSCALL_1_DEBUG, "Using (forced) string >>{}<< at {:p}", this_arg_string, (FlatPtr)this_arg); return (FlatPtr)this_arg; } // Is it the output buffer? - if (strcmp(this_arg, "buf") == 0) + if (this_arg_string == "buf"sv) return (FlatPtr)outbuf; // Is it a parameter buffer? - if (strcmp(this_arg, "[") == 0) + if (this_arg_string == "["sv) return parse_parameter_buffer(iter); // Is it a number? - char* endptr = nullptr; - FlatPtr l = strtoul(this_arg, &endptr, 0); - if (*endptr == 0) { - return l; - } + if (auto l = this_arg_string.to_uint(); l.has_value()) + return *l; // Then it must be a string: - if (strcmp(this_arg, "]") == 0) + if (this_arg_string == "]"sv) fprintf(stderr, "Warning: Treating unmatched ']' as literal string\n"); - dbgln_if(SYSCALL_1_DEBUG, "Using (detected) string >>{}<< at {:p}", this_arg, (FlatPtr)this_arg); + dbgln_if(SYSCALL_1_DEBUG, "Using (detected) string >>{}<< at {:p}", this_arg_string, (FlatPtr)this_arg); return (FlatPtr)this_arg; } diff --git a/Userland/Utilities/watch.cpp b/Userland/Utilities/watch.cpp index b0f3051020..3fe9f3a6c6 100644 --- a/Userland/Utilities/watch.cpp +++ b/Userland/Utilities/watch.cpp @@ -28,7 +28,7 @@ static bool flag_beep_on_fail = false; static int volatile exit_code = 0; static volatile pid_t child_pid = -1; -static DeprecatedString build_header_string(Vector const& command, struct timeval const& interval) +static DeprecatedString build_header_string(Vector const& command, struct timeval const& interval) { StringBuilder builder; builder.appendff("Every {}.{}s: \x1b[1m", interval.tv_sec, interval.tv_usec / 100000); @@ -37,7 +37,7 @@ static DeprecatedString build_header_string(Vector const& command, return builder.to_deprecated_string(); } -static DeprecatedString build_header_string(Vector const& command, Vector const& filenames) +static DeprecatedString build_header_string(Vector const& command, Vector const& filenames) { StringBuilder builder; builder.appendff("Every time any of {} changes: \x1b[1m", filenames); @@ -78,11 +78,15 @@ static void handle_signal(int signal) exit(exit_code); } -static int run_command(Vector const& command) +static int run_command(Vector const& command) { - VERIFY(command[command.size() - 1] == nullptr); + Vector argv; + argv.ensure_capacity(command.size() + 1); + for (auto& arg : command) + argv.unchecked_append(arg.characters()); + argv.unchecked_append(nullptr); - if ((errno = posix_spawnp(const_cast(&child_pid), command[0], nullptr, nullptr, const_cast(command.data()), environ))) { + if ((errno = posix_spawnp(const_cast(&child_pid), argv[0], nullptr, nullptr, const_cast(argv.data()), environ))) { exit_code = 1; perror("posix_spawn"); return errno; @@ -113,7 +117,7 @@ ErrorOr serenity_main(Main::Arguments arguments) TRY(Core::System::pledge("stdio proc exec rpath")); Vector files_to_watch; - Vector command; + Vector command; Core::ArgsParser args_parser; args_parser.set_stop_on_first_non_option(true); args_parser.set_general_help("Execute a command repeatedly, and watch its output over time."); @@ -135,8 +139,6 @@ ErrorOr serenity_main(Main::Arguments arguments) args_parser.add_positional_argument(command, "Command to run", "command"); args_parser.parse(arguments); - command.append(nullptr); - DeprecatedString header; auto watch_callback = [&] {