You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
473 lines
13 KiB
473 lines
13 KiB
/* /////////////////////////////////////////////////////////////////////////
|
|
* 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 <stlsoft/stlsoft.h>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
|
|
#ifdef STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING
|
|
# include <string>
|
|
#else /* ? STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING */
|
|
# ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING
|
|
# include <stlsoft/string/simple_string.hpp>
|
|
# endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING */
|
|
#endif /* STLSOFT_SYSTEM_CMDARGS_USE_STD_STRING */
|
|
#ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS
|
|
# include <stlsoft/string/split_functions.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS */
|
|
#ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_VIEW
|
|
# include <stlsoft/string/string_view.hpp>
|
|
#endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_VIEW */
|
|
|
|
#ifndef STLSOFT_INCL_UTILITY
|
|
# define STLSOFT_INCL_UTILITY
|
|
# include <utility>
|
|
#endif /* !STLSOFT_INCL_UTILITY */
|
|
#ifndef STLSOFT_INCL_VECTOR
|
|
# define STLSOFT_INCL_VECTOR
|
|
# include <vector>
|
|
#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 <code>argv</code> 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<char> string_view_type;
|
|
|
|
enum
|
|
{
|
|
singleDash = 1
|
|
, doubleDash = 2
|
|
, tripleDash = 3
|
|
};
|
|
|
|
/// Represents a command-line option
|
|
///
|
|
/// \warning The value of the <code>original</code> 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 <code>name</code> 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_value_type> options_type;
|
|
typedef stlsoft_ns_qual_std(vector)<values_value_type> 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 <ss_typename_param_k S>
|
|
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 <ss_typename_param_k S>
|
|
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 <ss_typename_param_k S>
|
|
bool_type has_value(S const& valueName) const
|
|
{
|
|
return m_values.end() != has_value_(c_str_ptr(valueName));
|
|
}
|
|
template <ss_typename_param_k S>
|
|
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 <ss_typename_param_k S>
|
|
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 <ss_typename_param_k S>
|
|
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 //////////////////////////// */
|