occlum/demos/ra_tls/grpc/v1.38.1/examples/cpp/ratls/getopt.hpp
yuanwu 2810b8e4ce Enable the grpc ra-tls demo
Signed-off-by: yuanwu <yuan.wu@intel.com>
2022-03-09 15:53:45 +08:00

316 lines
9.8 KiB
C++

// Simple getopt replacement class (C++11).
// - rlyeh, zlib/libpng licensed.
// https://github.com/r-lyeh-archived/getopt/blob/master/getopt.hpp
// Two APIs provided:
//
// 1) Simple functional api `getarg(...)`.
// - No initialization required: (argc, argv) pair automatically retrieved.
// - First argument is default option value, then all option indentifiers follow.
//
// int main() {
// bool help = getarg( false, "-h", "--help", "-?" );
// int version = getarg( 0, "-v", "--version", "--show-version" );
// int depth = getarg( 1, "-d", "--depth", "--max-depth");
// std::string file = getarg( "", "-f", "--file" );
// [...]
// }
//
// 2) Simple OOP map-based api `getopt class`. Initialization (argc, argv) pair required.
//
// This getopt class is a std::map replacement where key/value are std::string types.
// Given invokation './app.out --user=me --pass=123 -h' this class delivers not only:
// map[0] = "./app.out", map[1] = "--user=me", map[2]="--pass=123", map[3]='-h'
// but also, map["--user"]="me", map["--pass"]="123" and also, map["-h"]=true
//
// Additional API:
// - .cmdline() for a print app invokation string
// - .str() for pretty map printing
// - .size() number of arguments (equivalent to argc), rather than std::map.size()
//
// int main( int argc, const char **argv ) {
// getopt args( argc, argv );
// if( args.has("-h") || args.has("--help") || args.has("-?") || args.size() == 1 ) {
// std::cout << args["0"] << " [-?|-h|--help] [-v|--version] [--depth=number]" << std::endl;
// return 0;
// }
// if( args.has("-v") || args.has("--version") ) {
// std::cout << args["0"] << " sample v1.0.0. Compiled on " << __DATE__ << std::endl;
// }
// if( args.has("--depth") ) {
// int depth = atoi( args["--depth"].c_str() );
// std::cout << "depth set to " << depth << std::endl;
// }
// [...]
// }
#pragma once
#include <map>
#include <string>
#include <sstream>
#include <vector>
#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
#include <shellapi.h>
#pragma comment(lib, "Shell32.lib")
#else
#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#endif
#define GETOPT_VERSION "1.0.0" // (2016/04/18) Initial version
namespace getopt_utils
{
// string conversion
template< typename T >
inline T as( const std::string &self ) {
T t;
return (std::istringstream(self) >> t) ? t :
(T)(self.size() && (self != "0") && (self != "false"));
}
template<>
inline char as( const std::string &self ) {
return self.size() == 1 ? (char)(self[0]) : (char)(as<int>(self));
}
template<>
inline signed char as( const std::string &self ) {
return self.size() == 1 ? (signed char)(self[0]) : (signed char)(as<int>(self));
}
template<>
inline unsigned char as( const std::string &self ) {
return self.size() == 1 ? (unsigned char)(self[0]) : (unsigned char)(as<int>(self));
}
template<>
inline const char *as( const std::string &self ) {
return self.c_str();
}
template<>
inline std::string as( const std::string &self ) {
return self;
}
// token split
inline size_t split( std::vector<std::string> &tokens, const std::string &self, const std::string &delimiters ) {
std::string str;
tokens.clear();
for( auto &ch : self ) {
if( delimiters.find_first_of( ch ) != std::string::npos ) {
if( str.size() ) tokens.push_back( str ), str = "";
tokens.push_back( std::string() + ch );
} else str += ch;
}
return str.empty() ? tokens.size() : ( tokens.push_back( str ), tokens.size() );
};
// portable cmdline
inline std::vector<std::string> cmdline() {
std::vector<std::string> args;
std::string arg;
# ifdef _WIN32
int argv;
auto *list = CommandLineToArgvW( GetCommandLineW(), &argv );
if( list ) {
for( int i = 0; i < argv; ++i ) {
std::wstring ws( list[i] );
args.push_back( std::string( ws.begin(), ws.end() ) );
}
LocalFree(list);
}
# else
pid_t pid = getpid();
char fname[32] = {};
sprintf(fname, "/proc/%d/cmdline", pid);
std::ifstream ifs(fname);
if( ifs.good() ) {
std::stringstream ss;
ifs >> ss.rdbuf();
arg = ss.str();
}
for( auto end = arg.size(), i = end - end; i < end; ++i ) {
auto st = i;
while (i < arg.size() && arg[i] != '\0') ++i;
args.push_back( arg.substr(st, i - st) );
}
# endif
return args;
}
}
// main map class; explicit initialization
struct getopt : public std::map< std::string, std::string >
{
using super = std::map< std::string, std::string >;
getopt( int argc, const char **argv ) : super() {
// reconstruct vector
std::vector<std::string> args( argc, std::string() );
for( int i = 0; i < argc; ++i ) {
args[ i ] = argv[ i ];
}
// create key=value and key= args as well
for( auto &it : args ) {
std::vector<std::string> tokens;
auto size = getopt_utils::split( tokens, it, "=" );
if( size == 3 && tokens[1] == "=" )
(*this)[ tokens[0] ] = tokens[2];
else
if( size == 2 && tokens[1] == "=" )
(*this)[ tokens[0] ] = true;
else
if( size == 1 && tokens[0] != argv[0] )
(*this)[ tokens[0] ] = true;
}
// recreate args
while( argc-- ) {
(*this)[ std::to_string(argc) ] = std::string( argv[argc] );
}
}
getopt( const std::vector<std::string> &args ) : super() {
std::vector<const char *> argv;
for( auto &it : args ) {
argv.push_back( it.c_str() );
}
*this = getopt( argv.size(), argv.data() );
}
size_t size() const {
unsigned i = 0;
while( has(std::to_string(i)) ) ++i;
return i;
}
bool has( const std::string &op ) const {
return this->find(op) != this->end();
}
std::string str() const {
std::stringstream ss;
std::string sep;
for( auto &it : *this ) {
ss << sep << it.first << "=" << it.second;
sep = ',';
}
return ss.str();
}
std::string cmdline() const {
std::stringstream cmd;
std::string sep;
// concatenate args
for( auto end = size(), arg = end - end; arg < end; ++arg ) {
cmd << sep << this->find(std::to_string(arg))->second;
sep = ' ';
}
return cmd.str();
}
};
// variadic syntax sugars {
template< typename T >
inline T getarg( const T &defaults, const char *argv ) {
static struct getopt map( getopt_utils::cmdline() );
return map.has( argv ) ? getopt_utils::as<T>(map[ argv ]) : defaults;
}
template< typename T, typename... Args >
inline T getarg( const T &defaults, const char *arg0, Args... argv ) {
T t = getarg<T>( defaults, arg0 );
return t == defaults ? getarg<T>( defaults, argv... ) : t;
}
inline const char * getarg( const char *defaults, const char *argv ) {
static struct getopt map( getopt_utils::cmdline() );
return map.has( argv ) ? getopt_utils::as<const char *>(map[ argv ]) : defaults;
}
template< typename... Args >
inline const char * getarg( const char *defaults, const char *arg0, Args... argv ) {
const char *t = getarg( defaults, arg0 );
return t == defaults ? getarg( defaults, argv... ) : t;
}
// }
#ifdef GETOPT_BUILD_DEMO
#include <iostream>
#include <stdlib.h>
int main( int argc, const char **argv ) {
auto show_help = [&]() {
std::cout << argv[0] << " [-h|--help|-?] [-f=path|--file=path] [-v|--version] [-d=number|--depth=number|--max-depth=number]" << std::endl;
exit(0);
};
// Simple functional api. No initialization required.
bool help = getarg( false, "-h", "--help", "-?" );
int version = getarg( 0, "-v", "--version", "--show-version" );
int depth = getarg( 0, "-d", "--depth", "--max-depth");
std::string file = getarg( "", "-f", "--file" );
if( help || argc <= 1 ) {
show_help();
}
if( version ) {
std::cout << argv[0] << " demo v1.0.0. Compiled on " << __DATE__ << std::endl;
}
if( depth ) {
std::cout << "provided depth: " << depth << std::endl;
}
if( !file.empty() ) {
std::cout << "provided file: " << file << std::endl;
}
// OOP map-based api. Explicit (argc, argv) initialization required.
struct getopt args( argc, argv );
if( args.has("-h") || args.has("--help") || args.has("-?") || args.size() == 1 ) {
show_help();
}
if( args.has("-v") || args.has("--version") ) {
std::cout << args["0"] << " demo v1.0.0. Compiled on " << __DATE__ << std::endl;
}
if( args.has("-d") || args.has("--depth") || args.has("--max-depth") ) {
std::string arg = args["-d"];
if( arg.empty() ) arg = args["--depth"];
if( arg.empty() ) arg = args["--max-depth"];
int depth = atoi( arg.c_str() );
std::cout << "provided depth: " << depth << std::endl;
}
if( args.has("-f") || args.has("--file") ) {
std::string arg = args["-f"];
if( arg.empty() ) arg = args["--file"];
std::string fname = arg;
std::cout << "provided file: " << fname << std::endl;
}
std::cout << "---" << std::endl;
std::cout << args.cmdline() << std::endl;
//std::cout << args.size() << " provided args: " << args.str() << std::endl;
}
#endif