cmdline.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,228 行 · 第 1/3 页
CPP
1,228 行
wxCmdLineParamType type,
int flags)
{
// do some consistency checks: a required parameter can't follow an
// optional one and nothing should follow a parameter with MULTIPLE flag
#ifdef __WXDEBUG__
if ( !m_data->m_paramDesc.IsEmpty() )
{
wxCmdLineParam& param = m_data->m_paramDesc.Last();
wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE),
_T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
if ( !(flags & wxCMD_LINE_PARAM_OPTIONAL) )
{
wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL),
_T("a required parameter can't follow an optional one") );
}
}
#endif // Debug
wxCmdLineParam *param = new wxCmdLineParam(desc, type, flags);
m_data->m_paramDesc.Add(param);
}
// ----------------------------------------------------------------------------
// access to parse command line
// ----------------------------------------------------------------------------
bool wxCmdLineParser::Found(const wxString& name) const
{
int i = m_data->FindOption(name);
if ( i == wxNOT_FOUND )
i = m_data->FindOptionByLongName(name);
wxCHECK_MSG( i != wxNOT_FOUND, false, _T("unknown switch") );
wxCmdLineOption& opt = m_data->m_options[(size_t)i];
if ( !opt.HasValue() )
return false;
return true;
}
bool wxCmdLineParser::Found(const wxString& name, wxString *value) const
{
int i = m_data->FindOption(name);
if ( i == wxNOT_FOUND )
i = m_data->FindOptionByLongName(name);
wxCHECK_MSG( i != wxNOT_FOUND, false, _T("unknown option") );
wxCmdLineOption& opt = m_data->m_options[(size_t)i];
if ( !opt.HasValue() )
return false;
wxCHECK_MSG( value, false, _T("NULL pointer in wxCmdLineOption::Found") );
*value = opt.GetStrVal();
return true;
}
bool wxCmdLineParser::Found(const wxString& name, long *value) const
{
int i = m_data->FindOption(name);
if ( i == wxNOT_FOUND )
i = m_data->FindOptionByLongName(name);
wxCHECK_MSG( i != wxNOT_FOUND, false, _T("unknown option") );
wxCmdLineOption& opt = m_data->m_options[(size_t)i];
if ( !opt.HasValue() )
return false;
wxCHECK_MSG( value, false, _T("NULL pointer in wxCmdLineOption::Found") );
*value = opt.GetLongVal();
return true;
}
#if wxUSE_DATETIME
bool wxCmdLineParser::Found(const wxString& name, wxDateTime *value) const
{
int i = m_data->FindOption(name);
if ( i == wxNOT_FOUND )
i = m_data->FindOptionByLongName(name);
wxCHECK_MSG( i != wxNOT_FOUND, false, _T("unknown option") );
wxCmdLineOption& opt = m_data->m_options[(size_t)i];
if ( !opt.HasValue() )
return false;
wxCHECK_MSG( value, false, _T("NULL pointer in wxCmdLineOption::Found") );
*value = opt.GetDateVal();
return true;
}
#endif // wxUSE_DATETIME
size_t wxCmdLineParser::GetParamCount() const
{
return m_data->m_parameters.size();
}
wxString wxCmdLineParser::GetParam(size_t n) const
{
wxCHECK_MSG( n < GetParamCount(), wxEmptyString, _T("invalid param index") );
return m_data->m_parameters[n];
}
// Resets switches and options
void wxCmdLineParser::Reset()
{
for ( size_t i = 0; i < m_data->m_options.Count(); i++ )
{
wxCmdLineOption& opt = m_data->m_options[i];
opt.SetHasValue(false);
}
}
// ----------------------------------------------------------------------------
// the real work is done here
// ----------------------------------------------------------------------------
int wxCmdLineParser::Parse(bool showUsage)
{
bool maybeOption = true; // can the following arg be an option?
bool ok = true; // true until an error is detected
bool helpRequested = false; // true if "-h" was given
bool hadRepeatableParam = false; // true if found param with MULTIPLE flag
size_t currentParam = 0; // the index in m_paramDesc
size_t countParam = m_data->m_paramDesc.GetCount();
wxString errorMsg;
Reset();
// parse everything
wxString arg;
size_t count = m_data->m_arguments.size();
for ( size_t n = 1; ok && (n < count); n++ ) // 0 is program name
{
arg = m_data->m_arguments[n];
// special case: "--" should be discarded and all following arguments
// should be considered as parameters, even if they start with '-' and
// not like options (this is POSIX-like)
if ( arg == _T("--") )
{
maybeOption = false;
continue;
}
// empty argument or just '-' is not an option but a parameter
if ( maybeOption && arg.length() > 1 &&
wxStrchr(m_data->m_switchChars, arg[0u]) )
{
bool isLong;
wxString name;
int optInd = wxNOT_FOUND; // init to suppress warnings
// an option or a switch: find whether it's a long or a short one
if ( arg[0u] == _T('-') && arg[1u] == _T('-') )
{
// a long one
isLong = true;
// Skip leading "--"
const wxChar *p = arg.c_str() + 2;
bool longOptionsEnabled = AreLongOptionsEnabled();
name = GetLongOptionName(p);
if (longOptionsEnabled)
{
optInd = m_data->FindOptionByLongName(name);
if ( optInd == wxNOT_FOUND )
{
errorMsg << wxString::Format(_("Unknown long option '%s'"), name.c_str()) << wxT("\n");
}
}
else
{
optInd = wxNOT_FOUND; // Sanity check
// Print the argument including leading "--"
name.Prepend( wxT("--") );
errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str()) << wxT("\n");
}
}
else
{
isLong = false;
// a short one: as they can be cumulated, we try to find the
// longest substring which is a valid option
const wxChar *p = arg.c_str() + 1;
name = GetShortOptionName(p);
size_t len = name.length();
do
{
if ( len == 0 )
{
// we couldn't find a valid option name in the
// beginning of this string
errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str()) << wxT("\n");
break;
}
else
{
optInd = m_data->FindOption(name.Left(len));
// will try with one character less the next time
len--;
}
}
while ( optInd == wxNOT_FOUND );
len++; // compensates extra len-- above
if ( (optInd != wxNOT_FOUND) && (len != name.length()) )
{
// first of all, the option name is only part of this
// string
name = name.Left(len);
// our option is only part of this argument, there is
// something else in it - it is either the value of this
// option or other switches if it is a switch
if ( m_data->m_options[(size_t)optInd].kind
== wxCMD_LINE_SWITCH )
{
// pretend that all the rest of the argument is the
// next argument, in fact
wxString arg2 = arg[0u];
arg2 += arg.Mid(len + 1); // +1 for leading '-'
m_data->m_arguments.insert
(m_data->m_arguments.begin() + n + 1, arg2);
count++;
}
//else: it's our value, we'll deal with it below
}
}
if ( optInd == wxNOT_FOUND )
{
ok = false;
continue; // will break, in fact
}
wxCmdLineOption& opt = m_data->m_options[(size_t)optInd];
if ( opt.kind == wxCMD_LINE_SWITCH )
{
// nothing more to do
opt.SetHasValue();
if ( opt.flags & wxCMD_LINE_OPTION_HELP )
{
helpRequested = true;
// it's not an error, but we still stop here
ok = false;
}
}
else
{
// get the value
// +1 for leading '-'
const wxChar *p = arg.c_str() + 1 + name.length();
if ( isLong )
{
p++; // for another leading '-'
if ( *p++ != _T('=') )
{
errorMsg << wxString::Format(_("Option '%s' requires a value, '=' expected."), name.c_str()) << wxT("\n");
ok = false;
}
}
else
{
switch ( *p )
{
case _T('='):
case _T(':'):
// the value follows
p++;
break;
case 0:
// the value is in the next argument
if ( ++n == count )
{
// ... but there is none
errorMsg << wxString::Format(_("Option '%s' requires a value."),
name.c_str()) << wxT("\n");
ok = false;
}
else
{
// ... take it from there
p = m_data->m_arguments[n].c_str();
}
break;
default:
// the value is right here: this may be legal or
// not depending on the option style
if ( opt.flags & wxCMD_LINE_NEEDS_SEPARATOR )
{
errorMsg << wxString::Format(_("Separator expected after the option '%s'."),
name.c_str()) << wxT("\n");
ok = false;
}
}
}
if ( ok )
{
wxString value = p;
switch ( opt.type )
{
default:
wxFAIL_MSG( _T("unknown option type") );
// still fall through
case wxCMD_LINE_VAL_STRING:
opt.SetStrVal(value);
break;
case wxCMD_LINE_VAL_NUMBER:
{
long val;
if ( value.ToLong(&val) )
{
opt.SetLongVal(val);
}
else
{
errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
value.c_str(), name.c_str()) << wxT("\n");
ok = false;
}
}
break;
#if wxUSE_DATETIME
case wxCMD_LINE_VAL_DATE:
{
wxDateTime dt;
const wxChar *res = dt.ParseDate(value);
if ( !res || *res )
{
errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
name.c_str(), value.c_str()) << wxT("\n");
ok = false;
}
else
{
opt.SetDateVal(dt);
}
}
break;
#endif // wxUSE_DATETIME
}
}
}
}
else
{
// a parameter
if ( currentParam < countParam )
{
wxCmdLineParam& param = m_data->m_paramDesc[currentParam];
// TODO check the param type
m_data->m_parameters.push_back(arg);
if ( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE) )
{
currentParam++;
}
else
{
wxASSERT_MSG( currentParam == countParam - 1,
_T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
// remember that we did have this last repeatable parameter
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?