/* ///////////////////////////////////////////////////////////////////////// * File: stlsoft/system/cmdargs.hpp * * Purpose: Command-line sequences class. * * Created: 25th June 2005 * Updated: 10th August 2009 * * Home: http://stlsoft.org/ * * Copyright (c) 2005-2009, Matthew Wilson and Synesis Software * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the * names of any contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ////////////////////////////////////////////////////////////////////// */ /** \file stlsoft/system/cmdargs.hpp * * [C++ only] Definition of the stlsoft::cmdargs class * (\ref group__library__system "System" Library). */ #ifndef STLSOFT_INCL_STLSOFT_SYSTEM_HPP_CMDARGS #define STLSOFT_INCL_STLSOFT_SYSTEM_HPP_CMDARGS #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION # define STLSOFT_VER_STLSOFT_SYSTEM_HPP_CMDARGS_MAJOR 3 # define STLSOFT_VER_STLSOFT_SYSTEM_HPP_CMDARGS_MINOR 0 # define STLSOFT_VER_STLSOFT_SYSTEM_HPP_CMDARGS_REVISION 3 # define STLSOFT_VER_STLSOFT_SYSTEM_HPP_CMDARGS_EDIT 30 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */ /* ///////////////////////////////////////////////////////////////////////// * Compatibility */ /* [Incompatibilies-start] STLSOFT_COMPILER_IS_WATCOM: [Incompatibilies-end] */ /* ///////////////////////////////////////////////////////////////////////// * Includes */ #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT # include #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */ #ifdef STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING # include #else /* ? STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING */ # ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING # include # endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING */ #endif /* STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING */ #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS # include #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS */ #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_VIEW # include #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_VIEW */ #ifndef STLSOFT_INCL_UTILITY # define STLSOFT_INCL_UTILITY # include #endif /* !STLSOFT_INCL_UTILITY */ #ifndef STLSOFT_INCL_VECTOR # define STLSOFT_INCL_VECTOR # include #endif /* !STLSOFT_INCL_VECTOR */ /* ///////////////////////////////////////////////////////////////////////// * Namespace */ #ifndef _STLSOFT_NO_NAMESPACE namespace stlsoft { #endif /* _STLSOFT_NO_NAMESPACE */ /* ///////////////////////////////////////////////////////////////////////// * Classes */ /** Facade class that presents argc+argv command line parameters as * two separate sequences of options (those arguments with - or -- * prefixes and, optionally, separated from an option value by a =) and * values (those without any leading hyphens) * * \ingroup group__library__system * * \note The cmdargs instance maintains views onto the actual arguments in * the argv array. Therefore, the behaviour is undefined if any code * modifies the strings pointed to by the elements in the argv array, or * repoints any of the argv elements to different strings. */ class cmdargs { public: #ifdef STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING typedef std::string string_type; #else /* ? STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING */ typedef simple_string string_type; #endif /* STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING */ typedef basic_string_view string_view_type; enum { singleDash = 1 , doubleDash = 2 , tripleDash = 3 }; /// Represents a command-line option /// /// \warning The value of the original member will be /// undefined if a copy of the instance is kept beyond the lifetime of /// the cmdargs instance from which it was obtained. struct option { string_type name; string_type value; int type; int index; string_view_type original; option() : name() , value() , type(-1) , index(-1) , original() {} option(string_type const& n, string_type const& v, int t, int i, string_view_type const& o) : name(n) , value(v) , type(t) , index(i) , original(o) {} }; /// Represents a command-line value /// /// \warning The value of the name member will be undefined /// if a copy of the instance is kept beyond the lifetime of the /// cmdargs instance from which it was obtained. struct value { string_view_type name; int index; value() : name() , index(-1) {} value(string_view_type const& v, int i) : name(v) , index(i) {} }; typedef option options_value_type; typedef value values_value_type; typedef stlsoft_ns_qual_std(vector) options_type; typedef stlsoft_ns_qual_std(vector) values_type; typedef options_type::const_iterator const_options_iterator; typedef values_type::const_iterator const_values_iterator; typedef ss_size_t size_type; typedef ss_bool_t bool_type; /// \name Construction /// @{ public: /// Constructs from argc/argv cmdargs(int argc, char /*const*/ ** argv); /// Releases any resources ~cmdargs() stlsoft_throw_0(); /// @} /// \name Attributes /// @{ public: /// non-mutating reference to the options options_type const& options() const; /// non-mutating reference to the values values_type const& values() const; const_options_iterator options_begin() const; const_options_iterator options_end() const; const_values_iterator values_begin() const; const_values_iterator values_end() const; /// The number of options size_type options_size() const; /// The number of values size_type values_size() const; /// The numbers options and values size_type size() const; /// Indicates whether there are any options and/or values bool_type empty() const; /// Determines whether the options collection contains an option of /// the given name /// /// \param optionName The name of the option to search for /// \param type The type of the option (i.e the number of hyphens). It /// defaults to -1, which indicates that the caller does not care. template bool_type has_option(S const& optionName, int type = -1) const { return m_options.end() != has_option_(c_str_ptr(optionName)); } /// Determines whether the options collection contains an option of /// the given name, and copies the found option's details into a /// caller-supplied instance /// /// \param optionName The name of the option to search for /// \param type The type of the option (i.e the number of hyphens). The /// caller can specify -1 to indicate that it does not care. /// \param opt The instance into which the template bool_type has_option(S const& optionName, int type, option& opt) const { options_type::const_iterator it = has_option_(c_str_ptr(optionName), type); if(m_options.end() != it) { opt = *it; return true; } return false; } template bool_type has_value(S const& valueName) const { return m_values.end() != has_value_(c_str_ptr(valueName)); } template bool_type has_value(S const& valueName, value& val) const { values_type::const_iterator it = has_value_(c_str_ptr(valueName)); if(m_values.end() != it) { val = *it; return true; } return false; } /// @} /// \name Implementation /// @{ private: values_type::const_iterator has_value_(char const* valueName) const; options_type::const_iterator has_option_(char const* optionName, int type) const; /// @} /// \name Members /// @{ private: options_type m_options; values_type m_values; /// @} }; //////////////////////////////////////////////////////////////////////////// // Unit-testing #ifdef STLSOFT_UNITTEST # include "./unittest/cmdargs_unittest_.h" #endif /* STLSOFT_UNITTEST */ //////////////////////////////////////////////////////////////////////////// // Implementation #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION inline cmdargs::cmdargs(int argc, char /*const*/ **argv) { for(int i = 1; i < argc; ++i) { char const *arg = argv[i]; if('-' == arg[0]) { ++arg; const int type = ('-' != arg[0]) ? singleDash : (++arg, doubleDash); string_type s0; string_type s1; split(arg, '=', s0, s1); m_options.push_back(option(s0, s1, type, i, argv[i])); } else { m_values.push_back(value(arg, i)); } } } inline cmdargs::~cmdargs() stlsoft_throw_0() { } inline cmdargs::options_type const& cmdargs::options() const { return m_options; } inline cmdargs::values_type const& cmdargs::values() const { return m_values; } inline cmdargs::const_options_iterator cmdargs::options_begin() const { return m_options.begin(); } inline cmdargs::const_options_iterator cmdargs::options_end() const { return m_options.end(); } inline cmdargs::const_values_iterator cmdargs::values_begin() const { return m_values.begin(); } inline cmdargs::const_values_iterator cmdargs::values_end() const { return m_values.end(); } inline cmdargs::size_type cmdargs::options_size() const { return m_options.size(); } inline cmdargs::size_type cmdargs::values_size() const { return m_values.size(); } inline cmdargs::size_type cmdargs::size() const { return options_size() + values_size(); } inline cmdargs::bool_type cmdargs::empty() const { return 0 == size(); } inline cmdargs::values_type::const_iterator cmdargs::has_value_(char const* valueName) const { STLSOFT_ASSERT(NULL != valueName); values_type::const_iterator b; for(b = m_values.begin(); b != m_values.end(); ++b) { if((*b).name == valueName) { break; } } return b; } inline cmdargs::options_type::const_iterator cmdargs::has_option_(char const* optionName, int type) const { STLSOFT_ASSERT(NULL != optionName); options_type::const_iterator b; for(b = m_options.begin(); b != m_options.end(); ++b) { if( (*b).name == optionName && ( -1 == type || type == (*b).type)) { break; } } return b; } #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */ template inline S& operator <<(S &stm, cmdargs::option const& option) { static const char s_dashes[] = { '-' , '-' , '\0' }; char const *dashes = &s_dashes[(option.type == cmdargs::singleDash)]; if(option.value.empty()) { stm << dashes << option.name; } else { stm << dashes << option.name << '=' << option.value; } return stm; } template inline S& operator <<(S &stm, cmdargs::value const& value) { stm << value.name; return stm; } /* ////////////////////////////////////////////////////////////////////// */ #ifndef _STLSOFT_NO_NAMESPACE } // namespace stlsoft #endif /* _STLSOFT_NO_NAMESPACE */ /* ////////////////////////////////////////////////////////////////////// */ #endif /* !STLSOFT_INCL_STLSOFT_SYSTEM_HPP_CMDARGS */ /* ///////////////////////////// end of file //////////////////////////// */