#include "wx/arrstr.h"
#include "wx/cmdargs.h"
+// determines ConvertStringToArgs() behaviour
+enum wxCmdLineSplitType
+{
+ wxCMD_LINE_SPLIT_DOS,
+ wxCMD_LINE_SPLIT_UNIX
+};
+
#if wxUSE_CMDLINE_PARSER
class WXDLLIMPEXP_FWD_BASE wxDateTime;
void Reset();
// break down the command line in arguments
- static wxArrayString ConvertStringToArgs(const wxString& cmdline);
+ static wxArrayString
+ ConvertStringToArgs(const wxString& cmdline,
+ wxCmdLineSplitType type = wxCMD_LINE_SPLIT_DOS);
private:
// common part of all ctors
class WXDLLIMPEXP_BASE wxCmdLineParser
{
public:
- static wxArrayString ConvertStringToArgs(const wxString& cmdline);
+ static wxArrayString
+ ConvertStringToArgs(const wxString& cmdline,
+ wxCmdLineSplitType type = wxCMD_LINE_SPLIT_DOS);
};
#endif // wxUSE_CMDLINE_PARSER/!wxUSE_CMDLINE_PARSER
wxCMD_LINE_NONE ///< Use this to terminate the list.
};
+/**
+ Flags determining ConvertStringToArgs() behaviour.
+ */
+enum wxCmdLineSplitType
+{
+ wxCMD_LINE_SPLIT_DOS,
+ wxCMD_LINE_SPLIT_UNIX
+};
+
/**
The structure wxCmdLineEntryDesc is used to describe the one command line
switch, option or parameter. An array of such structures should be passed
bool AreLongOptionsEnabled() const;
/**
- Breaks down the string containing the full command line in words. The
- words are separated by whitespace. The quotes can be used in the input
- string to quote the white space and the back slashes can be used to
- quote the quotes.
+ Breaks down the string containing the full command line in words.
+
+ Words are separated by whitespace and double quotes can be used to
+ preserve the spaces inside the words.
+
+ By default, this function uses Windows-like word splitting algorithm,
+ i.e. single quotes have no special meaning and backslash can't be used
+ to escape spaces neither. With @c wxCMD_LINE_SPLIT_UNIX flag Unix
+ semantics is used, i.e. both single and double quotes can be used and
+ backslash can be used to escape all the other special characters.
*/
- static wxArrayString ConvertStringToArgs(const wxChar cmdline);
+ static wxArrayString
+ ConvertStringToArgs(const wxChar cmdline,
+ wxCmdLineSplitType flags = wxCMD_LINE_SPLIT_DOS);
/**
Identical to EnableLongOptions(@false).
*/
/* static */
-wxArrayString wxCmdLineParser::ConvertStringToArgs(const wxString& cmdline)
+wxArrayString
+wxCmdLineParser::ConvertStringToArgs(const wxString& cmdline,
+ wxCmdLineSplitType type)
{
wxArrayString args;
wxString arg;
arg.reserve(1024);
- bool isInsideQuotes = false;
-
const wxString::const_iterator end = cmdline.end();
wxString::const_iterator p = cmdline.begin();
break;
// parse this parameter
- bool lastBS = false;
+ bool lastBS = false,
+ isInsideQuotes = false;
+ wxChar chDelim = '\0';
for ( arg.clear(); p != end; ++p )
{
const wxChar ch = *p;
- if ( ch == '"' )
+
+ if ( type == wxCMD_LINE_SPLIT_DOS )
{
- if ( !lastBS )
+ if ( ch == '"' )
{
- isInsideQuotes = !isInsideQuotes;
+ if ( !lastBS )
+ {
+ isInsideQuotes = !isInsideQuotes;
- // don't put quote in arg
- continue;
+ // don't put quote in arg
+ continue;
+ }
+ //else: quote has no special meaning but the backslash
+ // still remains -- makes no sense but this is what
+ // Windows does
+ }
+ // note that backslash does *not* quote the space, only quotes do
+ else if ( !isInsideQuotes && (ch == ' ' || ch == '\t') )
+ {
+ ++p; // skip this space anyhow
+ break;
}
- //else: quote has no special meaning but the backslash
- // still remains -- makes no sense but this is what
- // Windows does
+
+ lastBS = ch == '\\';
}
- // note that backslash does *not* quote the space, only quotes do
- else if ( !isInsideQuotes && (ch == ' ' || ch == '\t') )
+ else // type == wxCMD_LINE_SPLIT_UNIX
{
- ++p; // skip this space anyhow
- break;
- }
+ if ( !lastBS )
+ {
+ if ( isInsideQuotes )
+ {
+ if ( ch == chDelim )
+ {
+ isInsideQuotes = false;
+
+ continue; // don't use the quote itself
+ }
+ }
+ else // not in quotes and not escaped
+ {
+ if ( ch == '\'' || ch == '"' )
+ {
+ isInsideQuotes = true;
+ chDelim = ch;
- lastBS = ch == '\\';
+ continue; // don't use the quote itself
+ }
+
+ if ( ch == ' ' || ch == '\t' )
+ {
+ ++p; // skip this space anyhow
+ break;
+ }
+ }
+
+ lastBS = ch == '\\';
+ if ( lastBS )
+ continue;
+ }
+ else // escaped by backslash, just use as is
+ {
+ lastBS = false;
+ }
+ }
arg += ch;
}
void CmdLineTestCase::ConvertStringTestCase()
{
- #define WX_ASSERT_ARGS_EQUAL(s, args) \
+ #define WX_ASSERT_DOS_ARGS_EQUAL(s, args) \
+ { \
+ const wxArrayString \
+ argsDOS(wxCmdLineParser::ConvertStringToArgs(args, \
+ wxCMD_LINE_SPLIT_DOS)); \
+ WX_ASSERT_STRARRAY_EQUAL(s, argsDOS); \
+ }
+
+ #define WX_ASSERT_UNIX_ARGS_EQUAL(s, args) \
{ \
- const wxArrayString a(wxCmdLineParser::ConvertStringToArgs(args));\
- WX_ASSERT_STRARRAY_EQUAL(s, a); \
+ const wxArrayString \
+ argsUnix(wxCmdLineParser::ConvertStringToArgs(args, \
+ wxCMD_LINE_SPLIT_UNIX)); \
+ WX_ASSERT_STRARRAY_EQUAL(s, argsUnix); \
}
+ #define WX_ASSERT_ARGS_EQUAL(s, args) \
+ WX_ASSERT_DOS_ARGS_EQUAL(s, args) \
+ WX_ASSERT_UNIX_ARGS_EQUAL(s, args)
+
// normal cases
WX_ASSERT_ARGS_EQUAL( "foo", "foo" )
WX_ASSERT_ARGS_EQUAL( "foo bar", "\"foo bar\"" )
WX_ASSERT_ARGS_EQUAL( "foo", "foo \t " )
WX_ASSERT_ARGS_EQUAL( "foo|bar", "foo bar " )
WX_ASSERT_ARGS_EQUAL( "foo|bar|", "foo bar \"" )
- WX_ASSERT_ARGS_EQUAL( "foo|bar|\\", "foo bar \\" )
+ WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar|\\", "foo bar \\" )
+ WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar|", "foo bar \\" )
- // check for (broken) Windows semantics: backslash doesn't escape spaces
- WX_ASSERT_ARGS_EQUAL( "foo|bar\\|baz", "foo bar\\ baz" );
- WX_ASSERT_ARGS_EQUAL( "foo|bar\\\"baz", "foo \"bar\\\"baz\"" );
+ WX_ASSERT_ARGS_EQUAL( "12 34", "1\"2 3\"4" );
+ WX_ASSERT_ARGS_EQUAL( "1|2 34", "1 \"2 3\"4" );
+ WX_ASSERT_ARGS_EQUAL( "1|2 3|4", "1 \"2 3\" 4" );
+ // check for (broken) Windows semantics: backslash doesn't escape spaces
+ WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar\\|baz", "foo bar\\ baz" );
+ WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar\\\"baz", "foo \"bar\\\"baz\"" );
+
+ // check for more sane Unix semantics: backslash does escape spaces and
+ // quotes
+ WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo bar\\ baz" );
+ WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar\"baz", "foo \"bar\\\"baz\"" );
+
+ // check that single quotes work too with Unix semantics
+ WX_ASSERT_UNIX_ARGS_EQUAL( "foo bar", "'foo bar'" )
+ WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo 'bar baz'" )
+ WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo 'bar baz'" )
+ WX_ASSERT_UNIX_ARGS_EQUAL( "O'Henry", "\"O'Henry\"" )
+ WX_ASSERT_UNIX_ARGS_EQUAL( "O'Henry", "O\\'Henry" )
+
+ #undef WX_ASSERT_DOS_ARGS_EQUAL
+ #undef WX_ASSERT_UNIX_ARGS_EQUAL
#undef WX_ASSERT_ARGS_EQUAL
}