博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个不错的命令行参数解析类
阅读量:5799 次
发布时间:2019-06-18

本文共 12766 字,大约阅读时间需要 42 分钟。

  hot3.png

下载路径:https://github.com/tanakh/cmdline

测试代码:

#include "cmdline.h"#include 
using namespace std;int main(int argc, char *argv[]){ cmdline::parser a; a.add
("host", 'h', "host name", true, ""); a.add
("port", 'p', "port number", false, 80, cmdline::range(1, 65535)); a.add
("type", 't', "protocol type", false, "http", cmdline::oneof
("http", "https", "ssh", "ftp")); a.add("gzip", '\0', "gzip when transfer"); a.parse_check(argc, argv); cout << a.get
("type") << "://" << a.get
("host") << ":" << a.get
("port") << endl; if (a.exist("gzip")) cout << "gzip" << endl; return 0;}

编译输出:

xxx@(none):cmdline-master> ./test usage: ./test --host=string [options] ... options:  -h, --host    host name (string)  -p, --port    port number (int [=80])  -t, --type    protocol type (string [=http])      --gzip    gzip when transfer  -?, --help    print this messagexxx@(none):cmdline-master> ./test -h 127.0.0.1http://127.0.0.1:80

 

cmdline.h 头文件

/*  Copyright (c) 2009, Hideyuki Tanaka  All rights reserved.  Redistribution and use in source and binary forms, with or without  modification, are permitted provided that the following conditions are met:  * Redistributions of source code must retain the above copyright  notice, this list of conditions and the following disclaimer.  * Redistributions in binary form must reproduce the above copyright  notice, this list of conditions and the following disclaimer in the  documentation and/or other materials provided with the distribution.  * Neither the name of the 
nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY
''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/#pragma once#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace cmdline{namespace detail{template
class lexical_cast_t{public: static Target cast(const Source &arg){ Target ret; std::stringstream ss; if (!(ss<
>ret && ss.eof())) throw std::bad_cast(); return ret; }};template
class lexical_cast_t
{public: static Target cast(const Source &arg){ return arg; } };template
class lexical_cast_t
{public: static std::string cast(const Source &arg){ std::ostringstream ss; ss<
class lexical_cast_t
{public: static Target cast(const std::string &arg){ Target ret; std::istringstream ss(arg); if (!(ss>>ret && ss.eof())) throw std::bad_cast(); return ret; }};template
struct is_same { static const bool value = false;};template
struct is_same
{ static const bool value = true;};template
Target lexical_cast(const Source &arg){ return lexical_cast_t
::value>::cast(arg);}static inline std::string demangle(const std::string &name){ int status=0; char *p=abi::__cxa_demangle(name.c_str(), 0, 0, &status); std::string ret(p); free(p); return ret;}template
std::string readable_typename(){ return demangle(typeid(T).name());}template
std::string default_value(T def){ return detail::lexical_cast
(def);}template <>inline std::string readable_typename
(){ return "string";}} // detail//-----class cmdline_error : public std::exception {public: cmdline_error(const std::string &msg): msg(msg){} ~cmdline_error() throw() {} const char *what() const throw() { return msg.c_str(); }private: std::string msg;};template
struct default_reader{ T operator()(const std::string &str){ return detail::lexical_cast
(str); }};template
struct range_reader{ range_reader(const T &low, const T &high): low(low), high(high) {} T operator()(const std::string &s) const { T ret=default_reader
()(s); if (!(ret>=low && ret<=high)) throw cmdline::cmdline_error("range_error"); return ret; }private: T low, high;};template
range_reader
range(const T &low, const T &high){ return range_reader
(low, high);}template
struct oneof_reader{ T operator()(const std::string &s){ T ret=default_reader
()(s); if (std::find(alt.begin(), alt.end(), ret)==alt.end()) throw cmdline_error(""); return ret; } void add(const T &v){ alt.push_back(v); }private: std::vector
alt;};template
oneof_reader
oneof(T a1){ oneof_reader
ret; ret.add(a1); return ret;}template
oneof_reader
oneof(T a1, T a2){ oneof_reader
ret; ret.add(a1); ret.add(a2); return ret;}template
oneof_reader
oneof(T a1, T a2, T a3){ oneof_reader
ret; ret.add(a1); ret.add(a2); ret.add(a3); return ret;}template
oneof_reader
oneof(T a1, T a2, T a3, T a4){ oneof_reader
ret; ret.add(a1); ret.add(a2); ret.add(a3); ret.add(a4); return ret;}template
oneof_reader
oneof(T a1, T a2, T a3, T a4, T a5){ oneof_reader
ret; ret.add(a1); ret.add(a2); ret.add(a3); ret.add(a4); ret.add(a5); return ret;}template
oneof_reader
oneof(T a1, T a2, T a3, T a4, T a5, T a6){ oneof_reader
ret; ret.add(a1); ret.add(a2); ret.add(a3); ret.add(a4); ret.add(a5); ret.add(a6); return ret;}template
oneof_reader
oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7){ oneof_reader
ret; ret.add(a1); ret.add(a2); ret.add(a3); ret.add(a4); ret.add(a5); ret.add(a6); ret.add(a7); return ret;}template
oneof_reader
oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8){ oneof_reader
ret; ret.add(a1); ret.add(a2); ret.add(a3); ret.add(a4); ret.add(a5); ret.add(a6); ret.add(a7); ret.add(a8); return ret;}template
oneof_reader
oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9){ oneof_reader
ret; ret.add(a1); ret.add(a2); ret.add(a3); ret.add(a4); ret.add(a5); ret.add(a6); ret.add(a7); ret.add(a8); ret.add(a9); return ret;}template
oneof_reader
oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10){ oneof_reader
ret; ret.add(a1); ret.add(a2); ret.add(a3); ret.add(a4); ret.add(a5); ret.add(a6); ret.add(a7); ret.add(a8); ret.add(a9); ret.add(a10); return ret;}//-----class parser{public: parser(){ } ~parser(){ for (std::map
::iterator p=options.begin(); p!=options.end(); p++) delete p->second; } void add(const std::string &name, char short_name=0, const std::string &desc=""){ if (options.count(name)) throw cmdline_error("multiple definition: "+name); options[name]=new option_without_value(name, short_name, desc); ordered.push_back(options[name]); } template
void add(const std::string &name, char short_name=0, const std::string &desc="", bool need=true, const T def=T()){ add(name, short_name, desc, need, def, default_reader
()); } template
void add(const std::string &name, char short_name=0, const std::string &desc="", bool need=true, const T def=T(), F reader=F()){ if (options.count(name)) throw cmdline_error("multiple definition: "+name); options[name]=new option_with_value_with_reader
(name, short_name, need, def, desc, reader); ordered.push_back(options[name]); } void footer(const std::string &f){ ftr=f; } void set_program_name(const std::string &name){ prog_name=name; } bool exist(const std::string &name) const { if (options.count(name)==0) throw cmdline_error("there is no flag: --"+name); return options.find(name)->second->has_set(); } template
const T &get(const std::string &name) const { if (options.count(name)==0) throw cmdline_error("there is no flag: --"+name); const option_with_value
*p=dynamic_cast
*>(options.find(name)->second); if (p==NULL) throw cmdline_error("type mismatch flag '"+name+"'"); return p->get(); } const std::vector
&rest() const { return others; } bool parse(const std::string &arg){ std::vector
args; std::string buf; bool in_quote=false; for (std::string::size_type i=0; i
=arg.length()){ errors.push_back("unexpected occurrence of '\\' at end of string"); return false; } } buf+=arg[i]; } if (in_quote){ errors.push_back("quote is not closed"); return false; } if (buf.length()>0) args.push_back(buf); for (size_t i=0; i
&args){ int argc=static_cast
(args.size()); std::vector
argv(argc); for (int i=0; i
lookup; for (std::map
::iterator p=options.begin(); p!=options.end(); p++){ if (p->first.length()==0) continue; char initial=p->second->short_name(); if (initial){ if (lookup.count(initial)>0){ lookup[initial]=""; errors.push_back(std::string("short option '")+initial+"' is ambiguous"); return false; } else lookup[initial]=p->first; } } for (int i=1; i
&args){ if (!options.count("help")) add("help", '?', "print this message"); check(args.size(), parse(args)); } void parse_check(int argc, char *argv[]){ if (!options.count("help")) add("help", '?', "print this message"); check(argc, parse(argc, argv)); } std::string error() const{ return errors.size()>0?errors[0]:""; } std::string error_full() const{ std::ostringstream oss; for (size_t i=0; i
must()) oss<
short_description()<<" "; } oss<<"[options] ... "<
<
name().length()); } for (size_t i=0; i
short_name()){ oss<<" -"<
short_name()<<", "; } else{ oss<<" "; } oss<<"--"<
name(); for (size_t j=ordered[i]->name().length(); j
description()<
set()){ errors.push_back("option needs value: --"+name); return; } } void set_option(const std::string &name, const std::string &value){ if (options.count(name)==0){ errors.push_back("undefined option: --"+name); return; } if (!options[name]->set(value)){ errors.push_back("option value is invalid: --"+name+"="+value); return; } } class option_base{ public: virtual ~option_base(){} virtual bool has_value() const=0; virtual bool set()=0; virtual bool set(const std::string &value)=0; virtual bool has_set() const=0; virtual bool valid() const=0; virtual bool must() const=0; virtual const std::string &name() const=0; virtual char short_name() const=0; virtual const std::string &description() const=0; virtual std::string short_description() const=0; }; class option_without_value : public option_base { public: option_without_value(const std::string &name, char short_name, const std::string &desc) :nam(name), snam(short_name), desc(desc), has(false){ } ~option_without_value(){} bool has_value() const { return false; } bool set(){ has=true; return true; } bool set(const std::string &){ return false; } bool has_set() const { return has; } bool valid() const{ return true; } bool must() const{ return false; } const std::string &name() const{ return nam; } char short_name() const{ return snam; } const std::string &description() const { return desc; } std::string short_description() const{ return "--"+nam; } private: std::string nam; char snam; std::string desc; bool has; }; template
class option_with_value : public option_base { public: option_with_value(const std::string &name, char short_name, bool need, const T &def, const std::string &desc) : nam(name), snam(short_name), need(need), has(false) , def(def), actual(def) { this->desc=full_description(desc); } ~option_with_value(){} const T &get() const { return actual; } bool has_value() const { return true; } bool set(){ return false; } bool set(const std::string &value){ try{ actual=read(value); has=true; } catch(const std::exception &e){ return false; } return true; } bool has_set() const{ return has; } bool valid() const{ if (need && !has) return false; return true; } bool must() const{ return need; } const std::string &name() const{ return nam; } char short_name() const{ return snam; } const std::string &description() const { return desc; } std::string short_description() const{ return "--"+nam+"="+detail::readable_typename
(); } protected: std::string full_description(const std::string &desc){ return desc+" ("+detail::readable_typename
()+ (need?"":" [="+detail::default_value
(def)+"]") +")"; } virtual T read(const std::string &s)=0; std::string nam; char snam; bool need; std::string desc; bool has; T def; T actual; }; template
class option_with_value_with_reader : public option_with_value
{ public: option_with_value_with_reader(const std::string &name, char short_name, bool need, const T def, const std::string &desc, F reader) : option_with_value
(name, short_name, need, def, desc), reader(reader){ } private: T read(const std::string &s){ return reader(s); } F reader; }; std::map
options; std::vector
ordered; std::string ftr; std::string prog_name; std::vector
others; std::vector
errors;};} // cmdline

 

转载于:https://my.oschina.net/tsh/blog/1549485

你可能感兴趣的文章
iOS开发,UIWebview与H5之间的交互
查看>>
poll 示例
查看>>
给scrapy设置HTTP代理
查看>>
Elastix的TCP/UDP端口映射
查看>>
Linux时间变慢解决方法
查看>>
如何利用python使用libsvm
查看>>
python:numpy(文件存取)
查看>>
MySQL 参数浅析之 innodb_file_per_table
查看>>
RHEL6启动原理和故障排除
查看>>
iOS 绝对路径和相对路径
查看>>
jquery插件页面滚动元素进入视口触发动画jquery-aniview
查看>>
(译)MySQL:在 WHERE 条件语句中使用 IF 语句
查看>>
C++程序windows To linux移植经验案例
查看>>
论文翻译-语音合成:WaveNet
查看>>
使用Python读Excel数据Insert到MySQL
查看>>
heartbeat搭建高可用NFS
查看>>
Nginx工作原理和优化、漏洞。
查看>>
Spring Boot之使用JPA操作mysql
查看>>
Spring <context:annotation-config/>解析
查看>>
独立博客的几点建议:必须找准定位,不要太SEO
查看>>