← index
cplusplus17.Examples/examples/cmd-switch/source/cmd-switch.hpp
Source: cplusplus17.Examples/examples/cmd-switch/source/cmd-switch.hpp
// use form argument=value
// so switch
// --argument=value
// or
// --arguemnt="value 1 2 3"

#ifndef __CMDSWITCH_HPP__
#define __CMDSWITCH_HPP__
#include<iostream>
#include<string>
#include<vector>
#include<ctype.h>
#include<cstddef>

namespace cmd {

    template<typename T>
    class ArgExcep {
    public:
        ArgExcep(const T &ww) : w{ww} {}
        T what() const { return w; }
    protected:
        T w;
    };

    template<typename T>
    class Token {
    public:
        T key,value;
    };

    // template so you can subclass string if you want
    template<typename T>
    class ArgumentList {
    public:
        ArgumentList(int argc, char **argv, std::string err_msg = "");
        bool check(T key);
        bool check_require(T key);
        bool extract(T key, T &value);
        bool require(T key, T &value, T desc);
        void print();
        Token<T> &item(unsigned int index) { return items[index]; }
        unsigned int size() const { return items.size(); }
    protected:
        std::vector<Token<T>> items;
        
    };

    class ArgumentStringList {
    public:
        ArgumentStringList(int argc, char **argv);
        ArgumentList<std::string> argz;
    };

    bool Argument_FindInList(std::vector<std::string> &lst, ArgumentStringList &alst);
    
    template<typename T>
    T _tolower_x(const T &str) {
        T temp;
        for(std::size_t i = 0; i < str.length(); ++i) {
            temp += tolower(str[i]);
        }
        return temp;
    }
    
    template<typename T>
    T _toupper_x(const T &str) {
        T temp;
        for(std::size_t i = 0; i < str.length(); ++i) {
            temp += toupper(str[i]);
        }
        return temp;
    }

    template<typename T>
    ArgumentList<T>::ArgumentList(int argc, char **argv, std::string err_msg) {
        if(argc == 1) {
            std::cout << err_msg << "\n";
            return;
        }
        for(int i = 1; i < argc; ++i) {
            T s{argv[i]};
            auto pos = s.find("=");
            if(pos != std::string::npos) {
                T left = s.substr(0, pos);
                T right = s.substr(pos+1, s.length());
                if(right.length() == 0)
                    throw ArgExcep<T>("Argument Error: Zero Length");
                
                Token<T> token;
                token.key = left;
                token.value = right;
                items.push_back(token);
            } else {
                Token<T> token;
                token.key = "$";
                token.value = argv[i];
                items.push_back(token);
            }
        }
    }
    template<typename T>
    bool ArgumentList<T>::check(T key) {
        for(std::size_t i = 0; i < items.size(); ++i) {
            if(items[i].key == "$") {
                if(_tolower_x(items[i].value) == _tolower_x(key)) {
                    return true;
                }
            }
        }
        return false;
    }

    template<typename T>
    bool ArgumentList<T>::check_require(T key) {
        for(std::size_t i = 0; i < items.size(); ++i) {
            if(items[i].key == "$") {
                if(_tolower_x(items[i].value) == _tolower_x(key)) {
                    return true;
                }
            }
        }
        throw ArgExcep<T>("Argument Error: " + key + " required");
        return false;
    }

    template<typename T>
    bool ArgumentList<T>::extract(T key, T &value) {
        for(std::size_t i = 0; i < items.size(); ++i) {
            if(items[i].key == "$" && items[i].value == key) {
                return false;
            }
            if(items[i].key == key) {
                value = items[i].value;
                return true;
            }
        }
        return false;
    }

    template<typename T>
    bool ArgumentList<T>::require(T key, T &value, T desc) {
        for(std::size_t i = 0; i < items.size(); ++i) {
            
            if(items[i].key == "$" && items[i].value == key) {
                throw ArgExcep<T>("Argument Error: " + key + " required argument missing value...");
                return false;
            }
            
            if(items[i].key == key) {
                value = items[i].value;
                return true;
            }
        }
        throw ArgExcep<T>("Argument Error: " + key + " Required [" + desc + "]");
        return false;
    }


    template<typename T>
    void ArgumentList<T>::print() {
        for(std::size_t i = 0; i < items.size(); ++i) {
            if(items[i].key == "$")
                std::cout << items[i].value << "\n";
            else
                std::cout << items[i].key << ":" << items[i].value << "\n";
        }
    }

}

#endif