]> git.saurik.com Git - wxWidgets.git/commitdiff
implement flag for Unix-like behaviour in wxCmdLineParser::ConverStringToArgs()
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 16 Jul 2008 00:49:25 +0000 (00:49 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 16 Jul 2008 00:49:25 +0000 (00:49 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54648 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/cmdline.h
interface/wx/cmdline.h
src/common/cmdline.cpp
tests/cmdline/cmdlinetest.cpp

index 4539dd61abcbdb2dc11b1d7acb4267239fe4075a..10bf956eb0052af0cf0127481b53e97ca95acdc1 100644 (file)
 #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;
@@ -233,7 +240,9 @@ public:
     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
@@ -251,7 +260,9 @@ private:
 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
index 5aae4a95b705b2055b9b7080f84d148319b1ec9c..6dd779f8ce95752a8f7b5e863e31020b11d3ce8f 100644 (file)
@@ -59,6 +59,15 @@ enum wxCmdLineEntryType
     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
@@ -301,12 +310,20 @@ public:
     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).
index f05552219050af16cc5368b989b7f6b3188942a7..95afbfe27f0b262814fffb0e21e40fb1bacb4f75 100644 (file)
@@ -1280,15 +1280,15 @@ static wxString GetLongOptionName(wxString::const_iterator p,
  */
 
 /* 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();
 
@@ -1303,31 +1303,76 @@ wxArrayString wxCmdLineParser::ConvertStringToArgs(const wxString& cmdline)
             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;
         }
index 388166ffaf4377fc2a8346f71e8c7d6ca0887735..d1f8ec7c4e15c570196cf5740ea0ac926342db98 100644 (file)
@@ -55,12 +55,26 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( CmdLineTestCase, "CmdLineTestCase" );
 
 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\"" )
@@ -74,12 +88,31 @@ void CmdLineTestCase::ConvertStringTestCase()
     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
 }