diff options
author | Erti-Chris Eelmaa <chriseelmaa@gmail.com> | 2017-02-14 16:35:16 +0000 |
---|---|---|
committer | Tarek Mahmoud Sayed <tarekms@microsoft.com> | 2017-02-14 08:35:16 -0800 |
commit | d0f8481cd42e58013879326871455586a86bec6e (patch) | |
tree | 39e51171f99801e56a9e167cd56dbb1ff4d40791 /src | |
parent | 3e7d8a5deb0cb761b848e0370e57cf64b283c4f4 (diff) | |
download | coreclr-d0f8481cd42e58013879326871455586a86bec6e.tar.gz coreclr-d0f8481cd42e58013879326871455586a86bec6e.tar.bz2 coreclr-d0f8481cd42e58013879326871455586a86bec6e.zip |
Add case-insensitive String.Replace overloads (#9316)
Added overloads for String.Replace so that they now accept
StringComparison and CultureInfo as input parameters.
Diffstat (limited to 'src')
-rw-r--r-- | src/classlibnative/inc/nlsinfo.h | 3 | ||||
-rw-r--r-- | src/classlibnative/nls/nlsinfo.cpp | 17 | ||||
-rw-r--r-- | src/corefx/System.Globalization.Native/collation.cpp | 10 | ||||
-rw-r--r-- | src/inc/newapis.h | 16 | ||||
-rw-r--r-- | src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs | 2 | ||||
-rw-r--r-- | src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs | 26 | ||||
-rw-r--r-- | src/mscorlib/corefx/System/Globalization/CompareInfo.cs | 4 | ||||
-rw-r--r-- | src/mscorlib/ref/mscorlib.cs | 2 | ||||
-rw-r--r-- | src/mscorlib/src/System/Globalization/CompareInfo.cs | 37 | ||||
-rw-r--r-- | src/mscorlib/src/System/String.Manipulation.cs | 90 | ||||
-rw-r--r-- | src/utilcode/downlevel.cpp | 4 | ||||
-rw-r--r-- | src/utilcode/newapis.cpp | 30 |
12 files changed, 200 insertions, 41 deletions
diff --git a/src/classlibnative/inc/nlsinfo.h b/src/classlibnative/inc/nlsinfo.h index 67677c7576..3c17465655 100644 --- a/src/classlibnative/inc/nlsinfo.h +++ b/src/classlibnative/inc/nlsinfo.h @@ -165,7 +165,8 @@ public: __in int cchSource, // number of characters lpStringSource after sourceIndex __in int sourceIndex, // index from where the search will start in lpStringSource __in_ecount(cchValue) LPCWSTR lpStringValue, // the string we search for - __in int cchValue); // length of the string we search for + __in int cchValue, // length of the string we search for + __out_opt LPINT pcchFound); // length of the string we found in source static int QCALLTYPE InternalGetSortKey( __in_opt INT_PTR handle, // PSORTHANDLE diff --git a/src/classlibnative/nls/nlsinfo.cpp b/src/classlibnative/nls/nlsinfo.cpp index 507a18b221..b43b8f6b11 100644 --- a/src/classlibnative/nls/nlsinfo.cpp +++ b/src/classlibnative/nls/nlsinfo.cpp @@ -2452,7 +2452,8 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx( __in int cchSource, // number of characters lpStringSource after sourceIndex __in int sourceIndex, // index from where the search will start in lpStringSource __in_ecount(cchValue) LPCWSTR lpStringValue, // the string we search for - __in int cchValue) // length of the string we search for + __in int cchValue, // length of the string we search for + __out_opt LPINT pcchFound) // length of the string we found in source { CONTRACTL { QCALL_CHECK; @@ -2496,7 +2497,8 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx( lpStringValue, cchValue, dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, - dwFindNLSStringFlags & FIND_ENDSWITH); + dwFindNLSStringFlags & FIND_ENDSWITH, + pcchFound); if (retValue >= 0) { retValue += sourceIndex - cchSource + 1; @@ -2511,7 +2513,8 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx( lpStringValue, cchValue, dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, - dwFindNLSStringFlags & FIND_STARTSWITH); + dwFindNLSStringFlags & FIND_STARTSWITH, + pcchFound); if (retValue >= 0) { @@ -2530,7 +2533,9 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx( &lpStringSource[sourceIndex - cchSource + 1], cchSource, lpStringValue, - cchValue, NULL, NULL, NULL, (LPARAM) handle); + cchValue, + pcchFound, + NULL, NULL, (LPARAM) handle); } if (retValue >= 0) @@ -2547,7 +2552,9 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx( &lpStringSource[sourceIndex], cchSource, lpStringValue, - cchValue, NULL, NULL, NULL, (LPARAM) handle); + cchValue, + pcchFound, + NULL, NULL, (LPARAM) handle); } if (retValue >= 0) diff --git a/src/corefx/System.Globalization.Native/collation.cpp b/src/corefx/System.Globalization.Native/collation.cpp index f37211208e..a8c24e16ad 100644 --- a/src/corefx/System.Globalization.Native/collation.cpp +++ b/src/corefx/System.Globalization.Native/collation.cpp @@ -440,7 +440,8 @@ extern "C" int32_t GlobalizationNative_IndexOf( int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, - int32_t options) + int32_t options, + int32_t* pMatchedLength) { static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found"); @@ -455,6 +456,13 @@ extern "C" int32_t GlobalizationNative_IndexOf( if (U_SUCCESS(err)) { result = usearch_first(pSearch, &err); + + // if the search was successful, + // we'll try to get the matched string length. + if(result != USEARCH_DONE && pMatchedLength != NULL) + { + *pMatchedLength = usearch_getMatchedLength(pSearch); + } usearch_close(pSearch); } } diff --git a/src/inc/newapis.h b/src/inc/newapis.h index dfe77a5000..e0e6d999e1 100644 --- a/src/inc/newapis.h +++ b/src/inc/newapis.h @@ -288,15 +288,17 @@ namespace NewApis __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for __in int cchCount2, // length of pString2 __in DWORD dwFlags, // search flags - __in BOOL startWith); + __in BOOL startWith, + __out_opt LPINT pcchFound); int LastIndexOfString(__in LPCWSTR lpLocaleName, - __in_ecount(cchCount1) LPCWSTR pString1, // String to search in - __in int cchCount1, // length of pString1 - __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for - __in int cchCount2, // length of pString2 - __in DWORD dwFlags, - __in BOOL endWith); + __in_ecount(cchCount1) LPCWSTR pString1, // String to search in + __in int cchCount1, // length of pString1 + __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for + __in int cchCount2, // length of pString2 + __in DWORD dwFlags, + __in BOOL endWith, + __out_opt LPINT pcchFound); int FindNLSStringEx(__in LPCWSTR lpLocaleName, __in DWORD dwFindNLSStringFlags, diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs index 25585c6dfb..79aedd74d3 100644 --- a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs +++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs @@ -21,7 +21,7 @@ internal static partial class Interop internal unsafe static extern int CompareString(SafeSortHandle sortHandle, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options); [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOf")] - internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options); + internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options, int* matchLengthPtr); [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_LastIndexOf")] internal unsafe static extern int LastIndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options); diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs index 21c3c9f7e4..a5232b8883 100644 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs @@ -159,30 +159,46 @@ namespace System.Globalization } } - private unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options) + internal unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options, int* matchLengthPtr) { Debug.Assert(!string.IsNullOrEmpty(source)); Debug.Assert(target != null); Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0); + int index; + if (target.Length == 0) { + if(matchLengthPtr != null) + *matchLengthPtr = 0; return startIndex; } if (options == CompareOptions.Ordinal) { - return IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false); + index = IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false); + if(index != -1) + { + if(matchLengthPtr != null) + *matchLengthPtr = target.Length; + } + return index; } if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && target.IsFastSort()) { - return IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options)); + index = IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options)); + if(index != -1) + { + if(matchLengthPtr != null) + *matchLengthPtr = target.Length; + } + return index; } - + fixed (char* pSource = source) { - int index = Interop.GlobalizationInterop.IndexOf(_sortHandle, target, target.Length, pSource + startIndex, count, options); + index = Interop.GlobalizationInterop.IndexOf(_sortHandle, target, target.Length, pSource + startIndex, count, options, matchLengthPtr); return index != -1 ? index + startIndex : -1; } diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs index 64dbfe84f7..94cfcad709 100644 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs @@ -694,7 +694,7 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - return IndexOfCore(source, new string(value, 1), startIndex, count, options); + return IndexOfCore(source, new string(value, 1), startIndex, count, options, null); } @@ -741,7 +741,7 @@ namespace System.Globalization if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal)) throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options)); - return IndexOfCore(source, value, startIndex, count, options); + return IndexOfCore(source, value, startIndex, count, options, null); } //////////////////////////////////////////////////////////////////////// diff --git a/src/mscorlib/ref/mscorlib.cs b/src/mscorlib/ref/mscorlib.cs index 680bf20675..945e9689da 100644 --- a/src/mscorlib/ref/mscorlib.cs +++ b/src/mscorlib/ref/mscorlib.cs @@ -3245,6 +3245,8 @@ namespace System [System.Security.SecuritySafeCriticalAttribute] public System.String Replace(char oldChar, char newChar) { throw null; } public System.String Replace(System.String oldValue, System.String newValue) { throw null; } + public System.String Replace(System.String oldValue, System.String newValue, System.StringComparison comparison) { throw null; } + public System.String Replace(System.String oldValue, System.String newValue, System.Boolean ignoreCase, System.Globalization.CultureInfo cultureInfo) { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] public string[] Split(char separator, int count, System.StringSplitOptions options = (System.StringSplitOptions)(0)) { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)] diff --git a/src/mscorlib/src/System/Globalization/CompareInfo.cs b/src/mscorlib/src/System/Globalization/CompareInfo.cs index 6c2230b66b..dac7b0bf4e 100644 --- a/src/mscorlib/src/System/Globalization/CompareInfo.cs +++ b/src/mscorlib/src/System/Globalization/CompareInfo.cs @@ -564,11 +564,11 @@ namespace System.Globalization { // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. - return (InternalFindNLSStringEx( m_dataHandle, m_handleOrigin, m_sortName, GetNativeCompareFlags(options) | Win32Native.FIND_STARTSWITH | ((source.IsAscii() && prefix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), - source, source.Length, 0, prefix, prefix.Length) > -1); + source, source.Length, 0, prefix, prefix.Length, + null) > -1); } public virtual bool IsPrefix(String source, String prefix) @@ -618,7 +618,7 @@ namespace System.Globalization { return InternalFindNLSStringEx( m_dataHandle, m_handleOrigin, m_sortName, GetNativeCompareFlags(options) | Win32Native.FIND_ENDSWITH | ((source.IsAscii() && suffix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), - source, source.Length, source.Length - 1, suffix, suffix.Length) >= 0; + source, source.Length, source.Length - 1, suffix, suffix.Length, null) >= 0; } @@ -760,12 +760,16 @@ namespace System.Globalization { return InternalFindNLSStringEx( m_dataHandle, m_handleOrigin, m_sortName, GetNativeCompareFlags(options) | Win32Native.FIND_FROMSTART | ((source.IsAscii() && (value <= '\x007f')) ? RESERVED_FIND_ASCII_STRING : 0), - source, count, startIndex, new String(value, 1), 1); + source, count, startIndex, new String(value, 1), 1, null); } - public unsafe virtual int IndexOf(String source, String value, int startIndex, int count, CompareOptions options) { + return IndexOfCore(source, value, startIndex, count, options, null); + } + + internal unsafe int IndexOfCore(String source, String value, int startIndex, int count, CompareOptions options, int* matchLengthPtr) + { // Validate inputs if (source == null) throw new ArgumentNullException(nameof(source)); @@ -784,6 +788,8 @@ namespace System.Globalization { { if (value.Length == 0) { + if(matchLengthPtr != null) + *matchLengthPtr = 0; return 0; } return -1; @@ -795,11 +801,17 @@ namespace System.Globalization { } if (count < 0 || startIndex > source.Length - count) - throw new ArgumentOutOfRangeException(nameof(count),Environment.GetResourceString("ArgumentOutOfRange_Count")); + throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); if (options == CompareOptions.OrdinalIgnoreCase) { - return source.IndexOf(value, startIndex, count, StringComparison.OrdinalIgnoreCase); + int index = source.IndexOf(value, startIndex, count, StringComparison.OrdinalIgnoreCase); + if (index != -1) + { + if(matchLengthPtr != null) + *matchLengthPtr = value.Length; + } + return index; } // Validate CompareOptions @@ -810,9 +822,9 @@ namespace System.Globalization { // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. return InternalFindNLSStringEx( - m_dataHandle, m_handleOrigin, m_sortName, + m_dataHandle, m_handleOrigin, m_sortName, GetNativeCompareFlags(options) | Win32Native.FIND_FROMSTART | ((source.IsAscii() && value.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), - source, count, startIndex, value, value.Length); + source, count, startIndex, value, value.Length, matchLengthPtr); } //////////////////////////////////////////////////////////////////////// @@ -956,7 +968,7 @@ namespace System.Globalization { return InternalFindNLSStringEx( m_dataHandle, m_handleOrigin, m_sortName, GetNativeCompareFlags(options) | Win32Native.FIND_FROMEND | ((source.IsAscii() && (value <= '\x007f')) ? RESERVED_FIND_ASCII_STRING : 0), - source, count, startIndex, new String(value, 1), 1); + source, count, startIndex, new String(value, 1), 1, null); } @@ -1010,7 +1022,7 @@ namespace System.Globalization { return InternalFindNLSStringEx( m_dataHandle, m_handleOrigin, m_sortName, GetNativeCompareFlags(options) | Win32Native.FIND_FROMEND | ((source.IsAscii() && value.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), - source, count, startIndex, value, value.Length); + source, count, startIndex, value, value.Length, null); } @@ -1292,7 +1304,8 @@ namespace System.Globalization { // Call through to NewApis::FindNLSStringEx so we can get the right behavior [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] - private static extern int InternalFindNLSStringEx(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, int startIndex, string target, int targetCount); + private unsafe static extern int InternalFindNLSStringEx(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, int startIndex, string target, int targetCount, int* matchLengthPtr); + // Call through to NewAPis::LCMapStringEx so we can get appropriate behavior for all platforms [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] diff --git a/src/mscorlib/src/System/String.Manipulation.cs b/src/mscorlib/src/System/String.Manipulation.cs index e06141d669..5a9be5c248 100644 --- a/src/mscorlib/src/System/String.Manipulation.cs +++ b/src/mscorlib/src/System/String.Manipulation.cs @@ -946,7 +946,95 @@ namespace System Contract.EndContractBlock(); return Substring(0, startIndex); - } + } + + public string Replace(string oldValue, string newValue, bool ignoreCase, CultureInfo culture) + { + Contract.Ensures(Contract.Result<String>() != null); + Contract.EndContractBlock(); + + return ReplaceCore(oldValue, newValue, culture, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None); + } + + public string Replace(string oldValue, string newValue, StringComparison comparisonType) + { + Contract.Ensures(Contract.Result<String>() != null); + Contract.EndContractBlock(); + + switch (comparisonType) + { + case StringComparison.CurrentCulture: + return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.None); + + case StringComparison.CurrentCultureIgnoreCase: + return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase); + + case StringComparison.InvariantCulture: + return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.None); + + case StringComparison.InvariantCultureIgnoreCase: + return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase); + + case StringComparison.Ordinal: + return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.Ordinal); + + case StringComparison.OrdinalIgnoreCase: + return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.OrdinalIgnoreCase); + + default: + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType)); + } + } + + private unsafe String ReplaceCore(string oldValue, string newValue, CultureInfo culture, CompareOptions options) + { + if (oldValue == null) + throw new ArgumentNullException(nameof(oldValue)); + + // If they asked to replace oldValue with a null, replace all occurences + // with the empty string. + if (newValue == null) + newValue = string.Empty; + + CultureInfo referenceCulture = culture ?? CultureInfo.CurrentCulture; + StringBuilder result = StringBuilderCache.Acquire(); + + int startIndex = 0; + int index = 0; + + int matchLength = 0; + + bool hasDoneAnyReplacements = false; + + do + { + index = referenceCulture.CompareInfo.IndexOfCore(this, oldValue, startIndex, m_stringLength - startIndex, options, &matchLength); + if (index >= 0) + { + // append the unmodified portion of string + result.Append(this, startIndex, index - startIndex); + + // append the replacement + result.Append(newValue); + + startIndex = index + matchLength; + hasDoneAnyReplacements = true; + } + else if (!hasDoneAnyReplacements) + { + // small optimization, + // if we have not done any replacements, + // we will return the original string + return this; + } + else + { + result.Append(this, startIndex, m_stringLength - startIndex); + } + } while (index >= 0); + + return StringBuilderCache.GetStringAndRelease(result); + } // Replaces all instances of oldChar with newChar. // diff --git a/src/utilcode/downlevel.cpp b/src/utilcode/downlevel.cpp index ec8d3f5a15..6ff7b82815 100644 --- a/src/utilcode/downlevel.cpp +++ b/src/utilcode/downlevel.cpp @@ -1924,11 +1924,11 @@ namespace DownLevel if (dwFindNLSStringFlags & (FIND_ENDSWITH | FIND_FROMEND)) { - retValue = NewApis::LastIndexOfString(lpLocaleName, lpStringSource, cchSource, lpStringValue, cchValue, (int) dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, dwFindNLSStringFlags & FIND_ENDSWITH); + retValue = NewApis::LastIndexOfString(lpLocaleName, lpStringSource, cchSource, lpStringValue, cchValue, (int) dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, dwFindNLSStringFlags & FIND_ENDSWITH, pcchFound); } else { - retValue = NewApis::IndexOfString(lpLocaleName, lpStringSource, cchSource, lpStringValue, cchValue, (int) dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, dwFindNLSStringFlags & FIND_STARTSWITH); + retValue = NewApis::IndexOfString(lpLocaleName, lpStringSource, cchSource, lpStringValue, cchValue, (int) dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, dwFindNLSStringFlags & FIND_STARTSWITH, pcchFound); } return retValue; } diff --git a/src/utilcode/newapis.cpp b/src/utilcode/newapis.cpp index c05d024b7e..599197c944 100644 --- a/src/utilcode/newapis.cpp +++ b/src/utilcode/newapis.cpp @@ -754,12 +754,14 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) int IndexOfString( __in LPCWSTR lpLocaleName, __in_ecount(cchCount1) LPCWSTR pString1, // String to search in __in int cchCount1, // length of pString1 - __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for + __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for __in int cchCount2, // length of pString2 __in DWORD dwFlags, // search flags - __in BOOL startWith) // true if we need to check for prefix case + __in BOOL startWith, // true if we need to check for prefix case + __out_opt LPINT pcchFound) // length of the string we found in source { int iRetVal = -1; + int foundLengthInSource = 0; // // Check the ranges. @@ -788,6 +790,7 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) if (dwFlags == COMPARE_OPTIONS_ORDINAL) { iRetVal = FastIndexOfString(pString1, cchCount1, pString2, cchCount2); + foundLengthInSource = cchCount2; goto lExit; } //For dwFlags, 0 is the default, 1 is ignore case, we can handle both. @@ -801,6 +804,11 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) iRetVal = FastIndexOfString(pString1, cchCount1, pString2, cchCount2); else iRetVal = FastIndexOfStringInsensitive(pString1, cchCount1, pString2, cchCount2); + + // both are ascii strings, + // the length should be the same as the length of the string we are searching for. + foundLengthInSource = cchCount2; + goto lExit; } } @@ -832,6 +840,7 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) if (result == CSTR_EQUAL) { iRetVal = iOffset; + foundLengthInSource = iLength; break; } else if (result == 0) @@ -848,6 +857,9 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) { iRetVal = -1; } + + if(iRetVal != -1 && pcchFound != NULL) + *pcchFound = foundLengthInSource; return iRetVal; } @@ -859,13 +871,16 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) int LastIndexOfString( __in LPCWSTR lpLocaleName, __in_ecount(cchCount1) LPCWSTR pString1, // String to search in __in int cchCount1, // length of pString1 - __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for + __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for __in int cchCount2, // length of pString2 __in DWORD dwFlags, - __in BOOL endWith) // check suffix case + __in BOOL endWith, // check suffix case + __out_opt LPINT pcchFound) // length of the string we found in source { INT32 iRetVal = -1; BOOL comparedOrdinal = FALSE; + + int foundLengthInSource = 0; // Check for empty strings if (cchCount1 == 0) @@ -896,6 +911,7 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) { iRetVal = FastLastIndexOfString(pString1, cchCount1, pString2, cchCount2); comparedOrdinal = TRUE; + foundLengthInSource = cchCount2; goto lExit; } @@ -910,6 +926,8 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) else iRetVal = FastLastIndexOfStringInsensitive(pString1, cchCount1, pString2, cchCount2); comparedOrdinal = TRUE; + + foundLengthInSource = cchCount2; goto lExit; } } @@ -923,6 +941,7 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) if (NewApis::CompareStringEx(lpLocaleName, dwFlags, pString2, cchCount2, &pString1[cchCount1 + iOffset - iLength], iLength, NULL, NULL, 0) == CSTR_EQUAL) { iRetVal= cchCount1 + iOffset - iLength; + foundLengthInSource = iLength; break; } } @@ -940,6 +959,9 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags) iRetVal = -1; } } + + if(iRetVal != -1 && pcchFound != NULL) + *pcchFound = foundLengthInSource; return iRetVal; } |