This commit is contained in:
2025-04-09 10:22:44 +02:00
commit 96ff5392c8
330 changed files with 28300 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 3.28)
# define CXX interface library
# define target & alias (for other projects consuming the "source-tree")
add_library(iue-po_po INTERFACE)
# define sources of target
target_sources(iue-po_po
INTERFACE FILE_SET public_headers TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR} FILES po.hpp)
# define installation step
install(TARGETS iue-po_po EXPORT iue-po-export
FILE_SET public_headers DESTINATION "./")
# define test
if(BUILD_TESTING AND PROJECT_IS_TOP_LEVEL)
add_executable(iue-po_po.test po.test.cpp)
target_link_libraries(iue-po_po.test iue-po_po)
add_test(NAME iue-po_po.test COMMAND iue-po_po.test --option1 100 -option2 o2)
endif()
# define C interface library
# define target & alias (for other projects consuming the "source-tree")
add_library(iue-po_cpo INTERFACE)
# define sources of target
target_sources(iue-po_cpo
INTERFACE FILE_SET public_headers TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR} FILES cpo.h)
# define installation step
install(TARGETS iue-po_cpo EXPORT iue-po-export
FILE_SET public_headers DESTINATION "./")
# define test
if(BUILD_TESTING AND PROJECT_IS_TOP_LEVEL)
add_executable(iue-po_cpo.test cpo.test.c)
target_link_libraries(iue-po_cpo.test iue-po_cpo)
add_test(NAME iue-po_cpo.test COMMAND iue-po_cpo.test --option1 100 -option2 o2)
endif()
# export targets for consuming cmake projects
# generate and install a .cmake file to allow dependend projects consuming the "install-tree" to import all targets
install(EXPORT iue-po-export DESTINATION "iue-po" )
# allow dependend projects consuming the "build-tree" to use all targets
export(EXPORT iue-po-export)
+104
View File
@@ -0,0 +1,104 @@
#pragma once
#include <stdbool.h> // bool
#include <stdio.h> // snprintf|stderr
#include <stdlib.h> // EXIT_FAILURE|EXIT_SUCCESS
#include <string.h> // strncmp|strlen
/// @brief internal function
static bool iuepo_find_option(const char* option, const char* arg) {
char buffer[256];
snprintf(buffer, sizeof(buffer) / sizeof(char), "%s%s", "-", option);
if (strncmp(buffer, arg, strlen(buffer)) == 0)
return true;
snprintf(buffer, sizeof(buffer) / sizeof(char), "%s%s", "--", option);
if (strncmp(buffer, arg, strlen(buffer)) == 0)
return true;
return false;
}
/// @brief internal function
static int iuepo_count_if(const char* option, char** begin, char** end) {
int res = 0;
for (char** iter = begin; iter != end; ++iter) {
if (iuepo_find_option(option, *iter))
++res;
}
return res;
}
/// @brief internal function
static char** iuepo_find_if(const char* option, char** begin, char** end) {
int res = 0;
for (char** iter = begin; iter != end; ++iter) {
if (iuepo_find_option(option, *iter))
return iter;
}
return end;
}
/// @todo Improve documentation of this enum
enum iuepo_option { IUEPO_REQUIRED = 0, IUEPO_OPTIONAL };
/// @todo Improve documentation of this function
/// @brief Optain a string option from command line arguments
static int iuepo_get_string(int argc, char* argv[], const char* option, char* default_value, int N,
enum iuepo_option op) {
int count = iuepo_count_if(option, argv + 1, argv + argc);
if (count == 0) {
if (op == IUEPO_REQUIRED) {
fprintf(stderr, "required option not provided: -/-- %s\n", option);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
if (count > 1) {
fprintf(stderr, "option not unique: -/-- %s (count = %i )\n", option, count);
return EXIT_FAILURE;
}
char** iter = iuepo_find_if(option, argv + 1, argv + argc);
++iter;
if (iter == argv + argc) {
fprintf(stderr, "option not followed by value: -/-- %s\n", option);
return EXIT_FAILURE;
}
if (strncmp("-", *iter, 1) == 0) {
fprintf(stderr, "option -/-- %s not followed by value but another option -/-- %s\n", option, *iter);
return EXIT_FAILURE;
}
if (snprintf(default_value, N, "%s", *iter) >= N) {
fprintf(stderr, "provided buffer size %i for option -/-- %s not sufficient\n", N, option);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/// @todo Improve documentation of this function
/// @brief Wrapping iuepo_get_string with a subsequent conversion
static int iuepo_get_int(int argc, char* argv[], const char* option, int* default_value, enum iuepo_option op) {
char default_value_string[256] = "\0";
snprintf(default_value_string, sizeof(default_value_string), "%i", *default_value);
if (iuepo_get_string(argc, argv, option, default_value_string, sizeof(default_value_string), op) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
int res = sscanf(default_value_string, "%i", default_value);
if (res != 1) {
fprintf(stderr, "value for option -/-- %s could not be converted\n", option);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
+32
View File
@@ -0,0 +1,32 @@
#include "iue-po/cpo.h"
#include <assert.h> // assert
#include <stdio.h> // printf
#include <stdlib.h>
#include <string.h> // strcmp
int main(int argc, char* argv[]) {
int value1 = 1;
if (iuepo_get_int(argc, argv, "option1", &value1, IUEPO_REQUIRED) != EXIT_SUCCESS)
return EXIT_FAILURE;
char value2[256] = "default2";
if (iuepo_get_string(argc, argv, "option2", value2, sizeof(value2), IUEPO_REQUIRED) != EXIT_SUCCESS)
return EXIT_FAILURE;
char value3[256] = "default3";
if (iuepo_get_string(argc, argv, "option3", value3, sizeof(value3), IUEPO_OPTIONAL) != EXIT_SUCCESS)
return EXIT_FAILURE;
printf("'%i'\n", value1);
printf("'%s'\n", value2);
printf("'%s'\n", value3);
assert(value1 == 100);
assert(strcmp(value2, "o2") == 0);
assert(strcmp(value3, "default3") == 0);
return EXIT_SUCCESS;
}
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
namespace iue::po {
inline std::vector<std::string> init(int argc, char* argv[]) {
return {argv + 1, argv + argc};
}
enum struct option { optional, required };
template <typename T>
inline T get(std::vector<std::string> args, std::string option, T default_value, enum option op = option::optional) {
auto find_option = [&option](const std::string& arg) -> bool {
return arg.starts_with("-" + option) || arg.starts_with("--" + option);
};
const auto count = std::ranges::count_if(args, find_option);
if (count == 0) {
if (op == option::required) {
throw std::runtime_error("required option not provided: -/--" + option);
}
return default_value;
}
if (count > 1) {
throw std::runtime_error("option not unique: -/--" + option + " (count = " + std::to_string(count) + ")");
}
auto it = std::ranges::find_if(args, find_option);
auto value = std::next(it);
if (value == args.end()) {
throw std::runtime_error("option not followed by value: -/--" + option);
}
if (value->starts_with('-')) {
throw std::runtime_error("option -/--" + option + " not followed by value but another option -/--" + *value);
}
std::istringstream ss(*value);
ss.exceptions(std::ios::failbit);
T num;
try {
ss >> num;
} catch (std::exception& e) {
throw std::runtime_error("value for option -/--" + option + " could not be converted");
}
return num;
}
} // namespace iue::po
+23
View File
@@ -0,0 +1,23 @@
#include "iue-po/po.hpp"
#include <cassert> // assert
#include <iostream> // std::cout|endl
int main(int argc, char* argv[]) {
auto args = iue::po::init(argc, argv);
auto value1 = iue::po::get(args, "option1", 1, iue::po::option::required);
auto value2 = iue::po::get(args, "option2", std::string("default2"), iue::po::option::required);
auto value3 = iue::po::get(args, "option3", std::string("default3"));
std::cout << value1 << std::endl;
std::cout << value2 << std::endl;
std::cout << value3 << std::endl;
assert(value1 == 100);
assert(value2 == "o2");
assert(value3 == "default3");
return 0;
}