[mapserver-commits] r9610 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Wed Dec 9 13:08:53 EST 2009


Author: aboudreault
Date: 2009-12-09 13:08:52 -0500 (Wed, 09 Dec 2009)
New Revision: 9610

Modified:
   trunk/mapserver/mapjoin.c
   trunk/mapserver/mapserver.h
   trunk/mapserver/mapstring.c
Log:
Modified msStringSplitComplex to avoid memory freeing crash on windows (#471)

Modified: trunk/mapserver/mapjoin.c
===================================================================
--- trunk/mapserver/mapjoin.c	2009-12-09 14:57:56 UTC (rev 9609)
+++ trunk/mapserver/mapjoin.c	2009-12-09 18:08:52 UTC (rev 9610)
@@ -370,7 +370,7 @@
   i = 0;
   while(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) {  
     msStringTrimEOL(buffer);  
-    joininfo->rows[i] = msStringSplit(buffer, ',', &(join->numitems));
+    joininfo->rows[i] = msStringSplitComplex(buffer, ",", &(join->numitems), MS_ALLOWEMPTYTOKENS);
     i++;
   }
   fclose(stream);

Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h	2009-12-09 14:57:56 UTC (rev 9609)
+++ trunk/mapserver/mapserver.h	2009-12-09 18:08:52 UTC (rev 9610)
@@ -126,10 +126,6 @@
 
 #include <gd.h>
 
-#ifdef USE_GDAL
-#include "cpl_string.h"
-#endif
-
 #if defined USE_PDF
 #include <pdflib.h>
 #endif
@@ -250,6 +246,14 @@
 #define MS_ISTRING 2006
 #define MS_BINDING 2007
 
+/* string split flags */
+#define MS_HONOURSTRINGS      0x0001
+#define MS_ALLOWEMPTYTOKENS   0x0002
+#define MS_PRESERVEQUOTES     0x0004
+#define MS_PRESERVEESCAPES    0x0008
+#define MS_STRIPLEADSPACES    0x0010
+#define MS_STRIPENDSPACES     0x0020
+
 /* boolean options for the expression object. */
 #define MS_EXP_INSENSITIVE 1
 
@@ -1764,7 +1768,7 @@
 MS_DLL_EXPORT char *msTryBuildPath(char *szReturnPath, const char *abs_path, const char *path);
 MS_DLL_EXPORT char *msTryBuildPath3(char *szReturnPath, const char *abs_path, const char *path1, const char *path2);
 MS_DLL_EXPORT char **msStringSplit(const char *string, char cd, int *num_tokens);
-MS_DLL_EXPORT char **msStringSplitComplex(const char *string, char ch, int *num_tokens, int CSLTFlags);
+MS_DLL_EXPORT char ** msStringSplitComplex( const char * pszString, const char * pszDelimiters, int *num_tokens, int nFlags);
 MS_DLL_EXPORT char **msStringTokenize( const char *pszLine, const char *pszDelim, int *num_tokens, int preserve_quote);
 MS_DLL_EXPORT int msCountChars(char *str, char ch);
 MS_DLL_EXPORT char *msLongToString(long value);

Modified: trunk/mapserver/mapstring.c
===================================================================
--- trunk/mapserver/mapstring.c	2009-12-09 14:57:56 UTC (rev 9609)
+++ trunk/mapserver/mapstring.c	2009-12-09 18:08:52 UTC (rev 9610)
@@ -756,41 +756,175 @@
 }
 
 /*
- If GDAL is not available, msStringSplit is used: flags are ignored and only the 
- first char of the delimiters variable is passed through msStringSplit.
- 
+ This function is a copy of CSLTokenizeString2() function of the CPL component.
  See the port/cpl_string.cpp file in gdal source for the complete documentation.
  Available Flags:
- * - CSLT_ALLOWEMPTYTOKENS: allow the return of empty tokens when two 
+ * - MS_ALLOWEMPTYTOKENS: allow the return of empty tokens when two 
  * delimiters in a row occur with no other text between them.  If not set, 
  * empty tokens will be discarded;
- * - CSLT_STRIPLEADSPACES: strip leading space characters from the token (as
+ * - MS_STRIPLEADSPACES: strip leading space characters from the token (as
  * reported by isspace());
- * - CSLT_STRIPENDSPACES: strip ending space characters from the token (as
+ * - MS_STRIPENDSPACES: strip ending space characters from the token (as
  * reported by isspace());
- * - CSLT_HONOURSTRINGS: double quotes can be used to hold values that should 
+ * - MS_HONOURSTRINGS: double quotes can be used to hold values that should 
  * not be broken into multiple tokens; 
- * - CSLT_PRESERVEQUOTES: string quotes are carried into the tokens when this
+ * - MS_PRESERVEQUOTES: string quotes are carried into the tokens when this
  * is set, otherwise they are removed;
- * - CSLT_PRESERVEESCAPES: if set backslash escapes (for backslash itself, 
+ * - MS_PRESERVEESCAPES: if set backslash escapes (for backslash itself, 
  * and for literal double quotes) will be preserved in the tokens, otherwise
  * the backslashes will be removed in processing.
  */
