diff --git a/src/misc/getoptdata.cpp b/src/misc/getoptdata.cpp index a8fdc9d2b5..fbc4907375 100644 --- a/src/misc/getoptdata.cpp +++ b/src/misc/getoptdata.cpp @@ -21,15 +21,14 @@ */ int GetOptData::GetOpt() { - char *s = this->cont; + const char *s = this->cont; if (s == nullptr) { - if (this->numleft == 0) return -1; // No arguments left -> finished. + if (this->arguments.empty()) return -1; // No arguments left -> finished. - s = this->argv[0]; + s = this->arguments[0]; if (*s != '-') return -1; // No leading '-' -> not an option -> finished. - this->argv++; - this->numleft--; + this->arguments = this->arguments.subspan(1); /* Is it a long option? */ for (auto &option : this->options) { @@ -68,14 +67,13 @@ int GetOptData::GetOpt(const OptionData &option) return option.id; } /* No more arguments, either return an error or a value-less option. */ - if (this->numleft == 0) return (option.type == ODF_HAS_VALUE) ? -2 : option.id; + if (this->arguments.empty()) return (option.type == ODF_HAS_VALUE) ? -2 : option.id; /* Next argument looks like another option, let's not return it as option value. */ - if (option.type == ODF_OPTIONAL_VALUE && this->argv[0][0] == '-') return option.id; + if (option.type == ODF_OPTIONAL_VALUE && this->arguments[0][0] == '-') return option.id; - this->opt = this->argv[0]; // Next argument is the option value. - this->argv++; - this->numleft--; + this->opt = this->arguments[0]; // Next argument is the option value. + this->arguments = this->arguments.subspan(1); return option.id; default: NOT_REACHED(); diff --git a/src/misc/getoptdata.h b/src/misc/getoptdata.h index 40950e0078..244c96358b 100644 --- a/src/misc/getoptdata.h +++ b/src/misc/getoptdata.h @@ -28,26 +28,19 @@ struct OptionData { /** Data storage for parsing command line options. */ struct GetOptData { using OptionSpan = std::span; - char *opt; ///< Option value, if available (else \c nullptr). - int numleft; ///< Number of arguments left in #argv. - char **argv; ///< Remaining command line arguments. - OptionSpan options; ///< Command line option descriptions. - char *cont; ///< Next call to #GetOpt should start here (in the middle of an argument). + using ArgumentSpan = std::span; + + ArgumentSpan arguments; ///< Remaining command line arguments. + const OptionSpan options; ///< Command line option descriptions. + const char *opt = nullptr; ///< Option value, if available (else \c nullptr). + const char *cont = nullptr; ///< Next call to #GetOpt should start here (in the middle of an argument). /** * Constructor of the data store. - * @param argc Number of command line arguments, excluding the program name. - * @param argv Command line arguments, excluding the program name. + * @param argument The command line arguments, excluding the program name. * @param options Command line option descriptions. */ - GetOptData(int argc, char **argv, OptionSpan options) : - opt(nullptr), - numleft(argc), - argv(argv), - options(options), - cont(nullptr) - { - } + GetOptData(ArgumentSpan arguments, OptionSpan options) : arguments(arguments), options(options) {} int GetOpt(); int GetOpt(const OptionData &option); diff --git a/src/openttd.cpp b/src/openttd.cpp index bece97833e..55862f6ba3 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -530,7 +530,7 @@ int openttd_main(int argc, char *argv[]) _switch_mode = SM_MENU; auto options = CreateOptions(); - GetOptData mgo(argc - 1, argv + 1, options); + GetOptData mgo(std::span(argv + 1, argc - 1), options); int ret = 0; int i; @@ -654,7 +654,7 @@ int openttd_main(int argc, char *argv[]) if (i == -2) break; } - if (i == -2 || mgo.numleft > 0) { + if (i == -2 || !mgo.arguments.empty()) { /* Either the user typed '-h', they made an error, or they added unrecognized command line arguments. * In all cases, print the help, and exit. * diff --git a/src/settingsgen/settingsgen.cpp b/src/settingsgen/settingsgen.cpp index cb161033b8..9a55d0d170 100644 --- a/src/settingsgen/settingsgen.cpp +++ b/src/settingsgen/settingsgen.cpp @@ -435,7 +435,7 @@ int CDECL main(int argc, char *argv[]) const char *before_file = nullptr; const char *after_file = nullptr; - GetOptData mgo(argc - 1, argv + 1, _opts); + GetOptData mgo(std::span(argv + 1, argc - 1), _opts); for (;;) { int i = mgo.GetOpt(); if (i == -1) break; @@ -472,7 +472,7 @@ int CDECL main(int argc, char *argv[]) _stored_output.Clear(); _post_amble_output.Clear(); - for (int i = 0; i < mgo.numleft; i++) ProcessIniFile(mgo.argv[i]); + for (auto &argument : mgo.arguments) ProcessIniFile(argument); /* Write output. */ if (output_file == nullptr) { diff --git a/src/strgen/strgen.cpp b/src/strgen/strgen.cpp index 306a4f8c63..8acb4dfbe5 100644 --- a/src/strgen/strgen.cpp +++ b/src/strgen/strgen.cpp @@ -328,7 +328,7 @@ int CDECL main(int argc, char *argv[]) std::filesystem::path src_dir("."); std::filesystem::path dest_dir; - GetOptData mgo(argc - 1, argv + 1, _opts); + GetOptData mgo(std::span(argv + 1, argc - 1), _opts); for (;;) { int i = mgo.GetOpt(); if (i == -1) break; @@ -412,7 +412,7 @@ int CDECL main(int argc, char *argv[]) * strgen generates strings.h to the destination directory. If it is supplied * with a (free) parameter the program will translate that language to destination * directory. As input english.txt is parsed from the source directory */ - if (mgo.numleft == 0) { + if (mgo.arguments.empty()) { std::filesystem::path input_path = src_dir; input_path /= "english.txt"; @@ -431,7 +431,7 @@ int CDECL main(int argc, char *argv[]) writer.WriteHeader(data); writer.Finalise(data); if (_errors != 0) return 1; - } else if (mgo.numleft >= 1) { + } else { std::filesystem::path input_path = src_dir; input_path /= "english.txt"; @@ -440,10 +440,10 @@ int CDECL main(int argc, char *argv[]) FileStringReader master_reader(data, input_path, true, false); master_reader.ParseFile(); - for (int i = 0; i < mgo.numleft; i++) { + for (auto &argument: mgo.arguments) { data.FreeTranslation(); - std::filesystem::path lang_file = mgo.argv[i]; + std::filesystem::path lang_file = argument; FileStringReader translation_reader(data, lang_file, false, lang_file.filename() != "english.txt"); translation_reader.ParseFile(); // target file if (_errors != 0) return 1;