source: 3DVCSoftware/branches/HTM-15.1-dev0/source/Lib/TAppCommon/program_options_lite.h @ 1328

Last change on this file since 1328 was 1328, checked in by tech, 9 years ago

Integrated general SEI changes and following SEIs:

  • Multiview view position SEI
  • Multiview acquisition information SEI
  • Multiview scene information SEI
  • Inter-layer constrained tile sets SEI
File size: 20.3 KB
Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license.
5 *
6 * Copyright (c) 2010-2015, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33#include <iostream>
34#include <sstream>
35#include <string>
36#include <list>
37#include <map>
38#include  "../TLibCommon/CommonDef.h"
39
40#if NH_MV
41#include <vector>
42#include <errno.h>
43#include <cstring>
44
45#ifdef WIN32
46#define strdup _strdup
47#endif
48#endif
49
50
51#ifndef __PROGRAM_OPTIONS_LITE__
52#define __PROGRAM_OPTIONS_LITE__
53
54//! \ingroup TAppCommon
55//! \{
56
57
58namespace df
59{
60  namespace program_options_lite
61  {
62    struct Options;
63
64    struct ParseFailure : public std::exception
65    {
66      ParseFailure(std::string arg0, std::string val0) throw()
67      : arg(arg0), val(val0)
68      {}
69
70      ~ParseFailure() throw() {};
71
72      std::string arg;
73      std::string val;
74
75      const char* what() const throw() { return "Option Parse Failure"; }
76    };
77
78    struct ErrorReporter
79    {
80#if NH_MV_SEI
81      ErrorReporter() : is_errored(0), output_on_unknow_parameter(true)  {}
82#else
83      ErrorReporter() : is_errored(0) {}
84#endif
85      virtual ~ErrorReporter() {}
86      virtual std::ostream& error(const std::string& where);
87      virtual std::ostream& warn(const std::string& where);
88      bool is_errored;
89#if NH_MV_SEI
90      bool output_on_unknow_parameter;
91#endif
92    };
93
94    extern ErrorReporter default_error_reporter;
95
96    void doHelp(std::ostream& out, Options& opts, unsigned columns = 80);
97    std::list<const char*> scanArgv(Options& opts, unsigned argc, const char* argv[], ErrorReporter& error_reporter = default_error_reporter);
98    void setDefaults(Options& opts);
99    void parseConfigFile(Options& opts, const std::string& filename, ErrorReporter& error_reporter = default_error_reporter);
100
101    /** OptionBase: Virtual base class for storing information relating to a
102     * specific option This base class describes common elements.  Type specific
103     * information should be stored in a derived class. */
104    struct OptionBase
105    {
106#if NH_MV     
107#if NH_MV_SEI     
108      OptionBase(const std::string& name, const std::string& desc, bool duplicate = false, std::vector< int > maxdim = std::vector< int >(0) )
109        : opt_string(name), opt_desc(desc), opt_duplicate(duplicate), max_dim( maxdim )
110#else
111      OptionBase(const std::string& name, const std::string& desc, bool duplicate = false)
112        : opt_string(name), opt_desc(desc), opt_duplicate(duplicate)
113#endif
114#else
115      OptionBase(const std::string& name, const std::string& desc)
116      : opt_string(name), opt_desc(desc)
117#endif
118      {};
119
120      virtual ~OptionBase() {}
121
122      /* parse argument arg, to obtain a value for the option */
123#if NH_MV_SEI
124      virtual void parse(const std::string& arg, const std::vector<int>& idcs,  ErrorReporter&) = 0;
125     
126      bool   checkDim( std::vector< int > dims, ErrorReporter& err )
127      {     
128        bool doParsing = true; 
129        if ( dims.size() != max_dim.size() )
130        {
131            err.error(" ") << "Number of indices of `" <<  opt_string << "' not matching. Should be " << max_dim.size() << std::endl; 
132            doParsing = false; 
133        }
134
135        for (size_t i = 0 ; i < dims.size(); i++ )
136        {
137          if ( dims[i] >= max_dim[i] )
138          {
139            if (err.output_on_unknow_parameter )
140            {       
141              err.warn(" ") << "Index " << i  << " of  " <<  opt_string << " should be less than " << max_dim[i] << std::endl;             
142              doParsing = false; 
143            }
144          }
145        }
146        return doParsing; 
147      }
148
149      void   xParseVec( const std::string& arg, BoolAry1d& storage )
150      {       
151        char* pcNextStart = (char*) arg.data();
152        char* pcEnd = pcNextStart + arg.length();
153
154        char* pcOldStart = 0; 
155
156        size_t iIdx = 0; 
157
158        while (pcNextStart < pcEnd)
159        {
160          if ( iIdx < storage.size() )
161          {
162            storage[iIdx] = (strtol(pcNextStart, &pcNextStart,10) != 0);
163          }
164          else
165          {
166            storage.push_back(strtol(pcNextStart, &pcNextStart,10) != 0) ;
167          }
168          iIdx++; 
169
170          if ( errno == ERANGE || (pcNextStart == pcOldStart) )
171          {
172            std::cerr << "Error Parsing Bools: `" << arg << "'" << std::endl;
173            exit(EXIT_FAILURE);
174          };   
175          while( (pcNextStart < pcEnd) && ( *pcNextStart == ' ' || *pcNextStart == '\t' || *pcNextStart == '\r' ) ) pcNextStart++; 
176          pcOldStart = pcNextStart;
177        }
178      }
179
180      void   xParseVec( const std::string& arg, IntAry1d& storage )
181      {       
182        storage.clear();
183
184        char* pcNextStart = (char*) arg.data();
185        char* pcEnd = pcNextStart + arg.length();
186
187        char* pcOldStart = 0; 
188
189        size_t iIdx = 0; 
190
191
192        while (pcNextStart < pcEnd)
193        {
194
195          if ( iIdx < storage.size() )
196          {
197            storage[iIdx] = (int) strtol(pcNextStart, &pcNextStart,10);
198          }
199          else
200          {
201            storage.push_back( (int) strtol(pcNextStart, &pcNextStart,10)) ;
202          }
203          iIdx++; 
204          if ( errno == ERANGE || (pcNextStart == pcOldStart) )
205          {
206            std::cerr << "Error Parsing Integers: `" << arg << "'" << std::endl;
207            exit(EXIT_FAILURE);
208          };   
209          while( (pcNextStart < pcEnd) && ( *pcNextStart == ' ' || *pcNextStart == '\t' || *pcNextStart == '\r' ) ) pcNextStart++; 
210          pcOldStart = pcNextStart;
211        }     
212      }
213#else
214      virtual void parse(const std::string& arg, ErrorReporter&) = 0;
215#endif
216      /* set the argument to the default value */
217      virtual void setDefault() = 0;
218
219      std::string opt_string;
220      std::string opt_desc;
221#if NH_MV
222      bool        opt_duplicate; 
223#if NH_MV_SEI
224      std::vector<int> max_dim;
225#endif
226#endif
227    };
228
229    /** Type specific option storage */
230    template<typename T>
231    struct Option : public OptionBase
232    {
233#if NH_MV
234#if NH_MV_SEI
235      Option(const std::string& name, T& storage, T default_val, const std::string& desc, bool duplicate = false, std::vector< int > maxdim = std::vector< int >(0) )
236        : OptionBase(name, desc, duplicate, maxdim), opt_storage(storage), opt_default_val(default_val)
237#else
238      Option(const std::string& name, T& storage, T default_val, const std::string& desc, bool duplicate = false)
239        : OptionBase(name, desc, duplicate), opt_storage(storage), opt_default_val(default_val)
240#endif
241#else
242      Option(const std::string& name, T& storage, T default_val, const std::string& desc)
243      : OptionBase(name, desc), opt_storage(storage), opt_default_val(default_val)
244#endif
245      {}
246
247#if NH_MV_SEI
248      void parse(const std::string& arg, const std::vector<int>& idcs, ErrorReporter&);
249#else
250      void parse(const std::string& arg, ErrorReporter&);
251#endif
252
253      void setDefault()
254      {
255        opt_storage = opt_default_val;
256      }
257
258      T& opt_storage;
259      T opt_default_val;
260    };
261
262    /* Generic parsing */
263    template<typename T>
264    inline void
265#if NH_MV_SEI
266    Option<T>::parse(const std::string& arg, const std::vector<int>& idcs, ErrorReporter&)
267#else
268    Option<T>::parse(const std::string& arg, ErrorReporter&)
269#endif
270    {
271#if NH_MV_SEI
272      assert( idcs.size() == 0 ); 
273#endif
274     
275      std::istringstream arg_ss (arg,std::istringstream::in);
276      arg_ss.exceptions(std::ios::failbit);
277      try
278      {
279        arg_ss >> opt_storage;
280      }
281      catch (...)
282      {
283        throw ParseFailure(opt_string, arg);
284      }
285    }
286
287    /* string parsing is specialized -- copy the whole string, not just the
288     * first word */
289    template<>
290    inline void
291#if NH_MV_SEI
292    Option<std::string>::parse(const std::string& arg, const std::vector<int>& idcs, ErrorReporter&)
293#else
294    Option<std::string>::parse(const std::string& arg, ErrorReporter&)
295#endif
296    {
297#if NH_MV_SEI
298      assert( idcs.size() == 0 ); 
299#endif
300      opt_storage = arg;
301    }
302
303#if NH_MV   
304    template<>
305    inline void
306#if NH_MV_SEI
307      Option<char*>::parse(const std::string& arg, const std::vector<int>& idcs, ErrorReporter&)
308#else
309      Option<char*>::parse(const std::string& arg, ErrorReporter&)
310#endif
311    {
312#if NH_MV_SEI
313      assert( idcs.size() == 0 ); 
314#endif
315      opt_storage = arg.empty() ? NULL : strdup(arg.c_str()) ;
316    }
317
318#if !NH_MV_SEI
319
320    template<>
321    inline void
322      Option< std::vector<char*> >::parse(const std::string& arg, ErrorReporter&)
323    {
324      opt_storage.clear(); 
325
326      char* pcStart = (char*) arg.data();     
327      char* pcEnd = strtok (pcStart," ");
328
329      while (pcEnd != NULL)
330      {
331        size_t uiStringLength = pcEnd - pcStart;
332        char* pcNewStr = (char*) malloc( uiStringLength + 1 );
333        strncpy( pcNewStr, pcStart, uiStringLength); 
334        pcNewStr[uiStringLength] = '\0'; 
335        pcStart = pcEnd+1; 
336        pcEnd = strtok (NULL, " ,.-");
337        opt_storage.push_back( pcNewStr ); 
338      }     
339    }
340#endif
341
342    template<>   
343    inline void
344#if NH_MV_SEI
345      Option< std::vector<double> >::parse(const std::string& arg, const std::vector< int > & idcs, ErrorReporter&)
346#else
347      Option< std::vector<double> >::parse(const std::string& arg, ErrorReporter&)
348#endif
349    {
350#if NH_MV_SEI
351      assert( idcs.size() == 0 ); 
352#endif
353      char* pcNextStart = (char*) arg.data();
354      char* pcEnd = pcNextStart + arg.length();
355
356      char* pcOldStart = 0; 
357
358      size_t iIdx = 0; 
359
360      while (pcNextStart < pcEnd)
361      {
362        errno = 0; 
363
364        if ( iIdx < opt_storage.size() )
365        {
366          opt_storage[iIdx] = strtod(pcNextStart, &pcNextStart);
367        }
368        else
369        {
370          opt_storage.push_back( strtod(pcNextStart, &pcNextStart)) ;
371        }
372        iIdx++; 
373
374        if ( errno == ERANGE || (pcNextStart == pcOldStart) )
375        {
376          std::cerr << "Error Parsing Doubles: `" << arg << "'" << std::endl;
377          exit(EXIT_FAILURE);   
378        };   
379        while( (pcNextStart < pcEnd) && ( *pcNextStart == ' ' || *pcNextStart == '\t' || *pcNextStart == '\r' ) ) pcNextStart++; 
380        pcOldStart = pcNextStart; 
381
382      }
383    }
384
385
386#if NH_MV_SEI
387    template<>
388    inline void
389      Option< IntAry1d >::parse(const std::string& arg, const IntAry1d& idcs, ErrorReporter& err)
390    {
391      xParseVec( arg, opt_storage );
392    };
393
394    template<>
395    inline void
396      Option< IntAry2d >::parse(const std::string& arg, const IntAry1d& idcs, ErrorReporter&)
397    {
398      xParseVec( arg, opt_storage[ idcs[0] ] );
399    };
400
401    template<>
402    inline void
403      Option< IntAry3d >::parse(const std::string& arg, const IntAry1d& idcs, ErrorReporter&)
404    {
405      xParseVec ( arg, opt_storage[ idcs[0] ][ idcs[1] ] );
406    };
407#else
408    template<>
409    inline void
410      Option< std::vector<int> >::parse(const std::string& arg, ErrorReporter&)
411    {
412      opt_storage.clear();
413
414
415      char* pcNextStart = (char*) arg.data();
416      char* pcEnd = pcNextStart + arg.length();
417
418      char* pcOldStart = 0; 
419
420      size_t iIdx = 0; 
421
422
423      while (pcNextStart < pcEnd)
424      {
425
426        if ( iIdx < opt_storage.size() )
427        {
428          opt_storage[iIdx] = (int) strtol(pcNextStart, &pcNextStart,10);
429        }
430        else
431        {
432          opt_storage.push_back( (int) strtol(pcNextStart, &pcNextStart,10)) ;
433        }
434        iIdx++; 
435        if ( errno == ERANGE || (pcNextStart == pcOldStart) )
436        {
437          std::cerr << "Error Parsing Integers: `" << arg << "'" << std::endl;
438          exit(EXIT_FAILURE);
439        };   
440        while( (pcNextStart < pcEnd) && ( *pcNextStart == ' ' || *pcNextStart == '\t' || *pcNextStart == '\r' ) ) pcNextStart++; 
441        pcOldStart = pcNextStart;
442      }
443    }
444#endif
445
446#if NH_MV_SEI
447
448    template<>
449    inline void
450      Option< std::vector< char*>  >::parse(const std::string& arg, const std::vector<int>& idcs, ErrorReporter& err )
451    {
452     
453      opt_storage[ idcs[ 0 ] ] = arg.empty() ? NULL : strdup(arg.c_str()) ;
454    };
455
456    template<>
457    inline void
458      Option< BoolAry1d >::parse(const std::string& arg, const std::vector<int>& idcs, ErrorReporter& err)
459    {     
460      xParseVec( arg, opt_storage );
461    };
462
463    template<>
464    inline void
465      Option< BoolAry2d >::parse(const std::string& arg, const IntAry1d& idcs, ErrorReporter& err)
466    {     
467      xParseVec( arg, opt_storage[ idcs[0] ] );
468    };
469
470    template<>
471    inline void
472      Option< BoolAry3d >::parse(const std::string& arg, const IntAry1d& idcs, ErrorReporter& err )
473    {     
474      xParseVec( arg, opt_storage[idcs[0]][idcs[1]] );
475    };
476#else
477    template<>
478    inline void
479      Option< std::vector<bool> >::parse(const std::string& arg, ErrorReporter&)
480    {
481      char* pcNextStart = (char*) arg.data();
482      char* pcEnd = pcNextStart + arg.length();
483
484      char* pcOldStart = 0; 
485
486      size_t iIdx = 0; 
487
488      while (pcNextStart < pcEnd)
489      {
490        if ( iIdx < opt_storage.size() )
491        {
492          opt_storage[iIdx] = (strtol(pcNextStart, &pcNextStart,10) != 0);
493        }
494        else
495        {
496          opt_storage.push_back(strtol(pcNextStart, &pcNextStart,10) != 0) ;
497        }
498        iIdx++; 
499
500        if ( errno == ERANGE || (pcNextStart == pcOldStart) )
501        {
502          std::cerr << "Error Parsing Bools: `" << arg << "'" << std::endl;
503          exit(EXIT_FAILURE);
504        };   
505        while( (pcNextStart < pcEnd) && ( *pcNextStart == ' ' || *pcNextStart == '\t' || *pcNextStart == '\r' ) ) pcNextStart++; 
506        pcOldStart = pcNextStart;
507      }
508    }
509#endif
510#endif
511    /** Option class for argument handling using a user provided function */
512    struct OptionFunc : public OptionBase
513    {
514      typedef void (Func)(Options&, const std::string&, ErrorReporter&);
515
516      OptionFunc(const std::string& name, Options& parent_, Func *func_, const std::string& desc)
517      : OptionBase(name, desc), parent(parent_), func(func_)
518      {}
519
520#if NH_MV_SEI
521      void parse(const std::string& arg, const std::vector<int>& idcs, ErrorReporter& error_reporter)
522#else
523      void parse(const std::string& arg, ErrorReporter& error_reporter)
524#endif
525      {
526        func(parent, arg, error_reporter);
527      }
528
529      void setDefault()
530      {
531        return;
532      }
533
534    private:
535      Options& parent;
536      Func* func;
537    };
538
539    class OptionSpecific;
540    struct Options
541    {
542      ~Options();
543
544      OptionSpecific addOptions();
545
546      struct Names
547      {
548        Names() : opt(0) {};
549        ~Names()
550        {
551          if (opt)
552          {
553            delete opt;
554          }
555        }
556        std::list<std::string> opt_long;
557        std::list<std::string> opt_short;
558        OptionBase* opt;
559      };
560
561      void addOption(OptionBase *opt);
562
563      typedef std::list<Names*> NamesPtrList;
564      NamesPtrList opt_list;
565
566      typedef std::map<std::string, NamesPtrList> NamesMap;
567      NamesMap opt_long_map;
568      NamesMap opt_short_map;
569    };
570
571    /* Class with templated overloaded operator(), for use by Options::addOptions() */
572    class OptionSpecific
573    {
574    public:
575      OptionSpecific(Options& parent_) : parent(parent_) {}
576
577      /**
578       * Add option described by name to the parent Options list,
579       *   with storage for the option's value
580       *   with default_val as the default value
581       *   with desc as an optional help description
582       */
583      template<typename T>
584      OptionSpecific&
585      operator()(const std::string& name, T& storage, T default_val, const std::string& desc = "")
586      {
587        parent.addOption(new Option<T>(name, storage, default_val, desc));
588        return *this;
589      }
590
591#if NH_MV
592      template<typename T>
593      OptionSpecific&
594        operator()(const std::string& name, std::vector<T>& storage, T default_val, unsigned uiMaxNum, const std::string& desc = "" )
595      {
596#if NH_MV_SEI
597        std::vector<T> defVal;
598        defVal.resize( uiMaxNum, default_val ); 
599        std::vector< int > maxSize; 
600        maxSize.push_back( uiMaxNum ); 
601        parent.addOption(new Option< std::vector<T> >( name, storage, defVal, desc, false, maxSize ));
602
603        return *this;
604      }
605      template<typename T>
606      OptionSpecific&
607        operator()(const std::string& name, std::vector< std::vector<T> >& storage, T default_val, unsigned uiMaxNumDim1, unsigned uiMaxNumDim2, const std::string& desc = "" )
608      {
609        std::vector< std::vector<T> > defVal;
610        defVal.resize(uiMaxNumDim1);
611        for ( unsigned int idxDim1 = 0; idxDim1 < uiMaxNumDim1; idxDim1++ )
612        {
613          defVal[ idxDim1 ].resize(uiMaxNumDim2, default_val );         
614        }
615
616        std::vector< int > maxSize; 
617        maxSize.push_back( uiMaxNumDim1 ); 
618        maxSize.push_back( uiMaxNumDim2 ); 
619
620        parent.addOption(new Option< std::vector< std::vector<T> > >( name, storage, defVal, desc, false, maxSize ));
621        return *this;
622      }
623#else
624        std::string cNameBuffer;
625        std::string cDescBuffer;
626
627        storage.resize(uiMaxNum);
628        for ( unsigned int uiK = 0; uiK < uiMaxNum; uiK++ )
629        {
630          cNameBuffer       .resize( name.size() + 10 );
631          cDescBuffer.resize( desc.size() + 10 );
632
633          Bool duplicate = (uiK != 0); 
634          // isn't there are sprintf function for string??
635          sprintf((char*) cNameBuffer.c_str()       ,name.c_str(),uiK,uiK);
636
637          if ( !duplicate )
638          {         
639            sprintf((char*) cDescBuffer.c_str(),desc.c_str(),uiK,uiK);
640          }
641
642          cNameBuffer.resize( std::strlen(cNameBuffer.c_str()) ); 
643          cDescBuffer.resize( std::strlen(cDescBuffer.c_str()) ); 
644         
645
646          parent.addOption(new Option<T>( cNameBuffer, (storage[uiK]), default_val, cDescBuffer, duplicate ));
647        }
648
649        return *this;
650      }
651#endif
652#endif
653      /**
654       * Add option described by name to the parent Options list,
655       *   with desc as an optional help description
656       * instead of storing the value somewhere, a function of type
657       * OptionFunc::Func is called.  It is upto this function to correctly
658       * handle evaluating the option's value.
659       */
660      OptionSpecific&
661      operator()(const std::string& name, OptionFunc::Func *func, const std::string& desc = "")
662      {
663        parent.addOption(new OptionFunc(name, parent, func, desc));
664        return *this;
665      }
666    private:
667      Options& parent;
668    };
669
670  } /* namespace: program_options_lite */
671} /* namespace: df */
672
673//! \}
674
675#endif
Note: See TracBrowser for help on using the repository browser.