mirror of https://github.com/OpenTTD/OpenTTD
Codechange: replace char* in GetOptData with std::string_view
parent
c1a287ad17
commit
fbe80f31fe
|
@ -21,30 +21,30 @@
|
|||
*/
|
||||
int GetOptData::GetOpt()
|
||||
{
|
||||
const char *s = this->cont;
|
||||
if (s == nullptr) {
|
||||
std::string_view s = this->cont;
|
||||
if (s.empty()) {
|
||||
if (this->arguments.empty()) return -1; // No arguments left -> finished.
|
||||
|
||||
s = this->arguments[0];
|
||||
if (*s != '-') return -1; // No leading '-' -> not an option -> finished.
|
||||
if (s[0] != '-') return -1; // No leading '-' -> not an option -> finished.
|
||||
|
||||
this->arguments = this->arguments.subspan(1);
|
||||
|
||||
/* Is it a long option? */
|
||||
for (auto &option : this->options) {
|
||||
if (option.longname != nullptr && !strcmp(option.longname, s)) { // Long options always use the entire argument.
|
||||
this->cont = nullptr;
|
||||
if (option.longname == s) { // Long options always use the entire argument.
|
||||
this->cont = {};
|
||||
return this->GetOpt(option);
|
||||
}
|
||||
}
|
||||
|
||||
s++; // Skip leading '-'.
|
||||
s.remove_prefix(1); // Skip leading '-'.
|
||||
}
|
||||
|
||||
/* Is it a short option? */
|
||||
for (auto &option : this->options) {
|
||||
if (option.shortname != '\0' && *s == option.shortname) {
|
||||
this->cont = (s[1] != '\0') ? s + 1 : nullptr;
|
||||
if (option.shortname != '\0' && s[0] == option.shortname) {
|
||||
this->cont = s.substr(1);
|
||||
return this->GetOpt(option);
|
||||
}
|
||||
}
|
||||
|
@ -54,16 +54,16 @@ int GetOptData::GetOpt()
|
|||
|
||||
int GetOptData::GetOpt(const OptionData &option)
|
||||
{
|
||||
this->opt = nullptr;
|
||||
this->opt = {};
|
||||
switch (option.type) {
|
||||
case ODF_NO_VALUE:
|
||||
return option.id;
|
||||
|
||||
case ODF_HAS_VALUE:
|
||||
case ODF_OPTIONAL_VALUE:
|
||||
if (this->cont != nullptr) { // Remainder of the argument is the option value.
|
||||
if (!this->cont.empty()) { // Remainder of the argument is the option value.
|
||||
this->opt = this->cont;
|
||||
this->cont = nullptr;
|
||||
this->cont = {};
|
||||
return option.id;
|
||||
}
|
||||
/* No more arguments, either return an error or a value-less option. */
|
||||
|
|
|
@ -22,18 +22,18 @@ struct OptionData {
|
|||
OptionDataType type; ///< The type of option.
|
||||
char id; ///< Unique identification of this option data, often the same as #shortname.
|
||||
char shortname = '\0'; ///< Short option letter if available, else use \c '\0'.
|
||||
const char *longname = nullptr; ///< Long option name including '-'/'--' prefix, use \c nullptr if not available.
|
||||
std::string_view longname{}; ///< Long option name including '-'/'--' prefix, leave empty if not available.
|
||||
};
|
||||
|
||||
/** Data storage for parsing command line options. */
|
||||
struct GetOptData {
|
||||
using OptionSpan = std::span<const OptionData>;
|
||||
using ArgumentSpan = std::span<char * const>;
|
||||
using ArgumentSpan = std::span<std::string_view>;
|
||||
|
||||
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).
|
||||
std::string_view opt; ///< Option value, if available (else empty).
|
||||
std::string_view cont; ///< Next call to #GetOpt should start here (in the middle of an argument).
|
||||
|
||||
/**
|
||||
* Constructor of the data store.
|
||||
|
|
|
@ -497,7 +497,7 @@ static std::vector<OptionData> CreateOptions()
|
|||
* @param arguments The command line arguments passed to the application.
|
||||
* @return 0 when there is no error.
|
||||
*/
|
||||
int openttd_main(std::span<char * const> arguments)
|
||||
int openttd_main(std::span<std::string_view> arguments)
|
||||
{
|
||||
_game_session_stats.start_time = std::chrono::steady_clock::now();
|
||||
_game_session_stats.savegame_size = std::nullopt;
|
||||
|
@ -541,7 +541,7 @@ int openttd_main(std::span<char * const> arguments)
|
|||
blitter = "null";
|
||||
dedicated = true;
|
||||
SetDebugString("net=4", ShowInfoI);
|
||||
if (mgo.opt != nullptr) {
|
||||
if (!mgo.opt.empty()) {
|
||||
scanner->dedicated_host = ParseFullConnectionString(mgo.opt, scanner->dedicated_port);
|
||||
}
|
||||
break;
|
||||
|
@ -564,7 +564,7 @@ int openttd_main(std::span<char * const> arguments)
|
|||
#if defined(_WIN32)
|
||||
CreateConsole();
|
||||
#endif
|
||||
if (mgo.opt != nullptr) SetDebugString(mgo.opt, ShowInfoI);
|
||||
if (!mgo.opt.empty()) SetDebugString(mgo.opt, ShowInfoI);
|
||||
break;
|
||||
}
|
||||
case 'e':
|
||||
|
@ -577,7 +577,7 @@ int openttd_main(std::span<char * const> arguments)
|
|||
}
|
||||
break;
|
||||
case 'g':
|
||||
if (mgo.opt != nullptr) {
|
||||
if (!mgo.opt.empty()) {
|
||||
_file_to_saveload.name = mgo.opt;
|
||||
|
||||
std::string extension = FS2OTTD(std::filesystem::path(OTTD2FS(_file_to_saveload.name)).extension().native());
|
||||
|
@ -609,7 +609,7 @@ int openttd_main(std::span<char * const> arguments)
|
|||
break;
|
||||
case 'q': {
|
||||
DeterminePaths(arguments[0], only_local_path);
|
||||
if (StrEmpty(mgo.opt)) {
|
||||
if (mgo.opt.empty()) {
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ extern PauseModes _pause_mode;
|
|||
void AskExitGame();
|
||||
void AskExitToGameMenu();
|
||||
|
||||
int openttd_main(std::span<char * const> arguments);
|
||||
int openttd_main(std::span<std::string_view> arguments);
|
||||
void StateGameLoop();
|
||||
void HandleExitGameRequest();
|
||||
|
||||
|
|
|
@ -26,13 +26,16 @@ void CocoaReleaseAutoreleasePool();
|
|||
int CDECL main(int argc, char *argv[])
|
||||
{
|
||||
/* Make sure our arguments contain only valid UTF-8 characters. */
|
||||
for (int i = 0; i < argc; i++) StrMakeValidInPlace(argv[i]);
|
||||
std::vector<std::string_view> params;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
StrMakeValidInPlace(argv[i]);
|
||||
params.emplace_back(argv[i]);
|
||||
}
|
||||
|
||||
CocoaSetupAutoreleasePool();
|
||||
/* This is passed if we are launched by double-clicking */
|
||||
if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) {
|
||||
argv[1] = nullptr;
|
||||
argc = 1;
|
||||
if (params.size() >= 2 && params[1].starts_with("-psn")) {
|
||||
params.resize(1);
|
||||
}
|
||||
|
||||
CrashLog::InitialiseCrashLog();
|
||||
|
@ -41,7 +44,7 @@ int CDECL main(int argc, char *argv[])
|
|||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
int ret = openttd_main(std::span(argv, argc));
|
||||
int ret = openttd_main(params);
|
||||
|
||||
CocoaReleaseAutoreleasePool();
|
||||
|
||||
|
|
|
@ -21,7 +21,11 @@
|
|||
int CDECL main(int argc, char *argv[])
|
||||
{
|
||||
/* Make sure our arguments contain only valid UTF-8 characters. */
|
||||
for (int i = 0; i < argc; i++) StrMakeValidInPlace(argv[i]);
|
||||
std::vector<std::string_view> params;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
StrMakeValidInPlace(argv[i]);
|
||||
params.emplace_back(argv[i]);
|
||||
}
|
||||
|
||||
CrashLog::InitialiseCrashLog();
|
||||
|
||||
|
@ -29,5 +33,5 @@ int CDECL main(int argc, char *argv[])
|
|||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
return openttd_main(std::span(argv, argc));
|
||||
return openttd_main(params);
|
||||
}
|
||||
|
|
|
@ -12,37 +12,31 @@
|
|||
#include <mmsystem.h>
|
||||
#include "../../openttd.h"
|
||||
#include "../../core/random_func.hpp"
|
||||
#include "../../core/string_consumer.hpp"
|
||||
#include "../../string_func.h"
|
||||
#include "../../crashlog.h"
|
||||
#include "../../debug.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
static auto ParseCommandLine(char *line)
|
||||
static auto ParseCommandLine(std::string_view line)
|
||||
{
|
||||
std::vector<char *> arguments;
|
||||
for (;;) {
|
||||
/* skip whitespace */
|
||||
while (*line == ' ' || *line == '\t') line++;
|
||||
std::vector<std::string_view> arguments;
|
||||
|
||||
/* end? */
|
||||
if (*line == '\0') break;
|
||||
StringConsumer consumer{line};
|
||||
while (consumer.AnyBytesLeft()) {
|
||||
consumer.SkipUntilCharNotIn(StringConsumer::WHITESPACE_NO_NEWLINE);
|
||||
if (!consumer.AnyBytesLeft()) break;
|
||||
|
||||
/* special handling when quoted */
|
||||
if (*line == '"') {
|
||||
arguments.push_back(++line);
|
||||
while (*line != '"') {
|
||||
if (*line == '\0') return arguments;
|
||||
line++;
|
||||
}
|
||||
std::string_view argument;
|
||||
if (consumer.ReadIf("\"")) {
|
||||
/* special handling when quoted */
|
||||
argument = consumer.ReadUntil("\"", StringConsumer::SKIP_ONE_SEPARATOR);
|
||||
} else {
|
||||
arguments.push_back(line);
|
||||
while (*line != ' ' && *line != '\t') {
|
||||
if (*line == '\0') return arguments;
|
||||
line++;
|
||||
}
|
||||
argument = consumer.ReadUntilCharIn(StringConsumer::WHITESPACE_NO_NEWLINE);
|
||||
}
|
||||
*line++ = '\0';
|
||||
|
||||
arguments.push_back(argument);
|
||||
};
|
||||
|
||||
return arguments;
|
||||
|
@ -57,8 +51,8 @@ int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
|||
|
||||
CrashLog::InitialiseCrashLog();
|
||||
|
||||
/* Convert the command line to UTF-8. */
|
||||
std::string cmdline = FS2OTTD(GetCommandLine());
|
||||
/* Convert the command line to valid UTF-8. */
|
||||
std::string cmdline = StrMakeValid(FS2OTTD(GetCommandLine()));
|
||||
|
||||
/* Set the console codepage to UTF-8. */
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
|
@ -72,11 +66,7 @@ int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
|||
/* setup random seed to something quite random */
|
||||
SetRandomSeed(GetTickCount());
|
||||
|
||||
auto arguments = ParseCommandLine(cmdline.data());
|
||||
|
||||
/* Make sure our arguments contain only valid UTF-8 characters. */
|
||||
for (auto argument : arguments) StrMakeValidInPlace(argument);
|
||||
|
||||
auto arguments = ParseCommandLine(cmdline);
|
||||
int ret = openttd_main(arguments);
|
||||
|
||||
/* Restore system timer resolution. */
|
||||
|
|
|
@ -403,7 +403,9 @@ int CDECL main(int argc, char *argv[])
|
|||
std::optional<std::string_view> before_file;
|
||||
std::optional<std::string_view> after_file;
|
||||
|
||||
GetOptData mgo(std::span(argv + 1, argc - 1), _opts);
|
||||
std::vector<std::string_view> params;
|
||||
for (int i = 1; i < argc; ++i) params.emplace_back(argv[i]);
|
||||
GetOptData mgo(params, _opts);
|
||||
for (;;) {
|
||||
int i = mgo.GetOpt();
|
||||
if (i == -1) break;
|
||||
|
|
|
@ -322,7 +322,9 @@ int CDECL main(int argc, char *argv[])
|
|||
std::filesystem::path src_dir(".");
|
||||
std::filesystem::path dest_dir;
|
||||
|
||||
GetOptData mgo(std::span(argv + 1, argc - 1), _opts);
|
||||
std::vector<std::string_view> params;
|
||||
for (int i = 1; i < argc; ++i) params.emplace_back(argv[i]);
|
||||
GetOptData mgo(params, _opts);
|
||||
for (;;) {
|
||||
int i = mgo.GetOpt();
|
||||
if (i == -1) break;
|
||||
|
|
Loading…
Reference in New Issue