-char **msStringSplitComplex(const char *string, char ch, int *num_tokens, int CSLTFlags) 
+char ** msStringSplitComplex( const char * pszString,
+                              const char * pszDelimiters,
+                              int *num_tokens,
+                              int nFlags )
+
 {
-    char **tokens;
-#ifdef USE_GDAL
-    char delimiter[2] = {ch, '\0'};
-    int i;
-    tokens = CSLTokenizeString2(string, &delimiter[0], CSLTFlags);
-    *num_tokens = 0;
-    for (i = 0; tokens != NULL && tokens[i] != NULL; ++i) 
-        ++(*num_tokens);
-#else
-    tokens = msStringSplit(string, ch, num_tokens);
-#endif
+    char        **papszRetList = NULL;
+    int         nRetMax = 0, nRetLen = 0;
+    char        *pszToken;
+    int         nTokenMax, nTokenLen;
+    int         bHonourStrings = (nFlags & MS_HONOURSTRINGS);
+    int         bAllowEmptyTokens = (nFlags & MS_ALLOWEMPTYTOKENS);
+    int         bStripLeadSpaces = (nFlags & MS_STRIPLEADSPACES);
+    int         bStripEndSpaces = (nFlags & MS_STRIPENDSPACES);
 
-    return tokens;
+    pszToken = (char *) malloc(sizeof(char*)*10);;
+    nTokenMax = 10;
+    
+    while( pszString != NULL && *pszString != '\0' )
+    {
+        int     bInString = FALSE;
+        int     bStartString = TRUE;
+
+        nTokenLen = 0;
+        
+        /* Try to find the next delimeter, marking end of token */
+        for( ; *pszString != '\0'; pszString++ )
+        {
+
+            /* End if this is a delimeter skip it and break. */
+            if( !bInString && strchr(pszDelimiters, *pszString) != NULL )
+            {
+                pszString++;
+                break;
+            }
+            
+            /* If this is a quote, and we are honouring constant
+               strings, then process the constant strings, with out delim
+               but don't copy over the quotes */
+            if( bHonourStrings && *pszString == '"' )
+            {
+                if( nFlags & MS_PRESERVEQUOTES )
+                {
+                    pszToken[nTokenLen] = *pszString;
+                    nTokenLen++;
+                }
+
+                if( bInString )
+                {
+                    bInString = FALSE;
+                    continue;
+                }
+                else
+                {
+                    bInString = TRUE;
+                    continue;
+                }
+            }
+
+            /*
+             * Within string constants we allow for escaped quotes, but in
+             * processing them we will unescape the quotes and \\ sequence
+             * reduces to \
+             */
+            if( bInString && pszString[0] == '\\' )
+            {
+                if ( pszString[1] == '"' || pszString[1] == '\\' )
+                {
+                    if( nFlags & MS_PRESERVEESCAPES )
+                    {
+                        pszToken[nTokenLen] = *pszString;
+                        nTokenLen++;
+                    }
+
+                    pszString++;
+                }
+            }
+
+            /*
+             * Strip spaces at the token start if requested.
+             */
+            if ( !bInString && bStripLeadSpaces
+                 && bStartString && isspace((unsigned char)*pszString) )
+                continue;
+
+            bStartString = FALSE;
+
+            /*
+             * Extend token buffer if we are running close to its end.
+             */
+            if( nTokenLen >= nTokenMax-3 )
+            {
+                nTokenMax = nTokenMax * 2 + 10;
+                pszToken = (char *) realloc(pszToken, sizeof(char*)*nTokenMax);
+            }
+
+            pszToken[nTokenLen] = *pszString;
+            nTokenLen++;
+        }
+
+        /*
+         * Strip spaces at the token end if requested.
+         */
+        if ( !bInString && bStripEndSpaces )
+        {
+            while ( nTokenLen && isspace((unsigned char)pszToken[nTokenLen - 1]) )
+                nTokenLen--;
+        }
+
+        pszToken[nTokenLen] = '\0';
+
+        /*
+         * Add the token.
+         */
+        if( pszToken[0] != '\0' || bAllowEmptyTokens )
+        {
+            if( nRetLen >= nRetMax - 1 )
+            {
+                nRetMax = nRetMax * 2 + 10;
+                papszRetList = (char **) realloc(papszRetList, sizeof(char*)*nRetMax);
+            }
+
+            papszRetList[nRetLen++] = strdup( pszToken );
+            papszRetList[nRetLen] = NULL;
+        }
+    }
+
+    /*
+     * If the last token was empty, then we need to capture
+     * it now, as the loop would skip it.
+     */
+    if( *pszString == '\0' && bAllowEmptyTokens && nRetLen > 0 
+        && strchr(pszDelimiters,*(pszString-1)) != NULL )
+    {
+        if( nRetLen >= nRetMax - 1 )
+        {
+            nRetMax = nRetMax * 2 + 10;
+            papszRetList = (char **) realloc(papszRetList, sizeof(char*)*nRetMax);
+        }
+
+        papszRetList[nRetLen++] = strdup("");
+        papszRetList[nRetLen] = NULL;
+    }
+
+    if( papszRetList == NULL )
+        papszRetList = (char **) malloc(sizeof(char *)*1);
+
+    *num_tokens = nRetLen;
+    free(pszToken);
+
+    return papszRetList;
 }
 
 /* This method is similar to msStringSplit but support quoted strings. 



More information about the mapserver-commits mailing list