}
FCIMPLEND
-/*===================================Replace====================================
-**Action: Replaces all instances of oldChar with newChar.
-**Returns: A new String with all instances of oldChar replaced with newChar
-**Arguments: oldChar -- the character to replace
-** newChar -- the character with which to replace oldChar.
-**Exceptions: None
-==============================================================================*/
-FCIMPL3(LPVOID, COMString::Replace, StringObject* thisRefUNSAFE, CLR_CHAR oldChar, CLR_CHAR newChar)
-{
- FCALL_CONTRACT;
-
- int length = 0;
- int firstFoundIndex = -1;
- WCHAR *oldBuffer = NULL;
- WCHAR *newBuffer;
-
- STRINGREF newString = NULL;
- STRINGREF thisRef = (STRINGREF)thisRefUNSAFE;
-
- if (thisRef==NULL) {
- FCThrowRes(kNullReferenceException, W("NullReference_This"));
- }
-
- //Perf: If no replacements required, return initial reference
-
- // Do it if the chars are the same...
-
- if ((WCHAR)oldChar == (WCHAR)newChar)
- {
- return thisRefUNSAFE;
- }
-
- // Or if the old char isn't found.
- oldBuffer = thisRef->GetBuffer();
- length = thisRef->GetStringLength();
-
- for(int i=0; i<length; i++)
- {
- if ((WCHAR)oldChar==oldBuffer[i])
- {
- firstFoundIndex = i;
- break;
- }
- }
-
- if (-1==firstFoundIndex)
- {
- return thisRefUNSAFE;
- }
-
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(newString, thisRef);
-
- //Get the length and allocate a new String
- //We will definitely do an allocation here, but there's nothing which
- //requires GC_PROTECT.
- newString = StringObject::NewString(length);
-
- //After allocation, thisRef may have moved
- oldBuffer = thisRef->GetBuffer();
-
- //Get the buffers in both of the Strings.
- newBuffer = newString->GetBuffer();
-
- //Copy the characters, doing the replacement as we go.
- for (int i=0; i<firstFoundIndex; i++) {
- newBuffer[i]=oldBuffer[i];
- }
- for (int i=firstFoundIndex; i<length; i++) {
- newBuffer[i]=(oldBuffer[i]==((WCHAR)oldChar))?((WCHAR)newChar):oldBuffer[i];
- }
-
- HELPER_METHOD_FRAME_END();
-
- return OBJECTREFToObject(newString);
-}
-FCIMPLEND
-
// HELPER METHODS
//
//
//
static FCDECL4(Object*, PadHelper, StringObject* thisRefUNSAFE, INT32 totalWidth, CLR_CHAR paddingChar, CLR_BOOL isRightPadded);
- static FCDECL3(LPVOID, Replace, StringObject* thisRef, CLR_CHAR oldChar, CLR_CHAR newChar);
static FCDECL3(Object*, ReplaceString, StringObject* thisRef, StringObject* oldValue, StringObject* newValue);
static FCDECL3(Object*, Insert, StringObject* thisRefUNSAFE, INT32 startIndex, StringObject* valueUNSAFE);
// Replaces all instances of oldChar with newChar.
//
[System.Security.SecuritySafeCritical] // auto-generated
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern String ReplaceInternal(char oldChar, char newChar);
-
public String Replace(char oldChar, char newChar)
{
Contract.Ensures(Contract.Result<String>() != null);
Contract.Ensures(Contract.Result<String>().Length == this.Length);
Contract.EndContractBlock();
- return ReplaceInternal(oldChar, newChar);
+ if (oldChar == newChar)
+ return this;
+
+ unsafe
+ {
+ int remainingLength = Length;
+
+ fixed (char* pChars = &m_firstChar)
+ {
+ char* pSrc = pChars;
+
+ while (remainingLength > 0)
+ {
+ if (*pSrc == oldChar)
+ {
+ break;
+ }
+
+ remainingLength--;
+ pSrc++;
+ }
+ }
+
+ if (remainingLength == 0)
+ return this;
+
+ String result = FastAllocateString(Length);
+
+ fixed (char* pChars = &m_firstChar)
+ {
+ fixed (char* pResult = &result.m_firstChar)
+ {
+ int copyLength = Length - remainingLength;
+
+ //Copy the characters already proven not to match.
+ if (copyLength > 0)
+ {
+ wstrcpy(pResult, pChars, copyLength);
+ }
+
+ //Copy the remaining characters, doing the replacement as we go.
+ char* pSrc = pChars + copyLength;
+ char* pDst = pResult + copyLength;
+
+ do
+ {
+ char currentChar = *pSrc;
+ if (currentChar == oldChar)
+ currentChar = newChar;
+ *pDst = currentChar;
+
+ remainingLength--;
+ pSrc++;
+ pDst++;
+ } while (remainingLength > 0);
+ }
+ }
+
+ return result;
+ }
}
// This method contains the same functionality as StringBuilder Replace. The only difference is that
FCFuncElement("IndexOfAny", COMString::IndexOfCharArray)
FCFuncElement("LastIndexOf", COMString::LastIndexOfChar)
FCFuncElement("LastIndexOfAny", COMString::LastIndexOfCharArray)
- FCFuncElementSig("ReplaceInternal", &gsig_IM_Char_Char_RetStr, COMString::Replace)
FCFuncElementSig("ReplaceInternal", &gsig_IM_Str_Str_RetStr, COMString::ReplaceString)
FCFuncElement("PadHelper", COMString::PadHelper)
#ifdef FEATURE_COMINTEROP