feat: Introduce core argument parsing framework with platform-specific parsers, conventions, and type-based value parsing.

This commit is contained in:
2026-03-15 23:05:13 +04:00
parent a1dc3c0149
commit 7e2c09cbf9
10 changed files with 258 additions and 301 deletions

View File

@@ -1,4 +1,5 @@
#include "windows_argument_convention.hpp"
#include <stdexcept>
namespace argument_parser::conventions::implementations {
windows_argument_convention::windows_argument_convention(bool accept_dash) : accept_dash_(accept_dash) {}

View File

@@ -0,0 +1,28 @@
#include "traits.hpp"
#include <stdexcept>
namespace argument_parser::parsing_traits {
std::string parser_trait<std::string>::parse(const std::string &input) {
return input;
}
bool parser_trait<bool>::parse(const std::string &input) {
if (input == "t" || input == "true" || input == "1")
return true;
if (input == "f" || input == "false" || input == "0")
return false;
throw std::runtime_error("Invalid boolean value: " + input);
}
int parser_trait<int>::parse(const std::string &input) {
return std::stoi(input);
}
float parser_trait<float>::parse(const std::string &input) {
return std::stof(input);
}
double parser_trait<double>::parse(const std::string &input) {
return std::stod(input);
}
} // namespace argument_parser::parsing_traits

View File

@@ -0,0 +1,18 @@
#ifdef __linux__
#include "linux_parser.hpp"
#include <fstream>
#include <string>
namespace argument_parser {
linux_parser::linux_parser() {
std::ifstream command_line_file{"/proc/self/cmdline"};
std::getline(command_line_file, program_name, '\0');
for (std::string line; std::getline(command_line_file, line, '\0');) {
parsed_arguments.emplace_back(line);
}
}
} // namespace argument_parser
#endif

View File

@@ -0,0 +1,42 @@
#ifdef _WIN32
#include "windows_parser.hpp"
#include <Windows.h>
#include <shellapi.h>
#include <string>
std::string utf8_from_wstring(const std::wstring &w) {
if (w.empty())
return {};
int needed = ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, w.c_str(), -1, nullptr, 0, nullptr, nullptr);
if (needed <= 0) {
throw std::runtime_error("WideCharToMultiByte sizing failed (" + std::to_string(::GetLastError()) + ")");
}
std::string out;
out.resize(static_cast<size_t>(needed - 1));
int written =
::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, w.c_str(), -1, out.data(), needed - 1, nullptr, nullptr);
if (written <= 0) {
throw std::runtime_error("WideCharToMultiByte convert failed (" + std::to_string(::GetLastError()) + ")");
}
return out;
}
namespace argument_parser {
windows_parser::windows_parser() {
LPWSTR *argv_w;
int argc_w;
argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
if (argv_w == nullptr) {
throw std::runtime_error("CommandLineToArgvW failed");
}
for (int i = 0; i < argc_w; i++) {
std::string arg = utf8_from_wstring(argv_w[i]);
parsed_arguments.emplace_back(arg);
}
LocalFree(argv_w);
}
} // namespace argument_parser
#endif