[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