setopt/setopt.hpp
2023-06-12 15:38:07 +02:00

106 lines
1.9 KiB
C++

#pragma once
/*
TODO:
- implement setopt_long and setopt_long_only
- add support repeated options
- add support for embeding format strings
*/
#include <unordered_map>
#include <string>
#include <string.h>
#include <ctype.h>
#define OPTPREFIX "-"
#define OPTLONGPREFIX "--"
#define OPTGAP " "
enum {
SETOPTINVALIDOPTSTRING = 1,
SETOPTMISSINGREQUIRED,
SETOPTUNKNOWNOPT
};
struct option {
const char *name;
int has_arg;
int *flag;
int val;
};
enum {
no_argument = 0,
required_argument = 1,
optional_argument = 2
};
int optc, optred, opterrno = 0;
static inline void setopt_init(){
optc = 0;
}
char* setopt(const char* optstring, std::unordered_map<char, std::string> argv){
setopt_init();
std::string rs;
for(const char* i = optstring; *i; i++){
if(not isgraph(*i) or
*i == '-' or
*i == ':' or
*i == ';'
){
opterrno = SETOPTINVALIDOPTSTRING;
continue;
}
auto h = argv.find(*i);
if(h != argv.end()){
const char &opt = h->first;
const std::string &optarg = h->second;
rs += OPTGAP;
rs += OPTPREFIX;
rs += opt;
++optc;
if(*(i+1) == ':'){
if(optarg != ""){
rs += OPTGAP;
rs += optarg;
}else if(*(i+2) == ':'){
++i;
}else{
opterrno = SETOPTMISSINGREQUIRED;
}
++i;
}
argv.erase(h);
}else{
for(int j = 0; j < 2; j++){
if(*(i+1) == ':'){
++i;
}
}
}
}
if(argv.size()){
opterrno = SETOPTUNKNOWNOPT;
}
char* r;
if(rs.size()){
r = new char[rs.size()-1];
strcpy(r, rs.c_str()+sizeof(OPTGAP)-1);
}else{
r = new char[1];
r[0] = '\00';
}
return r;
}
char* setopt_long(const char* optstring, std::unordered_map<std::string, std::string> argv, const struct option* longopts){ return NULL; }
char* setopt_long_only(const char* optstring, std::unordered_map<std::string, std::string> argv, const struct option* longopts){ return NULL; }