Ignore:
Timestamp:
13 Aug 2015, 17:38:13 (9 years ago)
Author:
tech
Message:

Merged 14.1-update-dev1@1312.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/Lib/TAppCommon/program_options_lite.cpp

    r1179 r1313  
    22 * License, included below. This software may be subject to other third party
    33 * and contributor rights, including patent rights, and no such rights are
    4  * granted under this license. 
     4 * granted under this license.
    55 *
    6 * Copyright (c) 2010-2015, ITU/ISO/IEC
     6 * Copyright (c) 2010-2015, ITU/ISO/IEC
    77 * All rights reserved.
    88 *
     
    4040#include <algorithm>
    4141#include "program_options_lite.h"
    42 #include  "../TLibCommon/TypeDef.h"
     42#include  "../TLibCommon/CommonDef.h"
    4343using namespace std;
    4444
     
    5050  namespace program_options_lite
    5151  {
    52    
     52    ErrorReporter default_error_reporter;
     53
     54    ostream& ErrorReporter::error(const string& where)
     55    {
     56      is_errored = 1;
     57      cerr << where << " error: ";
     58      return cerr;
     59    }
     60
     61    ostream& ErrorReporter::warn(const string& where)
     62    {
     63      cerr << where << " warning: ";
     64      return cerr;
     65    }
     66
    5367    Options::~Options()
    5468    {
     
    5872      }
    5973    }
    60    
     74
    6175    void Options::addOption(OptionBase *opt)
    6276    {
     
    6478      names->opt = opt;
    6579      string& opt_string = opt->opt_string;
    66      
     80
    6781      size_t opt_start = 0;
    6882      for (size_t opt_end = 0; opt_end != string::npos;)
     
    96110      return OptionSpecific(*this);
    97111    }
    98    
    99     static void setOptions(Options::NamesPtrList& opt_list, const string& value)
     112
     113    static void setOptions(Options::NamesPtrList& opt_list, const string& value, ErrorReporter& error_reporter)
    100114    {
    101115      /* multiple options may be registered for the same name:
     
    103117      for (Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); ++it)
    104118      {
    105         (*it)->opt->parse(value);
     119        (*it)->opt->parse(value, error_reporter);
    106120      }
    107121    }
    108122
    109123    static const char spaces[41] = "                                        ";
    110    
     124
    111125    /* format help text for a single option:
    112126     * using the formatting: "-x, --long",
     
    138152      }
    139153    }
    140    
     154
    141155    /* format the help text */
    142156    void doHelp(ostream& out, Options& opts, unsigned columns)
     
    147161      for(Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++)
    148162      {
    149 #if H_MV
     163#if NH_MV
    150164        if  ( (*it)->opt->opt_duplicate ) continue;
    151165#endif
     
    157171      unsigned opt_width = min(max_width+2, 28u + pad_short) + 2;
    158172      unsigned desc_width = columns - opt_width;
    159      
     173
    160174      /* second pass: write out formatted option and help text.
    161175       *  - align start of help text to start at opt_width
     
    165179      for(Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++)
    166180      {
    167 #if H_MV
     181#if NH_MV
    168182        if  ( (*it)->opt->opt_duplicate ) continue;
    169183#endif
     
    215229            split_pos = opt_desc.find_last_not_of(' ', split_pos) + 1;
    216230          }
    217          
     231
    218232          /* bad split if no suitable space to split at.  fall back to width */
    219233          bool bad_split = split_pos == string::npos || split_pos <= cur_pos;
     
    223237          }
    224238          line << opt_desc.substr(cur_pos, split_pos - cur_pos);
    225          
     239
    226240          /* eat up any space for the start of the next line */
    227241          if (!bad_split)
     
    230244          }
    231245          cur_pos = newline_pos = split_pos;
    232          
     246
    233247          if (cur_pos >= opt_desc.size())
    234248          {
     
    241255      }
    242256    }
    243    
    244     bool storePair(Options& opts, bool allow_long, bool allow_short, const string& name, const string& value)
     257
     258    struct OptionWriter
     259    {
     260      OptionWriter(Options& rOpts, ErrorReporter& err)
     261      : opts(rOpts), error_reporter(err)
     262      {}
     263      virtual ~OptionWriter() {}
     264
     265      virtual const string where() = 0;
     266
     267      bool storePair(bool allow_long, bool allow_short, const string& name, const string& value);
     268      bool storePair(const string& name, const string& value)
     269      {
     270        return storePair(true, true, name, value);
     271      }
     272
     273      Options& opts;
     274      ErrorReporter& error_reporter;
     275    };
     276
     277    bool OptionWriter::storePair(bool allow_long, bool allow_short, const string& name, const string& value)
    245278    {
    246279      bool found = false;
     
    254287        }
    255288      }
    256      
     289
    257290      /* check for the short list */
    258291      if (allow_short && !(found && allow_long))
     
    267300      if (!found)
    268301      {
    269         /* not found */
    270         cerr << "Unknown option: `" << name << "' (value:`" << value << "')" << endl;
     302        error_reporter.error(where())
     303          << "Unknown option `" << name << "' (value:`" << value << "')\n";
    271304        return false;
    272305      }
    273306
    274       setOptions((*opt_it).second, value);
     307      setOptions((*opt_it).second, value, error_reporter);
    275308      return true;
    276309    }
    277    
    278     bool storePair(Options& opts, const string& name, const string& value)
    279     {
    280       return storePair(opts, true, true, name, value);
    281     }
    282    
     310
     311    struct ArgvParser : public OptionWriter
     312    {
     313      ArgvParser(Options& rOpts, ErrorReporter& rError_reporter)
     314      : OptionWriter(rOpts, rError_reporter)
     315      {}
     316
     317      const string where() { return "command line"; }
     318
     319      unsigned parseGNU(unsigned argc, const char* argv[]);
     320      unsigned parseSHORT(unsigned argc, const char* argv[]);
     321    };
     322
    283323    /**
    284324     * returns number of extra arguments consumed
    285325     */
    286     unsigned parseGNU(Options& opts, unsigned argc, const char* argv[])
     326    unsigned ArgvParser::parseGNU(unsigned argc, const char* argv[])
    287327    {
    288328      /* gnu style long options can take the forms:
     
    294334      size_t arg_opt_sep = arg.find_first_of('=');
    295335      string option = arg.substr(arg_opt_start, arg_opt_sep - arg_opt_start);
    296      
     336
    297337      unsigned extra_argc_consumed = 0;
    298338      if (arg_opt_sep == string::npos)
     
    305345        * booleans */
    306346        if (argc == 1)
     347        {
    307348          return 0; /* run out of argv for argument */
     349        }
    308350        extra_argc_consumed = 1;
    309351#endif
    310         if(!storePair(opts, true, false, option, "1"))
     352        if(!storePair(true, false, option, "1"))
    311353        {
    312354          return 0;
     
    317359        /* argument occurs after option_sep */
    318360        string val = arg.substr(arg_opt_sep + 1);
    319         storePair(opts, true, false, option, val);
     361        storePair(true, false, option, val);
    320362      }
    321363
     
    323365    }
    324366
    325     unsigned parseSHORT(Options& opts, unsigned argc, const char* argv[])
     367    unsigned ArgvParser::parseSHORT(unsigned argc, const char* argv[])
    326368    {
    327369      /* short options can take the forms:
     
    338380      if (argc == 1)
    339381      {
    340         cerr << "Not processing option without argument `" << option << "'" << endl;
     382        error_reporter.error(where())
     383          << "Not processing option `" << option << "' without argument\n";
    341384        return 0; /* run out of argv for argument */
    342385      }
    343       storePair(opts, false, true, option, string(argv[1]));
     386      storePair(false, true, option, string(argv[1]));
    344387
    345388      return 1;
    346389    }
    347    
     390
    348391    list<const char*>
    349     scanArgv(Options& opts, unsigned argc, const char* argv[])
    350     {
     392    scanArgv(Options& opts, unsigned argc, const char* argv[], ErrorReporter& error_reporter)
     393    {
     394      ArgvParser avp(opts, error_reporter);
     395
    351396      /* a list for anything that didn't get handled as an option */
    352397      list<const char*> non_option_arguments;
     
    370415        {
    371416          /* handle short (single dash) options */
    372 #if 0
    373           i += parsePOSIX(opts, argc - i, &argv[i]);
    374 #else
    375           i += parseSHORT(opts, argc - i, &argv[i]);
    376 #endif
     417          i += avp.parseSHORT(argc - i, &argv[i]);
    377418          continue;
    378419        }
     
    382423          /* a lone double dash ends option processing */
    383424          while (++i < argc)
     425          {
    384426            non_option_arguments.push_back(argv[i]);
     427          }
    385428          break;
    386429        }
    387430
    388431        /* handle long (double dash) options */
    389         i += parseGNU(opts, argc - i, &argv[i]);
     432        i += avp.parseGNU(argc - i, &argv[i]);
    390433      }
    391434
    392435      return non_option_arguments;
    393436    }
    394    
    395     void scanLine(Options& opts, string& line)
     437
     438    struct CfgStreamParser : public OptionWriter
     439    {
     440      CfgStreamParser(const string& rName, Options& rOpts, ErrorReporter& rError_reporter)
     441      : OptionWriter(rOpts, rError_reporter)
     442      , name(rName)
     443      , linenum(0)
     444      {}
     445
     446      const string name;
     447      int linenum;
     448      const string where()
     449      {
     450        ostringstream os;
     451        os << name << ":" << linenum;
     452        return os.str();
     453      }
     454
     455      void scanLine(string& line);
     456      void scanStream(istream& in);
     457    };
     458
     459    void CfgStreamParser::scanLine(string& line)
    396460    {
    397461      /* strip any leading whitespace */
     
    416480      {
    417481        /* error: badly formatted line */
     482        error_reporter.warn(where()) << "line formatting error\n";
    418483        return;
    419484      }
     
    421486      {
    422487        /* error: badly formatted line */
     488        error_reporter.warn(where()) << "line formatting error\n";
    423489        return;
    424490      }
     
    429495      {
    430496        /* error: badly formatted line */
     497#if !NH_MV
     498        error_reporter.warn(where()) << "line formatting error\n";
     499#else
     500        // HTM also allows empty parameters.
     501#endif
    431502        return;
    432503      }
     
    447518         * any trailing whitespace will be removed shortly */
    448519        value_end = line.find_first_not_of(" \t\n\r", value_end);
    449       }
    450       while (value_end != string::npos);
     520      } while (value_end != string::npos);
    451521      /* strip any trailing space from value*/
    452522      value_end = line.find_last_not_of(" \t\n\r", value_end);
     
    460530      {
    461531        /* error: no value */
     532#if !NH_MV
     533        error_reporter.warn(where()) << "no value found\n";
     534#else
     535        // This is ok for HTM.
     536#endif
    462537        return;
    463538      }
    464539
    465540      /* store the value in option */
    466       storePair(opts, true, false, option, value);
    467     }
    468 
    469     void scanFile(Options& opts, istream& in)
     541      storePair(true, false, option, value);
     542    }
     543
     544    void CfgStreamParser::scanStream(istream& in)
    470545    {
    471546      do
    472547      {
     548        linenum++;
    473549        string line;
    474550        getline(in, line);
    475         scanLine(opts, line);
    476       }
    477       while(!!in);
     551        scanLine(line);
     552      } while(!!in);
    478553    }
    479554
     
    488563    }
    489564
    490     void parseConfigFile(Options& opts, const string& filename)
     565    void parseConfigFile(Options& opts, const string& filename, ErrorReporter& error_reporter)
    491566    {
    492567      ifstream cfgstream(filename.c_str(), ifstream::in);
    493568      if (!cfgstream)
    494569      {
    495         cerr << "Failed to open config file: `" << filename << "'" << endl;
    496         exit(EXIT_FAILURE);
    497       }
    498       scanFile(opts, cfgstream);
    499     }
    500 
    501   };
    502 };
     570        error_reporter.error(filename) << "Failed to open config file\n";
     571        return;
     572      }
     573      CfgStreamParser csp(filename, opts, error_reporter);
     574      csp.scanStream(cfgstream);
     575    }
     576
     577  }
     578}
    503579
    504580//! \}
Note: See TracChangeset for help on using the changeset viewer.