chore(simu): remove dependency to getopt() (#6474)

This commit is contained in:
Raphael Coeffic
2025-07-28 09:00:43 +10:00
committed by GitHub
parent 2a1538417b
commit 3285b8a6fd
7 changed files with 184 additions and 112 deletions
+1
View File
@@ -172,6 +172,7 @@ if(TARGET SDL2:SDL2)
display.cpp
widgets.cpp
knobs.cpp
arg_parser.cpp
sdl_simu.cpp
)
+117
View File
@@ -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;
}
+39
View File
@@ -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);
};
+1 -1
View File
@@ -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;
+26 -81
View File
@@ -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 &&
-27
View File
@@ -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()
-3
View File
@@ -21,9 +21,6 @@
#pragma once
#include <unistd.h>
#define sleep(x) usleep(1000*x)
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>