chore(simu): remove dependency to getopt() (#6474)
This commit is contained in:
@@ -172,6 +172,7 @@ if(TARGET SDL2:SDL2)
|
||||
display.cpp
|
||||
widgets.cpp
|
||||
knobs.cpp
|
||||
arg_parser.cpp
|
||||
sdl_simu.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
#include "arg_parser.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cctype>
|
||||
#include <climits>
|
||||
|
||||
ArgumentParser::ArgumentParser(const std::string &prog_name)
|
||||
: program_name(prog_name) {}
|
||||
|
||||
bool ArgumentParser::parse(int argc, char *argv[]) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string arg = argv[i];
|
||||
|
||||
if (arg == "--width") {
|
||||
if (!parseIntOption(argc, argv, i, width, "width"))
|
||||
return false;
|
||||
} else if (arg == "--height") {
|
||||
if (!parseIntOption(argc, argv, i, height, "height"))
|
||||
return false;
|
||||
} else if (arg == "--storage") {
|
||||
if (!getNextArg(argc, argv, i, storage_path, "storage"))
|
||||
return false;
|
||||
} else if (arg == "--settings") {
|
||||
if (!getNextArg(argc, argv, i, settings_path, "settings"))
|
||||
return false;
|
||||
} else if (arg == "-h" || arg == "--help") {
|
||||
help_requested = true;
|
||||
return true;
|
||||
} else {
|
||||
printf("Unknown option: %s\n", arg.c_str());
|
||||
printUsage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArgumentParser::printUsage() const {
|
||||
printf("usage: %s [--width width] [--height height] [--storage path] "
|
||||
"[--settings path] [-h | --help]\n",
|
||||
program_name.c_str());
|
||||
}
|
||||
|
||||
void ArgumentParser::printHelp() const {
|
||||
printUsage();
|
||||
printf("\nOptions:\n");
|
||||
printf(" --width width Set the width (integer)\n");
|
||||
printf(" --height height Set the height (integer)\n");
|
||||
printf(" --storage path Set the storage path\n");
|
||||
printf(" --settings path Set the settings path\n");
|
||||
printf(" -h, --help Show this help message\n");
|
||||
}
|
||||
|
||||
bool ArgumentParser::isHelpRequested() const { return help_requested; }
|
||||
|
||||
int ArgumentParser::getWidth() const { return width; }
|
||||
|
||||
int ArgumentParser::getHeight() const { return height; }
|
||||
|
||||
const std::string &ArgumentParser::getStoragePath() const {
|
||||
return storage_path;
|
||||
}
|
||||
|
||||
const std::string &ArgumentParser::getSettingsPath() const {
|
||||
return settings_path;
|
||||
}
|
||||
|
||||
bool ArgumentParser::hasWidth() const { return width != -1; }
|
||||
|
||||
bool ArgumentParser::hasHeight() const { return height != -1; }
|
||||
|
||||
bool ArgumentParser::hasStoragePath() const { return !storage_path.empty(); }
|
||||
|
||||
bool ArgumentParser::hasSettingsPath() const { return !settings_path.empty(); }
|
||||
|
||||
bool ArgumentParser::getNextArg(int argc, char *argv[], int &i,
|
||||
std::string &value,
|
||||
const std::string &option_name) {
|
||||
if (i + 1 >= argc) {
|
||||
printf("Option --%s requires an argument\n", option_name.c_str());
|
||||
printUsage();
|
||||
return false;
|
||||
}
|
||||
value = argv[++i];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArgumentParser::parseIntOption(int argc, char *argv[], int &i, int &value,
|
||||
const std::string &option_name) {
|
||||
if (i + 1 >= argc) {
|
||||
printf("Option --%s requires an argument\n", option_name.c_str());
|
||||
printUsage();
|
||||
return false;
|
||||
}
|
||||
|
||||
char *endptr;
|
||||
const char *str = argv[++i];
|
||||
|
||||
// Check if string is empty or starts with non-digit (except for optional '+')
|
||||
if (!str || *str == '\0' || (!isdigit(*str) && *str != '+')) {
|
||||
printf("Option --%s requires a valid integer\n", option_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
long result = strtol(str, &endptr, 10);
|
||||
|
||||
// Check for conversion errors
|
||||
if (*endptr != '\0' || result <= 0 || result > INT_MAX) {
|
||||
printf("Option --%s requires a valid positive integer\n",
|
||||
option_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
value = static_cast<int>(result);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class ArgumentParser {
|
||||
private:
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
std::string storage_path;
|
||||
std::string settings_path;
|
||||
bool help_requested = false;
|
||||
std::string program_name;
|
||||
|
||||
public:
|
||||
ArgumentParser(const std::string &prog_name);
|
||||
|
||||
bool parse(int argc, char *argv[]);
|
||||
void printUsage() const;
|
||||
void printHelp() const;
|
||||
|
||||
// Getters
|
||||
bool isHelpRequested() const;
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
const std::string &getStoragePath() const;
|
||||
const std::string &getSettingsPath() const;
|
||||
|
||||
// Check if option was provided
|
||||
bool hasWidth() const;
|
||||
bool hasHeight() const;
|
||||
bool hasStoragePath() const;
|
||||
bool hasSettingsPath() const;
|
||||
|
||||
private:
|
||||
bool getNextArg(int argc, char *argv[], int &i, std::string &value,
|
||||
const std::string &option_name);
|
||||
bool parseIntOption(int argc, char *argv[], int &i, int &value,
|
||||
const std::string &option_name);
|
||||
};
|
||||
@@ -25,6 +25,6 @@ void bluetoothInit(unsigned int, bool) {}
|
||||
void bluetoothWrite(const void*, uint32_t) {}
|
||||
int bluetoothRead(uint8_t*) { return 0; }
|
||||
void bluetoothDisable() {}
|
||||
bool bluetoothIsWriting() { return false; }
|
||||
uint8_t bluetoothIsWriting() { return false; }
|
||||
volatile uint8_t btChipPresent;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include <SDL.h>
|
||||
#include <SDL_keycode.h>
|
||||
|
||||
@@ -26,12 +27,10 @@
|
||||
#include <imgui_impl_sdl2.h>
|
||||
#include <imgui_impl_sdlrenderer2.h>
|
||||
|
||||
#include <libgen.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
@@ -72,14 +71,10 @@
|
||||
#include "debug.h"
|
||||
#include "edgetx.h"
|
||||
|
||||
#include "arg_parser.h"
|
||||
|
||||
#define TIMER_INTERVAL 10 // 10ms
|
||||
|
||||
int window_width = 800;
|
||||
int window_height = 600;
|
||||
|
||||
std::string storage_path;
|
||||
std::string settings_path;
|
||||
|
||||
static SDL_Window* window;
|
||||
static SDL_Renderer* renderer;
|
||||
static SDL_Texture* screen_frame_buffer;
|
||||
@@ -677,81 +672,30 @@ int find_input_mode()
|
||||
return default_input_mode();
|
||||
}
|
||||
|
||||
static void print_usage(const char* path)
|
||||
{
|
||||
const char usage[] =
|
||||
"usage: %s [--width width] [--height height] [--storage path] "
|
||||
"[--settings path] [-h | --help]\n";
|
||||
|
||||
printf(usage, basename((char*)path));
|
||||
}
|
||||
|
||||
static int parse_args(int argc, char* argv[])
|
||||
{
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"width", required_argument, 0, 'w'},
|
||||
{"height", required_argument, 0, 'e'},
|
||||
{"storage", required_argument, 0, 's'},
|
||||
{"settings", required_argument, 0, 'c'},
|
||||
{0, 0, 0, 0}};
|
||||
|
||||
int option_index = 0;
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", long_options, &option_index)) !=
|
||||
-1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
|
||||
case 'w':
|
||||
window_width = std::atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
window_height = std::atoi(optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
storage_path = std::string(optarg);
|
||||
break;
|
||||
|
||||
case 'c': // 'c' for config/settings
|
||||
settings_path = std::string(optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
// getopt_long already printed an error message
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
// Check for non-option arguments
|
||||
if (optind < argc) {
|
||||
printf("Error: Unexpected arguments: ");
|
||||
while (optind < argc) {
|
||||
printf("%s ", argv[optind++]);
|
||||
}
|
||||
printf("\n");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (parse_args(argc, argv) != 0) {
|
||||
auto progname = std::filesystem::path(argv[0]).filename();
|
||||
ArgumentParser args(progname.string());
|
||||
|
||||
if (!args.parse(argc, argv)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (args.isHelpRequested()) {
|
||||
args.printHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int window_height = 600;
|
||||
if (args.hasHeight()) {
|
||||
window_height = args.getHeight();
|
||||
}
|
||||
|
||||
int window_width = 800;
|
||||
if (args.hasWidth()) {
|
||||
window_width = args.getWidth();
|
||||
}
|
||||
|
||||
// Setup SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER) != 0) {
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
@@ -829,8 +773,9 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Init simulation
|
||||
simuInit();
|
||||
simuStart(true, storage_path.c_str(), settings_path.c_str());
|
||||
|
||||
simuStart(true, args.getStoragePath().c_str(),
|
||||
args.getSettingsPath().c_str());
|
||||
|
||||
// Main loop
|
||||
SDL_SetEventFilter([](void*, SDL_Event* event){
|
||||
if (event->type == SDL_WINDOWEVENT &&
|
||||
|
||||
@@ -69,35 +69,8 @@ void lcdCopy(void * dest, void * src);
|
||||
|
||||
uint64_t simuTimerMicros(void)
|
||||
{
|
||||
#if SIMPGMSPC_USE_QT
|
||||
static QElapsedTimer ticker;
|
||||
if (!ticker.isValid())
|
||||
ticker.start();
|
||||
return ticker.nsecsElapsed() / 1000;
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
static double freqScale = 0.0;
|
||||
static LARGE_INTEGER firstTick;
|
||||
LARGE_INTEGER newTick;
|
||||
|
||||
if (!freqScale) {
|
||||
LARGE_INTEGER frequency;
|
||||
// get ticks per second
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
// 1us resolution
|
||||
freqScale = 1e6 / frequency.QuadPart;
|
||||
// init timer
|
||||
QueryPerformanceCounter(&firstTick);
|
||||
TRACE_SIMPGMSPACE("microsTimer() init: first tick = %llu @ %llu Hz", firstTick.QuadPart, frequency.QuadPart);
|
||||
}
|
||||
// read the timer
|
||||
QueryPerformanceCounter(&newTick);
|
||||
// compute the elapsed time
|
||||
return (newTick.QuadPart - firstTick.QuadPart) * freqScale;
|
||||
#else // GNUC
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
return (uint64_t) std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t getTmr16KHz()
|
||||
|
||||
@@ -21,9 +21,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unistd.h>
|
||||
#define sleep(x) usleep(1000*x)
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
Reference in New Issue
Block a user