chore(simu): remove dependency to getopt() (#6474)
This commit is contained in:
@@ -172,6 +172,7 @@ if(TARGET SDL2:SDL2)
|
|||||||
display.cpp
|
display.cpp
|
||||||
widgets.cpp
|
widgets.cpp
|
||||||
knobs.cpp
|
knobs.cpp
|
||||||
|
arg_parser.cpp
|
||||||
sdl_simu.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) {}
|
void bluetoothWrite(const void*, uint32_t) {}
|
||||||
int bluetoothRead(uint8_t*) { return 0; }
|
int bluetoothRead(uint8_t*) { return 0; }
|
||||||
void bluetoothDisable() {}
|
void bluetoothDisable() {}
|
||||||
bool bluetoothIsWriting() { return false; }
|
uint8_t bluetoothIsWriting() { return false; }
|
||||||
volatile uint8_t btChipPresent;
|
volatile uint8_t btChipPresent;
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define SDL_MAIN_HANDLED
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL_keycode.h>
|
#include <SDL_keycode.h>
|
||||||
|
|
||||||
@@ -26,12 +27,10 @@
|
|||||||
#include <imgui_impl_sdl2.h>
|
#include <imgui_impl_sdl2.h>
|
||||||
#include <imgui_impl_sdlrenderer2.h>
|
#include <imgui_impl_sdlrenderer2.h>
|
||||||
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -72,14 +71,10 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "edgetx.h"
|
#include "edgetx.h"
|
||||||
|
|
||||||
|
#include "arg_parser.h"
|
||||||
|
|
||||||
#define TIMER_INTERVAL 10 // 10ms
|
#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_Window* window;
|
||||||
static SDL_Renderer* renderer;
|
static SDL_Renderer* renderer;
|
||||||
static SDL_Texture* screen_frame_buffer;
|
static SDL_Texture* screen_frame_buffer;
|
||||||
@@ -677,81 +672,30 @@ int find_input_mode()
|
|||||||
return default_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[])
|
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;
|
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
|
// Setup SDL
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER) != 0) {
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER) != 0) {
|
||||||
printf("Error: %s\n", SDL_GetError());
|
printf("Error: %s\n", SDL_GetError());
|
||||||
@@ -829,7 +773,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Init simulation
|
// Init simulation
|
||||||
simuInit();
|
simuInit();
|
||||||
simuStart(true, storage_path.c_str(), settings_path.c_str());
|
simuStart(true, args.getStoragePath().c_str(),
|
||||||
|
args.getSettingsPath().c_str());
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
SDL_SetEventFilter([](void*, SDL_Event* event){
|
SDL_SetEventFilter([](void*, SDL_Event* event){
|
||||||
|
|||||||
@@ -69,35 +69,8 @@ void lcdCopy(void * dest, void * src);
|
|||||||
|
|
||||||
uint64_t simuTimerMicros(void)
|
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();
|
auto now = std::chrono::steady_clock::now();
|
||||||
return (uint64_t) std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
|
return (uint64_t) std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getTmr16KHz()
|
uint16_t getTmr16KHz()
|
||||||
|
|||||||
@@ -21,9 +21,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#define sleep(x) usleep(1000*x)
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user