Advertisement
Guest User

Untitled

a guest
Dec 20th, 2014
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.73 KB | None | 0 0
  1. #ifndef __CLIFW_ARGUMENTS_H__
  2. #define __CLIFW_ARGUMENTS_H__
  3.  
  4. #include <string>
  5. #include <list>
  6. #include <regex>
  7.  
  8. namespace clifw {
  9.     template <typename UserApp>
  10.         struct app;
  11.  
  12.     template <typename UserApp>
  13.         struct arguments {
  14.             typedef typename app<UserApp>::argument_type argument_type;
  15.             typedef typename app<UserApp>::option_type option_type;
  16.             typedef app<UserApp> app_type;
  17.  
  18.             arguments (app<UserApp> &app, int const argc,
  19.                 char const * const * const argv,
  20.                 char const * const * const envp);
  21.  
  22.             argument_type const & operator [] (std::string const &key) const;
  23.             argument_type & operator [] (std::string const &key) ;
  24.    
  25.         private:
  26.            
  27.  
  28.             app<UserApp> &_app;
  29.             std::map<std::string, argument_type> _option_list;
  30.         };
  31.  
  32.     template <typename UserApp>
  33.         arguments<UserApp>::arguments (
  34.             app<UserApp> &app, int const argc,
  35.             char const * const * const argv,
  36.             char const * const * const envp) :
  37.             _app (app)
  38.         {
  39.             static const std::string _help_option = "help";
  40.             static const std::string _help_alias = "?";
  41.  
  42.  
  43.             struct helper {
  44.                 static bool match_option (std::string const &_haystack, std::string &_name, std::string &_value, bool &_is_alias, bool &_has_value) {
  45.                     logger &l = logger::clog ();
  46.  
  47.                     static const std::regex _long_option_needle ("^--([a-zA-Z0-9][a-zA-Z0-9_\\-]*)([:=](.+))?$");          
  48.                     static const std::regex _short_option_needle ("^-([\\?a-zA-Z0-9]+)$");         
  49.  
  50.                     bool _is_option;
  51.                     std::smatch _needles_found;
  52.  
  53.                     _is_alias = std::regex_match ( _haystack, _needles_found, _short_option_needle);
  54.                     _is_option = _is_alias || std::regex_match (_haystack, _needles_found, _long_option_needle);
  55.                     _has_value = _needles_found [2].str () != "" ;     
  56.  
  57. //                  l.info ("Checking '%s' is_option:%d, is_alias:%d, has_value:%d\n", _haystack.c_str (), _is_option, _is_alias, _has_value);
  58.  
  59.                     _name = _needles_found [1].str ();
  60.                     _value = _has_value ? _needles_found [3].str () : _haystack;
  61.                    
  62.                     return _is_option;
  63.                 }
  64.            
  65.             };
  66.  
  67.             if (argc < 2) {            
  68.                 _app.option (_help_option).value ("", true);
  69.                 return;    
  70.             }
  71.            
  72.             bool _is_alias = false;
  73.             bool _has_value = false;
  74.  
  75.             int _takes_value = 0;
  76.             int _needs_value = 0;
  77.  
  78.             std::string _name, _value;
  79.  
  80.             std::string _was_name;
  81.             bool _was_alias = false;
  82.             int index = 0 ;
  83.             int check = 0 ;
  84.  
  85.             for (int i = 1; i < argc; ++i) {
  86.                 if (helper::match_option (argv [i], _name, _value, _is_alias, _has_value)) {                   
  87.                     if (_needs_value > 0) {
  88.                         throw value_expected_exception (::clifw::helper::sprintf_format_string (
  89.                             "Option '%s' expected value.", _was_name.c_str ()));
  90.                     }
  91.                    
  92.                     auto &_option = _app.option (_name, _is_alias);
  93.                     _takes_value = _option.takes_value () ;
  94.                     _needs_value = _option.needs_value () ;
  95.  
  96.                     if (!_takes_value) {
  97.                         _option.value ("", true);
  98.                         continue;
  99.                     }
  100.  
  101.                     if (_has_value) {
  102.                         if (!_takes_value) {
  103.                             throw value_unexpected_exception (::clifw::helper::sprintf_format_string (
  104.                                 "Option '%s' doesn't take a value", _name.c_str ()));
  105.                         }
  106.  
  107.                         _option.value (_value, true);
  108.                         if (_name == _help_option || (_name == _help_alias && _is_alias))
  109.                             return ;
  110.                         _takes_value = _takes_value > 0 ? _takes_value - 1 : 0;
  111.                         _needs_value = _needs_value > 0 ? _needs_value - 1 : 0;                
  112.                     }
  113.  
  114.                     _was_name = _name;
  115.                     _was_alias = _is_alias;
  116.                     continue;                  
  117.                 }
  118.                 else {
  119.                     ++check;
  120.  
  121.                     if (_takes_value) {
  122.                         auto &_option = _app.option (_was_name, _was_alias);
  123.                         _option.value (_value, true);
  124.                         if (_was_name == "help" || (_was_name == "?" && _was_alias))
  125.                             return ;
  126.                         _takes_value = _takes_value > 0 ? _takes_value - 1 : 0;
  127.                         _needs_value = _needs_value > 0 ? _needs_value - 1 : 0;                
  128.                         continue;
  129.                     }
  130.  
  131.                     _app.argument (index++).value (_value, true);
  132.                     continue;
  133.                 }
  134.             }
  135.  
  136.             if (_takes_value) {            
  137.                 auto &_option = _app.option (_was_name, _was_alias);
  138.                 if (_needs_value) {
  139.                     throw value_expected_exception (::clifw::helper::sprintf_format_string (
  140.                         "Option '%s' expected value.", _was_name.c_str ()));
  141.                 }
  142.  
  143.                 _option.value ("", true);
  144.                 if (_was_name == _help_option || (_was_name == _help_alias && _was_alias))
  145.                     return;
  146.             }
  147.  
  148.             if (check)
  149.                 _app.check_arguments (true);
  150.            
  151.         }
  152.            
  153.  
  154.         template <typename UserApp>
  155.             typename arguments<UserApp>::argument_type & arguments<UserApp>::operator [] (std::string const &key) {
  156.                 return _app.option (key).value ();
  157.             }
  158.  
  159.         template <typename UserApp>
  160.             typename arguments<UserApp>::argument_type const & arguments<UserApp>::operator [] (std::string const &key) const {
  161.                 return _app.option (key).value ();
  162.             }
  163.        
  164. }
  165.  
  166.  
  167. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement