aboutsummaryrefslogtreecommitdiff
path: root/tools/iDSK/src/getopt_pp.h
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-11-05 11:22:55 +0000
committerJuan J. Martinez <jjm@usebox.net>2023-11-05 11:31:28 +0000
commit2fbdf974338bde8576efdae40a819a76b2391033 (patch)
tree64d41a37470143f142344f9a439d96de3e7918c2 /tools/iDSK/src/getopt_pp.h
downloadkitsunes-curse-2fbdf974338bde8576efdae40a819a76b2391033.tar.gz
kitsunes-curse-2fbdf974338bde8576efdae40a819a76b2391033.zip
Initial import of the open source release
Diffstat (limited to 'tools/iDSK/src/getopt_pp.h')
-rw-r--r--tools/iDSK/src/getopt_pp.h745
1 files changed, 745 insertions, 0 deletions
diff --git a/tools/iDSK/src/getopt_pp.h b/tools/iDSK/src/getopt_pp.h
new file mode 100644
index 0000000..117575f
--- /dev/null
+++ b/tools/iDSK/src/getopt_pp.h
@@ -0,0 +1,745 @@
+/*
+GetOpt_pp: Yet another C++ version of getopt.
+ This file is part of GetOpt_pp.
+
+ Copyright (C) Daniel Gutson, FuDePAN 2007-2010
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt in the root directory or
+ copy at http://www.boost.org/LICENSE_1_0.txt)
+
+ GetOpt_pp IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef GETOPT_PP_H
+#define GETOPT_PP_H
+
+#include <string>
+#include <vector> // candidate to be removed
+#include <map>
+#include <sstream>
+#include <list>
+
+/*
+ DESIGN GOALS:
+ - EASY to use
+ - EASY to learn
+ - mimc STL's streams
+ - EASY to extend
+*/
+
+#ifndef GETOPT_INLINE
+# define GETOPT_INLINE
+#endif
+
+namespace GetOpt
+{
+
+struct Token
+{
+ enum Type
+ {
+ ShortOption,
+ LongOption,
+ GlobalArgument,
+ GlobalArgumentUsed, // already read, skip in the next read
+ OptionArgument,
+ PossibleNegativeArgument,
+ UnknownYet // can be a global option, or an option of the previous one
+ };
+
+ Type type;
+ std::string value;
+ Token* next;
+
+ Token(const std::string& value, Type type = UnknownYet)
+ : type(type), value(value), next(NULL)
+ {}
+
+ bool is_last() const
+ {
+ return next == NULL;
+ }
+
+ void link_to(Token* new_next)
+ {
+ next = new_next;
+ }
+
+ Token* get_next_option_argument() const
+ {
+ if (is_last())
+ return NULL;
+ else
+ {
+ if (next->type == UnknownYet || next->type == OptionArgument || next->type == PossibleNegativeArgument)
+ return next;
+ else
+ return NULL;
+ }
+ }
+};
+
+struct OptionData
+{
+ enum _Flags
+ {
+ CmdLine_NotExtracted,
+ CmdLine_Extracted,
+ Envir
+ };
+
+ _Flags flags;
+ Token* token;
+ OptionData() : flags(CmdLine_NotExtracted) {}
+};
+
+typedef std::map<std::string, OptionData> LongOptions;
+typedef std::map<char, OptionData> ShortOptions;
+
+
+struct _Option
+{
+ enum Result
+ {
+ OK,
+ ParsingError,
+ OptionNotFound,
+ BadType,
+ NoArgs,
+ TooManyArgs,
+ OptionNotFound_NoEx
+ };
+
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const = 0;
+ virtual ~_Option() {}
+
+ static const char NO_SHORT_OPT = 0;
+protected:
+ static void setTokenAsUsed(Token* token, ShortOptions& short_ops, Token::Type usedAs)
+ {
+ if (token->type == Token::PossibleNegativeArgument)
+ short_ops.erase(token->value[1]);
+
+ token->type = usedAs;
+ }
+};
+
+template <class T> inline _Option::Result convert(const std::string& s, T& result, std::ios::fmtflags flags)
+{
+ std::stringstream ss;
+ ss.clear();
+ ss.flags(flags);
+ ss << s;
+ ss >> result;
+ if (ss.fail() || !ss.eof())
+ return _Option::BadType;
+ else
+ return _Option::OK;
+}
+
+template <> inline _Option::Result convert<std::string>(const std::string& s, std::string& result, std::ios::fmtflags /*flags*/)
+{
+ result = s;
+ return _Option::OK;
+}
+
+
+template <class T> class _OptionTBase : public _Option
+{
+ const char short_opt;
+ const std::string long_opt;
+protected:
+ T& target;
+ virtual Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const = 0;
+
+public:
+ _OptionTBase(const _OptionTBase<T>& other)
+ : _Option(), short_opt(other.short_opt), long_opt(other.long_opt), target(other.target)
+ {}
+
+ _OptionTBase(char short_opt, const std::string& long_opt, T& target)
+ : short_opt(short_opt), long_opt(long_opt), target(target)
+ {}
+
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* /*first*/, std::ios::fmtflags flags) const
+ {
+ Result ret = OptionNotFound;
+ ShortOptions::iterator it;
+ if (short_opt == _Option::NO_SHORT_OPT)
+ it = short_ops.end();
+ else
+ it = short_ops.find(short_opt);
+
+ if (it != short_ops.end())
+ {
+ it->second.flags = OptionData::CmdLine_Extracted;
+ ret = _assign(it->second.token, flags, short_ops);
+ }
+ else if (!long_opt.empty())
+ {
+ LongOptions::iterator it = long_ops.find(long_opt);
+ if (it != long_ops.end())
+ {
+ it->second.flags = OptionData::CmdLine_Extracted;
+ ret = _assign(it->second.token, flags, short_ops);
+ }
+ }
+
+ return ret;
+ }
+};
+
+
+template <class T> class _OptionT : public _OptionTBase<T>
+{
+protected:
+ virtual _Option::Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const
+ {
+ Token* const option_token = token->get_next_option_argument();
+ if (option_token == NULL)
+ return _Option::NoArgs;
+ else
+ {
+ this->setTokenAsUsed(option_token, short_ops, Token::OptionArgument);
+ return convert<T>(option_token->value, this->target, flags);
+ }
+ }
+public:
+ _OptionT(const _OptionT<T>& other)
+ : _OptionTBase<T>(other)
+ {}
+
+ _OptionT(char short_opt, const std::string& long_opt, T& target)
+ : _OptionTBase<T>(short_opt, long_opt, target)
+ {}
+
+};
+
+template <class T> class _OptionT<std::vector<T> > : public _OptionTBase<std::vector<T> >
+{
+protected:
+ virtual _Option::Result _assign(Token* token, std::ios::fmtflags flags, ShortOptions& short_ops) const
+ {
+ Token* option_token = token->get_next_option_argument();
+ if (option_token != NULL)
+ {
+ _Option::Result result;
+ //OptionArgs::const_iterator it = args.begin();
+ T temp;
+
+ do
+ {
+ this->setTokenAsUsed(option_token, short_ops, Token::OptionArgument);
+ result = convert<T>(option_token->value, temp, flags);
+ if (result == _Option::OK)
+ this->target.push_back(temp);
+
+ option_token = option_token->get_next_option_argument();
+ }
+ while (option_token != NULL && result == _Option::OK);
+
+ return result;
+ }
+ else
+ return _Option::NoArgs;
+ }
+
+public:
+ _OptionT(const _OptionT<std::vector<T> >& other)
+ : _OptionTBase<std::vector<T> >(other)
+ {}
+
+ _OptionT(char short_opt, const std::string& long_opt, std::vector<T>& target)
+ : _OptionTBase<std::vector<T> >(short_opt, long_opt, target)
+ {}
+};
+
+
+template <class T, class BaseOption>
+class _DefValOption : public BaseOption
+{
+ const T default_value;
+public:
+
+ _DefValOption(const _DefValOption<T, BaseOption>& other)
+ : BaseOption(other), default_value(other.default_value)
+ {}
+
+ _DefValOption(char short_opt, const std::string& long_opt, T& target, const T& default_value)
+ : BaseOption(short_opt, long_opt, target), default_value(default_value)
+ {}
+
+ virtual _Option::Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const
+ {
+ _Option::Result ret = BaseOption::operator()(short_ops, long_ops, first, flags);
+
+ if (ret == _Option::OptionNotFound)
+ {
+ this->target = default_value;
+ ret = _Option::OK;
+ }
+
+ return ret;
+ }
+};
+
+template <class T>
+class _GlobalOption : public _Option
+{
+ T& target;
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* first, std::ios::fmtflags flags) const
+ {
+ // find first token GlobalArgument or UnknownYet (candidate) or PossibleNegativeArgument (candidate too)
+ Token* token(first);
+ bool found(false);
+ while (token != NULL && !found)
+ {
+ found = (token->type == Token::GlobalArgument || token->type == Token::UnknownYet || token->type == Token::PossibleNegativeArgument);
+ if (!found)
+ token = token->next;
+ }
+ if (found)
+ {
+ this->setTokenAsUsed(token, short_ops, Token::GlobalArgumentUsed);
+ return convert<T>(token->value, target, flags);
+ }
+ else
+ return OptionNotFound;
+ }
+public:
+ _GlobalOption(const _GlobalOption<T>& other)
+ : target(other.target)
+ {}
+
+ _GlobalOption(T& target)
+ : target(target)
+ {}
+};
+
+template <class T>
+class _GlobalOption<std::vector<T> > : public _Option
+{
+ std::vector<T>& target;
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& /*long_ops*/, Token* first, std::ios::fmtflags flags) const
+ {
+ // find first token GlobalArgument or UnknownYet (candidate) or PossibleNegativeArgument (candidate too)
+ Token* token(first);
+ bool found_any(false);
+ T tmp;
+ Result res(OK);
+
+ while (token != NULL && res == OK)
+ {
+ if (token->type == Token::GlobalArgument || token->type == Token::UnknownYet || token->type == Token::PossibleNegativeArgument)
+ {
+ res = convert<T>(token->value, tmp, flags);
+ if (res == OK)
+ {
+ this->setTokenAsUsed(token, short_ops, Token::GlobalArgumentUsed);
+ found_any = true;
+ target.push_back(tmp);
+ }
+ }
+ token = token->next;
+ }
+ if (res == OK)
+ {
+ if (found_any)
+ return res;
+ else
+ return OptionNotFound;
+ }
+ else
+ return res;
+ }
+public:
+ _GlobalOption(const _GlobalOption<std::vector<T> >& other)
+ : target(other.target)
+ {}
+
+ _GlobalOption(std::vector<T>& target)
+ : target(target)
+ {}
+};
+
+template <class T>
+inline _OptionT<T> Option(char short_opt, const std::string& long_opt, T& target)
+{
+ return _OptionT<T>(short_opt, long_opt, target);
+}
+
+template <class T>
+inline _OptionT<T> Option(char short_opt, T& target)
+{
+ return _OptionT<T>(short_opt, std::string(), target);
+}
+
+// LongOpt only
+template <class T>
+inline _OptionT<T> Option(const std::string& long_opt, T& target)
+{
+ return _OptionT<T>(_Option::NO_SHORT_OPT, long_opt, target);
+}
+
+// Defaulted version
+template <class T>
+inline _DefValOption<T, _OptionT<T> >
+Option(char short_opt, const std::string& long_opt, T& target, const T& def)
+{
+ return _DefValOption<T, _OptionT<T> >(short_opt, long_opt, target, def);
+}
+
+template <class T>
+inline _DefValOption<T, _OptionT<T> > Option(char short_opt, T& target, const T& def)
+{
+ return _DefValOption<T, _OptionT<T> >(short_opt, std::string(), target, def);
+}
+
+// no short opt.
+template <class T>
+inline _DefValOption<T, _OptionT<T> >
+Option(const std::string& long_opt, T& target, const T& def)
+{
+ return _DefValOption<T, _OptionT<T> >(_Option::NO_SHORT_OPT, long_opt, target, def);
+}
+
+// Defaults for strings:
+inline _DefValOption<std::string, _OptionT<std::string> >
+Option(char short_opt, const std::string& long_opt, std::string& target, const char* def)
+{
+ return _DefValOption<std::string, _OptionT<std::string> >(short_opt, long_opt, target, def);
+}
+
+inline _OptionT<std::string> Option(char short_opt, std::string& target, const char* def)
+{
+ return _DefValOption<std::string, _OptionT<std::string> >(short_opt, std::string(), target, def);
+}
+
+// no short opt.
+inline _DefValOption<std::string, _OptionT<std::string> >
+Option(const std::string& long_opt, std::string& target, const char* def)
+{
+ return _DefValOption<std::string, _OptionT<std::string> >(_Option::NO_SHORT_OPT, long_opt, target, def);
+}
+
+// Global Option:
+template <class T>
+inline _GlobalOption<T> GlobalOption(T& target)
+{
+ return _GlobalOption<T>(target);
+}
+
+class OptionPresent : public _Option
+{
+ const char short_opt;
+ const std::string long_opt;
+ bool* const present;
+public:
+ // two combinations: with/without target, and with/without long opt.
+
+ // WITH long_opt:
+ OptionPresent(char short_opt, const std::string& long_opt, bool& present)
+ : short_opt(short_opt), long_opt(long_opt), present(&present)
+ {}
+
+ OptionPresent(char short_opt, const std::string& long_opt)
+ : short_opt(short_opt), long_opt(long_opt), present(NULL)
+ {}
+
+ // WITHOUT long_opt:
+ OptionPresent(char short_opt, bool& present)
+ : short_opt(short_opt), present(&present)
+ {}
+
+ OptionPresent(char short_opt)
+ : short_opt(short_opt), present(NULL)
+ {}
+
+ // WITHOUT short_opt
+ OptionPresent(const std::string& long_opt, bool& present)
+ : short_opt(_Option::NO_SHORT_OPT), long_opt(long_opt), present(&present)
+ {}
+
+ OptionPresent(const std::string& long_opt)
+ : short_opt(_Option::NO_SHORT_OPT), long_opt(long_opt), present(NULL)
+ {}
+protected:
+ virtual Result operator()(ShortOptions& short_ops, LongOptions& long_ops, Token* /*first*/, std::ios::fmtflags /*flags*/) const
+ {
+ bool found;
+ ShortOptions::iterator it = short_ops.find(short_opt);
+
+ found = (it != short_ops.end());
+ if (found)
+ {
+ it->second.flags = OptionData::CmdLine_Extracted;
+ }
+ else if (!long_opt.empty())
+ {
+ LongOptions::iterator it = long_ops.find(long_opt);
+ found = (it != long_ops.end());
+ if (found)
+ {
+ it->second.flags = OptionData::CmdLine_Extracted;
+ }
+ }
+
+ if (present != NULL)
+ {
+ *present = found;
+ return OK;
+ }
+ else
+ {
+ return found ? OK : OptionNotFound_NoEx;
+ }
+ }
+};
+
+class GetOptEx : public std::exception {};
+struct ParsingErrorEx : GetOptEx {};
+struct InvalidFormatEx : GetOptEx {};
+struct ArgumentNotFoundEx : GetOptEx {};
+struct TooManyArgumentsEx : GetOptEx {};
+struct OptionNotFoundEx : GetOptEx {};
+struct TooManyOptionsEx : GetOptEx {};
+struct OptionsFileNotFoundEx : GetOptEx
+{
+ const std::string targetFile;
+ OptionsFileNotFoundEx(const std::string& file) : targetFile(file) {}
+ ~OptionsFileNotFoundEx() throw() {}
+};
+
+enum _EnvTag
+{
+ Include_Environment
+};
+
+class GetOpt_pp
+{
+ ShortOptions _shortOps;
+ LongOptions _longOps;
+ std::ios_base::iostate _exc;
+ _Option::Result _last;
+ std::ios::fmtflags _flags;
+ std::string _app_name;
+ Token* _first_token;
+ Token* _last_token;
+
+ class TokensDeleter
+ {
+ Token*& _first;
+ public:
+ TokensDeleter(Token*& first) : _first(first) {}
+
+ GETOPT_INLINE ~TokensDeleter();
+ };
+
+ TokensDeleter _tokens_deleter;
+
+ GETOPT_INLINE Token* _add_token(const std::string& value, Token::Type type);
+ GETOPT_INLINE void _init_flags();
+ GETOPT_INLINE void _parse(const std::vector<std::string>& args);
+ GETOPT_INLINE void _parse_env();
+ static GETOPT_INLINE void _argc_argv_to_vector(int argc, const char* const* const argv, std::vector<std::string>& args);
+ GETOPT_INLINE void _parse_sub_file(const std::string& file);
+public:
+ GETOPT_INLINE GetOpt_pp(int argc, const char* const* const argv);
+ GETOPT_INLINE GetOpt_pp(int argc, const char* const* const argv, _EnvTag);
+
+ std::ios_base::iostate exceptions() const
+ {
+ return _exc;
+ }
+ void exceptions(std::ios_base::iostate except)
+ {
+ _exc = except;
+ }
+ void exceptions_all()
+ {
+ _exc = std::ios_base::failbit | std::ios_base::eofbit;
+ }
+
+ operator bool() const
+ {
+ return _last == _Option::OK;
+ }
+
+ GETOPT_INLINE bool options_remain() const;
+
+ void end_of_options() const
+ {
+ if (options_remain() && (_exc & std::ios_base::eofbit))
+ throw TooManyOptionsEx();
+ }
+
+ std::ios::fmtflags flags() const
+ {
+ return _flags;
+ }
+ void flags(std::ios::fmtflags flags)
+ {
+ _flags = flags;
+ }
+
+ const std::string& app_name() const
+ {
+ return _app_name;
+ }
+
+ GETOPT_INLINE GetOpt_pp& operator >> (const _Option& opt);
+
+ GETOPT_INLINE GetOpt_pp& operator >> (std::ios_base& (*iomanip)(std::ios_base&));
+
+ // Alternative to manipulators, for those who don't like them: the 'getopt' method :)
+ // Combination 1: with long option:
+ template <class T> inline T getopt(char short_opt, const std::string& long_opt)
+ {
+ T result;
+ operator >> (Option(short_opt, long_opt, result));
+ return result;
+ }
+
+ template <class T> inline T getopt(char short_opt, const std::string& long_opt, const T& def_value)
+ {
+ T result;
+ operator >> (Option(short_opt, long_opt, result, def_value));
+ return result;
+ }
+
+ // Combination 2: without long option:
+ template <class T> inline T getopt(char short_opt)
+ {
+ T result;
+ operator >> (Option(short_opt, result));
+ return result;
+ }
+
+ template <class T> inline T getopt(char short_opt, const T& def_value)
+ {
+ T result;
+ operator >> (Option(short_opt, result, def_value));
+ return result;
+ }
+
+ struct ItCtorData
+ {
+ ShortOptions::const_iterator short_iter;
+ LongOptions::const_iterator long_iter;
+ GetOpt_pp* getopt_pp;
+ };
+
+ template <class Container, class Adapter, class OptionType>
+ class _iterator
+ {
+ typename Container::const_iterator _it;
+ GetOpt_pp* _getopt_pp;
+ public:
+ _iterator(const ItCtorData& ctor_data)
+ {
+ _it = Adapter::adapt(ctor_data);
+ _getopt_pp = ctor_data.getopt_pp;
+ }
+
+ _iterator() : _getopt_pp(NULL)
+ {}
+
+ _iterator<Container, Adapter, OptionType>& operator = (const _iterator<Container, Adapter, OptionType>& other)
+ {
+ _it = other._it;
+ _getopt_pp = other._getopt_pp;
+ return *this;
+ }
+
+ bool operator != (const _iterator<Container, Adapter, OptionType>& other) const
+ {
+ return _it != other._it;
+ }
+
+ OptionType option() const
+ {
+ return _it->first;
+ }
+ OptionType operator*() const
+ {
+ return option();
+ }
+
+ _iterator<Container, Adapter, OptionType>& operator ++()
+ {
+ ++_it;
+ return *this;
+ }
+
+ template <class T>
+ GetOpt_pp& operator >> (T& t)
+ {
+ Adapter::extract(t, *_getopt_pp, option());
+ return *_getopt_pp;
+ }
+ };
+
+ ItCtorData begin()
+ {
+ ItCtorData ret;
+ ret.short_iter = _shortOps.begin();
+ ret.long_iter = _longOps.begin();
+ ret.getopt_pp = this;
+ return ret;
+ }
+
+ ItCtorData end()
+ {
+ ItCtorData ret;
+ ret.short_iter = _shortOps.end();
+ ret.long_iter = _longOps.end();
+ ret.getopt_pp = this;
+ return ret;
+ }
+
+ struct ShortAdapter
+ {
+ static ShortOptions::const_iterator adapt(const ItCtorData& data)
+ {
+ return data.short_iter;
+ }
+
+ template <class T>
+ static void extract(T& t, GetOpt_pp& getopt_pp, char option)
+ {
+ getopt_pp >> Option(option, t);
+ }
+ };
+
+ struct LongAdapter
+ {
+ static LongOptions::const_iterator adapt(const ItCtorData& data)
+ {
+ return data.long_iter;
+ }
+
+ template <class T>
+ static void extract(T& t, GetOpt_pp& getopt_pp, const std::string& option)
+ {
+ getopt_pp >> Option('\0', option, t);
+ }
+ };
+
+ typedef _iterator<ShortOptions, ShortAdapter, char> short_iterator;
+ typedef _iterator<LongOptions, LongAdapter, const std::string&> long_iterator;
+};
+
+class Environment
+{
+ // Coming soon!
+};
+
+}
+
+#endif