aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/getopt/small/last_getopt_parser.h
blob: 2cf8a6c308dc9d7b10a324399322f87aecf66b7f (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                             
                                      
 


                                  
       




                                                                              





                                                            
 
                                                 
 

                           
 

                                                                                      
 

                             
 
                           
 


                                                                  
 

                                                                                                      
 

                                                                                  
 
                                        
 

                                                                      
 
                                                                                                       
 




                                                                   
 
                      
 
                                                  
 
                                     
 


                                                                         
 

                                                                   
 
                                                                
 


















                                                         

                                    
 

                                        
 

                                             
 




                                                                
 




                                                                         
 


                                                                 
 

                                                   
 

                                            
 
                                                        
 

                                                                                    
#pragma once

#include "last_getopt_opts.h"

#include <library/cpp/colorizer/fwd.h>

#include <util/generic/hash_set.h>
#include <util/generic/list.h>

namespace NLastGetopt {
    /**
* NLastGetopt::TOptsParser is an implementation of parsing
* argv/argv into TOptsParseResult by rules of TOpts.
*
* The class allows to make complicated handlers.
* Note, that if PERMUTE mode is on, then data, pointed by argv can be changed.
*/
    class TOptsParser {
        enum EIsOpt {
            EIO_NONE,  //is not an option name
            EIO_SDASH, //single-dashed ('-c') option name
            EIO_DDASH, //double-dashed ("--opt") option name
            EIO_PLUS,  //plus prefix ("+opt") option name
        };

    public:                 // TODO: make private
        const TOpts* Opts_; //rules of parsing

        // argc/argv pair
        size_t Argc_;
        const char** Argv_;

    private:
        //the storage of last unkown options. TODO: can be moved to local-method scope
        TCopyPtr<TOpt> TempCurrentOpt_;

    public:
        //storage of argv[0]
        TString ProgramName_;

        //state of parsing:

        size_t Pos_; // current element withing argv
        size_t Sop_; // current char within arg
        bool Stopped_;
        bool GotMinusMinus_; //true if "--" have been seen in argv

    protected:
        const TOpt* CurrentOpt_;  // ptr on the last meeted option
        TStringBuf CurrentValue_; // the value of the last met argument (corresponding to CurrentOpt_)

    private:
        typedef THashSet<const TOpt*> TdOptSet;
        TdOptSet OptsSeen_; //the set of options that have been met during parsing

        TList<const TOpt*> OptsDefault_;

    private:
        void Init(const TOpts* options, int argc, const char* argv[]);
        void Init(const TOpts* options, int argc, char* argv[]);

        bool CommitEndOfOptions(size_t pos);
        bool Commit(const TOpt* currentOption, const TStringBuf& currentValue, size_t pos, size_t sop);

        bool ParseShortOptArg(size_t pos);
        bool ParseOptArg(size_t pos);
        bool ParseOptParam(const TOpt* opt, size_t pos);
        bool ParseUnknownShortOptWithinArg(size_t pos, size_t sop);
        bool ParseShortOptWithinArg(size_t pos, size_t sop);
        bool ParseWithPermutation();

        bool DoNext();
        void Finish();

        EIsOpt IsOpt(const TStringBuf& arg) const;

        void Swap(TOptsParser& that);

    public:
        TOptsParser(const TOpts* options, int argc, const char* argv[]) {
            Init(options, argc, argv);
        }

        TOptsParser(const TOpts* options, int argc, char* argv[]) {
            Init(options, argc, argv);
        }

        /// fetch next argument, false if no more arguments left
        bool Next();

        bool Seen(const TOpt* opt) const {
            return OptsSeen_.contains(opt);
        }

        bool Seen(TStringBuf name) const {
            if (auto opt = Opts_->FindLongOption(name)) {
                return Seen(opt);
            } else {
                return false;
            }
        }

        bool Seen(char name) const {
            if (auto opt = Opts_->FindCharOption(name)) {
                return Seen(opt);
            } else {
                return false;
            }
        }

        const TOpt* CurOpt() const {
            return CurrentOpt_;
        }

        const char* CurVal() const {
            return CurrentValue_.data();
        }

        const TStringBuf& CurValStr() const {
            return CurrentValue_;
        }

        TStringBuf CurValOrOpt() const {
            TStringBuf val(CurValStr());
            if (!val.IsInited() && CurOpt()->HasOptionalValue())
                val = CurOpt()->GetOptionalValue();
            return val;
        }

        TStringBuf CurValOrDef(bool useDef = true) const {
            TStringBuf val(CurValOrOpt());
            if (!val.IsInited() && useDef && CurOpt()->HasDefaultValue())
                val = CurOpt()->GetDefaultValue();
            return val;
        }

        // true if this option was actually specified by the user
        bool IsExplicit() const {
            return nullptr == CurrentOpt_ || !OptsSeen_.empty();
        }

        bool CurrentIs(const TString& name) const {
            return CurOpt()->NameIs(name);
        }

        const TString& ProgramName() const {
            return ProgramName_;
        }

        void PrintUsage(IOutputStream& os = Cout) const;

        void PrintUsage(IOutputStream& os, const NColorizer::TColors& colors) const;
    };
} //namespace NLastGetopt